Skip to content

Commit 6bf9ba6

Browse files
authored
Updates tests for execution on non Apple hosts. (#8407)
- 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 3f949d8 commit 6bf9ba6

File tree

5 files changed

+100
-56
lines changed

5 files changed

+100
-56
lines changed

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

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
}

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

IntegrationTests/Tests/IntegrationTests/BasicTests.swift

+39-33
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
@@ -25,13 +26,15 @@ private struct BasicTests {
2526
.skipSwiftCISelfHosted(
2627
"These packages don't use the latest runtime library, which doesn't work with self-hosted builds."
2728
),
28-
.requireUnrestrictedNetworkAccess("Test requires access to https://github.com")
29+
.requireUnrestrictedNetworkAccess("Test requires access to https://github.com"),
30+
.skipHostOS(.windows, "Issue #8409 - random.swift:34:8: error: unsupported platform")
2931
)
3032
func testExamplePackageDealer() throws {
3133
try withTemporaryDirectory { tempDir in
3234
let packagePath = tempDir.appending(component: "dealer")
33-
try sh("git", "clone", "https://github.com/apple/example-package-dealer", packagePath)
35+
try sh("git\(ProcessInfo.exeSuffix)", "clone", "https://github.com/apple/example-package-dealer", packagePath)
3436
let build1Output = try sh(swiftBuild, "--package-path", packagePath).stdout
37+
3538
// Check the build log.
3639
#expect(build1Output.contains("Build complete"))
3740

@@ -43,7 +46,7 @@ private struct BasicTests {
4346

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

4952
// Verify that another 'swift build' does nothing.
@@ -84,9 +87,9 @@ private struct BasicTests {
8487
#expect(try #/swiftc.* -module-name tool/#.firstMatch(in: buildOutput) != nil)
8588

8689
// Verify that the tool exists and works.
87-
let toolOutput = try sh(packagePath.appending(components: ".build", "debug", "tool")).stdout
88-
#expect(toolOutput.contains("HI"))
89-
#expect(toolOutput.contains("\n"))
90+
let toolOutput = try sh(packagePath.appending(components: ".build", "debug", "tool"))
91+
.stdout
92+
#expect(toolOutput == "HI\(ProcessInfo.EOL)")
9093
}
9194
}
9295

@@ -108,7 +111,7 @@ private struct BasicTests {
108111

109112
// Check the file runs.
110113
let helloOutput = try sh(helloBinaryPath).stdout
111-
#expect(helloOutput == "hello\n")
114+
#expect(helloOutput == "hello\(ProcessInfo.EOL)")
112115
}
113116
}
114117

@@ -140,24 +143,26 @@ private struct BasicTests {
140143
}
141144
}
142145

143-
@Test(.skip("FIXME: swift-test invocations are timing out in Xcode and self-hosted CI"))
146+
@Test
144147
func testSwiftPackageInitExecTests() throws {
145148
try withTemporaryDirectory { tempDir in
146149
// Create a new package with an executable target.
147150
let packagePath = tempDir.appending(component: "Project")
148151
try localFileSystem.createDirectory(packagePath)
149-
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "executable")
150-
let testOutput = try sh(swiftTest, "--package-path", packagePath).stdout
151-
152-
// Check the test log.
153-
let checker = StringChecker(string: testOutput)
154-
#expect(checker.check(.regex("Compiling .*ProjectTests.*")))
155-
#expect(checker.check("Test Suite 'All tests' passed"))
156-
#expect(checker.checkNext("Executed 1 test"))
157-
158-
// Check there were no compile errors or warnings.
159-
#expect(testOutput.contains("error") == false)
160-
#expect(testOutput.contains("warning") == false)
152+
withKnownIssue("error: no tests found; create a target in the 'Tests' directory") {
153+
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "executable")
154+
let testOutput = try sh(swiftTest, "--package-path", packagePath).stdout
155+
156+
// Check the test log.
157+
let checker = StringChecker(string: testOutput)
158+
#expect(checker.check(.regex("Compiling .*ProjectTests.*")))
159+
#expect(checker.check("Test Suite 'All tests' passed"))
160+
#expect(checker.checkNext("Executed 1 test"))
161+
162+
// Check there were no compile errors or warnings.
163+
#expect(testOutput.contains("error") == false)
164+
#expect(testOutput.contains("warning") == false)
165+
}
161166
}
162167
}
163168

@@ -180,7 +185,7 @@ private struct BasicTests {
180185
}
181186
}
182187

183-
@Test(.skip("FIXME: swift-test invocations are timing out in Xcode and self-hosted CI"))
188+
@Test
184189
func testSwiftPackageLibsTests() throws {
185190
try withTemporaryDirectory { tempDir in
186191
// Create a new package with an executable target.
@@ -191,9 +196,9 @@ private struct BasicTests {
191196

192197
// Check the test log.
193198
let checker = StringChecker(string: testOutput)
194-
#expect(checker.check(.regex("Compiling .*ProjectTests.*")))
195-
#expect(checker.check("Test Suite 'All tests' passed"))
196-
#expect(checker.checkNext("Executed 1 test"))
199+
#expect(checker.check(.contains("Test Suite 'All tests' started")))
200+
#expect(checker.check(.contains("Test example() passed after")))
201+
#expect(checker.checkNext(.contains("Test run with 1 test passed after")))
197202

198203
// Check there were no compile errors or warnings.
199204
#expect(testOutput.contains("error") == false)
@@ -235,17 +240,19 @@ private struct BasicTests {
235240

236241
// Check the build.
237242
let buildOutput = try sh(swiftBuild, "--package-path", packagePath, "-v").stdout
238-
#expect(try
239-
#/swiftc.* -module-name special_tool .* '@.*/more spaces/special tool/.build/[^/]+/debug/special_tool.build/sources'/#
240-
.firstMatch(in: buildOutput) != nil
241-
)
243+
let expression = ProcessInfo
244+
.hostOperatingSystem != .windows ?
245+
#/swiftc.* -module-name special_tool .* '@.*/more spaces/special tool/.build/[^/]+/debug/special_tool.build/sources'/# :
246+
#/swiftc.* -module-name special_tool .* "@.*\\more spaces\\special tool\\.build\\[^\\]+\\debug\\special_tool.build\\sources"/#
247+
#expect(try expression.firstMatch(in: buildOutput) != nil)
242248
#expect(buildOutput.contains("Build complete"))
243249

244250
// Verify that the tool exists and works.
245251
let toolOutput = try sh(
246252
packagePath.appending(components: ".build", "debug", "special tool")
247253
).stdout
248-
#expect(toolOutput == "HI\n")
254+
255+
#expect(toolOutput == "HI\(ProcessInfo.EOL)")
249256
}
250257
}
251258

@@ -284,11 +291,10 @@ private struct BasicTests {
284291
#expect(checker.check(.regex("Linking .*secho")))
285292
#expect(checker.check(.contains("Build of product 'secho' complete")))
286293

287-
#expect(runOutput == "1 \"two\"\n")
294+
#expect(runOutput == "1 \"two\"\(ProcessInfo.EOL)")
288295
}
289296
}
290297

291-
@Test(.skip("FIXME: swift-test invocations are timing out in Xcode and self-hosted CI"))
292298
func testSwiftTest() throws {
293299
try withTemporaryDirectory { tempDir in
294300
let packagePath = tempDir.appending(component: "swiftTest")
@@ -325,7 +331,7 @@ private struct BasicTests {
325331
}
326332
}
327333

328-
@Test(.skip("FIXME: swift-test invocations are timing out in Xcode and self-hosted CI"))
334+
@Test
329335
func testSwiftTestWithResources() throws {
330336
try withTemporaryDirectory { tempDir in
331337
let packagePath = tempDir.appending(component: "swiftTestResources")
@@ -406,7 +412,7 @@ private struct BasicTests {
406412

407413
let testOutput = try sh(
408414
swiftTest, "--package-path", packagePath, "--filter", "MyTests.*"
409-
).stderr
415+
).stdout
410416

411417
// Check the test log.
412418
let checker = StringChecker(string: testOutput)

IntegrationTests/Tests/IntegrationTests/SwiftPMTests.swift

+46-22
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))
@@ -69,46 +75,64 @@ private struct SwiftPMTests {
6975
}
7076

7177
@Test(
72-
.requireThreadSafeWorkingDirectory
78+
.requireThreadSafeWorkingDirectory,
79+
.bug(
80+
"https://github.com/swiftlang/swift-package-manager/issues/8416",
81+
"swift run using --build-system swiftbuild fails to run executable"
82+
),
83+
arguments: BuildSystemProvider.allCases
7384
)
74-
func packageInitExecutable() throws {
85+
func packageInitExecutable(_ buildSystemProvider: BuildSystemProvider) throws {
7586
// Executable
7687
do {
7788
try withTemporaryDirectory { tmpDir in
7889
let packagePath = tmpDir.appending(component: "foo")
7990
try localFileSystem.createDirectory(packagePath)
8091
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "executable")
81-
try sh(swiftBuild, "--package-path", packagePath, "--build-system", "swiftbuild")
82-
// SWBINTTODO: Path issues related to swift test of the output from a swiftbuild buildsystem
83-
// let (stdout, stderr) = try sh(
84-
// swiftRun, "--package-path", packagePath, "--build-system", "swiftbuild"
85-
// )
86-
// #expect(!stderr.contains("error:"))
87-
// #expect(stdout.contains("Hello, world!"))
92+
try sh(swiftBuild, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue)
93+
94+
try withKnownIssue("Error while loading shared libraries: libswiftCore.so: cannot open shared object file: No such file or directory") {
95+
// The 'native' build system uses 'swiftc' as the linker driver, which adds an RUNPATH to the swift runtime libraries in the SDK.
96+
// 'swiftbuild' directly calls clang, which does not add the extra RUNPATH, so runtime libraries cannot be found.
97+
let (stdout, stderr) = try sh(
98+
swiftRun, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue
99+
)
100+
#expect(!stderr.contains("error:"))
101+
#expect(stdout.contains("Hello, world!"))
102+
} when: {
103+
buildSystemProvider == .swiftbuild && ProcessInfo.hostOperatingSystem == .linux
104+
}
88105
}
89106
}
90107
}
91108

92109
@Test(
93-
.skipHostOS(
94-
.windows,
95-
"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"
96-
),
97-
.requireThreadSafeWorkingDirectory
110+
.requireThreadSafeWorkingDirectory,
111+
.bug(id: 0, "SWBINTTODO: Linux: /lib/x86_64-linux-gnu/Scrt1.o:function _start: error:"),
112+
.bug("https://github.com/swiftlang/swift-package-manager/issues/8380", "lld-link: error: subsystem must be defined"),
113+
.bug(id:0, "SWBINTTODO: MacOS: Could not find or use auto-linked library 'Testing': library 'Testing' not found"),
114+
arguments: BuildSystemProvider.allCases
98115
)
99-
func packageInitLibrary() throws {
116+
func packageInitLibrary(_ buildSystemProvider: BuildSystemProvider) throws {
100117
do {
101118
try withTemporaryDirectory { tmpDir in
102119
let packagePath = tmpDir.appending(component: "foo")
103120
try localFileSystem.createDirectory(packagePath)
104121
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "library")
105-
try sh(swiftBuild, "--package-path", packagePath, "--build-system", "swiftbuild")
106-
// SWBINTTODO: Path issues related to swift test of the output from a swiftbuild buildsystem
107-
// let (stdout, stderr) = try sh(
108-
// swiftTest, "--package-path", packagePath, "--build-system", "swiftbuild"
109-
// )
110-
// #expect(!stderr.contains("error:"))
111-
// #expect(stdout.contains("Test Suite 'All tests' passed"))
122+
try withKnownIssue("""
123+
Linux: /lib/x86_64-linux-gnu/Scrt1.o:function _start: error: undefined reference to 'main'
124+
Windows: lld-link: error: subsystem must be defined
125+
MacOS: Could not find or use auto-linked library 'Testing': library 'Testing' not found
126+
""") {
127+
try sh(swiftBuild, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue, "--vv")
128+
let (stdout, stderr) = try sh(
129+
swiftTest, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue, "--vv"
130+
)
131+
#expect(!stderr.contains("error:"))
132+
#expect(stdout.contains("Test Suite 'All tests' passed"))
133+
} when: {
134+
buildSystemProvider == .swiftbuild
135+
}
112136
}
113137
}
114138
}

0 commit comments

Comments
 (0)