Skip to content

Commit 3107349

Browse files
authored
Add .default reporter, deprecate .runtimeWarning (#174)
* Add `.default` reporter, deprecate `.runtimeWarning` This patch moves the test reporting logic into a `default` reporter so that changing the reporters can influence tests. This is an alternate solution to #146. * wip * wip * wip * wip
1 parent f1c0bb0 commit 3107349

File tree

9 files changed

+166
-124
lines changed

9 files changed

+166
-124
lines changed

.github/workflows/ci.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ concurrency:
1414
cancel-in-progress: true
1515

1616
jobs:
17-
macos-15:
17+
macos-26:
1818
strategy:
1919
matrix:
2020
config:
2121
- debug
2222
- release
2323
xcode:
24-
- '16.4'
25-
name: macOS 15
26-
runs-on: macos-15
24+
- '26.1'
25+
name: macOS 26
26+
runs-on: macos-26
2727
steps:
28-
- uses: actions/checkout@v4
28+
- uses: actions/checkout@v5
2929
- name: Select Xcode
3030
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
3131
- name: Run tests
@@ -35,7 +35,7 @@ jobs:
3535
name: Library evolution
3636
runs-on: macos-15
3737
steps:
38-
- uses: actions/checkout@v4
38+
- uses: actions/checkout@v5
3939
- name: Select Xcode
4040
run: sudo xcode-select -s /Applications/Xcode_16.4.app
4141
- name: Run tests
@@ -48,11 +48,11 @@ jobs:
4848
- Debug
4949
- Release
5050
xcode:
51-
- '16.4'
51+
- '26.1'
5252
name: Examples
53-
runs-on: macos-15
53+
runs-on: macos-26
5454
steps:
55-
- uses: actions/checkout@v4
55+
- uses: actions/checkout@v5
5656
- name: Select Xcode
5757
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
5858
- name: Run tests
@@ -68,7 +68,7 @@ jobs:
6868
runs-on: ubuntu-latest
6969
container: swift:6.0.3
7070
steps:
71-
- uses: actions/checkout@v4
71+
- uses: actions/checkout@v5
7272
- name: Install dependencies
7373
run: apt-get update && apt-get install -y build-essential libcurl4-openssl-dev
7474
- name: Run tests
@@ -80,7 +80,7 @@ jobs:
8080
name: Wasm
8181
runs-on: ubuntu-latest
8282
steps:
83-
- uses: actions/checkout@v4
83+
- uses: actions/checkout@v5
8484
- uses: bytecodealliance/actions/wasmtime/setup@v1
8585
- name: Install Swift and Swift SDK for WebAssembly
8686
run: |
@@ -111,7 +111,7 @@ jobs:
111111
# tag: 6.0.3-RELEASE
112112
# - name: Set long paths
113113
# run: git config --system core.longpaths true
114-
# - uses: actions/checkout@v4
114+
# - uses: actions/checkout@v5
115115
# - name: Build
116116
# run: swift build -c ${{ matrix.config }}
117117
# - name: Run tests (debug only)
@@ -121,6 +121,6 @@ jobs:
121121
# name: Android
122122
# runs-on: ubuntu-latest
123123
# steps:
124-
# - uses: actions/checkout@v4
124+
# - uses: actions/checkout@v5
125125
# - name: "Test Swift Package on Android"
126126
# uses: skiptools/swift-android-action@v2

Examples/ExamplesTests/SwiftTestingTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
withKnownIssue {
1919
reportIssue()
2020
} matching: { issue in
21-
issue.description == "Issue recorded"
21+
issue.description.hasPrefix("Issue recorded")
2222
}
2323
}
2424

2525
@Test func reportIssue_CustomMessage() {
2626
withKnownIssue {
2727
reportIssue("Something went wrong")
2828
} matching: { issue in
29-
issue.description == "Issue recorded: Something went wrong"
29+
issue.description.hasSuffix("Something went wrong")
3030
}
3131
}
3232

@@ -51,7 +51,7 @@
5151
withExpectedIssue {
5252
}
5353
} matching: { issue in
54-
issue.description == "Known issue was not recorded"
54+
issue.description.hasPrefix("Known issue was not recorded")
5555
}
5656
}
5757

@@ -60,7 +60,7 @@
6060
withExpectedIssue("This didn't fail") {
6161
}
6262
} matching: { issue in
63-
issue.description == "Known issue was not recorded: This didn't fail"
63+
issue.description.hasSuffix("This didn't fail")
6464
}
6565
}
6666

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ test-examples:
2222
-configuration $(CONFIG) \
2323
-workspace IssueReporting.xcworkspace \
2424
-scheme Examples \
25-
-destination platform="iOS Simulator,name=iPhone 16"
25+
-destination platform="iOS Simulator,name=iPhone 17"
2626

2727
test-wasm:
2828
echo wasm-DEVELOPMENT-SNAPSHOT-2024-07-16-a > .swift-version

Sources/IssueReporting/Internal/Deprecations.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
// NB: Deprecated after 1.7.0
2+
3+
extension IssueReporter where Self == _DefaultReporter {
4+
@available(*, deprecated, renamed: "default")
5+
#if canImport(Darwin)
6+
@_transparent
7+
#endif
8+
public static var runtimeWarning: Self { Self() }
9+
}
10+
11+
@available(*, unavailable, renamed: "_DefaultReporter")
12+
public typealias _RuntimeWarningReporter = _DefaultReporter
13+
114
// NB: Deprecated after 1.2.2
215

316
#if canImport(Darwin)
@@ -9,4 +22,4 @@
922
public typealias FatalErrorReporter = _FatalErrorReporter
1023

1124
@available(*, unavailable, renamed: "_RuntimeWarningReporter")
12-
public typealias RuntimeWarningReporter = _RuntimeWarningReporter
25+
public typealias RuntimeWarningReporter = _DefaultReporter

Sources/IssueReporting/IsTesting.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
extension ProcessInfo {
2929
fileprivate var isTesting: Bool {
3030
if environment.keys.contains("XCTestBundlePath") { return true }
31+
if environment.keys.contains("XCTestBundleInjectPath") { return true }
3132
if environment.keys.contains("XCTestConfigurationFilePath") { return true }
3233
if environment.keys.contains("XCTestSessionIdentifier") { return true }
3334

Sources/IssueReporting/IssueReporter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ public enum IssueReporters {
152152
set { _current.withLock { $0 = newValue } }
153153
}
154154

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

158158
/// Overrides the task's issue reporters for the duration of the synchronous operation.

Sources/IssueReporting/IssueReporters/RuntimeWarningReporter.swift renamed to Sources/IssueReporting/IssueReporters/DefaultReporter.swift

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,25 @@ import Foundation
44
import os
55
#endif
66

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

21-
/// A type representing an issue reporter that emits "purple" runtime warnings to Xcode and logs
22-
/// fault-level messages to the console.
22+
/// A type representing an issue reporter that emits "purple" runtime warnings and test failures.
2323
///
2424
/// Use ``IssueReporter/runtimeWarning`` to create one of these values.
25-
public struct _RuntimeWarningReporter: IssueReporter {
25+
public struct _DefaultReporter: IssueReporter {
2626
#if canImport(os)
2727
@UncheckedSendable
2828
#if canImport(Darwin)
@@ -64,55 +64,113 @@ public struct _RuntimeWarningReporter: IssueReporter {
6464
filePath: StaticString,
6565
line: UInt,
6666
column: UInt
67+
) {
68+
guard !isTesting else {
69+
_recordIssue(
70+
message: message(),
71+
fileID: "\(fileID)",
72+
filePath: "\(filePath)",
73+
line: Int(line),
74+
column: Int(column)
75+
)
76+
_XCTFail(
77+
message().withAppHostWarningIfNeeded() ?? "",
78+
file: filePath,
79+
line: line
80+
)
81+
return
82+
}
83+
runtimeWarn(message(), fileID: fileID, line: line)
84+
}
85+
86+
@_transparent
87+
public func reportIssue(
88+
_ error: any Error,
89+
_ message: @autoclosure () -> String?,
90+
fileID: StaticString,
91+
filePath: StaticString,
92+
line: UInt,
93+
column: UInt
94+
) {
95+
guard !isTesting else {
96+
_recordError(
97+
error: error,
98+
message: message(),
99+
fileID: "\(fileID)",
100+
filePath: "\(filePath)",
101+
line: Int(line),
102+
column: Int(column)
103+
)
104+
_XCTFail(
105+
"Caught error: \(error)\(message().map { ": \($0)" } ?? "")".withAppHostWarningIfNeeded(),
106+
file: filePath,
107+
line: line
108+
)
109+
return
110+
}
111+
runtimeWarn(
112+
"Caught error: \(error)\(message().map { ": \($0)" } ?? "")",
113+
fileID: fileID,
114+
line: line
115+
)
116+
}
117+
118+
public func expectIssue(
119+
_ message: @autoclosure () -> String?,
120+
fileID: StaticString,
121+
filePath: StaticString,
122+
line: UInt,
123+
column: UInt
67124
) {
68125
#if canImport(os)
69-
guard ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] != "1"
70-
else {
71-
print("🟣 \(fileID):\(line): \(message() ?? "")")
72-
return
73-
}
74126
let moduleName = String(
75127
Substring("\(fileID)".utf8.prefix(while: { $0 != UTF8.CodeUnit(ascii: "/") }))
76128
)
77129
var message = message() ?? ""
78130
if message.isEmpty {
79-
message = "Issue reported"
131+
message = "Issue expected"
80132
}
81133
os_log(
82-
.fault,
83-
dso: dso,
84-
log: OSLog(subsystem: "com.apple.runtime-issues", category: moduleName),
134+
.info,
135+
log: OSLog(subsystem: "co.pointfree.expected-issues", category: moduleName),
85136
"%@",
86137
"\(isTesting ? "\(fileID):\(line): " : "")\(message)"
87138
)
88139
#else
89-
printError("\(fileID):\(line): \(message() ?? "")")
140+
print("\(fileID):\(line): \(message() ?? "")")
90141
#endif
91142
}
92143

93-
public func expectIssue(
144+
@_transparent
145+
@inlinable
146+
func runtimeWarn(
94147
_ message: @autoclosure () -> String?,
95148
fileID: StaticString,
96-
filePath: StaticString,
97-
line: UInt,
98-
column: UInt
149+
line: UInt
99150
) {
100151
#if canImport(os)
152+
guard ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] != "1"
153+
else {
154+
print("🟣 \(fileID):\(line): \(message() ?? "")")
155+
return
156+
}
101157
let moduleName = String(
102158
Substring("\(fileID)".utf8.prefix(while: { $0 != UTF8.CodeUnit(ascii: "/") }))
103159
)
104160
var message = message() ?? ""
105161
if message.isEmpty {
106-
message = "Issue expected"
162+
message = "Issue reported"
107163
}
108164
os_log(
109-
.info,
110-
log: OSLog(subsystem: "co.pointfree.expected-issues", category: moduleName),
165+
.fault,
166+
dso: dso,
167+
log: OSLog(subsystem: "com.apple.runtime-issues", category: moduleName),
111168
"%@",
112169
"\(isTesting ? "\(fileID):\(line): " : "")\(message)"
113170
)
114171
#else
115-
print("\(fileID):\(line): \(message() ?? "")")
172+
printError("\(fileID):\(line): \(message() ?? "")")
116173
#endif
174+
117175
}
118176
}

0 commit comments

Comments
 (0)