Skip to content

Commit b4065c1

Browse files
committed
Updates tests for execution on non Apple hosts.
- Update StringChecker to handle Windows line endings. - Use .exe suffix for executables on Windows - Use where.exe on Windows for tool location detection. - Enable unconditionally skipped tests, marking with known issue where appropriate. - Fix unconditionally skipped tests, skipping was added many years ago and never removed. - Add matrix style testing for the build system (native/swiftbuild) on "swift init/build/test" tests.
1 parent 23f32be commit b4065c1

File tree

5 files changed

+89
-56
lines changed

5 files changed

+89
-56
lines changed

Diff for: IntegrationTests/Sources/IntegrationTestSupport/Helpers.swift

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public let toolchainPath: AbsolutePath = {
3737
let swiftcPath = try! AbsolutePath(
3838
validating: sh("xcrun", "--find", "swift").stdout.spm_chomp()
3939
)
40+
#elseif os(Windows)
41+
let swiftcPath = try! AbsolutePath(validating: sh("where.exe", "swift.exe").stdout.spm_chomp())
4042
#else
4143
let swiftcPath = try! AbsolutePath(validating: sh("which", "swift").stdout.spm_chomp())
4244
#endif

Diff for: IntegrationTests/Sources/IntegrationTestSupport/Process.swift

+12
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,16 @@ extension ProcessInfo {
2828
#else
2929
public static let hostOperatingSystem = OperatingSystem.unknown
3030
#endif
31+
32+
#if os(Windows)
33+
public static let EOL = "\r\n"
34+
#else
35+
public static let EOL = "\n"
36+
#endif
37+
38+
#if os(Windows)
39+
public static let exeSuffix = ".exe"
40+
#else
41+
public static let exeSuffix = ""
42+
#endif
3143
}

Diff for: IntegrationTests/Sources/IntegrationTestSupport/StringChecker.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class StringChecker {
1818

1919
public init(string: String) {
2020
self.string = string
21-
self.lines = string.split(separator: "\n")
21+
self.lines = string.split(separator: ProcessInfo.EOL)
2222
self.currentLineIndex = 0
2323
}
2424

Diff for: IntegrationTests/Tests/IntegrationTests/BasicTests.swift

+37-31
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11+
import Foundation
1112
import IntegrationTestSupport
1213
import Testing
1314
import TSCBasic
@@ -23,13 +24,15 @@ private struct BasicTests {
2324
.skipSwiftCISelfHosted(
2425
"These packages don't use the latest runtime library, which doesn't work with self-hosted builds."
2526
),
26-
.requireUnrestrictedNetworkAccess("Test requires access to https://github.com")
27+
.requireUnrestrictedNetworkAccess("Test requires access to https://github.com"),
28+
.skipHostOS(.windows, "Issue #8409 - random.swift:34:8: error: unsupported platform")
2729
)
2830
func testExamplePackageDealer() throws {
2931
try withTemporaryDirectory { tempDir in
3032
let packagePath = tempDir.appending(component: "dealer")
31-
try sh("git", "clone", "https://github.com/apple/example-package-dealer", packagePath)
33+
try sh("git\(ProcessInfo.exeSuffix)", "clone", "https://github.com/apple/example-package-dealer", packagePath)
3234
let build1Output = try sh(swiftBuild, "--package-path", packagePath).stdout
35+
3336
// Check the build log.
3437
#expect(build1Output.contains("Build complete"))
3538

@@ -41,7 +44,7 @@ private struct BasicTests {
4144

4245
// Verify that the 'git status' is clean after a build.
4346
try localFileSystem.changeCurrentWorkingDirectory(to: packagePath)
44-
let gitOutput = try sh("git", "status").stdout
47+
let gitOutput = try sh("git\(ProcessInfo.exeSuffix)", "status").stdout
4548
#expect(gitOutput.contains("nothing to commit, working tree clean"))
4649

4750
// Verify that another 'swift build' does nothing.
@@ -84,7 +87,7 @@ private struct BasicTests {
8487
// Verify that the tool exists and works.
8588
let toolOutput = try sh(packagePath.appending(components: ".build", "debug", "tool"))
8689
.stdout
87-
#expect(toolOutput == "HI\n")
90+
#expect(toolOutput == "HI\(ProcessInfo.EOL)")
8891
}
8992
}
9093

@@ -104,7 +107,7 @@ private struct BasicTests {
104107

105108
// Check the file runs.
106109
let helloOutput = try sh(helloBinaryPath).stdout
107-
#expect(helloOutput == "hello\n")
110+
#expect(helloOutput == "hello\(ProcessInfo.EOL)")
108111
}
109112
}
110113

@@ -134,24 +137,26 @@ private struct BasicTests {
134137
}
135138
}
136139

137-
@Test(.skip("FIXME: swift-test invocations are timing out in Xcode and self-hosted CI"))
140+
@Test
138141
func testSwiftPackageInitExecTests() throws {
139142
try withTemporaryDirectory { tempDir in
140143
// Create a new package with an executable target.
141144
let packagePath = tempDir.appending(component: "Project")
142145
try localFileSystem.createDirectory(packagePath)
143-
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "executable")
144-
let testOutput = try sh(swiftTest, "--package-path", packagePath).stdout
145-
146-
// Check the test log.
147-
let checker = StringChecker(string: testOutput)
148-
#expect(checker.check(.regex("Compiling .*ProjectTests.*")))
149-
#expect(checker.check("Test Suite 'All tests' passed"))
150-
#expect(checker.checkNext("Executed 1 test"))
151-
152-
// Check there were no compile errors or warnings.
153-
#expect(testOutput.contains("error") == false)
154-
#expect(testOutput.contains("warning") == false)
146+
withKnownIssue("error: no tests found; create a target in the 'Tests' directory") {
147+
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "executable")
148+
let testOutput = try sh(swiftTest, "--package-path", packagePath).stdout
149+
150+
// Check the test log.
151+
let checker = StringChecker(string: testOutput)
152+
#expect(checker.check(.regex("Compiling .*ProjectTests.*")))
153+
#expect(checker.check("Test Suite 'All tests' passed"))
154+
#expect(checker.checkNext("Executed 1 test"))
155+
156+
// Check there were no compile errors or warnings.
157+
#expect(testOutput.contains("error") == false)
158+
#expect(testOutput.contains("warning") == false)
159+
}
155160
}
156161
}
157162

@@ -174,7 +179,7 @@ private struct BasicTests {
174179
}
175180
}
176181

177-
@Test(.skip("FIXME: swift-test invocations are timing out in Xcode and self-hosted CI"))
182+
@Test
178183
func testSwiftPackageLibsTests() throws {
179184
try withTemporaryDirectory { tempDir in
180185
// Create a new package with an executable target.
@@ -185,9 +190,9 @@ private struct BasicTests {
185190

186191
// Check the test log.
187192
let checker = StringChecker(string: testOutput)
188-
#expect(checker.check(.regex("Compiling .*ProjectTests.*")))
189-
#expect(checker.check("Test Suite 'All tests' passed"))
190-
#expect(checker.checkNext("Executed 1 test"))
193+
#expect(checker.check(.contains("Test Suite 'All tests' started")))
194+
#expect(checker.check(.contains("Test example() passed after")))
195+
#expect(checker.checkNext(.contains("Test run with 1 test passed after")))
191196

192197
// Check there were no compile errors or warnings.
193198
#expect(testOutput.contains("error") == false)
@@ -227,17 +232,19 @@ private struct BasicTests {
227232

228233
// Check the build.
229234
let buildOutput = try sh(swiftBuild, "--package-path", packagePath, "-v").stdout
230-
#expect(try
231-
#/swiftc.* -module-name special_tool .* '@.*/more spaces/special tool/.build/[^/]+/debug/special_tool.build/sources'/#
232-
.firstMatch(in: buildOutput) != nil
233-
)
235+
let expression = ProcessInfo
236+
.hostOperatingSystem != .windows ?
237+
#/swiftc.* -module-name special_tool .* '@.*/more spaces/special tool/.build/[^/]+/debug/special_tool.build/sources'/# :
238+
#/swiftc.* -module-name special_tool .* "@.*\\more spaces\\special tool\\.build\\[^\\]+\\debug\\special_tool.build\\sources"/#
239+
#expect(try expression.firstMatch(in: buildOutput) != nil)
234240
#expect(buildOutput.contains("Build complete"))
235241

236242
// Verify that the tool exists and works.
237243
let toolOutput = try sh(
238244
packagePath.appending(components: ".build", "debug", "special tool")
239245
).stdout
240-
#expect(toolOutput == "HI\n")
246+
247+
#expect(toolOutput == "HI\(ProcessInfo.EOL)")
241248
}
242249
}
243250

@@ -274,11 +281,10 @@ private struct BasicTests {
274281
#expect(checker.check(.regex("Linking .*secho")))
275282
#expect(checker.check(.contains("Build of product 'secho' complete")))
276283

277-
#expect(runOutput == "1 \"two\"\n")
284+
#expect(runOutput == "1 \"two\"\(ProcessInfo.EOL)")
278285
}
279286
}
280287

281-
@Test(.skip("FIXME: swift-test invocations are timing out in Xcode and self-hosted CI"))
282288
func testSwiftTest() throws {
283289
try withTemporaryDirectory { tempDir in
284290
let packagePath = tempDir.appending(component: "swiftTest")
@@ -315,7 +321,7 @@ private struct BasicTests {
315321
}
316322
}
317323

318-
@Test(.skip("FIXME: swift-test invocations are timing out in Xcode and self-hosted CI"))
324+
@Test
319325
func testSwiftTestWithResources() throws {
320326
try withTemporaryDirectory { tempDir in
321327
let packagePath = tempDir.appending(component: "swiftTestResources")
@@ -396,7 +402,7 @@ private struct BasicTests {
396402

397403
let testOutput = try sh(
398404
swiftTest, "--package-path", packagePath, "--filter", "MyTests.*"
399-
).stderr
405+
).stdout
400406

401407
// Check the test log.
402408
let checker = StringChecker(string: testOutput)

Diff for: IntegrationTests/Tests/IntegrationTests/SwiftPMTests.swift

+37-24
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ import Testing
1414
import TSCBasic
1515
import TSCTestSupport
1616

17+
// TODO: This should be replaced with BuildSystem.BuildSystemProvider if 'IntegrationTests' are moved up under the swift-package-manager tests.
18+
public enum BuildSystemProvider: String, Codable, CaseIterable {
19+
case native
20+
case swiftbuild
21+
}
22+
1723
@Suite
1824
private struct SwiftPMTests {
1925
@Test(.requireHostOS(.macOS))
@@ -68,45 +74,52 @@ private struct SwiftPMTests {
6874
}
6975
}
7076

71-
@Test(.requireThreadSafeWorkingDirectory)
72-
func packageInitExecutable() throws {
77+
@Test(.requireThreadSafeWorkingDirectory, arguments: BuildSystemProvider.allCases)
78+
func packageInitExecutable(_ buildSystemProvider: BuildSystemProvider) throws {
7379
// Executable
7480
do {
7581
try withTemporaryDirectory { tmpDir in
7682
let packagePath = tmpDir.appending(component: "foo")
7783
try localFileSystem.createDirectory(packagePath)
7884
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "executable")
79-
try sh(swiftBuild, "--package-path", packagePath, "--build-system", "swiftbuild")
80-
// SWBINTTODO: Path issues related to swift test of the output from a swiftbuild buildsystem
81-
// let (stdout, stderr) = try sh(
82-
// swiftRun, "--package-path", packagePath, "--build-system", "swiftbuild"
83-
// )
84-
// #expect(!stderr.contains("error:"))
85-
// #expect(stdout.contains("Hello, world!"))
85+
try sh(swiftBuild, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue)
86+
87+
try withKnownIssue("Issue #8416 - error while loading shared libraries: libswiftCore.so: cannot open shared object file: No such file or directory") {
88+
// The 'native' build system uses 'swiftc' as the linker driver, which adds an RUNPATH to the swift runtime libraries in the SDK.
89+
// 'swiftbuild' directly calls clang, which does not add the extra RUNPATH, so runtime libraries cannot be found.
90+
let (stdout, stderr) = try sh(
91+
swiftRun, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue
92+
)
93+
#expect(!stderr.contains("error:"))
94+
#expect(stdout.contains("Hello, world!"))
95+
} when: {
96+
buildSystemProvider == .swiftbuild && ProcessInfo.hostOperatingSystem == .linux
97+
}
8698
}
8799
}
88100
}
89101

90-
@Test(
91-
.skipHostOS(
92-
.windows,
93-
"Windows fails to link this library package due to a 'lld-link: error: subsystem must be defined' error. See https://github.com/swiftlang/swift-build/issues/310"
94-
),
95-
.requireThreadSafeWorkingDirectory
96-
)
97-
func packageInitLibrary() throws {
102+
@Test(.requireThreadSafeWorkingDirectory, arguments: BuildSystemProvider.allCases)
103+
func packageInitLibrary(_ buildSystemProvider: BuildSystemProvider) throws {
98104
do {
99105
try withTemporaryDirectory { tmpDir in
100106
let packagePath = tmpDir.appending(component: "foo")
101107
try localFileSystem.createDirectory(packagePath)
102108
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "library")
103-
try sh(swiftBuild, "--package-path", packagePath, "--build-system", "swiftbuild")
104-
// SWBINTTODO: Path issues related to swift test of the output from a swiftbuild buildsystem
105-
// let (stdout, stderr) = try sh(
106-
// swiftTest, "--package-path", packagePath, "--build-system", "swiftbuild"
107-
// )
108-
// #expect(!stderr.contains("error:"))
109-
// #expect(stdout.contains("Test Suite 'All tests' passed"))
109+
try withKnownIssue("""
110+
Linux: /lib/x86_64-linux-gnu/Scrt1.o:function _start: error: undefined reference to 'main'
111+
Windows: lld-link: error: subsystem must be defined
112+
MacOS: Could not find or use auto-linked library 'Testing': library 'Testing' not found
113+
""") {
114+
try sh(swiftBuild, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue, "--vv")
115+
let (stdout, stderr) = try sh(
116+
swiftTest, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue, "--vv"
117+
)
118+
#expect(!stderr.contains("error:"))
119+
#expect(stdout.contains("Test Suite 'All tests' passed"))
120+
} when: {
121+
buildSystemProvider == .swiftbuild
122+
}
110123
}
111124
}
112125
}

0 commit comments

Comments
 (0)