From 80e9903d494ccef8c97a823dde450db2ddaa74ca Mon Sep 17 00:00:00 2001 From: Zigii Wong Date: Sat, 28 Dec 2019 18:03:57 +0800 Subject: [PATCH] Replaced TimeInterval with DispatchTimeInterval --- Nimble.xcodeproj/project.pbxproj | 8 +++++ Sources/Nimble/Adapters/NMBExpectation.swift | 5 +-- Sources/Nimble/DSL+Wait.swift | 31 +++++++++++------ Sources/Nimble/Matchers/Async.swift | 19 ++++++----- .../Nimble/Matchers/PostNotification.swift | 3 +- Sources/Nimble/Utils/Await.swift | 12 +++---- .../Nimble/Utils/DispatchTimeInterval.swift | 34 +++++++++++++++++++ Tests/NimbleTests/AsynchronousTest.swift | 22 ++++++------ 8 files changed, 94 insertions(+), 40 deletions(-) create mode 100644 Sources/Nimble/Utils/DispatchTimeInterval.swift diff --git a/Nimble.xcodeproj/project.pbxproj b/Nimble.xcodeproj/project.pbxproj index 567379e5a..7bf93b68b 100644 --- a/Nimble.xcodeproj/project.pbxproj +++ b/Nimble.xcodeproj/project.pbxproj @@ -21,6 +21,9 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 0477153523B740AD00402D4E /* DispatchTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */; }; + 0477153623B740B700402D4E /* DispatchTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */; }; + 0477153723B740B800402D4E /* DispatchTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */; }; 1F0648CC19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; 1F0648CD19639F5A001F9C46 /* ObjectWithLazyProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */; }; 1F0648D41963AAB2001F9C46 /* SynchronousTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */; }; @@ -484,6 +487,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchTimeInterval.swift; sourceTree = ""; }; 1F0648CB19639F5A001F9C46 /* ObjectWithLazyProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectWithLazyProperty.swift; sourceTree = ""; }; 1F0648D31963AAB2001F9C46 /* SynchronousTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousTest.swift; sourceTree = ""; }; 1F14FB63194180C5009F2A08 /* utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = utils.swift; sourceTree = ""; }; @@ -882,6 +886,7 @@ 1FD8CD271968AB07008ED995 /* SourceLocation.swift */, 1FD8CD281968AB07008ED995 /* Stringers.swift */, AE4BA9AC1C88DDB500B73906 /* Errors.swift */, + 0477153423B740AD00402D4E /* DispatchTimeInterval.swift */, ); path = Utils; sourceTree = ""; @@ -1318,6 +1323,7 @@ 1FDBD8671AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */, AE4BA9AD1C88DDB500B73906 /* Errors.swift in Sources */, 1FD8CD3C1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */, + 0477153623B740B700402D4E /* DispatchTimeInterval.swift in Sources */, 7A6AB2C51E7F628900A2F694 /* ToSucceed.swift in Sources */, 1FD8CD501968AB07008ED995 /* BeLogical.swift in Sources */, 1F1871CB1CA89EDB00A34BF2 /* NMBExpectation.swift in Sources */, @@ -1501,6 +1507,7 @@ CDD80B851F20307B0002CD65 /* MatcherProtocols.swift in Sources */, 1F5DF1721BDCA0F500C3A531 /* Expectation.swift in Sources */, 7B5358C01C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + 0477153723B740B800402D4E /* DispatchTimeInterval.swift in Sources */, 7B13BA0C1DD361D300C9098C /* ContainElementSatisfying.swift in Sources */, 1F5DF1871BDCA0F500C3A531 /* Match.swift in Sources */, ); @@ -1593,6 +1600,7 @@ 1F1871E71CA8A18400A34BF2 /* Async.swift in Sources */, 1FDBD8681AF8A4FF0089F27B /* AssertionDispatcher.swift in Sources */, AE4BA9AE1C88DDB500B73906 /* Errors.swift in Sources */, + 0477153523B740AD00402D4E /* DispatchTimeInterval.swift in Sources */, 1FD8CD3D1968AB07008ED995 /* BeAnInstanceOf.swift in Sources */, 1FD8CD511968AB07008ED995 /* BeLogical.swift in Sources */, 1F1871D91CA89EF100A34BF2 /* NMBExpectation.swift in Sources */, diff --git a/Sources/Nimble/Adapters/NMBExpectation.swift b/Sources/Nimble/Adapters/NMBExpectation.swift index 5338a4656..d83106ef5 100644 --- a/Sources/Nimble/Adapters/NMBExpectation.swift +++ b/Sources/Nimble/Adapters/NMBExpectation.swift @@ -1,4 +1,5 @@ import Foundation +import Dispatch #if canImport(Darwin) && !SWIFT_PACKAGE @@ -37,7 +38,7 @@ public class NMBExpectation: NSObject { internal var _negative: Bool internal let _file: FileString internal let _line: UInt - internal var _timeout: TimeInterval = 1.0 + internal var _timeout: DispatchTimeInterval = DispatchTimeInterval.seconds(1) // swiftlint:enable identifier_name @objc public init(actualBlock: @escaping () -> NSObject?, negative: Bool, file: FileString, line: UInt) { @@ -54,7 +55,7 @@ public class NMBExpectation: NSObject { } @objc public var withTimeout: (TimeInterval) -> NMBExpectation { - return { timeout in self._timeout = timeout + return { timeout in self._timeout = timeout.dispatchInterval return self } } diff --git a/Sources/Nimble/DSL+Wait.swift b/Sources/Nimble/DSL+Wait.swift index c049417ad..aa46dc5e1 100644 --- a/Sources/Nimble/DSL+Wait.swift +++ b/Sources/Nimble/DSL+Wait.swift @@ -20,6 +20,18 @@ internal class NMBWait: NSObject { timeout: TimeInterval, file: FileString = #file, line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) { + // Convert TimeInterval to DispatchTimeInterval + let dispatchTimeout: DispatchTimeInterval = timeout.dispatchInterval + return throwableUntil(timeout: dispatchTimeout, file: file, line: line) { done in + action(done) + } + } + + internal class func until( + timeout: DispatchTimeInterval, + file: FileString = #file, + line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) { return throwableUntil(timeout: timeout, file: file, line: line) { done in action(done) @@ -27,7 +39,7 @@ internal class NMBWait: NSObject { } #else internal class func until( - timeout: TimeInterval, + timeout: DispatchTimeInterval, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) { @@ -39,12 +51,12 @@ internal class NMBWait: NSObject { // Using a throwable closure makes this method not objc compatible. internal class func throwableUntil( - timeout: TimeInterval, + timeout: DispatchTimeInterval, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) throws -> Void) { let awaiter = NimbleEnvironment.activeInstance.awaiter - let leeway = timeout / 2.0 + let leeway = timeout.divided // swiftlint:disable:next line_length let result = awaiter.performBlock(file: file, line: line) { (done: @escaping (ErrorResult) -> Void) throws -> Void in DispatchQueue.main.async { @@ -72,8 +84,7 @@ internal class NMBWait: NSObject { fail(blockedRunLoopErrorMessageFor("-waitUntil()", leeway: leeway), file: file, line: line) case .timedOut: - let pluralize = (timeout == 1 ? "" : "s") - fail("Waited more than \(timeout) second\(pluralize)", file: file, line: line) + fail("Waited more than \(timeout.description)", file: file, line: line) case let .raisedException(exception): fail("Unexpected exception raised: \(exception)") case let .errorThrown(error): @@ -93,21 +104,21 @@ internal class NMBWait: NSObject { _ file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) { - until(timeout: 1, file: file, line: line, action: action) + until(timeout: DispatchTimeInterval.seconds(1), file: file, line: line, action: action) } #else internal class func until( _ file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) { - until(timeout: 1, file: file, line: line, action: action) + until(timeout: DispatchTimeInterval.seconds(1), file: file, line: line, action: action) } #endif } -internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> String { +internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: DispatchTimeInterval) -> String { // swiftlint:disable:next line_length - return "\(fnName) timed out but was unable to run the timeout handler because the main thread is unresponsive (\(leeway) seconds is allow after the wait times out). Conditions that may cause this include processing blocking IO on the main thread, calls to sleep(), deadlocks, and synchronous IPC. Nimble forcefully stopped run loop which may cause future failures in test run." + return "\(fnName) timed out but was unable to run the timeout handler because the main thread is unresponsive (\(leeway.description) is allow after the wait times out). Conditions that may cause this include processing blocking IO on the main thread, calls to sleep(), deadlocks, and synchronous IPC. Nimble forcefully stopped run loop which may cause future failures in test run." } /// Wait asynchronously until the done closure is called or the timeout has been reached. @@ -117,6 +128,6 @@ internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterv /// /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. -public func waitUntil(timeout: TimeInterval = AsyncDefaults.Timeout, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) { +public func waitUntil(timeout: DispatchTimeInterval = AsyncDefaults.Timeout, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) { NMBWait.until(timeout: timeout, file: file, line: line, action: action) } diff --git a/Sources/Nimble/Matchers/Async.swift b/Sources/Nimble/Matchers/Async.swift index 5022fe211..3924045c0 100644 --- a/Sources/Nimble/Matchers/Async.swift +++ b/Sources/Nimble/Matchers/Async.swift @@ -1,13 +1,14 @@ import Foundation +import Dispatch /// If you are running on a slower machine, it could be useful to increase the default timeout value /// or slow down poll interval. Default timeout interval is 1, and poll interval is 0.01. public struct AsyncDefaults { - public static var Timeout: TimeInterval = 1 - public static var PollInterval: TimeInterval = 0.01 + public static var Timeout: DispatchTimeInterval = DispatchTimeInterval.seconds(1) + public static var PollInterval: DispatchTimeInterval = DispatchTimeInterval.milliseconds(10) } -private func async(style: ExpectationStyle, predicate: Predicate, timeout: TimeInterval, poll: TimeInterval, fnName: String) -> Predicate { +private func async(style: ExpectationStyle, predicate: Predicate, timeout: DispatchTimeInterval, poll: DispatchTimeInterval, fnName: String) -> Predicate { return Predicate { actualExpression in let uncachedExpression = actualExpression.withoutCaching() let fnName = "expect(...).\(fnName)(...)" @@ -55,7 +56,7 @@ extension Expectation { /// @discussion /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. - public func toEventually(_ predicate: Predicate, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + public func toEventually(_ predicate: Predicate, timeout: DispatchTimeInterval = AsyncDefaults.Timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = execute( @@ -75,7 +76,7 @@ extension Expectation { /// @discussion /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. - public func toEventuallyNot(_ predicate: Predicate, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + public func toEventuallyNot(_ predicate: Predicate, timeout: DispatchTimeInterval = AsyncDefaults.Timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { nimblePrecondition(expression.isClosure, "NimbleInternalError", toEventuallyRequiresClosureError.stringValue) let (pass, msg) = execute( @@ -103,7 +104,7 @@ extension Expectation { /// @discussion /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. - public func toNotEventually(_ predicate: Predicate, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { + public func toNotEventually(_ predicate: Predicate, timeout: DispatchTimeInterval = AsyncDefaults.Timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.PollInterval, description: String? = nil) { return toEventuallyNot(predicate, timeout: timeout, pollInterval: pollInterval, description: description) } } @@ -116,7 +117,7 @@ extension Expectation { /// @discussion /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. - public func toEventually(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + public func toEventually(_ matcher: U, timeout: DispatchTimeInterval = AsyncDefaults.Timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.PollInterval, description: String? = nil) where U: Matcher, U.ValueType == T { if expression.isClosure { let (pass, msg) = execute( @@ -145,7 +146,7 @@ extension Expectation { /// @discussion /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. - public func toEventuallyNot(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + public func toEventuallyNot(_ matcher: U, timeout: DispatchTimeInterval = AsyncDefaults.Timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.PollInterval, description: String? = nil) where U: Matcher, U.ValueType == T { if expression.isClosure { let (pass, msg) = expressionDoesNotMatch( @@ -174,7 +175,7 @@ extension Expectation { /// @discussion /// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function /// is executing. Any attempts to touch the run loop may cause non-deterministic behavior. - public func toNotEventually(_ matcher: U, timeout: TimeInterval = AsyncDefaults.Timeout, pollInterval: TimeInterval = AsyncDefaults.PollInterval, description: String? = nil) + public func toNotEventually(_ matcher: U, timeout: DispatchTimeInterval = AsyncDefaults.Timeout, pollInterval: DispatchTimeInterval = AsyncDefaults.PollInterval, description: String? = nil) where U: Matcher, U.ValueType == T { return toEventuallyNot(matcher, timeout: timeout, pollInterval: pollInterval, description: description) } diff --git a/Sources/Nimble/Matchers/PostNotification.swift b/Sources/Nimble/Matchers/PostNotification.swift index 5e8bee3d5..cb2d595da 100644 --- a/Sources/Nimble/Matchers/PostNotification.swift +++ b/Sources/Nimble/Matchers/PostNotification.swift @@ -70,8 +70,7 @@ public func postNotifications( _ notificationsMatcher: T, fromNotificationCenter center: NotificationCenter = .default) -> Predicate - where T: Matcher, T.ValueType == [Notification] -{ + where T: Matcher, T.ValueType == [Notification] { _ = mainThread // Force lazy-loading of this value let collector = NotificationCollector(notificationCenter: center) collector.startObserving() diff --git a/Sources/Nimble/Utils/Await.swift b/Sources/Nimble/Utils/Await.swift index 0432a6b67..b28c3ed05 100644 --- a/Sources/Nimble/Utils/Await.swift +++ b/Sources/Nimble/Utils/Await.swift @@ -152,7 +152,7 @@ internal class AwaitPromiseBuilder { self.trigger = trigger } - func timeout(_ timeoutInterval: TimeInterval, forcefullyAbortTimeout: TimeInterval) -> Self { + func timeout(_ timeoutInterval: DispatchTimeInterval, forcefullyAbortTimeout: DispatchTimeInterval) -> Self { // = Discussion = // // There's a lot of technical decisions here that is useful to elaborate on. This is @@ -317,12 +317,12 @@ internal class Awaiter { trigger: trigger) } - func poll(_ pollInterval: TimeInterval, closure: @escaping () throws -> T?) -> AwaitPromiseBuilder { + func poll(_ pollInterval: DispatchTimeInterval, closure: @escaping () throws -> T?) -> AwaitPromiseBuilder { let promise = AwaitPromise() let timeoutSource = createTimerSource(timeoutQueue) let asyncSource = createTimerSource(asyncQueue) let trigger = AwaitTrigger(timeoutSource: timeoutSource, actionSource: asyncSource) { - let interval = DispatchTimeInterval.nanoseconds(Int(pollInterval * TimeInterval(NSEC_PER_SEC))) + let interval = pollInterval asyncSource.schedule(deadline: .now(), repeating: interval, leeway: pollLeeway) asyncSource.setEventHandler { do { @@ -349,8 +349,8 @@ internal class Awaiter { } internal func pollBlock( - pollInterval: TimeInterval, - timeoutInterval: TimeInterval, + pollInterval: DispatchTimeInterval, + timeoutInterval: DispatchTimeInterval, file: FileString, line: UInt, fnName: String = #function, @@ -361,7 +361,7 @@ internal func pollBlock( return true } return nil - }.timeout(timeoutInterval, forcefullyAbortTimeout: timeoutInterval / 2.0).wait(fnName, file: file, line: line) + }.timeout(timeoutInterval, forcefullyAbortTimeout: AsyncDefaults.Timeout).wait(fnName, file: file, line: line) return result } diff --git a/Sources/Nimble/Utils/DispatchTimeInterval.swift b/Sources/Nimble/Utils/DispatchTimeInterval.swift new file mode 100644 index 000000000..9b1367514 --- /dev/null +++ b/Sources/Nimble/Utils/DispatchTimeInterval.swift @@ -0,0 +1,34 @@ +import Dispatch + +extension DispatchTimeInterval { + // ** Note: We cannot simply divide the timeinterval because DispatchTimeInterval associated value type is Int + public var divided: DispatchTimeInterval { + switch self { + case let .seconds(val): return val < 2 ? .milliseconds(Int(Float(val)/2*1000)) : .seconds(val/2) + case let .milliseconds(val): return .milliseconds(val/2) + case let .microseconds(val): return .microseconds(val/2) + case let .nanoseconds(val): return .nanoseconds(val/2) + case .never: return .never + @unknown default: fatalError("Unknow DispatchTimeInterval value") + } + } + + var description: String { + switch self { + case let .seconds(val): return val == 1 ? "\(Float(val)) second" : "\(Float(val)) seconds" + case let .milliseconds(val): return "\(Float(val)/1000) seconds" + case let .microseconds(val): return "\(Float(val)/1000000) seconds" + case let .nanoseconds(val): return "\(Float(val)/1000000000) seconds" + default: fatalError("Unknow DispatchTimeInterval value") + } + } +} + +extension TimeInterval { + // swiftlint:disable line_length + public var dispatchInterval: DispatchTimeInterval { + let microseconds = Int64(self * TimeInterval(USEC_PER_SEC)) + // perhaps use nanoseconds, though would more often be > Int.max + return microseconds < Int.max ? DispatchTimeInterval.microseconds(Int(microseconds)) : DispatchTimeInterval.seconds(Int(self)) + } +} diff --git a/Tests/NimbleTests/AsynchronousTest.swift b/Tests/NimbleTests/AsynchronousTest.swift index 0195a92a7..ceb96c082 100644 --- a/Tests/NimbleTests/AsynchronousTest.swift +++ b/Tests/NimbleTests/AsynchronousTest.swift @@ -37,9 +37,9 @@ final class AsyncTest: XCTestCase { } func testToEventuallyWithCustomDefaultTimeout() { - AsyncDefaults.Timeout = 2 + AsyncDefaults.Timeout = DispatchTimeInterval.seconds(2) defer { - AsyncDefaults.Timeout = 1 + AsyncDefaults.Timeout = DispatchTimeInterval.seconds(1) } var value = 0 @@ -61,9 +61,9 @@ final class AsyncTest: XCTestCase { } func testWaitUntilWithCustomDefaultsTimeout() { - AsyncDefaults.Timeout = 3 + AsyncDefaults.Timeout = DispatchTimeInterval.seconds(3) defer { - AsyncDefaults.Timeout = 1 + AsyncDefaults.Timeout = DispatchTimeInterval.seconds(1) } waitUntil { done in Thread.sleep(forTimeInterval: 2.8) @@ -84,14 +84,14 @@ final class AsyncTest: XCTestCase { func testWaitUntilTimesOutIfNotCalled() { failsWithErrorMessage("Waited more than 1.0 second") { - waitUntil(timeout: 1) { _ in return } + waitUntil(timeout: DispatchTimeInterval.seconds(1)) { _ in return } } } func testWaitUntilTimesOutWhenExceedingItsTime() { var waiting = true failsWithErrorMessage("Waited more than 0.01 seconds") { - waitUntil(timeout: 0.01) { done in + waitUntil(timeout: .milliseconds(10)) { done in let asyncOperation: () -> Void = { Thread.sleep(forTimeInterval: 0.1) done() @@ -120,7 +120,7 @@ final class AsyncTest: XCTestCase { func testWaitUntilDetectsStalledMainThreadActivity() { let msg = "-waitUntil() timed out but was unable to run the timeout handler because the main thread is unresponsive (0.5 seconds is allow after the wait times out). Conditions that may cause this include processing blocking IO on the main thread, calls to sleep(), deadlocks, and synchronous IPC. Nimble forcefully stopped run loop which may cause future failures in test run." failsWithErrorMessage(msg) { - waitUntil(timeout: 1) { done in + waitUntil(timeout: DispatchTimeInterval.seconds(1)) { done in Thread.sleep(forTimeInterval: 3.0) done() } @@ -141,7 +141,7 @@ final class AsyncTest: XCTestCase { is currently managing the main run loop. """ failsWithErrorMessage(msg) { // reference line - waitUntil(timeout: 2.0) { done in + waitUntil(timeout: DispatchTimeInterval.seconds(2)) { done in var protected: Int = 0 DispatchQueue.main.async { protected = 1 @@ -203,11 +203,11 @@ final class AsyncTest: XCTestCase { var subject: ClassUnderTest? = ClassUnderTest() if let sub = subject { - expect(sub.count).toEventually(equal(0), timeout: 0.1) - expect(sub.count).toEventuallyNot(equal(1), timeout: 0.1) + expect(sub.count).toEventually(equal(0), timeout: .milliseconds(100)) + expect(sub.count).toEventuallyNot(equal(1), timeout: .milliseconds(100)) } - waitUntil(timeout: 0.5) { done in + waitUntil(timeout: .milliseconds(500)) { done in subject?.deinitCalled = { done() }