Skip to content

Commit c902f0f

Browse files
authored
Merge pull request #452 from apple/jgrynspan/waitForExpectations-should-be-main-actor-isolated
Add @mainactor to waitForExpectations(timeout:handler:) #428
2 parents 6682df5 + 333c1ea commit c902f0f

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

Sources/XCTest/Public/Asynchronous/XCTestCase+Asynchronous.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public extension XCTestCase {
4141
/// these environments. To ensure compatibility of tests between
4242
/// swift-corelibs-xctest and Apple XCTest, it is not recommended to pass
4343
/// explicit values for `file` and `line`.
44-
// 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`.
44+
@preconcurrency @MainActor
4545
func waitForExpectations(timeout: TimeInterval, file: StaticString = #file, line: Int = #line, handler: XCWaitCompletionHandler? = nil) {
4646
precondition(Thread.isMainThread, "\(#function) must be called on the main thread")
4747
if currentWaiter != nil {

Sources/XCTest/Public/XCTestCase.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ open class XCTestCase: XCTest {
4848
return 1
4949
}
5050

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

5454
/// The set of expectations made upon this test case.

Tests/Functional/Asynchronous/Expectations/main.swift

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,28 @@ class ExpectationsTestCase: XCTestCase {
551551
RunLoop.main.run(until: Date() + 1)
552552
}
553553

554+
// CHECK: Test Case 'ExpectationsTestCase.test_waitForExpectationsAsync' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
555+
// CHECK: Test Case 'ExpectationsTestCase.test_waitForExpectationsAsync' passed \(\d+\.\d+ seconds\)
556+
func test_waitForExpectationsAsync() async {
557+
// Basic check that waitForExpectations() is functional when used with the
558+
// await keyword in an async function.
559+
let expectation = self.expectation(description: "foo")
560+
expectation.fulfill()
561+
await self.waitForExpectations(timeout: 0.0)
562+
}
563+
564+
// CHECK: Test Case 'ExpectationsTestCase.test_waitForExpectationsFromMainActor' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
565+
// CHECK: Test Case 'ExpectationsTestCase.test_waitForExpectationsFromMainActor' passed \(\d+\.\d+ seconds\)
566+
func test_waitForExpectationsFromMainActor() async {
567+
await MainActor.run {
568+
// Basic check that waitForExpectations() is functional and does not need
569+
// the await keyword when used from a main-actor-isolated test function.
570+
let expectation = self.expectation(description: "foo")
571+
expectation.fulfill()
572+
self.waitForExpectations(timeout: 0.0)
573+
}
574+
}
575+
554576
static var allTests = {
555577
return [
556578
("test_waitingForAnUnfulfilledExpectation_fails", test_waitingForAnUnfulfilledExpectation_fails),
@@ -603,15 +625,19 @@ class ExpectationsTestCase: XCTestCase {
603625
("test_expectationCreationOnSecondaryThread", test_expectationCreationOnSecondaryThread),
604626
("test_expectationCreationWhileWaiting", test_expectationCreationWhileWaiting),
605627
("test_runLoopInsideDispatch", test_runLoopInsideDispatch),
628+
629+
// waitForExpectations() + @MainActor
630+
("test_waitForExpectationsAsync", asyncTest(test_waitForExpectationsAsync)),
631+
("test_waitForExpectationsFromMainActor", asyncTest(test_waitForExpectationsFromMainActor)),
606632
]
607633
}()
608634
}
609635
// CHECK: Test Suite 'ExpectationsTestCase' failed at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
610-
// CHECK: \t Executed 35 tests, with 16 failures \(2 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
636+
// CHECK: \t Executed 37 tests, with 16 failures \(2 unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds
611637

612638
XCTMain([testCase(ExpectationsTestCase.allTests)])
613639

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

0 commit comments

Comments
 (0)