Skip to content

Commit d192ad0

Browse files
authored
[6.0] Generated code for XCTest on non-Darwin needs to be actor-isolated. (#7569)
Explanation: Ensure that the synthesized entry point for swift-corelibs-xctest is concurrency-safe by marking it `@MainActor`. Scope: All XCTest-based tests built/run on non-Darwin platforms. Original PR: #7566 Risk: Low. The change is necessary to suppress a concurrency diagnostic. The synthesized `main()` function is implicitly main-actor-isolated. Testing: Added unit test to check for the diagnostic, verified it did not occur anymore with the change in place. Reviewer: @bnbarham, @MaxDesiatov, @stmontgomery, @briancroom
1 parent 3956d24 commit d192ad0

File tree

2 files changed

+17
-7
lines changed

2 files changed

+17
-7
lines changed

Sources/Build/BuildOperationBuildSystemDelegateHandler.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ final class TestDiscoveryCommand: CustomLLBuildCommand, TestBuildCommand {
8787
8888
fileprivate extension \#(className) {
8989
@available(*, deprecated, message: "Not actually deprecated. Marked as deprecated to allow inclusion of deprecated tests (which test deprecated functionality) without warnings")
90+
@MainActor
9091
static let __allTests__\#(className) = [
9192
\#(testMethods.map { $0.allTestsEntry }.joined(separator: ",\n "))
9293
]
@@ -98,6 +99,7 @@ final class TestDiscoveryCommand: CustomLLBuildCommand, TestBuildCommand {
9899
content +=
99100
#"""
100101
@available(*, deprecated, message: "Not actually deprecated. Marked as deprecated to allow inclusion of deprecated tests (which test deprecated functionality) without warnings")
102+
@MainActor
101103
func __\#(module)__allTests() -> [XCTestCaseEntry] {
102104
return [
103105
\#(testsByClassNames.map { "testCase(\($0.key).__allTests__\($0.key))" }
@@ -166,6 +168,7 @@ final class TestDiscoveryCommand: CustomLLBuildCommand, TestBuildCommand {
166168
import XCTest
167169
168170
@available(*, deprecated, message: "Not actually deprecated. Marked as deprecated to allow inclusion of deprecated tests (which test deprecated functionality) without warnings")
171+
@MainActor
169172
public func __allDiscoveredTests() -> [XCTestCaseEntry] {
170173
\#(testsKeyword) tests = [XCTestCaseEntry]()
171174
@@ -264,18 +267,15 @@ final class TestEntryPointCommand: CustomLLBuildCommand, TestBuildCommand {
264267
@main
265268
@available(*, deprecated, message: "Not actually deprecated. Marked as deprecated to allow inclusion of deprecated tests (which test deprecated functionality) without warnings")
266269
struct Runner {
267-
#if os(WASI)
268-
/// On WASI, we can't block the main thread, so XCTestMain is defined as async.
269270
static func main() async {
270271
\#(testObservabilitySetup)
272+
#if os(WASI)
273+
/// On WASI, we can't block the main thread, so XCTestMain is defined as async.
271274
await XCTMain(__allDiscoveredTests()) as Never
272-
}
273-
#else
274-
static func main() {
275-
\#(testObservabilitySetup)
275+
#else
276276
XCTMain(__allDiscoveredTests()) as Never
277+
#endif
277278
}
278-
#endif
279279
}
280280
"""#
281281
)

Tests/CommandsTests/TestCommandTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,4 +293,14 @@ final class TestCommandTests: CommandsTestCase {
293293
}
294294
}
295295
}
296+
297+
#if !canImport(Darwin)
298+
func testGeneratedMainIsConcurrencySafe_XCTest() throws {
299+
let strictConcurrencyFlags = ["-Xswiftc", "-strict-concurrency=complete"]
300+
try fixture(name: "Miscellaneous/TestDiscovery/Simple") { fixturePath in
301+
let (_, stderr) = try SwiftPM.Test.execute(strictConcurrencyFlags, packagePath: fixturePath)
302+
XCTAssertNoMatch(stderr, .contains("is not concurrency-safe"))
303+
}
304+
}
305+
#endif
296306
}

0 commit comments

Comments
 (0)