diff --git a/Sources/XCTest/Public/Asynchronous/XCTWaiter.swift b/Sources/XCTest/Public/Asynchronous/XCTWaiter.swift index 13a232f33..fb2e4fd11 100644 --- a/Sources/XCTest/Public/Asynchronous/XCTWaiter.swift +++ b/Sources/XCTest/Public/Asynchronous/XCTWaiter.swift @@ -117,7 +117,7 @@ open class XCTWaiter { internal var waitSourceLocation: SourceLocation? private weak var manager: WaiterManager? private var runLoop: RunLoop? - + private var runLoopSource: RunLoop._Source? private weak var _delegate: XCTWaiterDelegate? private let delegateQueue = DispatchQueue(label: "org.swift.XCTest.XCTWaiter.delegate") @@ -217,14 +217,7 @@ open class XCTWaiter { self.manager = manager // Begin the core wait loop. - let timeoutTimestamp = Date.timeIntervalSinceReferenceDate + timeout - while !isFinished { - let remaining = timeoutTimestamp - Date.timeIntervalSinceReferenceDate - if remaining <= 0 { - break - } - primitiveWait(using: runLoop, duration: remaining) - } + primitiveWait(using: runLoop, duration: timeout) manager.stopManaging(self) self.manager = nil @@ -356,22 +349,13 @@ open class XCTWaiter { private extension XCTWaiter { func primitiveWait(using runLoop: RunLoop, duration timeout: TimeInterval) { - // The contract for `primitiveWait(for:)` explicitly allows waiting for a shorter period than requested - // by the `timeout` argument. Only run for a short time in case `cancelPrimitiveWait()` was called and - // issued `CFRunLoopStop` just before we reach this point. - let timeIntervalToRun = min(0.1, timeout) - - // RunLoop.run(mode:before:) should have @discardableResult - _ = runLoop.run(mode: .default, before: Date(timeIntervalSinceNow: timeIntervalToRun)) + self.runLoopSource = RunLoop._Source() + self.runLoop?._add(self.runLoopSource!, forMode: .default) + _ = self.runLoop?.run(until: .init(timeIntervalSinceNow: timeout)) } func cancelPrimitiveWait() { - guard let runLoop = runLoop else { return } -#if os(Windows) - runLoop._stop() -#else - CFRunLoopStop(runLoop.getCFRunLoop()) -#endif + runLoopSource?.invalidate() } } @@ -405,7 +389,7 @@ extension XCTWaiter: ManageableWaiter { dispatchPrecondition(condition: .onQueue(XCTWaiter.subsystemQueue)) queue_validateExpectationFulfillment(dueToTimeout: true) - manager!.queue_handleWatchdogTimeout(of: self) + manager?.queue_handleWatchdogTimeout(of: self) cancelPrimitiveWait() }