Skip to content

Commit

Permalink
Merge pull request #452 from apple/jgrynspan/waitForExpectations-shou…
Browse files Browse the repository at this point in the history
…ld-be-main-actor-isolated

Add @mainactor to waitForExpectations(timeout:handler:) #428
  • Loading branch information
grynspan committed Jun 27, 2023
2 parents 6682df5 + 333c1ea commit c902f0f
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public extension XCTestCase {
/// these environments. To ensure compatibility of tests between
/// swift-corelibs-xctest and Apple XCTest, it is not recommended to pass
/// explicit values for `file` and `line`.
// FIXME: This should have `@MainActor` to match Xcode XCTest, but adding it causes errors in tests authored pre-Swift Concurrency which don't typically have `@MainActor`.
@preconcurrency @MainActor
func waitForExpectations(timeout: TimeInterval, file: StaticString = #file, line: Int = #line, handler: XCWaitCompletionHandler? = nil) {
precondition(Thread.isMainThread, "\(#function) must be called on the main thread")
if currentWaiter != nil {
Expand Down
2 changes: 1 addition & 1 deletion Sources/XCTest/Public/XCTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ open class XCTestCase: XCTest {
return 1
}

// FIXME: Once `waitForExpectations(timeout:...handler:)` gains `@MainActor`, this may be able to add it as well.
@MainActor
internal var currentWaiter: XCTWaiter?

/// The set of expectations made upon this test case.
Expand Down
32 changes: 29 additions & 3 deletions Tests/Functional/Asynchronous/Expectations/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,28 @@ class ExpectationsTestCase: XCTestCase {
RunLoop.main.run(until: Date() + 1)
}

// CHECK: Test Case 'ExpectationsTestCase.test_waitForExpectationsAsync' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
// CHECK: Test Case 'ExpectationsTestCase.test_waitForExpectationsAsync' passed \(\d+\.\d+ seconds\)
func test_waitForExpectationsAsync() async {
// Basic check that waitForExpectations() is functional when used with the
// await keyword in an async function.
let expectation = self.expectation(description: "foo")
expectation.fulfill()
await self.waitForExpectations(timeout: 0.0)
}

// CHECK: Test Case 'ExpectationsTestCase.test_waitForExpectationsFromMainActor' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
// CHECK: Test Case 'ExpectationsTestCase.test_waitForExpectationsFromMainActor' passed \(\d+\.\d+ seconds\)
func test_waitForExpectationsFromMainActor() async {
await MainActor.run {
// Basic check that waitForExpectations() is functional and does not need
// the await keyword when used from a main-actor-isolated test function.
let expectation = self.expectation(description: "foo")
expectation.fulfill()
self.waitForExpectations(timeout: 0.0)
}
}

static var allTests = {
return [
("test_waitingForAnUnfulfilledExpectation_fails", test_waitingForAnUnfulfilledExpectation_fails),
Expand Down Expand Up @@ -603,15 +625,19 @@ class ExpectationsTestCase: XCTestCase {
("test_expectationCreationOnSecondaryThread", test_expectationCreationOnSecondaryThread),
("test_expectationCreationWhileWaiting", test_expectationCreationWhileWaiting),
("test_runLoopInsideDispatch", test_runLoopInsideDispatch),

// waitForExpectations() + @MainActor
("test_waitForExpectationsAsync", asyncTest(test_waitForExpectationsAsync)),
("test_waitForExpectationsFromMainActor", asyncTest(test_waitForExpectationsFromMainActor)),
]
}()
}
// CHECK: Test Suite 'ExpectationsTestCase' failed at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
// CHECK: \t Executed 35 tests, with 16 failures \(2 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
// CHECK: \t Executed 37 tests, with 16 failures \(2 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds

XCTMain([testCase(ExpectationsTestCase.allTests)])

// CHECK: Test Suite '.*\.xctest' failed at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
// CHECK: \t Executed 35 tests, with 16 failures \(2 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
// CHECK: \t Executed 37 tests, with 16 failures \(2 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
// CHECK: Test Suite 'All tests' failed at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
// CHECK: \t Executed 35 tests, with 16 failures \(2 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
// CHECK: \t Executed 37 tests, with 16 failures \(2 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds

0 comments on commit c902f0f

Please sign in to comment.