Skip to content

Commit

Permalink
Merge branch 'main' into fix_testing_import_on_uitests
Browse files Browse the repository at this point in the history
  • Loading branch information
younata authored Oct 13, 2024
2 parents ac141cc + 61dcf0c commit cdcf108
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 40 deletions.
6 changes: 4 additions & 2 deletions Sources/Nimble/Adapters/AssertionRecorder+Async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler,
closure: () async throws -> Void) async {
let environment = NimbleEnvironment.activeInstance
let oldRecorder = environment.assertionHandler
_ = NMBExceptionCapture(handler: nil, finally: ({
defer {
environment.assertionHandler = oldRecorder
}))
}
environment.assertionHandler = tempAssertionHandler

do {
try await closure()
} catch is RequireError {
// ignore this
} catch {
let failureMessage = FailureMessage()
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
Expand Down
2 changes: 2 additions & 0 deletions Sources/Nimble/Adapters/AssertionRecorder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler,
try capturer.tryBlockThrows {
try closure()
}
} catch is RequireError {
// specifically ignore RequireError, will be caught by the assertion handler.
} catch {
let failureMessage = FailureMessage()
failureMessage.stringValue = "unexpected error thrown: <\(error)>"
Expand Down
46 changes: 30 additions & 16 deletions Sources/Nimble/DSL+Require.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ public func requirea<T>(fileID: String = #fileID, file: FileString = #filePath,
/// `unwrap` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
@discardableResult
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
}

/// Makes sure that the expression evaluates to a non-nil value, otherwise throw an error.
Expand All @@ -226,8 +226,8 @@ public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, li
/// `unwrap` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
@discardableResult
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
}

/// Makes sure that the expression evaluates to a non-nil value, otherwise throw an error.
Expand All @@ -236,8 +236,8 @@ public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, li
/// `unwraps` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
@discardableResult
public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
}

/// Makes sure that the expression evaluates to a non-nil value, otherwise throw an error.
Expand All @@ -246,8 +246,8 @@ public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, l
/// `unwraps` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
@discardableResult
public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
try requires(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
}

/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
Expand All @@ -256,8 +256,8 @@ public func unwraps<T>(fileID: String = #fileID, file: FileString = #filePath, l
/// `unwrap` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
@discardableResult
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @escaping () async throws -> T?) async throws -> T {
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, try await expression()).toNot(beNil())
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @escaping () async throws -> T?) async throws -> T {
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, try await expression()).toNot(beNil(), description: description)
}

/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
Expand All @@ -266,8 +266,8 @@ public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, li
/// `unwrap` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
@discardableResult
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: () -> (() async throws -> T?)) async throws -> T {
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: () -> (() async throws -> T?)) async throws -> T {
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
}

/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
Expand All @@ -276,8 +276,8 @@ public func unwrap<T>(fileID: String = #fileID, file: FileString = #filePath, li
/// `unwrapa` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
@discardableResult
public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure @escaping () async throws -> T?) async throws -> T {
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, try await expression()).toNot(beNil())
public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure @escaping () async throws -> T?) async throws -> T {
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, try await expression()).toNot(beNil(), description: description)
}

/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
Expand All @@ -286,6 +286,20 @@ public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, l
/// `unwrapa` will return the result of the expression if it is non-nil, and throw an error if the value is nil.
/// if a `customError` is given, then that will be thrown. Otherwise, a ``RequireError`` will be thrown.
@discardableResult
public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, _ expression: @autoclosure () -> (() async throws -> T?)) async throws -> T {
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil())
public func unwrapa<T>(fileID: String = #fileID, file: FileString = #filePath, line: UInt = #line, column: UInt = #column, customError: Error? = nil, description: String? = nil, _ expression: @autoclosure () -> (() async throws -> T?)) async throws -> T {
try await requirea(fileID: fileID, file: file, line: line, column: column, customError: customError, expression()).toNot(beNil(), description: description)
}

/// Always fails the test and throw an error to prevent further test execution.
///
/// - Parameter message: A custom message to use in place of the default one.
/// - Parameter customError: A custom error to throw in place of a ``RequireError``.
public func requireFail(_ message: String? = nil, customError: Error? = nil, fileID: String = #fileID, filePath: FileString = #filePath, line: UInt = #line, column: UInt = #column) throws {
let location = SourceLocation(fileID: fileID, filePath: filePath, line: line, column: column)
let handler = NimbleEnvironment.activeInstance.assertionHandler

let msg = message ?? "requireFail() always fails"
handler.assert(false, message: FailureMessage(stringValue: msg), location: location)

throw customError ?? RequireError(message: msg, location: location)
}
28 changes: 14 additions & 14 deletions Sources/Nimble/Polling+Require.swift
Original file line number Diff line number Diff line change
Expand Up @@ -713,50 +713,50 @@ public func pollUnwrap<T>(file: FileString = #file, line: UInt = #line, _ expres
/// Makes sure that the expression evaluates to a non-nil value, otherwise throw an error.
/// As you can tell, this is a much less verbose equivalent to `require(expression).toEventuallyNot(beNil())`
@discardableResult
public func pollUnwrap<T>(file: FileString = #file, line: UInt = #line, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
try require(file: file, line: line, expression()).toEventuallyNot(beNil())
public func pollUnwrap<T>(file: FileString = #file, line: UInt = #line, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
try require(file: file, line: line, expression()).toEventuallyNot(beNil(), timeout: timeout, pollInterval: pollInterval, description: description)
}

/// Makes sure that the expression evaluates to a non-nil value, otherwise throw an error.
/// As you can tell, this is a much less verbose equivalent to `require(expression).toEventuallyNot(beNil())`
@discardableResult
public func pollUnwraps<T>(file: FileString = #file, line: UInt = #line, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
try require(file: file, line: line, expression()).toEventuallyNot(beNil())
public func pollUnwraps<T>(file: FileString = #file, line: UInt = #line, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil, _ expression: @autoclosure @escaping () throws -> T?) throws -> T {
try require(file: file, line: line, expression()).toEventuallyNot(beNil(), timeout: timeout, pollInterval: pollInterval, description: description)
}

/// Makes sure that the expression evaluates to a non-nil value, otherwise throw an error.
/// As you can tell, this is a much less verbose equivalent to `require(expression).toEventuallyNot(beNil())`
@discardableResult
public func pollUnwraps<T>(file: FileString = #file, line: UInt = #line, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
try require(file: file, line: line, expression()).toEventuallyNot(beNil())
public func pollUnwraps<T>(file: FileString = #file, line: UInt = #line, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil, _ expression: @autoclosure () -> (() throws -> T?)) throws -> T {
try require(file: file, line: line, expression()).toEventuallyNot(beNil(), timeout: timeout, pollInterval: pollInterval, description: description)
}

/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
/// As you can tell, this is a much less verbose equivalent to `requirea(expression).toEventuallyNot(beNil())`
@discardableResult
public func pollUnwrap<T>(file: FileString = #file, line: UInt = #line, _ expression: @escaping () async throws -> T?) async throws -> T {
try await requirea(file: file, line: line, try await expression()).toEventuallyNot(beNil())
public func pollUnwrap<T>(file: FileString = #file, line: UInt = #line, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil, _ expression: @escaping () async throws -> T?) async throws -> T {
try await requirea(file: file, line: line, try await expression()).toEventuallyNot(beNil(), timeout: timeout, pollInterval: pollInterval, description: description)
}

/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
/// As you can tell, this is a much less verbose equivalent to `requirea(expression).toEventuallyNot(beNil())`
@discardableResult
public func pollUnwrap<T>(file: FileString = #file, line: UInt = #line, _ expression: () -> (() async throws -> T?)) async throws -> T {
try await requirea(file: file, line: line, expression()).toEventuallyNot(beNil())
public func pollUnwrap<T>(file: FileString = #file, line: UInt = #line, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil, _ expression: () -> (() async throws -> T?)) async throws -> T {
try await requirea(file: file, line: line, expression()).toEventuallyNot(beNil(), timeout: timeout, pollInterval: pollInterval, description: description)
}

/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
/// As you can tell, this is a much less verbose equivalent to `requirea(expression).toEventuallyNot(beNil())`
@discardableResult
public func pollUnwrapa<T>(file: FileString = #file, line: UInt = #line, _ expression: @autoclosure @escaping () async throws -> T?) async throws -> T {
try await requirea(file: file, line: line, try await expression()).toEventuallyNot(beNil())
public func pollUnwrapa<T>(file: FileString = #file, line: UInt = #line, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil, _ expression: @autoclosure @escaping () async throws -> T?) async throws -> T {
try await requirea(file: file, line: line, try await expression()).toEventuallyNot(beNil(), timeout: timeout, pollInterval: pollInterval, description: description)
}

/// Makes sure that the async expression evaluates to a non-nil value, otherwise throw an error.
/// As you can tell, this is a much less verbose equivalent to `requirea(expression).toEventuallyNot(beNil())`
@discardableResult
public func pollUnwrapa<T>(file: FileString = #file, line: UInt = #line, _ expression: @autoclosure () -> (() async throws -> T?)) async throws -> T {
try await requirea(file: file, line: line, expression()).toEventuallyNot(beNil())
public func pollUnwrapa<T>(file: FileString = #file, line: UInt = #line, timeout: NimbleTimeInterval = PollingDefaults.timeout, pollInterval: NimbleTimeInterval = PollingDefaults.pollInterval, description: String? = nil, _ expression: @autoclosure () -> (() async throws -> T?)) async throws -> T {
try await requirea(file: file, line: line, expression()).toEventuallyNot(beNil(), timeout: timeout, pollInterval: pollInterval, description: description)
}

#endif // #if !os(WASI)
2 changes: 1 addition & 1 deletion Tests/NimbleTests/AsyncAwaitTest+Require.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ final class AsyncAwaitRequireTest: XCTestCase { // swiftlint:disable:this type_b
}

func testPollUnwrapNegativeCase() async {
await failsWithErrorMessage("expected to eventually not be nil, got nil") {
await failsWithErrorMessage("expected to eventually not be nil, got <nil>") {
try await pollUnwrap { nil as Int? }
}
await failsWithErrorMessage("unexpected error thrown: <\(errorToThrow)>") {
Expand Down
2 changes: 1 addition & 1 deletion Tests/NimbleTests/AsyncAwaitTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ final class AsyncAwaitTest: XCTestCase { // swiftlint:disable:this type_body_len
}

func testWaitUntilDetectsStalledMainThreadActivity() async {
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."
let msg = "Waited more than 1.0 second"
await failsWithErrorMessage(msg) {
await waitUntil(timeout: .seconds(1)) { done in
Thread.sleep(forTimeInterval: 3.0)
Expand Down
Loading

0 comments on commit cdcf108

Please sign in to comment.