Skip to content

Commit 8fc6467

Browse files
authored
[6.1] Apply toolset's testRunner property in swift-test (#8258)
Cherry-pick of #8254 merged as b14e431. **Explanation**: Per [SE-0378 toolsets can specify an optional `testRunner` property](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md#toolsetjson-files), which so far had no effect. We should respect this property in `swift test` invocations when any toolsets or Swift SDKs are selected. This allows testing cross-compiled products in an environment other than the host, e.g. a container runtime when cross-compiled to Linux, QEMU or a firmware flasher and serial port setup script with Swift Embedded for microcontrollers, or in a Wasm runtime for a Wasm binary. **Scope**: Only impacts `swift-test` when a toolset or a Swift SDK are selected. **Risk**: Low, due to limited scope and automated testing. **Testing**: Added a new test cause to the existing XCTest suite. **Issue**: rdar://143815066 **Reviewer**: @dschaefer2
1 parent b7ce674 commit 8fc6467

File tree

8 files changed

+54
-21
lines changed

8 files changed

+54
-21
lines changed

Fixtures/Miscellaneous/EchoExecutable/Package.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ let package = Package(
77
.executable(name: "secho", targets: ["secho"])
88
],
99
targets: [
10-
.target(name: "secho", dependencies: [])
11-
])
10+
.target(name: "secho", dependencies: []),
11+
.testTarget(name: "TestSuite")
12+
])
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import XCTest
2+
3+
final class TestCase: XCTestCase {
4+
func testFoo() {
5+
XCTAssertTrue(true)
6+
}
7+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
#!/bin/sh
22

3+
echo sentinel
34
echo "$@"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"debugger": { "path": "echo.sh" },
3+
"testRunner": { "path": "echo.sh" },
34
"schemaVersion" : "1.0",
45
"rootPath" : "."
56
}

Sources/Commands/SwiftTestCommand.swift

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -948,23 +948,31 @@ final class TestRunner {
948948
/// Constructs arguments to execute XCTest.
949949
private func args(forTestAt testPath: AbsolutePath) throws -> [String] {
950950
var args: [String] = []
951+
952+
if let runner = self.toolchain.swiftSDK.toolset.knownTools[.testRunner], let runnerPath = runner.path {
953+
args.append(runnerPath.pathString)
954+
args.append(contentsOf: runner.extraCLIOptions)
955+
args.append(testPath.relative(to: localFileSystem.currentWorkingDirectory!).pathString)
956+
args.append(contentsOf: self.additionalArguments)
957+
} else {
951958
#if os(macOS)
952-
switch library {
953-
case .xctest:
954-
guard let xctestPath = self.toolchain.xctestPath else {
955-
throw TestError.xcodeNotInstalled
959+
switch library {
960+
case .xctest:
961+
guard let xctestPath = self.toolchain.xctestPath else {
962+
throw TestError.xcodeNotInstalled
963+
}
964+
args += [xctestPath.pathString]
965+
case .swiftTesting:
966+
let helper = try self.toolchain.getSwiftTestingHelper()
967+
args += [helper.pathString, "--test-bundle-path", testPath.pathString]
956968
}
957-
args += [xctestPath.pathString]
958-
case .swiftTesting:
959-
let helper = try self.toolchain.getSwiftTestingHelper()
960-
args += [helper.pathString, "--test-bundle-path", testPath.pathString]
969+
args += self.additionalArguments
970+
args += [testPath.pathString]
971+
#else
972+
args += [testPath.pathString]
973+
args += self.additionalArguments
974+
#endif
961975
}
962-
args += additionalArguments
963-
args += [testPath.pathString]
964-
#else
965-
args += [testPath.pathString]
966-
args += additionalArguments
967-
#endif
968976

969977
if library == .swiftTesting {
970978
// HACK: tell the test bundle/executable that we want to run Swift Testing, not XCTest.

Sources/SPMBuildCore/BuildParameters/BuildParameters.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,6 @@ public struct BuildParameters: Encodable {
302302
case .library(.automatic), .plugin:
303303
fatalError()
304304
case .test:
305-
guard !self.triple.isWasm else {
306-
return try RelativePath(validating: "\(product.name).wasm")
307-
}
308305
let base = "\(product.name).xctest"
309306
if self.triple.isDarwin() {
310307
return try RelativePath(validating: "\(base)/Contents/MacOS/\(product.name)")

Tests/BuildTests/CrossCompilationBuildPlanTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ final class CrossCompilationBuildPlanTests: XCTestCase {
210210
[
211211
result.plan.destinationBuildParameters.toolchain.swiftCompilerPath.pathString,
212212
"-L", buildPath.pathString,
213-
"-o", buildPath.appending(components: "PkgPackageTests.wasm").pathString,
213+
"-o", buildPath.appending(components: "PkgPackageTests.xctest").pathString,
214214
"-module-name", "PkgPackageTests",
215215
"-emit-executable",
216216
"@\(buildPath.appending(components: "PkgPackageTests.product", "Objects.LinkFileList"))",
@@ -220,7 +220,7 @@ final class CrossCompilationBuildPlanTests: XCTestCase {
220220
)
221221

222222
let testPathExtension = try testBuildDescription.binaryPath.extension
223-
XCTAssertEqual(testPathExtension, "wasm")
223+
XCTAssertEqual(testPathExtension, "xctest")
224224
}
225225

226226
func testMacros() async throws {

Tests/CommandsTests/TestCommandTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,24 @@ final class TestCommandTests: CommandsTestCase {
3636
XCTAssert(stdout.contains("Swift Package Manager"), "got stdout:\n" + stdout)
3737
}
3838

39+
// `echo.sh` script from the toolset won't work on Windows
40+
#if !os(Windows)
41+
func testToolsetRunner() async throws {
42+
try await fixture(name: "Miscellaneous/EchoExecutable") { fixturePath in
43+
let (stdout, stderr) = try await SwiftPM.Test.execute(
44+
["--toolset", "\(fixturePath)/toolset.json"], packagePath: fixturePath)
45+
46+
// We only expect tool's output on the stdout stream.
47+
XCTAssertMatch(stdout, .contains("sentinel"))
48+
XCTAssertMatch(stdout, .contains("\(fixturePath)"))
49+
50+
// swift-build-tool output should go to stderr.
51+
XCTAssertMatch(stderr, .regex("Compiling"))
52+
XCTAssertMatch(stderr, .contains("Linking"))
53+
}
54+
}
55+
#endif
56+
3957
func testNumWorkersParallelRequirement() async throws {
4058
#if !os(macOS)
4159
// Running swift-test fixtures on linux is not yet possible.

0 commit comments

Comments
 (0)