Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ concurrency:
cancel-in-progress: true

jobs:
macos-15:
macos-26:
strategy:
matrix:
config:
- debug
- release
xcode:
- '16.4'
name: macOS 15
runs-on: macos-15
- '26.1'
name: macOS 26
runs-on: macos-26
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: Run tests
Expand All @@ -35,7 +35,7 @@ jobs:
name: Library evolution
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_16.4.app
- name: Run tests
Expand All @@ -48,11 +48,11 @@ jobs:
- Debug
- Release
xcode:
- '16.4'
- '26.1'
name: Examples
runs-on: macos-15
runs-on: macos-26
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: Run tests
Expand All @@ -68,7 +68,7 @@ jobs:
runs-on: ubuntu-latest
container: swift:6.0.3
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Install dependencies
run: apt-get update && apt-get install -y build-essential libcurl4-openssl-dev
- name: Run tests
Expand All @@ -80,7 +80,7 @@ jobs:
name: Wasm
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: bytecodealliance/actions/wasmtime/setup@v1
- name: Install Swift and Swift SDK for WebAssembly
run: |
Expand Down Expand Up @@ -111,7 +111,7 @@ jobs:
# tag: 6.0.3-RELEASE
# - name: Set long paths
# run: git config --system core.longpaths true
# - uses: actions/checkout@v4
# - uses: actions/checkout@v5
# - name: Build
# run: swift build -c ${{ matrix.config }}
# - name: Run tests (debug only)
Expand All @@ -121,6 +121,6 @@ jobs:
# name: Android
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: actions/checkout@v5
# - name: "Test Swift Package on Android"
# uses: skiptools/swift-android-action@v2
8 changes: 4 additions & 4 deletions Examples/ExamplesTests/SwiftTestingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
withKnownIssue {
reportIssue()
} matching: { issue in
issue.description == "Issue recorded"
issue.description.hasPrefix("Issue recorded")
}
}

@Test func reportIssue_CustomMessage() {
withKnownIssue {
reportIssue("Something went wrong")
} matching: { issue in
issue.description == "Issue recorded: Something went wrong"
issue.description.hasSuffix("Something went wrong")
}
}

Expand All @@ -51,7 +51,7 @@
withExpectedIssue {
}
} matching: { issue in
issue.description == "Known issue was not recorded"
issue.description.hasPrefix("Known issue was not recorded")
}
}

Expand All @@ -60,7 +60,7 @@
withExpectedIssue("This didn't fail") {
}
} matching: { issue in
issue.description == "Known issue was not recorded: This didn't fail"
issue.description.hasSuffix("This didn't fail")
}
}

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test-examples:
-configuration $(CONFIG) \
-workspace IssueReporting.xcworkspace \
-scheme Examples \
-destination platform="iOS Simulator,name=iPhone 16"
-destination platform="iOS Simulator,name=iPhone 17"

test-wasm:
echo wasm-DEVELOPMENT-SNAPSHOT-2024-07-16-a > .swift-version
Expand Down
15 changes: 14 additions & 1 deletion Sources/IssueReporting/Internal/Deprecations.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
// NB: Deprecated after 1.7.0

extension IssueReporter where Self == _DefaultReporter {
@available(*, deprecated, renamed: "default")
#if canImport(Darwin)
@_transparent
#endif
public static var runtimeWarning: Self { Self() }
}

@available(*, unavailable, renamed: "_DefaultReporter")
public typealias _RuntimeWarningReporter = _DefaultReporter

// NB: Deprecated after 1.2.2

#if canImport(Darwin)
Expand All @@ -9,4 +22,4 @@
public typealias FatalErrorReporter = _FatalErrorReporter

@available(*, unavailable, renamed: "_RuntimeWarningReporter")
public typealias RuntimeWarningReporter = _RuntimeWarningReporter
public typealias RuntimeWarningReporter = _DefaultReporter
1 change: 1 addition & 0 deletions Sources/IssueReporting/IsTesting.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
extension ProcessInfo {
fileprivate var isTesting: Bool {
if environment.keys.contains("XCTestBundlePath") { return true }
if environment.keys.contains("XCTestBundleInjectPath") { return true }
if environment.keys.contains("XCTestConfigurationFilePath") { return true }
if environment.keys.contains("XCTestSessionIdentifier") { return true }

Expand Down
2 changes: 1 addition & 1 deletion Sources/IssueReporting/IssueReporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public enum IssueReporters {
set { _current.withLock { $0 = newValue } }
}

@TaskLocal fileprivate static var _current = LockIsolated<[any IssueReporter]>([.runtimeWarning])
@TaskLocal fileprivate static var _current = LockIsolated<[any IssueReporter]>([.default])
}

/// Overrides the task's issue reporters for the duration of the synchronous operation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@ import Foundation
import os
#endif

extension IssueReporter where Self == _RuntimeWarningReporter {
extension IssueReporter where Self == _DefaultReporter {
/// An issue reporter that emits "purple" runtime warnings to Xcode and logs fault-level messages
/// to the console.
///
/// This is the default issue reporter. On non-Apple platforms it logs messages to `stderr`.
/// During test runs it emits test failures, instead.
///
/// If this issue reporter receives an expected issue, it will log an info-level message to the
/// console, instead.
#if canImport(Darwin)
@_transparent
#endif
public static var runtimeWarning: Self { Self() }
public static var `default`: Self { Self() }
}

/// A type representing an issue reporter that emits "purple" runtime warnings to Xcode and logs
/// fault-level messages to the console.
/// A type representing an issue reporter that emits "purple" runtime warnings and test failures.
///
/// Use ``IssueReporter/runtimeWarning`` to create one of these values.
public struct _RuntimeWarningReporter: IssueReporter {
public struct _DefaultReporter: IssueReporter {
#if canImport(os)
@UncheckedSendable
#if canImport(Darwin)
Expand Down Expand Up @@ -64,55 +64,113 @@ public struct _RuntimeWarningReporter: IssueReporter {
filePath: StaticString,
line: UInt,
column: UInt
) {
guard !isTesting else {
_recordIssue(
message: message(),
fileID: "\(fileID)",
filePath: "\(filePath)",
line: Int(line),
column: Int(column)
)
_XCTFail(
message().withAppHostWarningIfNeeded() ?? "",
file: filePath,
line: line
)
return
}
runtimeWarn(message(), fileID: fileID, line: line)
}

@_transparent
public func reportIssue(
_ error: any Error,
_ message: @autoclosure () -> String?,
fileID: StaticString,
filePath: StaticString,
line: UInt,
column: UInt
) {
guard !isTesting else {
_recordError(
error: error,
message: message(),
fileID: "\(fileID)",
filePath: "\(filePath)",
line: Int(line),
column: Int(column)
)
_XCTFail(
"Caught error: \(error)\(message().map { ": \($0)" } ?? "")".withAppHostWarningIfNeeded(),
file: filePath,
line: line
)
return
}
runtimeWarn(
"Caught error: \(error)\(message().map { ": \($0)" } ?? "")",
fileID: fileID,
line: line
)
}

public func expectIssue(
_ message: @autoclosure () -> String?,
fileID: StaticString,
filePath: StaticString,
line: UInt,
column: UInt
) {
#if canImport(os)
guard ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] != "1"
else {
print("🟣 \(fileID):\(line): \(message() ?? "")")
return
}
let moduleName = String(
Substring("\(fileID)".utf8.prefix(while: { $0 != UTF8.CodeUnit(ascii: "/") }))
)
var message = message() ?? ""
if message.isEmpty {
message = "Issue reported"
message = "Issue expected"
}
os_log(
.fault,
dso: dso,
log: OSLog(subsystem: "com.apple.runtime-issues", category: moduleName),
.info,
log: OSLog(subsystem: "co.pointfree.expected-issues", category: moduleName),
"%@",
"\(isTesting ? "\(fileID):\(line): " : "")\(message)"
)
#else
printError("\(fileID):\(line): \(message() ?? "")")
print("\(fileID):\(line): \(message() ?? "")")
#endif
}

public func expectIssue(
@_transparent
@inlinable
func runtimeWarn(
_ message: @autoclosure () -> String?,
fileID: StaticString,
filePath: StaticString,
line: UInt,
column: UInt
line: UInt
) {
#if canImport(os)
guard ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] != "1"
else {
print("🟣 \(fileID):\(line): \(message() ?? "")")
return
}
let moduleName = String(
Substring("\(fileID)".utf8.prefix(while: { $0 != UTF8.CodeUnit(ascii: "/") }))
)
var message = message() ?? ""
if message.isEmpty {
message = "Issue expected"
message = "Issue reported"
}
os_log(
.info,
log: OSLog(subsystem: "co.pointfree.expected-issues", category: moduleName),
.fault,
dso: dso,
log: OSLog(subsystem: "com.apple.runtime-issues", category: moduleName),
"%@",
"\(isTesting ? "\(fileID):\(line): " : "")\(message)"
)
#else
print("\(fileID):\(line): \(message() ?? "")")
printError("\(fileID):\(line): \(message() ?? "")")
#endif

}
}
Loading