Skip to content

Updates tests for execution on non Apple hosts. #8407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public let toolchainPath: AbsolutePath = {
let swiftcPath = try! AbsolutePath(
validating: sh("xcrun", "--find", "swift").stdout.spm_chomp()
)
#elseif os(Windows)
let swiftcPath = try! AbsolutePath(validating: sh("where.exe", "swift.exe").stdout.spm_chomp())
#else
let swiftcPath = try! AbsolutePath(validating: sh("which", "swift").stdout.spm_chomp())
#endif
Expand Down
12 changes: 12 additions & 0 deletions IntegrationTests/Sources/IntegrationTestSupport/Process.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,16 @@ extension ProcessInfo {
#else
public static let hostOperatingSystem = OperatingSystem.unknown
#endif

#if os(Windows)
public static let EOL = "\r\n"
#else
public static let EOL = "\n"
#endif

#if os(Windows)
public static let exeSuffix = ".exe"
#else
public static let exeSuffix = ""
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class StringChecker {

public init(string: String) {
self.string = string
self.lines = string.split(separator: "\n")
self.lines = string.split(separator: ProcessInfo.EOL)
self.currentLineIndex = 0
}

Expand Down
72 changes: 39 additions & 33 deletions IntegrationTests/Tests/IntegrationTests/BasicTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Foundation
import IntegrationTestSupport
import Testing
import TSCBasic
Expand All @@ -25,13 +26,15 @@ private struct BasicTests {
.skipSwiftCISelfHosted(
"These packages don't use the latest runtime library, which doesn't work with self-hosted builds."
),
.requireUnrestrictedNetworkAccess("Test requires access to https://github.com")
.requireUnrestrictedNetworkAccess("Test requires access to https://github.com"),
.skipHostOS(.windows, "Issue #8409 - random.swift:34:8: error: unsupported platform")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (if-minor, if-updating): Can we use the .bug trait and include the URL to the GitHub issue?

FYI: There is no need to update the PR just to address this, but something to keep in mind for subsequent changes.

)
func testExamplePackageDealer() throws {
try withTemporaryDirectory { tempDir in
let packagePath = tempDir.appending(component: "dealer")
try sh("git", "clone", "https://github.com/apple/example-package-dealer", packagePath)
try sh("git\(ProcessInfo.exeSuffix)", "clone", "https://github.com/apple/example-package-dealer", packagePath)
let build1Output = try sh(swiftBuild, "--package-path", packagePath).stdout

// Check the build log.
#expect(build1Output.contains("Build complete"))

Expand All @@ -43,7 +46,7 @@ private struct BasicTests {

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

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

// Verify that the tool exists and works.
let toolOutput = try sh(packagePath.appending(components: ".build", "debug", "tool")).stdout
#expect(toolOutput.contains("HI"))
#expect(toolOutput.contains("\n"))
let toolOutput = try sh(packagePath.appending(components: ".build", "debug", "tool"))
.stdout
#expect(toolOutput == "HI\(ProcessInfo.EOL)")
}
}

Expand All @@ -108,7 +111,7 @@ private struct BasicTests {

// Check the file runs.
let helloOutput = try sh(helloBinaryPath).stdout
#expect(helloOutput == "hello\n")
#expect(helloOutput == "hello\(ProcessInfo.EOL)")
}
}

Expand Down Expand Up @@ -140,24 +143,26 @@ private struct BasicTests {
}
}

@Test(.skip("FIXME: swift-test invocations are timing out in Xcode and self-hosted CI"))
@Test
func testSwiftPackageInitExecTests() throws {
try withTemporaryDirectory { tempDir in
// Create a new package with an executable target.
let packagePath = tempDir.appending(component: "Project")
try localFileSystem.createDirectory(packagePath)
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "executable")
let testOutput = try sh(swiftTest, "--package-path", packagePath).stdout

// Check the test log.
let checker = StringChecker(string: testOutput)
#expect(checker.check(.regex("Compiling .*ProjectTests.*")))
#expect(checker.check("Test Suite 'All tests' passed"))
#expect(checker.checkNext("Executed 1 test"))

// Check there were no compile errors or warnings.
#expect(testOutput.contains("error") == false)
#expect(testOutput.contains("warning") == false)
withKnownIssue("error: no tests found; create a target in the 'Tests' directory") {
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "executable")
let testOutput = try sh(swiftTest, "--package-path", packagePath).stdout

// Check the test log.
let checker = StringChecker(string: testOutput)
#expect(checker.check(.regex("Compiling .*ProjectTests.*")))
#expect(checker.check("Test Suite 'All tests' passed"))
#expect(checker.checkNext("Executed 1 test"))

// Check there were no compile errors or warnings.
#expect(testOutput.contains("error") == false)
#expect(testOutput.contains("warning") == false)
}
}
}

Expand All @@ -180,7 +185,7 @@ private struct BasicTests {
}
}

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

// Check the test log.
let checker = StringChecker(string: testOutput)
#expect(checker.check(.regex("Compiling .*ProjectTests.*")))
#expect(checker.check("Test Suite 'All tests' passed"))
#expect(checker.checkNext("Executed 1 test"))
#expect(checker.check(.contains("Test Suite 'All tests' started")))
#expect(checker.check(.contains("Test example() passed after")))
#expect(checker.checkNext(.contains("Test run with 1 test passed after")))

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

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

// Verify that the tool exists and works.
let toolOutput = try sh(
packagePath.appending(components: ".build", "debug", "special tool")
).stdout
#expect(toolOutput == "HI\n")

#expect(toolOutput == "HI\(ProcessInfo.EOL)")
}
}

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

#expect(runOutput == "1 \"two\"\n")
#expect(runOutput == "1 \"two\"\(ProcessInfo.EOL)")
}
}

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

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

let testOutput = try sh(
swiftTest, "--package-path", packagePath, "--filter", "MyTests.*"
).stderr
).stdout

// Check the test log.
let checker = StringChecker(string: testOutput)
Expand Down
68 changes: 46 additions & 22 deletions IntegrationTests/Tests/IntegrationTests/SwiftPMTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ import Testing
import TSCBasic
import TSCTestSupport

// TODO: This should be replaced with BuildSystem.BuildSystemProvider if 'IntegrationTests' are moved up under the swift-package-manager tests.
public enum BuildSystemProvider: String, Codable, CaseIterable {
case native
case swiftbuild
}

@Suite
private struct SwiftPMTests {
@Test(.requireHostOS(.macOS))
Expand Down Expand Up @@ -69,46 +75,64 @@ private struct SwiftPMTests {
}

@Test(
.requireThreadSafeWorkingDirectory
.requireThreadSafeWorkingDirectory,
.bug(
"https://github.com/swiftlang/swift-package-manager/issues/8416",
"swift run using --build-system swiftbuild fails to run executable"
),
arguments: BuildSystemProvider.allCases
)
func packageInitExecutable() throws {
func packageInitExecutable(_ buildSystemProvider: BuildSystemProvider) throws {
// Executable
do {
try withTemporaryDirectory { tmpDir in
let packagePath = tmpDir.appending(component: "foo")
try localFileSystem.createDirectory(packagePath)
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "executable")
try sh(swiftBuild, "--package-path", packagePath, "--build-system", "swiftbuild")
// SWBINTTODO: Path issues related to swift test of the output from a swiftbuild buildsystem
// let (stdout, stderr) = try sh(
// swiftRun, "--package-path", packagePath, "--build-system", "swiftbuild"
// )
// #expect(!stderr.contains("error:"))
// #expect(stdout.contains("Hello, world!"))
try sh(swiftBuild, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue)

try withKnownIssue("Error while loading shared libraries: libswiftCore.so: cannot open shared object file: No such file or directory") {
// The 'native' build system uses 'swiftc' as the linker driver, which adds an RUNPATH to the swift runtime libraries in the SDK.
// 'swiftbuild' directly calls clang, which does not add the extra RUNPATH, so runtime libraries cannot be found.
let (stdout, stderr) = try sh(
swiftRun, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue
)
#expect(!stderr.contains("error:"))
#expect(stdout.contains("Hello, world!"))
} when: {
buildSystemProvider == .swiftbuild && ProcessInfo.hostOperatingSystem == .linux
}
}
}
}

@Test(
.skipHostOS(
.windows,
"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"
),
.requireThreadSafeWorkingDirectory
.requireThreadSafeWorkingDirectory,
.bug(id: 0, "SWBINTTODO: Linux: /lib/x86_64-linux-gnu/Scrt1.o:function _start: error:"),
.bug("https://github.com/swiftlang/swift-package-manager/issues/8380", "lld-link: error: subsystem must be defined"),
.bug(id:0, "SWBINTTODO: MacOS: Could not find or use auto-linked library 'Testing': library 'Testing' not found"),
arguments: BuildSystemProvider.allCases
)
func packageInitLibrary() throws {
func packageInitLibrary(_ buildSystemProvider: BuildSystemProvider) throws {
do {
try withTemporaryDirectory { tmpDir in
let packagePath = tmpDir.appending(component: "foo")
try localFileSystem.createDirectory(packagePath)
try sh(swiftPackage, "--package-path", packagePath, "init", "--type", "library")
try sh(swiftBuild, "--package-path", packagePath, "--build-system", "swiftbuild")
// SWBINTTODO: Path issues related to swift test of the output from a swiftbuild buildsystem
// let (stdout, stderr) = try sh(
// swiftTest, "--package-path", packagePath, "--build-system", "swiftbuild"
// )
// #expect(!stderr.contains("error:"))
// #expect(stdout.contains("Test Suite 'All tests' passed"))
try withKnownIssue("""
Linux: /lib/x86_64-linux-gnu/Scrt1.o:function _start: error: undefined reference to 'main'
Windows: lld-link: error: subsystem must be defined
MacOS: Could not find or use auto-linked library 'Testing': library 'Testing' not found
""") {
try sh(swiftBuild, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue, "--vv")
let (stdout, stderr) = try sh(
swiftTest, "--package-path", packagePath, "--build-system", buildSystemProvider.rawValue, "--vv"
)
#expect(!stderr.contains("error:"))
#expect(stdout.contains("Test Suite 'All tests' passed"))
} when: {
buildSystemProvider == .swiftbuild
}
}
}
}
Expand Down