26
26
@available ( macOS 13 , iOS 17 , watchOS 9 , tvOS 17 , visionOS 1 , * )
27
27
public func confirmPassesEventually(
28
28
_ comment: Comment ? = nil ,
29
+ maxPollingIterations: Int = 1000 ,
30
+ pollingInterval: Duration = . milliseconds( 1 ) ,
29
31
isolation: isolated ( any Actor ) ? = #isolation,
30
32
sourceLocation: SourceLocation = #_sourceLocation,
31
33
_ body: @escaping ( ) async throws -> Bool
32
34
) async {
33
35
let poller = Poller (
34
36
pollingBehavior: . passesOnce,
37
+ pollingIterations: maxPollingIterations,
38
+ pollingInterval: pollingInterval,
35
39
comment: comment,
36
40
sourceLocation: sourceLocation
37
41
)
@@ -70,15 +74,20 @@ public struct PollingFailedError: Error {}
70
74
/// through other forms of `confirmation`.
71
75
@_spi ( Experimental)
72
76
@available ( macOS 13 , iOS 17 , watchOS 9 , tvOS 17 , visionOS 1 , * )
77
+ @discardableResult
73
78
public func confirmPassesEventually< R> (
74
79
_ comment: Comment ? = nil ,
80
+ maxPollingIterations: Int = 1000 ,
81
+ pollingInterval: Duration = . milliseconds( 1 ) ,
75
82
isolation: isolated ( any Actor ) ? = #isolation,
76
83
sourceLocation: SourceLocation = #_sourceLocation,
77
84
_ body: @escaping ( ) async throws -> R ?
78
85
) async throws -> R where R: Sendable {
79
86
let recorder = PollingRecorder < R > ( )
80
87
let poller = Poller (
81
88
pollingBehavior: . passesOnce,
89
+ pollingIterations: maxPollingIterations,
90
+ pollingInterval: pollingInterval,
82
91
comment: comment,
83
92
sourceLocation: sourceLocation
84
93
)
@@ -113,12 +122,16 @@ public func confirmPassesEventually<R>(
113
122
@available ( macOS 13 , iOS 17 , watchOS 9 , tvOS 17 , visionOS 1 , * )
114
123
public func confirmAlwaysPasses(
115
124
_ comment: Comment ? = nil ,
125
+ maxPollingIterations: Int = 1000 ,
126
+ pollingInterval: Duration = . milliseconds( 1 ) ,
116
127
isolation: isolated ( any Actor ) ? = #isolation,
117
128
sourceLocation: SourceLocation = #_sourceLocation,
118
129
_ body: @escaping ( ) async throws -> Bool
119
130
) async {
120
131
let poller = Poller (
121
132
pollingBehavior: . passesAlways,
133
+ pollingIterations: maxPollingIterations,
134
+ pollingInterval: pollingInterval,
122
135
comment: comment,
123
136
sourceLocation: sourceLocation
124
137
)
@@ -153,28 +166,26 @@ public func confirmAlwaysPasses(
153
166
@available ( macOS 13 , iOS 17 , watchOS 9 , tvOS 17 , visionOS 1 , * )
154
167
public func confirmAlwaysPasses< R> (
155
168
_ comment: Comment ? = nil ,
169
+ maxPollingIterations: Int = 1000 ,
170
+ pollingInterval: Duration = . milliseconds( 1 ) ,
156
171
isolation: isolated ( any Actor ) ? = #isolation,
157
172
sourceLocation: SourceLocation = #_sourceLocation,
158
173
_ body: @escaping ( ) async throws -> R ?
159
- ) async throws -> R where R: Sendable {
160
- let recorder = PollingRecorder < R > ( )
174
+ ) async {
161
175
let poller = Poller (
162
176
pollingBehavior: . passesAlways,
177
+ pollingIterations: maxPollingIterations,
178
+ pollingInterval: pollingInterval,
163
179
comment: comment,
164
180
sourceLocation: sourceLocation
165
181
)
166
182
await poller. evaluate ( isolation: isolation) {
167
183
do {
168
- return try await recorder . record ( value : body ( ) )
184
+ return try await body ( ) != nil
169
185
} catch {
170
186
return false
171
187
}
172
188
}
173
-
174
- if let value = await recorder. lastValue {
175
- return value
176
- }
177
- throw PollingFailedError( )
178
189
}
179
190
180
191
/// A type to record the last value returned by a closure returning an optional
@@ -289,6 +300,11 @@ private struct Poller {
289
300
/// while the expression continues to pass)
290
301
let pollingBehavior : PollingBehavior
291
302
303
+ // How many times to poll
304
+ let pollingIterations : Int
305
+ // Minimum waiting period between polling
306
+ let pollingInterval : Duration
307
+
292
308
/// A comment from the test author associated with the polling
293
309
let comment : Comment ?
294
310
@@ -306,7 +322,6 @@ private struct Poller {
306
322
_ body: @escaping ( ) async -> Bool
307
323
) async {
308
324
let result = await poll (
309
- runAmount: 1_000_000 ,
310
325
expression: body
311
326
)
312
327
result. issue (
@@ -325,20 +340,22 @@ private struct Poller {
325
340
/// - timeout: How long to poll for unitl the timeout triggers.
326
341
/// - Returns: The result of this polling.
327
342
private func poll(
328
- runAmount: Int ,
329
343
isolation: isolated ( any Actor ) ? = #isolation,
330
344
expression: @escaping ( ) async -> Bool
331
345
) async -> PollResult {
332
- for _ in 0 ..< runAmount {
333
- if Task . isCancelled {
334
- return . cancelled
335
- }
346
+ for _ in 0 ..< pollingIterations {
336
347
if let result = await pollingBehavior. processFinishedExpression (
337
348
expressionResult: expression ( )
338
349
) {
339
350
return result
340
351
}
341
- await Task . yield ( )
352
+ do {
353
+ try await Task . sleep ( for: pollingInterval)
354
+ } catch {
355
+ // `Task.sleep` should only throw an error if it's cancelled
356
+ // during the sleep period.
357
+ return . cancelled
358
+ }
342
359
}
343
360
return . ranToCompletion
344
361
}
0 commit comments