Created
November 20, 2021 11:36
-
-
Save sidepelican/e1b802f22bd5e94294ff05154d7ef849 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if !canImport(ObjectiveC) | |
import Foundation | |
import XCTest | |
// INFO: | |
//typealias XCTestCaseClosure = (XCTestCase) throws -> Void | |
//typealias XCTestCaseEntry = (testCaseClass: XCTestCase.Type, allTests: [(String, XCTestCaseClosure)]) | |
func testCase<T: XCTestCase>(_ allTests: [(String, (T) -> () async throws -> Void)]) -> XCTestCaseEntry { | |
let tests: [(String, XCTestCaseClosure)] = allTests.map { ($0.0, asyncTest($0.1)) } | |
return (T.self, tests) | |
} | |
private func asyncTest<T: XCTestCase>( | |
_ testClosureGenerator: @escaping (T) -> () async throws -> Void | |
) -> XCTestCaseClosure { | |
return { testCaseType in | |
guard let testCase = testCaseType as? T else { | |
fatalError("Attempt to invoke test on class \(T.self) with incompatible instance type \(type(of: testCaseType))") | |
} | |
let testClosure = testClosureGenerator(testCase) | |
try awaitUsingExpectation(testClosure) | |
} | |
} | |
private func awaitUsingExpectation( | |
_ closure: @escaping () async throws -> Void | |
) throws -> Void { | |
let expectation = XCTestExpectation(description: "async test completion") | |
let thrownErrorWrapper = ThrownErrorWrapper() | |
Task { | |
defer { expectation.fulfill() } | |
do { | |
try await closure() | |
} catch { | |
thrownErrorWrapper.error = error | |
} | |
} | |
_ = XCTWaiter.wait(for: [expectation], timeout: asyncTestTimeout) | |
if let error = thrownErrorWrapper.error { | |
throw error | |
} | |
} | |
private final class ThrownErrorWrapper: @unchecked Sendable { | |
private let queue = DispatchQueue(label: "LinuxSupport.ThrownErrorWrapper") | |
private var _error: Error? | |
var error: Error? { | |
get { | |
queue.sync { _error } | |
} | |
set { | |
queue.sync { _error = newValue } | |
} | |
} | |
} | |
// This time interval is set to a very large value due to their being no real native timeout functionality within corelibs-xctest. | |
// With the introduction of async/await support, the framework now relies on XCTestExpectations internally to coordinate the addition async portions of setup and tear down. | |
// This time interval is the timeout corelibs-xctest uses with XCTestExpectations. | |
private let asyncTestTimeout: TimeInterval = 60 * 60 * 24 * 30 | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment