Skip to content

Commit e0c3868

Browse files
authored
Merge pull request #478 from kateinoigakukun/yt/xctest-wasm-upstream
Add support for WASI platform
2 parents be9cfd4 + da82bb9 commit e0c3868

14 files changed

+353
-54
lines changed

CMakeLists.txt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ project(XCTest LANGUAGES Swift)
88
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
99
option(USE_FOUNDATION_FRAMEWORK "Use Foundation.framework on Darwin" NO)
1010

11-
if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin)
11+
set(DISABLE_XCTWAITER_default NO)
12+
13+
if(CMAKE_SYSTEM_PROCESSOR STREQUAL wasm32)
14+
set(DISABLE_XCTWAITER_default ON)
15+
endif()
16+
17+
option(DISABLE_XCTWAITER "Disable XCTWaiter" "${DISABLE_XCTWAITER_default}")
18+
19+
if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin AND NOT DISABLE_XCTWAITER)
1220
find_package(dispatch CONFIG REQUIRED)
1321
find_package(Foundation CONFIG REQUIRED)
1422
endif()
@@ -49,6 +57,12 @@ add_library(XCTest
4957
Sources/XCTest/Public/Asynchronous/XCTWaiter.swift
5058
Sources/XCTest/Public/Asynchronous/XCTestCase+Asynchronous.swift
5159
Sources/XCTest/Public/Asynchronous/XCTestExpectation.swift)
60+
61+
if(DISABLE_XCTWAITER)
62+
target_compile_definitions(XCTest PRIVATE
63+
DISABLE_XCTWAITER)
64+
endif()
65+
5266
if(USE_FOUNDATION_FRAMEWORK)
5367
target_compile_definitions(XCTest PRIVATE
5468
USE_FOUNDATION_FRAMEWORK)

Sources/XCTest/Private/WaiterManager.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//
1010
// WaiterManager.swift
1111
//
12+
#if !DISABLE_XCTWAITER
1213

1314
internal protocol ManageableWaiter: AnyObject, Equatable {
1415
var isFinished: Bool { get }
@@ -143,3 +144,5 @@ internal final class WaiterManager<WaiterType: ManageableWaiter> : NSObject {
143144
}
144145

145146
}
147+
148+
#endif

Sources/XCTest/Private/XCTestCase.TearDownBlocksState.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,42 @@ extension XCTestCase {
1212
/// Supports async and sync throwing methods.
1313
final class TeardownBlocksState {
1414

15+
#if DISABLE_XCTWAITER
16+
typealias TeardownBlock = @Sendable @MainActor () async throws -> Void
17+
#else
18+
typealias TeardownBlock = () throws -> Void
19+
#endif
20+
1521
private var wasFinalized = false
16-
private var blocks: [() throws -> Void] = []
22+
private var blocks: [TeardownBlock] = []
1723

1824
// We don't want to overload append(_:) below because of how Swift will implicitly promote sync closures to async closures,
1925
// which can unexpectedly change their semantics in difficult to track down ways.
2026
//
2127
// Because of this, we chose the unusual decision to forgo overloading (which is a super sweet language feature <3) to prevent this issue from surprising any contributors to corelibs-xctest
2228
@available(macOS 12.0, *)
2329
func appendAsync(_ block: @Sendable @escaping () async throws -> Void) {
30+
#if DISABLE_XCTWAITER
31+
XCTestCase.subsystemQueue.sync {
32+
precondition(wasFinalized == false, "API violation -- attempting to add a teardown block after teardown blocks have been dequeued")
33+
blocks.append(block)
34+
}
35+
#else
2436
self.append {
2537
try awaitUsingExpectation { try await block() }
2638
}
39+
#endif
2740
}
2841

2942
func append(_ block: @escaping () throws -> Void) {
30-
XCTWaiter.subsystemQueue.sync {
43+
XCTestCase.subsystemQueue.sync {
3144
precondition(wasFinalized == false, "API violation -- attempting to add a teardown block after teardown blocks have been dequeued")
3245
blocks.append(block)
3346
}
3447
}
3548

36-
func finalize() -> [() throws -> Void] {
37-
XCTWaiter.subsystemQueue.sync {
49+
func finalize() -> [TeardownBlock] {
50+
XCTestCase.subsystemQueue.sync {
3851
precondition(wasFinalized == false, "API violation -- attempting to run teardown blocks after they've already run")
3952
wasFinalized = true
4053
return blocks

Sources/XCTest/Public/Asynchronous/XCTNSNotificationExpectation.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
// XCTNSNotificationExpectation.swift
1111
//
1212

13+
#if !DISABLE_XCTWAITER
14+
1315
/// Expectation subclass for waiting on a condition defined by a Foundation Notification instance.
1416
open class XCTNSNotificationExpectation: XCTestExpectation {
1517

@@ -114,3 +116,5 @@ open class XCTNSNotificationExpectation: XCTestExpectation {
114116
/// - SeeAlso: `XCTNSNotificationExpectation.handler`
115117
@available(*, deprecated, renamed: "XCTNSNotificationExpectation.Handler")
116118
public typealias XCNotificationExpectationHandler = XCTNSNotificationExpectation.Handler
119+
120+
#endif

Sources/XCTest/Public/Asynchronous/XCTNSPredicateExpectation.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
// XCTNSPredicateExpectation.swift
1111
//
1212

13+
#if !DISABLE_XCTWAITER
14+
1315
/// Expectation subclass for waiting on a condition defined by an NSPredicate and an optional object.
1416
open class XCTNSPredicateExpectation: XCTestExpectation {
1517

@@ -133,3 +135,4 @@ open class XCTNSPredicateExpectation: XCTestExpectation {
133135
/// - SeeAlso: `XCTNSPredicateExpectation.handler`
134136
@available(*, deprecated, renamed: "XCTNSPredicateExpectation.Handler")
135137
public typealias XCPredicateExpectationHandler = XCTNSPredicateExpectation.Handler
138+
#endif

Sources/XCTest/Public/Asynchronous/XCTWaiter+Validation.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//
1010
// XCTWaiter+Validation.swift
1111
//
12+
#if !DISABLE_XCTWAITER
1213

1314
protocol XCTWaiterValidatableExpectation: Equatable {
1415
var isFulfilled: Bool { get }
@@ -87,3 +88,5 @@ extension XCTWaiter {
8788
return .incomplete
8889
}
8990
}
91+
92+
#endif

Sources/XCTest/Public/Asynchronous/XCTWaiter.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//
1010
// XCTWaiter.swift
1111
//
12+
#if !DISABLE_XCTWAITER
1213

1314
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
1415
import CoreFoundation
@@ -479,3 +480,5 @@ extension XCTWaiter: ManageableWaiter {
479480
}
480481
}
481482
}
483+
484+
#endif

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
// Methods on XCTestCase for testing asynchronous operations
1212
//
1313

14+
#if !DISABLE_XCTWAITER
15+
1416
public extension XCTestCase {
1517

1618
/// Creates a point of synchronization in the flow of a test. Only one
@@ -265,3 +267,4 @@ internal extension XCTestCase {
265267
expected: false)
266268
}
267269
}
270+
#endif

Sources/XCTest/Public/Asynchronous/XCTestExpectation.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//
1010
// XCTestExpectation.swift
1111
//
12+
#if !DISABLE_XCTWAITER
1213

1314
/// Expectations represent specific conditions in asynchronous testing.
1415
open class XCTestExpectation: @unchecked Sendable {
@@ -320,3 +321,5 @@ extension XCTestExpectation: CustomStringConvertible {
320321
return expectationDescription
321322
}
322323
}
324+
325+
#endif

Sources/XCTest/Public/XCAbstractTest.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,43 @@ open class XCTest {
3636
/// testRunClass. If the test has not yet been run, this will be nil.
3737
open private(set) var testRun: XCTestRun? = nil
3838

39+
#if DISABLE_XCTWAITER
40+
internal var performTask: Task<Void, Never>?
41+
42+
internal func _performAsync(_ run: XCTestRun) async {
43+
fatalError("Must be overridden by subclasses.")
44+
}
45+
internal func _runAsync() async {
46+
guard let testRunType = testRunClass as? XCTestRun.Type else {
47+
fatalError("XCTest.testRunClass must be a kind of XCTestRun.")
48+
}
49+
testRun = testRunType.init(test: self)
50+
await _performAsync(testRun!)
51+
}
52+
#endif
53+
3954
/// The method through which tests are executed. Must be overridden by
4055
/// subclasses.
56+
#if DISABLE_XCTWAITER
57+
@available(*, unavailable)
58+
#endif
4159
open func perform(_ run: XCTestRun) {
4260
fatalError("Must be overridden by subclasses.")
4361
}
4462

4563
/// Creates an instance of the `testRunClass` and passes it as a parameter
4664
/// to `perform()`.
65+
#if DISABLE_XCTWAITER
66+
@available(*, unavailable)
67+
#endif
4768
open func run() {
69+
#if !DISABLE_XCTWAITER
4870
guard let testRunType = testRunClass as? XCTestRun.Type else {
4971
fatalError("XCTest.testRunClass must be a kind of XCTestRun.")
5072
}
5173
testRun = testRunType.init(test: self)
5274
perform(testRun!)
75+
#endif
5376
}
5477

5578
/// Async setup method called before the invocation of `setUpWithError` for each test method in the class.

0 commit comments

Comments
 (0)