Skip to content

Commit 35b34ed

Browse files
authored
Work around test discovery crash when running on older OS versions due to unguarded use of .timeLimit (#409)
Fix a test discovery crash when running on older Apple OS versions which don't support `Clock` and related APIs. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
1 parent a8f42e0 commit 35b34ed

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

Diff for: Tests/TestingTests/Test.SnapshotTests.swift

+21-1
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,33 @@ struct Test_SnapshotTests {
9797
private static let bug: Bug = Bug.bug(12345, "Lorem ipsum")
9898

9999
@available(_clockAPI, *)
100-
@Test("timeLimit property", .timeLimit(.minutes(999_999_999)))
100+
@Test("timeLimit property", _timeLimitIfAvailable(minutes: 999_999_999))
101101
func timeLimit() async throws {
102102
let test = try #require(Test.current)
103103
let snapshot = Test.Snapshot(snapshotting: test)
104104

105105
#expect(snapshot.timeLimit == .seconds(60) * 999_999_999)
106106
}
107+
108+
/// Create a time limit trait representing the specified number of minutes, if
109+
/// running on an OS which supports time limits.
110+
///
111+
/// - Parameters:
112+
/// - minutes: The number of minutes the returned time limit trait should
113+
/// represent.
114+
///
115+
/// - Returns: A time limit trait if the API is available, otherwise a
116+
/// disabled trait.
117+
///
118+
/// This is provided in order to work around a bug where traits with
119+
/// conditional API availability are not guarded by `@available` attributes on
120+
/// `@Test` functions (rdar://127811571).
121+
private static func _timeLimitIfAvailable(minutes: some BinaryInteger) -> any TestTrait {
122+
guard #available(_clockAPI, *) else {
123+
return .disabled(".timeLimit() not available")
124+
}
125+
return .timeLimit(.minutes(minutes))
126+
}
107127
}
108128

109129
extension Tag {

Diff for: Tests/TestingTests/Traits/TimeLimitTraitTests.swift

+7-3
Original file line numberDiff line numberDiff line change
@@ -243,17 +243,21 @@ struct TimeLimitTraitTests {
243243

244244
// MARK: - Fixtures
245245

246-
func timeLimitIfAvailable(minutes: UInt64) -> any SuiteTrait {
246+
private func _timeLimitIfAvailable(minutes: UInt64) -> any SuiteTrait {
247247
// @available can't be applied to a suite type, so we can't mark the suite as
248-
// available only on newer OSes.
248+
// available only on newer OSes. In addition, there is a related, known bug
249+
// where traits with conditional API availability are not guarded by
250+
// `@available` attributes on their associated `@Test` function
251+
// (rdar://127811571). That is not directly relevant here but is worth noting
252+
// if this trait is ever applied to `@Test` functions in this file.
249253
if #available(_clockAPI, *) {
250254
.timeLimit(.minutes(minutes))
251255
} else {
252256
.disabled(".timeLimit() not available")
253257
}
254258
}
255259

256-
@Suite(.hidden, timeLimitIfAvailable(minutes: 10))
260+
@Suite(.hidden, _timeLimitIfAvailable(minutes: 10))
257261
struct TestTypeThatTimesOut {
258262
@available(_clockAPI, *)
259263
@Test(.hidden, arguments: 0 ..< 10)

0 commit comments

Comments
 (0)