diff --git a/IntegrationTests/Sources/IntegrationTestSupport/SkippedTestSupport.swift b/IntegrationTests/Sources/IntegrationTestSupport/SkippedTestSupport.swift index b73727d1c64..f8902513745 100644 --- a/IntegrationTests/Sources/IntegrationTestSupport/SkippedTestSupport.swift +++ b/IntegrationTests/Sources/IntegrationTestSupport/SkippedTestSupport.swift @@ -57,14 +57,4 @@ extension Trait where Self == Testing.ConditionTrait { #endif } } - - /// Constructs a condition trait that causes a test to be disabled if the Foundation process spawning implementation - /// is not using `posix_spawn_file_actions_addchdir`. - public static var requireThreadSafeWorkingDirectory: Self { - disabled("Thread-safe process working directory support is unavailable.") { - // Amazon Linux 2 has glibc 2.26, and glibc 2.29 is needed for posix_spawn_file_actions_addchdir_np support - FileManager.default.contents(atPath: "/etc/system-release") - .map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false - } - } } diff --git a/IntegrationTests/Tests/IntegrationTests/SwiftPMTests.swift b/IntegrationTests/Tests/IntegrationTests/SwiftPMTests.swift index b69d6077426..ab614eca0f4 100644 --- a/IntegrationTests/Tests/IntegrationTests/SwiftPMTests.swift +++ b/IntegrationTests/Tests/IntegrationTests/SwiftPMTests.swift @@ -75,7 +75,6 @@ private struct SwiftPMTests { } @Test( - .requireThreadSafeWorkingDirectory, arguments: [BuildSystemProvider.native] ) func packageInitExecutable(_ buildSystemProvider: BuildSystemProvider) throws { @@ -84,7 +83,6 @@ private struct SwiftPMTests { @Test( .skipHostOS(.windows), - .requireThreadSafeWorkingDirectory, .bug( "https://github.com/swiftlang/swift-package-manager/issues/8416", "[Linux] swift run using --build-system swiftbuild fails to run executable" @@ -125,7 +123,6 @@ private struct SwiftPMTests { } @Test( - .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"), diff --git a/Sources/Basics/Process.swift b/Sources/Basics/Process.swift index 0d59706e7d6..9cc7f801daf 100644 --- a/Sources/Basics/Process.swift +++ b/Sources/Basics/Process.swift @@ -19,6 +19,7 @@ public enum OperatingSystem: Hashable, Sendable { case unknown } + extension ProcessInfo { public static var hostOperatingSystem: OperatingSystem { #if os(macOS) diff --git a/Sources/_InternalTestSupport/BuildSystemProvider+Configuration.swift b/Sources/_InternalTestSupport/BuildSystemProvider+Configuration.swift new file mode 100644 index 00000000000..5b7adcff485 --- /dev/null +++ b/Sources/_InternalTestSupport/BuildSystemProvider+Configuration.swift @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import struct SPMBuildCore.BuildSystemProvider +import enum PackageModel.BuildConfiguration + +extension BuildSystemProvider.Kind { + + public func binPathSuffixes(for config: BuildConfiguration) -> [String] { + let suffix: String + + #if os(Linux) + suffix = "-linux" + #elseif os(Windows) + suffix = "-windows" + #else + suffix = "" + #endif + switch self { + case .native: + return ["\(config)".lowercased()] + case .swiftbuild: + return ["Products" , "\(config)".capitalized + suffix] + case .xcode: + return ["apple", "Products" , "\(config)".capitalized + suffix] + } + } +} diff --git a/Sources/_InternalTestSupport/BuildSystemProvider+Supported.swift b/Sources/_InternalTestSupport/BuildSystemProvider+Supported.swift new file mode 100644 index 00000000000..16e56ffaf2d --- /dev/null +++ b/Sources/_InternalTestSupport/BuildSystemProvider+Supported.swift @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import struct SPMBuildCore.BuildSystemProvider + + +public var SupportedBuildSystemOnAllPlatforms: [BuildSystemProvider.Kind] = BuildSystemProvider.Kind.allCases.filter { $0 != .xcode } + +public var SupportedBuildSystemOnPlatform: [BuildSystemProvider.Kind] { + #if os(macOS) + BuildSystemProvider.Kind.allCases + #else + SupportedBuildSystemOnAllPlatforms + #endif +} diff --git a/Sources/_InternalTestSupport/SkippedTestSupport.swift b/Sources/_InternalTestSupport/SkippedTestSupport.swift index 0d8df76022e..21739213b0a 100644 --- a/Sources/_InternalTestSupport/SkippedTestSupport.swift +++ b/Sources/_InternalTestSupport/SkippedTestSupport.swift @@ -59,3 +59,50 @@ extension Trait where Self == Testing.ConditionTrait { } } } + +extension Trait where Self == Testing.Bug { + public static func SWBINTTODO(_ comment: Comment) -> Self { + bug(nil, id: 0, comment) + } +} +extension Tag { + public enum TestSize {} + public enum Feature {} + @Tag public static var UserWorkflow: Tag +} + +extension Tag.TestSize { + @Tag public static var small: Tag + @Tag public static var medium: Tag + @Tag public static var large: Tag +} + +extension Tag.Feature { + public enum Command {} + public enum PackageType {} + + @Tag public static var CodeCoverage: Tag + @Tag public static var Resource: Tag + @Tag public static var SpecialCharacters: Tag +} + + +extension Tag.Feature.Command { + public enum Package {} + @Tag public static var Build: Tag + @Tag public static var Test: Tag + @Tag public static var Run: Tag +} + +extension Tag.Feature.Command.Package { + @Tag public static var Init: Tag +} +extension Tag.Feature.PackageType { + @Tag public static var Library: Tag + @Tag public static var Executable: Tag + @Tag public static var Tool: Tag + @Tag public static var Plugin: Tag + @Tag public static var BuildToolPlugin: Tag + @Tag public static var CommandPlugin: Tag + @Tag public static var Macro: Tag + } \ No newline at end of file diff --git a/Sources/_InternalTestSupport/XCTAssertHelpers.swift b/Sources/_InternalTestSupport/XCTAssertHelpers.swift index 7eaf10707d0..79b04c15a1f 100644 --- a/Sources/_InternalTestSupport/XCTAssertHelpers.swift +++ b/Sources/_InternalTestSupport/XCTAssertHelpers.swift @@ -16,6 +16,7 @@ import Basics import class Foundation.Bundle #endif import SPMBuildCore +import enum PackageModel.BuildConfiguration import TSCTestSupport import XCTest @@ -55,7 +56,7 @@ public func XCTSkipIfPlatformCI(because reason: String? = nil, file: StaticStrin public func XCTSkipIfselfHostedCI(because reason: String, file: StaticString = #filePath, line: UInt = #line) throws { // TODO: is this actually the right variable now? - if isSelfHostedCiEnvironment { + if CiEnvironment.runningInSelfHostedPipeline { throw XCTSkip(reason, file: file, line: line) } } @@ -145,7 +146,7 @@ package func XCTAssertAsyncNoThrow( public func XCTAssertBuilds( _ path: AbsolutePath, - configurations: Set = [.Debug, .Release], + configurations: Set = [.debug, .release], extraArgs: [String] = [], Xcc: [String] = [], Xld: [String] = [], @@ -175,7 +176,7 @@ public func XCTAssertBuilds( public func XCTAssertSwiftTest( _ path: AbsolutePath, - configuration: Configuration = .Debug, + configuration: BuildConfiguration = .debug, extraArgs: [String] = [], Xcc: [String] = [], Xld: [String] = [], diff --git a/Sources/_InternalTestSupport/misc.swift b/Sources/_InternalTestSupport/misc.swift index 94e3cb97c1f..8ff3260dbe0 100644 --- a/Sources/_InternalTestSupport/misc.swift +++ b/Sources/_InternalTestSupport/misc.swift @@ -39,8 +39,18 @@ import enum TSCUtility.Git @_exported import func TSCTestSupport.systemQuietly @_exported import enum TSCTestSupport.StringPattern -public let isInCiEnvironment = ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] != nil -public let isSelfHostedCiEnvironment = ProcessInfo.processInfo.environment["SWIFTCI_IS_SELF_HOSTED"] != nil +@available(*, deprecated, message: "Use CiEnvironment.runningInSmokeTestPipeline") +public let isInCiEnvironment = CiEnvironment.runningInSmokeTestPipeline + +@available(*, deprecated, message: "Use CiEnvironment.isSelfHostedCiEnvironment") +public let isSelfHostedCiEnvironment = CiEnvironment.runningInSelfHostedPipeline + +public struct CiEnvironmentStruct { + public let runningInSmokeTestPipeline = ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] != nil + public let runningInSelfHostedPipeline = ProcessInfo.processInfo.environment["SWIFTCI_IS_SELF_HOSTED"] != nil +} + +public let CiEnvironment = CiEnvironmentStruct() public let isRealSigningIdentyEcLabelEnvVarSet = ProcessInfo.processInfo.environment["REAL_SIGNING_IDENTITY_EC_LABEL"] != nil @@ -281,13 +291,14 @@ public func getBuildSystemArgs(for buildSystem: BuildSystemProvider.Kind?) -> [S @discardableResult public func executeSwiftBuild( _ packagePath: AbsolutePath?, - configuration: Configuration = .Debug, + configuration: BuildConfiguration = .debug, extraArgs: [String] = [], Xcc: [String] = [], Xld: [String] = [], Xswiftc: [String] = [], env: Environment? = nil, - buildSystem: BuildSystemProvider.Kind = .native + buildSystem: BuildSystemProvider.Kind = .native, + throwIfCommandFails: Bool = true, ) async throws -> (stdout: String, stderr: String) { let args = swiftArgs( configuration: configuration, @@ -297,14 +308,14 @@ public func executeSwiftBuild( Xswiftc: Xswiftc, buildSystem: buildSystem ) - return try await SwiftPM.Build.execute(args, packagePath: packagePath, env: env) + return try await SwiftPM.Build.execute(args, packagePath: packagePath, env: env, throwIfCommandFails: throwIfCommandFails) } @discardableResult public func executeSwiftRun( _ packagePath: AbsolutePath?, _ executable: String?, - configuration: Configuration = .Debug, + configuration: BuildConfiguration = .debug, extraArgs: [String] = [], Xcc: [String] = [], Xld: [String] = [], @@ -329,7 +340,7 @@ public func executeSwiftRun( @discardableResult public func executeSwiftPackage( _ packagePath: AbsolutePath?, - configuration: Configuration = .Debug, + configuration: BuildConfiguration = .debug, extraArgs: [String] = [], Xcc: [String] = [], Xld: [String] = [], @@ -351,7 +362,7 @@ public func executeSwiftPackage( @discardableResult public func executeSwiftPackageRegistry( _ packagePath: AbsolutePath?, - configuration: Configuration = .Debug, + configuration: BuildConfiguration = .debug, extraArgs: [String] = [], Xcc: [String] = [], Xld: [String] = [], @@ -373,7 +384,7 @@ public func executeSwiftPackageRegistry( @discardableResult public func executeSwiftTest( _ packagePath: AbsolutePath?, - configuration: Configuration = .Debug, + configuration: BuildConfiguration = .debug, extraArgs: [String] = [], Xcc: [String] = [], Xld: [String] = [], @@ -394,7 +405,7 @@ public func executeSwiftTest( } private func swiftArgs( - configuration: Configuration, + configuration: BuildConfiguration, extraArgs: [String], Xcc: [String], Xld: [String], @@ -403,9 +414,9 @@ private func swiftArgs( ) -> [String] { var args = ["--configuration"] switch configuration { - case .Debug: + case .debug: args.append("debug") - case .Release: + case .release: args.append("release") } diff --git a/Tests/BasicsTests/ConcurrencyHelpersTests.swift b/Tests/BasicsTests/ConcurrencyHelpersTests.swift index e3ae5616b8e..ef7ecda22dd 100644 --- a/Tests/BasicsTests/ConcurrencyHelpersTests.swift +++ b/Tests/BasicsTests/ConcurrencyHelpersTests.swift @@ -20,7 +20,9 @@ struct ConcurrencyHelpersTest { struct ThreadSafeKeyValueStoreTests { let queue = DispatchQueue(label: "ConcurrencyHelpersTest", attributes: .concurrent) - @Test + @Test( + .bug("https://github.com/swiftlang/swift-package-manager/issues/8770"), + ) func threadSafeKeyValueStore() throws { for _ in 0 ..< 100 { let sync = DispatchGroup() @@ -45,14 +47,16 @@ struct ConcurrencyHelpersTest { } } - try #require(sync.wait(timeout: .now() + .seconds(2)) == .success) + try #require(sync.wait(timeout: .now() + .seconds(300)) == .success) expected.forEach { key, value in #expect(cache[key] == value) } } } - @Test + @Test( + .bug("https://github.com/swiftlang/swift-package-manager/issues/8770"), + ) func threadSafeArrayStore() throws { for _ in 0 ..< 100 { let sync = DispatchGroup() @@ -72,15 +76,18 @@ struct ConcurrencyHelpersTest { } } - try #require(sync.wait(timeout: .now() + .seconds(2)) == .success) + + try #require(sync.wait(timeout: .now() + .seconds(300)) == .success) let expectedSorted = expected.sorted() let resultsSorted = cache.get().sorted() #expect(expectedSorted == resultsSorted) } - } + } } - @Test + @Test( + .bug("https://github.com/swiftlang/swift-package-manager/issues/8770"), + ) func threadSafeBox() throws { let queue = DispatchQueue(label: "ConcurrencyHelpersTest", attributes: .concurrent) for _ in 0 ..< 100 { @@ -108,7 +115,7 @@ struct ConcurrencyHelpersTest { } } - try #require(sync.wait(timeout: .now() + .seconds(2)) == .success) + try #require(sync.wait(timeout: .now() + .seconds(300)) == .success) #expect(cache.get() == winner) } } diff --git a/Tests/BasicsTests/Environment/EnvironmentTests.swift b/Tests/BasicsTests/Environment/EnvironmentTests.swift index 984441ddefa..b7011b2dd14 100644 --- a/Tests/BasicsTests/Environment/EnvironmentTests.swift +++ b/Tests/BasicsTests/Environment/EnvironmentTests.swift @@ -148,7 +148,7 @@ struct EnvironmentTests { /// Important: This test is inherently race-prone, if it is proven to be /// flaky, it should run in a singled threaded environment/removed entirely. @Test( - .disabled(if: isInCiEnvironment || isSelfHostedCiEnvironment, "This test can disrupt other tests running in parallel."), + .disabled(if: isInCiEnvironment || CiEnvironment.runningInSelfHostedPipeline, "This test can disrupt other tests running in parallel."), ) func makeCustomPathEnv() async throws { let customEnvironment: Environment = .current diff --git a/Tests/CommandsTests/BuildCommandTests.swift b/Tests/CommandsTests/BuildCommandTests.swift index 8dd01fcbd23..0218326f213 100644 --- a/Tests/CommandsTests/BuildCommandTests.swift +++ b/Tests/CommandsTests/BuildCommandTests.swift @@ -17,11 +17,12 @@ import Basics import PackageGraph import PackageLoading import PackageModel +import enum PackageModel.BuildConfiguration import SPMBuildCore import _InternalTestSupport import TSCTestSupport import Workspace -import XCTest +import Testing struct BuildResult { let binPath: AbsolutePath @@ -31,35 +32,71 @@ struct BuildResult { let moduleContents: [String] } -class BuildCommandTestCases: CommandsBuildProviderTestCase { +@Suite( + .tags( + Tag.TestSize.small, + ), +) +struct SanitierTests { + @Test( + arguments: Sanitizer.allCases + ) + func creatingSanitizers(sanitizer: Sanitizer) throws { + #expect(sanitizer == Sanitizer(argument: sanitizer.shortName)) + } - override func setUpWithError() throws { - try XCTSkipIf(type(of: self) == BuildCommandTestCases.self, "Skipping this test since it will be run in subclasses that will provide different build systems to test.") + @Test + func invalidSanitizer() throws { + #expect(Sanitizer(argument: "invalid") == nil) } +} + +@Suite( + .serialized, // to limit the number of swift executable running. + .tags( + Tag.TestSize.large, + Tag.Feature.Command.Build, + ), +) +struct BuildCommandTestCases { @discardableResult func execute( _ args: [String] = [], environment: Environment? = nil, - packagePath: AbsolutePath? = nil + packagePath: AbsolutePath? = nil, + configuration: BuildConfiguration = .debug, + buildSystem: BuildSystemProvider.Kind, + throwIfCommandFails: Bool = true, ) async throws -> (stdout: String, stderr: String) { + return try await executeSwiftBuild( packagePath, + configuration: configuration, extraArgs: args, env: environment, - buildSystem: buildSystemProvider + buildSystem: buildSystem, + throwIfCommandFails: throwIfCommandFails, ) } - func build(_ args: [String], packagePath: AbsolutePath? = nil, isRelease: Bool = false, cleanAfterward: Bool = true) async throws -> BuildResult { + func build( + _ args: [String], + packagePath: AbsolutePath? = nil, + configuration: BuildConfiguration = .debug, + cleanAfterward: Bool = true, + buildSystem: BuildSystemProvider.Kind, + ) async throws -> BuildResult { do { - let buildConfigurationArguments = isRelease ? ["-c", "release"] : [] - let (stdout, stderr) = try await execute(args + buildConfigurationArguments, packagePath: packagePath) + // let buildConfigurationArguments = isRelease ? ["-c", "release"] : [] + let (stdout, stderr) = try await execute(args, packagePath: packagePath,configuration: configuration, buildSystem: buildSystem,) defer { } let (binPathOutput, _) = try await execute( - ["--show-bin-path"] + buildConfigurationArguments, - packagePath: packagePath + ["--show-bin-path"], + packagePath: packagePath, + configuration: configuration, + buildSystem: buildSystem, ) let binPath = try AbsolutePath(validating: binPathOutput.trimmingCharacters(in: .whitespacesAndNewlines)) let binContents = try localFileSystem.getDirectoryContents(binPath).filter { @@ -71,7 +108,7 @@ class BuildCommandTestCases: CommandsBuildProviderTestCase { return contents != ["output-file-map.json"] } var moduleContents: [String] = [] - if buildSystemProvider == .native { + if buildSystem == .native { moduleContents = (try? localFileSystem.getDirectoryContents(binPath.appending(component: "Modules"))) ?? [] } else { let moduleDirs = (try? localFileSystem.getDirectoryContents(binPath).filter { @@ -82,13 +119,13 @@ class BuildCommandTestCases: CommandsBuildProviderTestCase { (try? localFileSystem.getDirectoryContents(binPath.appending(component: dir)).map { "\(dir)/\($0)" }) ?? [] } } - + if cleanAfterward { try await executeSwiftPackage( packagePath, extraArgs: ["clean"], - buildSystem: buildSystemProvider + buildSystem: buildSystem ) } return BuildResult( @@ -103,454 +140,796 @@ class BuildCommandTestCases: CommandsBuildProviderTestCase { try await executeSwiftPackage( packagePath, extraArgs: ["clean"], - buildSystem: buildSystemProvider + buildSystem: buildSystem ) } throw error } } - func testUsage() async throws { - let stdout = try await execute(["-help"]).stdout - XCTAssertMatch(stdout, .contains("USAGE: swift build")) - } - - func testBinSymlink() async throws { - XCTAssertTrue(false, "Must be implemented at build system test class.") + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func usage(buildSystem: BuildSystemProvider.Kind) async throws { + let stdout = try await execute(["-help"], buildSystem: buildSystem).stdout + #expect(stdout.contains("USAGE: swift build")) } - func testSeeAlso() async throws { - let stdout = try await execute(["--help"]).stdout - XCTAssertMatch(stdout, .contains("SEE ALSO: swift run, swift package, swift test")) + @Test( + arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases + ) + func binSymlink( + buildSystem: BuildSystemProvider.Kind, + configuration: BuildConfiguration, + ) async throws { + // Test is not implemented for Xcode build system + try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in + let fullPath = try resolveSymlinks(fixturePath) + + let rootScrathPath = fullPath.appending(component: ".build") + let targetPath: AbsolutePath + if buildSystem == .xcode { + targetPath = rootScrathPath + } else { + targetPath = try rootScrathPath.appending(component: UserToolchain.default.targetTriple.platformBuildPathComponent) + } + let path = try await self.execute(["--show-bin-path"], packagePath: fullPath, configuration: configuration, buildSystem: buildSystem).stdout.trimmingCharacters(in: .whitespacesAndNewlines) + #expect( + AbsolutePath(path).pathString == targetPath + .appending(components: buildSystem.binPathSuffixes(for: configuration)).pathString + ) + } } - func testCommandDoesNotEmitDuplicateSymbols() async throws { - let (stdout, stderr) = try await SwiftPM.Build.execute(["--help"]) - XCTAssertNoMatch(stdout, duplicateSymbolRegex) - XCTAssertNoMatch(stderr, duplicateSymbolRegex) + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func seeAlso(buildSystem: BuildSystemProvider.Kind) async throws { + let stdout = try await execute(["--help"], buildSystem: buildSystem).stdout + #expect(stdout.contains("SEE ALSO: swift run, swift package, swift test")) } - func testVersion() async throws { - let stdout = try await execute(["--version"]).stdout - XCTAssertMatch(stdout, .regex(#"Swift Package Manager -( \w+ )?\d+.\d+.\d+(-\w+)?"#)) + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func commandDoesNotEmitDuplicateSymbols(buildSystem: BuildSystemProvider.Kind) async throws { + let duplicateSymbolRegex = try Regex(".*One of the duplicates must be removed or renamed.") + let (stdout, stderr) = try await execute(["--help"], buildSystem: buildSystem) + #expect(!stdout.contains(duplicateSymbolRegex)) + #expect(!stderr.contains(duplicateSymbolRegex)) } - func testCreatingSanitizers() throws { - for sanitizer in Sanitizer.allCases { - XCTAssertEqual(sanitizer, Sanitizer(argument: sanitizer.shortName)) - } + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func version(buildSystem: BuildSystemProvider.Kind) async throws { + let stdout = try await execute(["--version"], buildSystem: buildSystem).stdout + let expectedRegex = try Regex(#"Swift Package Manager -( \w+ )?\d+.\d+.\d+(-\w+)?"#) + #expect(stdout.contains(expectedRegex)) } - func testInvalidSanitizer() throws { - XCTAssertNil(Sanitizer(argument: "invalid")) - } - func testImportOfMissedDepWarning() async throws { - // Verify the warning flow - try await fixture(name: "Miscellaneous/ImportOfMissingDependency") { path in - let fullPath = try resolveSymlinks(path) - await XCTAssertAsyncThrowsError(try await self.build( - ["--explicit-target-dependency-import-check=warn"], - packagePath: fullPath - )) { error in - guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = error else { - XCTFail() + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func importOfMissedDepWarning(buildSystem: BuildSystemProvider.Kind) async throws { + try await withKnownIssue("SWBINTTODO: Test fails because the warning message regarding missing imports is expected to be more verbose and actionable at the SwiftPM level with mention of the involved targets. This needs to be investigated. See case targetDiagnostic(TargetDiagnosticInfo) as a message type that may help.") { + try await fixture(name: "Miscellaneous/ImportOfMissingDependency") { path in + let fullPath = try resolveSymlinks(path) + let error = await #expect(throws: SwiftPMError.self ) { + try await self.build( + ["--explicit-target-dependency-import-check=warn"], + packagePath: fullPath, + buildSystem: buildSystem, + ) + } + guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") return } - XCTAssertTrue( - stderr.contains( - "warning: Target A imports another target (B) in the package without declaring it a dependency." - ), - "got stdout: \(stdout), stderr: \(stderr)" + #expect( + stderr.contains("warning: Target A imports another target (B) in the package without declaring it a dependency."), + "got stdout: \(stdout), stderr: \(stderr)", ) } + } when: { + [.swiftbuild, .xcode].contains(buildSystem) } + } - // Verify the error flow - try await fixture(name: "Miscellaneous/ImportOfMissingDependency") { path in - let fullPath = try resolveSymlinks(path) - await XCTAssertAsyncThrowsError(try await self.build( - ["--explicit-target-dependency-import-check=error"], - packagePath: fullPath - )) { error in - guard case SwiftPMError.executionFailure(_, _, let stderr) = error else { - XCTFail() + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func importOfMissedDepWarningVerifyingErrorFlow(buildSystem: BuildSystemProvider.Kind) async throws { + try await withKnownIssue("SWBINTTODO: Test fails because the warning message regarding missing imports is expected to be more verbose and actionable at the SwiftPM level with mention of the involved targets. This needs to be investigated. See case targetDiagnostic(TargetDiagnosticInfo) as a message type that may help.") { + try await fixture(name: "Miscellaneous/ImportOfMissingDependency") { path in + let fullPath = try resolveSymlinks(path) + let error = await #expect(throws: SwiftPMError.self ) { + try await self.build( + ["--explicit-target-dependency-import-check=error"], + packagePath: fullPath, + buildSystem: buildSystem, + ) + } + guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { + Issue.record("Expected error did not occur") return } - XCTAssertTrue( - stderr.contains( - "error: Target A imports another target (B) in the package without declaring it a dependency." - ), - "got stdout: \(String(describing: stdout)), stderr: \(String(describing: stderr))" + #expect( + stderr.contains("error: Target A imports another target (B) in the package without declaring it a dependency."), + "got stdout: \(String(describing: stdout)), stderr: \(String(describing: stderr))", ) } + } when: { + [.swiftbuild, .xcode].contains(buildSystem) } + } - // Verify that the default does not run the check + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func importOfMissedDepWarningVerifyingDefaultDoesNotRunTheCheck(buildSystem: BuildSystemProvider.Kind) async throws { try await fixture(name: "Miscellaneous/ImportOfMissingDependency") { path in let fullPath = try resolveSymlinks(path) - await XCTAssertAsyncThrowsError(try await self.build([], packagePath: fullPath)) { error in - guard case SwiftPMError.executionFailure(_, _, let stderr) = error else { - XCTFail() - return - } - XCTAssertFalse( - stderr.contains( - "warning: Target A imports another target (B) in the package without declaring it a dependency." - ), - "got stdout: \(String(describing: stdout)), stderr: \(String(describing: stderr))" - ) + let error = await #expect(throws: SwiftPMError.self ) { + try await self.build([], packagePath: fullPath, buildSystem: buildSystem) + } + guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { + Issue.record("Expected error did not occur") + return } + #expect( + !stderr.contains("warning: Target A imports another target (B) in the package without declaring it a dependency."), + "got stdout: \(String(describing: stdout)), stderr: \(String(describing: stderr))", + ) } } - func testSymlink() async throws { - try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in - let fullPath = try resolveSymlinks(fixturePath) - let targetPath = try fullPath.appending(components: - ".build", - UserToolchain.default.targetTriple.platformBuildPathComponent - ) - // Test symlink. - try await self.execute(packagePath: fullPath) - XCTAssertEqual( - try resolveSymlinks(fullPath.appending(components: ".build", "debug")), - targetPath.appending("debug") - ) - try await self.execute(["-c", "release"], packagePath: fullPath) - XCTAssertEqual( - try resolveSymlinks(fullPath.appending(components: ".build", "release")), - targetPath.appending("release") - ) + @Test( + .SWBINTTODO("Test fails because of a difference in the build layout. This needs to be updated to the expected path"), + arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases + ) + func symlink( + buildSystem: BuildSystemProvider.Kind, + configuration: BuildConfiguration, + ) async throws { + try await withKnownIssue { + try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in + let fullPath = try resolveSymlinks(fixturePath) + let targetPath = try fullPath.appending(components: + ".build", + UserToolchain.default.targetTriple.platformBuildPathComponent + ) + // Test symlink. + let buildDir = fullPath.appending(components: ".build") + try await self.execute(packagePath: fullPath, configuration: configuration, buildSystem: buildSystem) + let actualDebug = try resolveSymlinks(buildDir.appending(components: buildSystem.binPathSuffixes(for: configuration))) + let expectedDebug = targetPath.appending(components: buildSystem.binPathSuffixes(for: configuration)) + #expect(actualDebug == expectedDebug) + } + } when: { + buildSystem != .native } } - func testProductAndTarget() async throws { - try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in - let fullPath = try resolveSymlinks(fixturePath) - - do { - let result = try await build(["--product", "exec1"], packagePath: fullPath) - XCTAssertMatch(result.binContents, [.equal(executableName("exec1"))]) - XCTAssertNoMatch(result.binContents, ["exec2.build"]) + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func buildExistingExecutableProductIsSuccessfull( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue("Failures possibly due to long file paths") { + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + let fullPath = try resolveSymlinks(fixturePath) + + let result = try await build(["--product", "exec1"], packagePath: fullPath, buildSystem: buildSystem,) + #expect(result.binContents.contains(executableName("exec1"))) + #expect(!result.binContents.contains("exec2.build")) } + } when: { + ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild + } + } - do { - let (_, stderr) = try await execute(["--product", "lib1"], packagePath: fullPath) - try await executeSwiftPackage( - fullPath, - extraArgs:["clean"], - buildSystem: buildSystemProvider - ) - XCTAssertMatch( - stderr, - .contains( - "'--product' cannot be used with the automatic product 'lib1'; building the default target instead" + @Test( + .SWBINTTODO("Found multiple targets named 'lib1'"), + arguments: SupportedBuildSystemOnPlatform, + ) + func buildExistingLibraryProductIsSuccessfull( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue("Found multiple targets named 'lib1'") { + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + let fullPath = try resolveSymlinks(fixturePath) + + let (_, stderr) = try await execute(["--product", "lib1"], packagePath: fullPath, buildSystem: buildSystem,) + if buildSystem != .xcode { + #expect( + stderr.contains( + "'--product' cannot be used with the automatic product 'lib1'; building the default target instead" + ) ) - ) + } } + } when: { + .swiftbuild == buildSystem + } + } - do { - let result = try await build(["--target", "exec2"], packagePath: fullPath) - XCTAssertMatch(result.binContents, ["exec2.build"]) - XCTAssertNoMatch(result.binContents, ["exec1"]) + @Test( + .SWBINTTODO("Could not find target named 'exec2'"), + arguments: SupportedBuildSystemOnPlatform, + ) + func buildExistingTargetIsSuccessfull( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue("Could not find target named 'exec2'") { + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + let fullPath = try resolveSymlinks(fixturePath) + + let result = try await build(["--target", "exec2"], packagePath: fullPath, buildSystem: buildSystem,) + #expect(result.binContents.contains("exec2.build")) + #expect(!result.binContents.contains(executableName("exec1"))) } + } when: { + [ + .swiftbuild, + .xcode, + ].contains(buildSystem) + } + } - await XCTAssertThrowsCommandExecutionError(try await self.execute( + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func buildProductAndTargetsFailsWithAMutuallyExclusiveMessage( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + let error = await #expect(throws: SwiftPMError.self ) { + try await self.execute( ["--product", "exec1", "--target", "exec2"], - packagePath: fixturePath - )) { error in - XCTAssertMatch(error.stderr, .contains("error: '--product' and '--target' are mutually exclusive")) + packagePath: fixturePath,buildSystem: buildSystem, + ) + } + // THEN I expect a failure + guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return } + #expect(stderr.contains("error: '--product' and '--target' are mutually exclusive")) + } + } - await XCTAssertThrowsCommandExecutionError(try await self.execute( + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func buildProductAndTestsFailsWithAMutuallyExclusiveMessage( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + let error = await #expect(throws: SwiftPMError.self ) { + try await self.execute( ["--product", "exec1", "--build-tests"], - packagePath: fixturePath - )) { error in - XCTAssertMatch(error.stderr, .contains("error: '--product' and '--build-tests' are mutually exclusive")) + packagePath: fixturePath,buildSystem: buildSystem, + ) + } + // THEN I expect a failure + guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return } + #expect(stderr.contains("error: '--product' and '--build-tests' are mutually exclusive")) + } + } - await XCTAssertThrowsCommandExecutionError(try await self.execute( + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func buildTargetAndTestsFailsWithAMutuallyExclusiveMessage( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + let error = await #expect(throws: SwiftPMError.self ) { + try await self.execute( ["--build-tests", "--target", "exec2"], - packagePath: fixturePath - )) { error in - XCTAssertMatch(error.stderr, .contains("error: '--target' and '--build-tests' are mutually exclusive")) + packagePath: fixturePath,buildSystem: buildSystem, + ) + } + // THEN I expect a failure + guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return } + #expect(stderr.contains("error: '--target' and '--build-tests' are mutually exclusive")) + } + } - await XCTAssertThrowsCommandExecutionError(try await self.execute( + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func buildProductTargetAndTestsFailsWithAMutuallyExclusiveMessage( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + let error = await #expect(throws: SwiftPMError.self ) { + try await self.execute( ["--build-tests", "--target", "exec2", "--product", "exec1"], - packagePath: fixturePath - )) { error in - XCTAssertMatch( - error.stderr, - .contains("error: '--product', '--target', and '--build-tests' are mutually exclusive") + packagePath: fixturePath,buildSystem: buildSystem, ) } + // THEN I expect a failure + guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return + } + #expect(stderr.contains("error: '--product', '--target', and '--build-tests' are mutually exclusive")) + } + } - await XCTAssertThrowsCommandExecutionError(try await self.execute( - ["--product", "UnkownProduct"], - packagePath: fixturePath - )) { error in - XCTAssertMatch(error.stderr, .contains("error: no product named 'UnkownProduct'")) + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func buildUnknownProductFailsWithAppropriateMessage( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + let productName = "UnknownProduct" + let error = await #expect(throws: SwiftPMError.self ) { + try await self.execute( + ["--product", productName], + packagePath: fixturePath,buildSystem: buildSystem, + ) + } + // THEN I expect a failure + guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return } - await XCTAssertThrowsCommandExecutionError(try await self.execute( - ["--target", "UnkownTarget"], - packagePath: fixturePath - )) { error in - XCTAssertMatch(error.stderr, .contains("error: no target named 'UnkownTarget'")) + try withKnownIssue { + if .native == buildSystem { + #expect(stderr.contains("error: no product named '\(productName)'")) + } else { + let expectedErrorMessageRegex = try Regex("error: Could not find target named '\(productName).*'") + #expect( + stderr.contains(expectedErrorMessageRegex), + "expect log not emitted.\nstdout: '\(stdout)'\n\nstderr: '\(stderr)'", + ) + } + } when: { + buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows && CiEnvironment.runningInSmokeTestPipeline } } } - func testAtMainSupport() async throws { - try await fixture(name: "Miscellaneous/AtMainSupport") { fixturePath in - let fullPath = try resolveSymlinks(fixturePath) - - do { - let result = try await build(["--product", "ClangExecSingleFile"], packagePath: fullPath) - XCTAssertMatch(result.binContents, [.equal(executableName("ClangExecSingleFile"))]) + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func buildUnknownTargetFailsWithAppropriateMessage( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await fixture(name: "Miscellaneous/MultipleExecutables") { fixturePath in + let targetName = "UnknownTargetName" + let error = await #expect(throws: SwiftPMError.self ) { + try await self.execute( + ["--target", targetName], + packagePath: fixturePath,buildSystem: buildSystem, + ) } - - do { - let result = try await build(["--product", "SwiftExecSingleFile"], packagePath: fullPath) - XCTAssertMatch(result.binContents, [.equal(executableName("SwiftExecSingleFile"))]) + // THEN I expect a failure + guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return } - - do { - let result = try await build(["--product", "SwiftExecMultiFile"], packagePath: fullPath) - XCTAssertMatch(result.binContents, [.equal(executableName("SwiftExecMultiFile"))]) + let expectedErrorMessage: String + if .native == buildSystem { + expectedErrorMessage = "error: no target named '\(targetName)'" + } else { + expectedErrorMessage = "error: Could not find target named '\(targetName)'" + } + withKnownIssue{ + #expect( + stderr.contains(expectedErrorMessage), + "expect log not emitted.\nstdout: '\(stdout)'\n\nstderr: '\(stderr)'", + ) + } when: { + buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows && CiEnvironment.runningInSmokeTestPipeline } } } - func testNonReachableProductsAndTargetsFunctional() async throws { - try await fixture(name: "Miscellaneous/UnreachableTargets") { fixturePath in - let aPath = fixturePath.appending("A") + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func atMainSupport(buildSystem: BuildSystemProvider.Kind) async throws { + try await withKnownIssue("SWBINTTODO: File not found or missing libclang errors on non-macOS platforms. This needs to be investigated") { + try await fixture(name: "Miscellaneous/AtMainSupport") { fixturePath in + let fullPath = try resolveSymlinks(fixturePath) + + do { + let result = try await build(["--product", "ClangExecSingleFile"], packagePath: fullPath, buildSystem: buildSystem) + #expect(result.binContents.contains(executableName("ClangExecSingleFile"))) + } - do { - let result = try await build([], packagePath: aPath) - XCTAssertNoMatch(result.binContents, ["bexec"]) - XCTAssertNoMatch(result.binContents, ["BTarget2.build"]) - XCTAssertNoMatch(result.binContents, ["cexec"]) - XCTAssertNoMatch(result.binContents, ["CTarget.build"]) + do { + let result = try await build(["--product", "SwiftExecSingleFile"], packagePath: fullPath, buildSystem: buildSystem) + #expect(result.binContents.contains(executableName("SwiftExecSingleFile"))) + } + + do { + let result = try await build(["--product", "SwiftExecMultiFile"], packagePath: fullPath, buildSystem: buildSystem) + #expect(result.binContents.contains(executableName("SwiftExecMultiFile"))) + } } + } when: { + ![.macOS, .linux].contains(ProcessInfo.hostOperatingSystem) && buildSystem == .swiftbuild + } + } - // Dependency contains a dependent product + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func nonReachableProductsAndTargetsFunctional( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + // skipped on Xcode + try await withKnownIssue { + try await fixture(name: "Miscellaneous/UnreachableTargets") { fixturePath in + let aPath = fixturePath.appending("A") + + let result = try await build([], packagePath: aPath, buildSystem: buildSystem) + #expect(!result.binContents.contains("bexec")) + #expect(!result.binContents.contains("BTarget2.build")) + #expect(!result.binContents.contains("cexec")) + #expect(!result.binContents.contains("CTarget.build")) + } + } when: { + buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows + } + } - do { - let result = try await build(["--product", "bexec"], packagePath: aPath) - XCTAssertMatch(result.binContents, ["BTarget2.build"]) - XCTAssertMatch(result.binContents, [.equal(executableName("bexec"))]) - XCTAssertNoMatch(result.binContents, [.equal(executableName("aexec"))]) - XCTAssertNoMatch(result.binContents, ["ATarget.build"]) - XCTAssertNoMatch(result.binContents, ["BLibrary.a"]) + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func nonReachableProductsAndTargetsFunctionalWhereDependencyContainsADependentProducts( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + // skipped on Xcode + // known failures in SwiftBuild + try await withKnownIssue("SWBINTTODO: Test failed. This needs to be investigated") { + try await fixture(name: "Miscellaneous/UnreachableTargets") { fixturePath in + let aPath = fixturePath.appending("A") + + // Dependency contains a dependent product + + let result = try await build(["--product", "bexec"], packagePath: aPath, buildSystem: buildSystem) + #expect(result.binContents.contains("BTarget2.build")) + #expect(result.binContents.contains(executableName("bexec"))) + #expect(!result.binContents.contains(executableName("aexec"))) + #expect(!result.binContents.contains("ATarget.build")) + #expect(!result.binContents.contains("BLibrary.a")) // FIXME: We create the modulemap during build planning, hence this ugliness. let bTargetBuildDir = - ((try? localFileSystem.getDirectoryContents(result.binPath.appending("BTarget1.build"))) ?? []) - .filter { $0 != moduleMapFilename } - XCTAssertTrue(bTargetBuildDir.isEmpty, "bTargetBuildDir should be empty") + ((try? localFileSystem.getDirectoryContents(result.binPath.appending("BTarget1.build"))) ?? []) + .filter { $0 != moduleMapFilename } + #expect(bTargetBuildDir.isEmpty, "bTargetBuildDir should be empty") - XCTAssertNoMatch(result.binContents, ["cexec"]) - XCTAssertNoMatch(result.binContents, ["CTarget.build"]) + #expect(!result.binContents.contains("cexec")) + #expect(!result.binContents.contains("CTarget.build")) // Also make sure we didn't emit parseable module interfaces // (do this here to avoid doing a second build in // testParseableInterfaces(). - XCTAssertNoMatch(result.moduleContents, ["ATarget.swiftinterface"]) - XCTAssertNoMatch(result.moduleContents, ["BTarget.swiftinterface"]) - XCTAssertNoMatch(result.moduleContents, ["CTarget.swiftinterface"]) + #expect(!result.moduleContents.contains("ATarget.swiftinterface")) + #expect(!result.moduleContents.contains("BTarget.swiftinterface")) + #expect(!result.moduleContents.contains("CTarget.swiftinterface")) } + } when: { + buildSystem != .native } } - func testParseableInterfaces() async throws { + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func parseableInterfaces( + buildSystem: BuildSystemProvider.Kind, + ) async throws { try await fixture(name: "Miscellaneous/ParseableInterfaces") { fixturePath in - do { - let result = try await build(["--enable-parseable-module-interfaces"], packagePath: fixturePath) - XCTAssertMatch(result.moduleContents, ["A.swiftinterface"]) - XCTAssertMatch(result.moduleContents, ["B.swiftinterface"]) - } catch SwiftPMError.executionFailure(_, _, let stderr) { - XCTFail(stderr) + try await withKnownIssue { + let result = try await build(["--enable-parseable-module-interfaces"], packagePath: fixturePath, buildSystem: buildSystem) + switch buildSystem { + case .native: + #expect(result.moduleContents.contains("A.swiftinterface")) + #expect(result.moduleContents.contains("B.swiftinterface")) + default: + let moduleARegex = try Regex(#"A[.]swiftmodule[/].*[.]swiftinterface"#) + let moduleBRegex = try Regex(#"B[.]swiftmodule[/].*[.]swiftmodule"#) + #expect(result.moduleContents.contains { $0.contains(moduleARegex) }) + #expect(result.moduleContents.contains { $0.contains(moduleBRegex) }) + } + } when: { + // errors with SwiftBuild on Windows possibly due to long path on windows only for swift build + buildSystem == .xcode || (ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild) } } } - func testAutomaticParseableInterfacesWithLibraryEvolution() async throws { - try await fixture(name: "Miscellaneous/LibraryEvolution") { fixturePath in - do { - let result = try await build([], packagePath: fixturePath) - XCTAssertMatch(result.moduleContents, ["A.swiftinterface"]) - XCTAssertMatch(result.moduleContents, ["B.swiftinterface"]) + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func automaticParseableInterfacesWithLibraryEvolution( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue { + try await fixture(name: "Miscellaneous/LibraryEvolution") { fixturePath in + let result = try await build([], packagePath: fixturePath, buildSystem: buildSystem) + switch buildSystem { + case .native: + #expect(result.moduleContents.contains("A.swiftinterface")) + #expect(result.moduleContents.contains("B.swiftinterface")) + default: + let moduleARegex = try Regex(#"A[.]swiftmodule[/].*[.]swiftinterface"#) + let moduleBRegex = try Regex(#"B[.]swiftmodule[/].*[.]swiftmodule"#) + withKnownIssue("SWBINTTODO: Test failed because of missing 'A.swiftmodule/*.swiftinterface' files") { + #expect(result.moduleContents.contains { $0.contains(moduleARegex) }) + } when: { + buildSystem == .swiftbuild + } + #expect(result.moduleContents.contains { $0.contains(moduleBRegex) }) + } } + } when: { + buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows } } - func testBuildCompleteMessage() async throws { - try await fixture(name: "DependencyResolution/Internal/Simple") { fixturePath in - do { - let result = try await execute(packagePath: fixturePath) - // This test fails to match the 'Compiling' regex; rdar://101815761 - // XCTAssertMatch(result.stdout, .regex("\\[[1-9][0-9]*\\/[1-9][0-9]*\\] Compiling")) - let lines = result.stdout.split(whereSeparator: { $0.isNewline }) - XCTAssertMatch(String(lines.last!), .regex("Build complete! \\([0-9]*\\.[0-9]*\\s*s(econds)?\\)")) - } + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func buildCompleteMessage( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue { + try await fixture(name: "DependencyResolution/Internal/Simple") { fixturePath in + let buildCompleteRegex = try Regex(#"Build complete!\s?(\([0-9]*\.[0-9]*\s*s(econds)?\))?"#) + do { + let result = try await execute(packagePath: fixturePath, buildSystem: buildSystem) + // This test fails to match the 'Compiling' regex; rdar://101815761 + // XCTAssertMatch(result.stdout, .regex("\\[[1-9][0-9]*\\/[1-9][0-9]*\\] Compiling")) + let lines = result.stdout.split(whereSeparator: { $0.isNewline }) + let lastLine = try #require(lines.last) + #expect(lastLine.contains(buildCompleteRegex)) + } - do { - // test second time, to stabilize the cache - try await self.execute(packagePath: fixturePath) - } + do { + // test second time, to stabilize the cache + try await self.execute(packagePath: fixturePath, buildSystem: buildSystem) + } - do { - // test third time, to make sure message is presented even when nothing to build (cached) - let result = try await execute(packagePath: fixturePath) - // This test fails to match the 'Compiling' regex; rdar://101815761 - // XCTAssertNoMatch(result.stdout, .regex("\\[[1-9][0-9]*\\/[1-9][0-9]*\\] Compiling")) - let lines = result.stdout.split(whereSeparator: { $0.isNewline }) - XCTAssertMatch(String(lines.last!), .regex("Build complete! \\([0-9]*\\.[0-9]*\\s*s(econds)?\\)")) + do { + // test third time, to make sure message is presented even when nothing to build (cached) + let result = try await execute(packagePath: fixturePath, buildSystem: buildSystem) + // This test fails to match the 'Compiling' regex; rdar://101815761 + // XCTAssertNoMatch(result.stdout, .regex("\\[[1-9][0-9]*\\/[1-9][0-9]*\\] Compiling")) + let lines = result.stdout.split(whereSeparator: { $0.isNewline }) + let lastLine = try #require(lines.last) + #expect(lastLine.contains(buildCompleteRegex)) + } } + } when: { + buildSystem == .swiftbuild && ((ProcessInfo.hostOperatingSystem == .windows)) } } - func testBuildStartMessage() async throws { + @Test( + arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases, + ) + func buildStartMessage( + buildSystem: BuildSystemProvider.Kind, + configuration: BuildConfiguration, + ) async throws { try await fixture(name: "DependencyResolution/Internal/Simple") { fixturePath in - do { - let result = try await execute(["-c", "debug"], packagePath: fixturePath) - XCTAssertMatch(result.stdout, .prefix("Building for debugging")) - } + let result = try await execute([], packagePath: fixturePath, configuration: configuration, buildSystem: buildSystem, throwIfCommandFails: false) + let expectedString: String + switch configuration { + case .debug: + expectedString = "debugging" + case .release: + expectedString = "production" - do { - let result = try await execute(["-c", "release"], packagePath: fixturePath) - XCTAssertMatch(result.stdout, .prefix("Building for production")) + } + withKnownIssue("Xcode build system does not emit the build started message.") { + #expect( + result.stdout.contains("Building for \(expectedString)"), + "expect log not emitted. got stdout: '\(result.stdout)'\n\nstderr '\(result.stderr)'") + } when: { + buildSystem == .xcode || (buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows && CiEnvironment.runningInSmokeTestPipeline) } } } - func testBuildSystemDefaultSettings() async throws { - try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in - // try await building using XCBuild with default parameters. This should succeed. We build verbosely so we get - // full command lines. - let output = try await execute(["-c", "debug", "-v"], packagePath: fixturePath) - - // In the case of the native build system check for the cross-compile target, only for macOS -#if os(macOS) - if buildSystemProvider == .native { - XCTAssertMatch( - output.stdout, - try .contains("-target \(UserToolchain.default.targetTriple.tripleString(forPlatformVersion: ""))") - ) - } -#endif - - // Look for build completion message from the particular build system - XCTAssertMatch( - output.stdout, - .contains("Build complete!") - ) - } - } + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func buildSystemDefaultSettings( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue("Sometimes failed to build due to a possible path issue", isIntermittent: true) { + try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in + // try await building using XCBuild with default parameters. This should succeed. We build verbosely so we get + // full command lines. + let output: (stdout: String, stderr: String) = try await execute( + ["-v"], + packagePath: fixturePath, + configuration: .debug, + buildSystem: buildSystem, + ) - func testXcodeBuildSystemWithAdditionalBuildFlags() async throws { - try XCTSkipIf( - true, - "Disabled for now because it is hitting 'IR generation failure: Cannot read legacy layout file' in CI (rdar://88828632)" - ) + // In the case of the native build system check for the cross-compile target, only for macOS + #if os(macOS) + if buildSystem == .native { + let targetTripleString = try UserToolchain.default.targetTriple.tripleString(forPlatformVersion: "") + #expect(output.stdout.contains("-target \(targetTripleString)")) + } + #endif - guard buildSystemProvider == .xcode || buildSystemProvider == .swiftbuild else { - throw XCTSkip("This test only works with the xcode or swift build build system") + // Look for build completion message from the particular build system + #expect(output.stdout.contains("Build complete!")) + } + } when: { + buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem == .windows } + } + @Test( + .disabled("Disabled for now because it is hitting 'IR generation failure: Cannot read legacy layout file' in CI (rdar://88828632)"), + arguments: [BuildSystemProvider.Kind.swiftbuild, .xcode], BuildConfiguration.allCases + ) + func xcodeBuildSystemWithAdditionalBuildFlags( + buildSystem: BuildSystemProvider.Kind, + configuration: BuildConfiguration + ) async throws { try await fixture(name: "ValidLayouts/SingleModule/ExecutableMixed") { fixturePath in // try await building using XCBuild with additional flags. This should succeed. We build verbosely so we get // full command lines. let defaultOutput = try await execute( [ - "-c", "debug", "-v", + "--very-verbose", "-Xlinker", "-rpath", "-Xlinker", "/fakerpath", "-Xcc", "-I/cfakepath", "-Xcxx", "-I/cxxfakepath", "-Xswiftc", "-I/swiftfakepath", ], - packagePath: fixturePath + packagePath: fixturePath, + configuration: configuration, + buildSystem: buildSystem, ).stdout // Look for certain things in the output from XCBuild. - XCTAssertMatch(defaultOutput, .contains("/fakerpath")) - XCTAssertMatch(defaultOutput, .contains("-I/cfakepath")) - XCTAssertMatch(defaultOutput, .contains("-I/cxxfakepath")) - XCTAssertMatch(defaultOutput, .contains("-I/swiftfakepath")) + #expect(defaultOutput.contains("/fakerpath")) + #expect(defaultOutput.contains("-I/cfakepath")) + #expect(defaultOutput.contains("-I/cxxfakepath")) + #expect(defaultOutput.contains("-I/swiftfakepath")) } } - func testBuildSystemOverrides() async throws { - guard buildSystemProvider == .xcode else { - throw XCTSkip("Build system overrides are only available with the xcode build system.") - } - + @Test( + .requireHostOS(.macOS), + arguments: [BuildSystemProvider.Kind.xcode], + ) + func buildSystemOverrides( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue { try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in - // try await building using XCBuild without specifying overrides. This should succeed, and should use the default + let swiftCompilerPath = try UserToolchain.default.swiftCompilerPath + // try await building without specifying overrides. This should succeed, and should use the default // compiler path. - let defaultOutput = try await execute(["-c", "debug", "--vv"], packagePath: fixturePath).stdout - XCTAssertMatch(defaultOutput, try .contains(UserToolchain.default.swiftCompilerPath.pathString)) + let defaultOutput = try await self.execute( + ["--vv"], + packagePath: fixturePath, + configuration: .debug, + buildSystem: buildSystem, + ).stdout + #expect(defaultOutput.contains(swiftCompilerPath.pathString)) - // Now try await building using XCBuild while specifying a faulty compiler override. This should fail. Note that + // Now try await building while specifying a faulty compiler override. This should fail. Note that // we need to set the executable to use for the manifest itself to the default one, since it defaults to // SWIFT_EXEC if not provided. - var overriddenOutput = "" - await XCTAssertThrowsCommandExecutionError( + let error = await #expect(throws: SwiftPMError.self ) { try await self.execute( - ["-c", "debug", "--vv"], + ["--vv"], environment: [ "SWIFT_EXEC": "/usr/bin/false", - "SWIFT_EXEC_MANIFEST": UserToolchain.default.swiftCompilerPath.pathString, + "SWIFT_EXEC_MANIFEST": swiftCompilerPath.pathString, ], - packagePath: fixturePath + packagePath: fixturePath, + configuration: .debug, + buildSystem: buildSystem, ) - ) { error in - overriddenOutput = error.stderr } - XCTAssertMatch(overriddenOutput, .contains("/usr/bin/false")) + // THEN I expect a failure + guard case SwiftPMError.executionFailure(_, _, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return + } + #expect(stderr.contains("/usr/bin/false")) + } + } when: { + buildSystem == .swiftbuild } } - func testPrintLLBuildManifestJobGraph() async throws { + @Test( + arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases + ) + func printLLBuildManifestJobGraph( + buildSystem: BuildSystemProvider.Kind, + configuration: BuildConfiguration + ) async throws { try await fixture(name: "DependencyResolution/Internal/Simple") { fixturePath in - let output = try await execute(["--print-manifest-job-graph"], packagePath: fixturePath).stdout - XCTAssertMatch(output, .prefix("digraph Jobs {")) + let output = try await execute( + ["--print-manifest-job-graph"], + packagePath: fixturePath, + configuration: configuration, + buildSystem: buildSystem, + ).stdout + #expect(output.hasPrefix("digraph Jobs {")) } } - func testSwiftDriverRawOutputGetsNewlines() async throws { - try await fixture(name: "DependencyResolution/Internal/Simple") { fixturePath in - // Building with `-wmo` should result in a `remark: Incremental compilation has been disabled: it is not - // compatible with whole module optimization` message, which should have a trailing newline. Since that - // message won't be there at all when the legacy compiler driver is used, we gate this check on whether the - // remark is there in the first place. - let result = try await execute(["-c", "release", "-Xswiftc", "-wmo"], packagePath: fixturePath) - if result.stdout.contains( - "remark: Incremental compilation has been disabled: it is not compatible with whole module optimization" - ) { - XCTAssertMatch(result.stdout, .contains("optimization\n")) - XCTAssertNoMatch(result.stdout, .contains("optimization[")) - XCTAssertNoMatch(result.stdout, .contains("optimizationremark")) + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func swiftDriverRawOutputGetsNewlines( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue("SWBINTTODO: Swift build produces an error building the fixture for this test.") { + try await fixture(name: "DependencyResolution/Internal/Simple") { fixturePath in + // Building with `-wmo` should result in a `remark: Incremental compilation has been disabled: it is not + // compatible with whole module optimization` message, which should have a trailing newline. Since that + // message won't be there at all when the legacy compiler driver is used, we gate this check on whether the + // remark is there in the first place. + let result = try await execute( + ["-Xswiftc", "-wmo"], + packagePath: fixturePath, + configuration: .release, + buildSystem: buildSystem, + ) + if result.stdout.contains( + "remark: Incremental compilation has been disabled: it is not compatible with whole module optimization" + ) { + #expect(result.stdout.contains("optimization\n")) + #expect(!result.stdout.contains("optimization[")) + #expect(!result.stdout.contains("optimizationremark")) + } } + } when: { + ProcessInfo.hostOperatingSystem != .macOS && buildSystem == .swiftbuild } } - func testSwiftGetVersion() async throws { - try XCTSkipOnWindows(because: "https://github.com/swiftlang/swift-package-manager/issues/8659, SWIFT_EXEC override is not working") + @Test( + .bug("https://github.com/swiftlang/swift-package-manager/issues/8659", "SWIFT_EXEC override is not working"), + .SWBINTTODO("Test fails because the dummy-swiftc used in the test isn't accepted by swift-build. This needs to be investigated"), + arguments: SupportedBuildSystemOnPlatform, + ) + func swiftGetVersion( + buildSystem: BuildSystemProvider.Kind, + ) async throws { try await fixture(name: "Miscellaneous/Simple") { fixturePath in func findSwiftGetVersionFile() throws -> AbsolutePath { let buildArenaPath = fixturePath.appending(components: ".build", "debug") let files = try localFileSystem.getDirectoryContents(buildArenaPath) - let filename = try XCTUnwrap(files.first { $0.hasPrefix("swift-version") }) + let filename = try #require(files.first { $0.hasPrefix("swift-version") }) return buildArenaPath.appending(component: filename) } - let dummySwiftcPath = SwiftPM.xctestBinaryPath(for: "dummy-swiftc") let swiftCompilerPath = try UserToolchain.default.swiftCompilerPath @@ -561,141 +940,248 @@ class BuildCommandTestCases: CommandsBuildProviderTestCase { "CUSTOM_SWIFT_VERSION": "1.0", ] - // Build with a swiftc that returns version 1.0, we expect a successful build which compiles our one source - // file. - do { - let result = try await execute(["--verbose"], environment: environment, packagePath: fixturePath) - XCTAssertTrue( - result.stdout.contains("\(dummySwiftcPath.pathString) -module-name"), - "compilation task missing from build result: \(result.stdout)" - ) - XCTAssertTrue(result.stdout.contains("Build complete!"), "unexpected build result: \(result.stdout)") - let swiftGetVersionFilePath = try findSwiftGetVersionFile() - XCTAssertEqual(try String(contentsOfFile: swiftGetVersionFilePath.pathString).spm_chomp(), "1.0") - } + try await withKnownIssue("https://github.com/swiftlang/swift-package-manager/issues/8659, SWIFT_EXEC override is not working"){ - // Build again with that same version, we do not expect any compilation tasks. - do { - let result = try await execute(["--verbose"], environment: environment, packagePath: fixturePath) - XCTAssertFalse( - result.stdout.contains("\(dummySwiftcPath.pathString) -module-name"), - "compilation task present in build result: \(result.stdout)" - ) - XCTAssertTrue(result.stdout.contains("Build complete!"), "unexpected build result: \(result.stdout)") - let swiftGetVersionFilePath = try findSwiftGetVersionFile() - XCTAssertEqual(try String(contentsOfFile: swiftGetVersionFilePath.pathString).spm_chomp(), "1.0") - } - - // Build again with a swiftc that returns version 2.0, we expect compilation happening once more. - do { - environment["CUSTOM_SWIFT_VERSION"] = "2.0" - let result = try await execute(["--verbose"], environment: environment, packagePath: fixturePath) - XCTAssertTrue( - result.stdout.contains("\(dummySwiftcPath.pathString) -module-name"), - "compilation task missing from build result: \(result.stdout)" - ) - XCTAssertTrue(result.stdout.contains("Build complete!"), "unexpected build result: \(result.stdout)") - let swiftGetVersionFilePath = try findSwiftGetVersionFile() - XCTAssertEqual(try String(contentsOfFile: swiftGetVersionFilePath.pathString).spm_chomp(), "2.0") - } - } - } - func testGetTaskAllowEntitlement() async throws { - try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in - #if os(macOS) - // try await building with default parameters. This should succeed. We build verbosely so we get full command - // lines. - var buildResult = try await build(["-v"], packagePath: fixturePath) + // Build with a swiftc that returns version 1.0, we expect a successful build which compiles our one source + // file. + do { + let result = try await execute(["--verbose"], environment: environment, packagePath: fixturePath, buildSystem: buildSystem) + #expect( + result.stdout.contains("\(dummySwiftcPath.pathString) -module-name"), + "compilation task missing from build result: \(result.stdout)", + ) + #expect( + result.stdout.contains("Build complete!"), + "unexpected build result: \(result.stdout)", + ) - // TODO verification of the ad-hoc code signing can be done by `swift run` of the executable in these cases once swiftbuild build system is working with that - XCTAssertMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) + let swiftGetVersionFilePath = try findSwiftGetVersionFile() + let actualVersion = try String(contentsOfFile: swiftGetVersionFilePath.pathString).spm_chomp() + #expect(actualVersion == "1.0") + } - buildResult = try await self.build(["-c", "debug", "-v"], packagePath: fixturePath) + // Build again with that same version, we do not expect any compilation tasks. + do { + let result = try await execute(["--verbose"], environment: environment, packagePath: fixturePath, buildSystem: buildSystem) + #expect( + !result.stdout.contains("\(dummySwiftcPath.pathString) -module-name"), + "compilation task present in build result: \(result.stdout)", + ) + #expect( + result.stdout.contains("Build complete!"), + "unexpected build result: \(result.stdout)", + ) - XCTAssertMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) + let swiftGetVersionFilePath = try findSwiftGetVersionFile() + let actualVersion = try String(contentsOfFile: swiftGetVersionFilePath.pathString).spm_chomp() + #expect(actualVersion == "1.0") + } - // Build with different combinations of the entitlement flag and debug/release build configurations. + // Build again with a swiftc that returns version 2.0, we expect compilation happening once more. + do { + environment["CUSTOM_SWIFT_VERSION"] = "2.0" + let result = try await execute(["--verbose"], environment: environment, packagePath: fixturePath, buildSystem: buildSystem) + #expect( + result.stdout.contains("\(dummySwiftcPath.pathString) -module-name"), + "compilation task missing from build result: \(result.stdout)", + ) + #expect( + result.stdout.contains("Build complete!"), + "unexpected build result: \(result.stdout)", + ) - buildResult = try await self.build( - ["--enable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - isRelease: true - ) + let swiftGetVersionFilePath = try findSwiftGetVersionFile() + let actualVersion = try String(contentsOfFile: swiftGetVersionFilePath.pathString).spm_chomp() + #expect(actualVersion == "2.0") + } + } when: { + (ProcessInfo.hostOperatingSystem == .windows) || ([.xcode, .swiftbuild].contains(buildSystem)) + } + } + } - XCTAssertMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) + @Test( + .SWBINTTODO("Test failed because swiftbuild doesn't output precis codesign commands. Once swift run works with swiftbuild the test can be investigated."), + arguments: SupportedBuildSystemOnPlatform, + ) + func getTaskAllowEntitlement( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue { + try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in + #if os(macOS) + // try await building with default parameters. This should succeed. We build verbosely so we get full command + // lines. + var buildResult = try await build(["-v"], packagePath: fixturePath, buildSystem: buildSystem,) + + // TODO verification of the ad-hoc code signing can be done by `swift run` of the executable in these cases once swiftbuild build system is working with that + #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) + + buildResult = try await self.build(["-v"], packagePath: fixturePath, configuration:.debug, buildSystem: buildSystem,) + + #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) + + // Build with different combinations of the entitlement flag and debug/release build configurations. + + buildResult = try await self.build( + ["--enable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .release, + buildSystem: buildSystem, + ) - buildResult = try await self.build( - ["-c", "debug", "--enable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath - ) + #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) - XCTAssertMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) + buildResult = try await self.build( + ["--enable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .debug, + buildSystem: buildSystem, + ) - buildResult = try await self.build( - ["-c", "debug", "--disable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath - ) + #expect(buildResult.stdout.contains("codesign --force --sign - --entitlements")) - XCTAssertNoMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) + buildResult = try await self.build( + ["--disable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .debug, + buildSystem: buildSystem, + ) - buildResult = try await self.build( - ["--disable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - isRelease: true - ) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) - XCTAssertNoMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) - #else - var buildResult = try await self.build(["-v"], packagePath: fixturePath) + buildResult = try await self.build( + ["--disable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .release, + buildSystem: buildSystem, + ) - XCTAssertNoMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #else + var buildResult = try await self.build(["-v"], packagePath: fixturePath, buildSystem: buildSystem,) - buildResult = try await self.build(["-v"], packagePath: fixturePath, isRelease: true) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) - XCTAssertNoMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) + buildResult = try await self.build(["-v"], packagePath: fixturePath, configuration: .release,buildSystem: buildSystem,) - buildResult = try await self.build( - ["--disable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - isRelease: true - ) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) - XCTAssertNoMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) - XCTAssertMatch(buildResult.stderr, .contains(SwiftCommandState.entitlementsMacOSWarning)) + buildResult = try await self.build( + ["--disable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .release, + buildSystem: buildSystem, + ) - buildResult = try await self.build( - ["--enable-get-task-allow-entitlement", "-v"], - packagePath: fixturePath, - isRelease: true - ) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning)) + + buildResult = try await self.build( + ["--enable-get-task-allow-entitlement", "-v"], + packagePath: fixturePath, + configuration: .release, + buildSystem: buildSystem, + ) - XCTAssertNoMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) - XCTAssertMatch(buildResult.stderr, .contains(SwiftCommandState.entitlementsMacOSWarning)) - #endif + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + #expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning)) + #endif - buildResult = try await self.build(["-c", "release", "-v"], packagePath: fixturePath, isRelease: true) + buildResult = try await self.build(["-v"], packagePath: fixturePath, configuration: .release, buildSystem: buildSystem) - XCTAssertNoMatch(buildResult.stdout, .contains("codesign --force --sign - --entitlements")) + #expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements")) + } + } when: { + [.swiftbuild, .xcode].contains(buildSystem) } } -#if os(Linux) - func testIgnoresLinuxMain() async throws { - try await fixture(name: "Miscellaneous/TestDiscovery/IgnoresLinuxMain") { fixturePath in - let buildResult = try await self.build(["-v", "--build-tests", "--enable-test-discovery"], packagePath: fixturePath, cleanAfterward: false) - let testBinaryPath = buildResult.binPath.appending("IgnoresLinuxMainPackageTests.xctest") + @Test( + .requireHostOS(.linux), + .SWBINTTODO("Swift build doesn't currently ignore Linux main when linking on Linux. This needs further investigation."), + arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases, + ) + func ignoresLinuxMain( + buildSystem: BuildSystemProvider.Kind, + configuration: BuildConfiguration, + ) async throws { + try await withKnownIssue { + try await fixture(name: "Miscellaneous/TestDiscovery/IgnoresLinuxMain") { fixturePath in + let buildResult = try await self.build( + ["-v", "--build-tests", "--enable-test-discovery"], + packagePath: fixturePath, + configuration: configuration, + cleanAfterward: false, + buildSystem: buildSystem, + ) + let testBinaryPath = buildResult.binPath.appending("IgnoresLinuxMainPackageTests.xctest") + + _ = try await AsyncProcess.checkNonZeroExit(arguments: [testBinaryPath.pathString]) + } + } when: { + buildSystem == .swiftbuild + } + } - _ = try await AsyncProcess.checkNonZeroExit(arguments: [testBinaryPath.pathString]) + + @Test( + .SWBINTTODO("Test failed because of missing plugin support in the PIF builder. This can be reinvestigated after the support is there."), + .tags( + Tag.Feature.CodeCoverage, + Tag.Feature.Command.Test, + ), + arguments: SupportedBuildSystemOnPlatform, + ) + func executingTestsWithCoverageWithoutCodeBuiltWithCoverageGeneratesAFailure( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + try await withKnownIssue(isIntermittent: (ProcessInfo.hostOperatingSystem == .linux && buildSystem == .swiftbuild)) { + try await fixture(name: "Miscellaneous/TestDiscovery/Simple") { path in + _ = try await self.build( + ["--build-tests"], + packagePath: path, + cleanAfterward: false, + buildSystem: buildSystem, + ) + await #expect(throws: (any Error).self ) { + try await executeSwiftTest( + path, + extraArgs: [ + "--skip-build", + "--enable-code-coverage", + ], + throwIfCommandFails: true, + buildSystem: buildSystem, + ) + } + } + } when: { + buildSystem == .xcode || (buildSystem == .swiftbuild && [.linux, .windows].contains(ProcessInfo.hostOperatingSystem)) } } -#endif - func testCodeCoverage() async throws { - // Test that no codecov directory is created if not specified when building. - try await fixture(name: "Miscellaneous/TestDiscovery/Simple") { path in - _ = try await self.build(["--build-tests"], packagePath: path, cleanAfterward: false) - await XCTAssertAsyncThrowsError( + @Test( + .SWBINTTODO("Test failed because of missing plugin support in the PIF builder. This can be reinvestigated after the support is there."), + .tags( + Tag.Feature.CodeCoverage, + Tag.Feature.Command.Test, + ), + arguments: SupportedBuildSystemOnPlatform, + ) + func executingTestsWithCoverageWithCodeBuiltWithCoverageGeneratesCodecove( + buildSystem: BuildSystemProvider.Kind, + ) async throws { + // Test that enabling code coverage during building produces the expected folder. + try await withKnownIssue { + try await fixture(name: "Miscellaneous/TestDiscovery/Simple") { path in + let buildResult = try await self.build( + ["--build-tests", "--enable-code-coverage"], + packagePath: path, + cleanAfterward: false, + buildSystem: buildSystem, + ) try await executeSwiftTest( path, extraArgs: [ @@ -703,249 +1189,49 @@ class BuildCommandTestCases: CommandsBuildProviderTestCase { "--enable-code-coverage", ], throwIfCommandFails: true, - buildSystem: buildSystemProvider + buildSystem: buildSystem, ) - ) - } - - // Test that enabling code coverage during building produces the expected folder. - try await fixture(name: "Miscellaneous/TestDiscovery/Simple") { path in - let buildResult = try await self.build(["--build-tests", "--enable-code-coverage"], packagePath: path, cleanAfterward: false) - try await executeSwiftTest( - path, - extraArgs: [ - "--skip-build", - "--enable-code-coverage", - ], - throwIfCommandFails: true, - buildSystem: buildSystemProvider - ) - let codeCovPath = buildResult.binPath.appending("codecov") - let codeCovFiles = try localFileSystem.getDirectoryContents(codeCovPath) - XCTAssertGreaterThan(codeCovFiles.count, 0) + let codeCovPath = buildResult.binPath.appending("codecov") + let codeCovFiles = try localFileSystem.getDirectoryContents(codeCovPath) + #expect(codeCovFiles.count > 0) + } + } when: { + [.swiftbuild, .xcode].contains(buildSystem) } } - func testFatalErrorDisplayedCorrectNumberOfTimesWhenSingleXCTestHasFatalErrorInBuildCompilation() async throws { + @Test( + arguments: SupportedBuildSystemOnPlatform, + ) + func fatalErrorDisplayedCorrectNumberOfTimesWhenSingleXCTestHasFatalErrorInBuildCompilation( + buildSystem: BuildSystemProvider.Kind, + ) async throws { let expected = 0 try await fixture(name: "Miscellaneous/Errors/FatalErrorInSingleXCTest/TypeLibrary") { fixturePath in // WHEN swift-build --build-tests is executed" - await XCTAssertAsyncThrowsError(try await self.execute(["--build-tests"], packagePath: fixturePath)) { error in - // THEN I expect a failure - guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = error else { - XCTFail("Building the package was expected to fail, but it was successful") - return - } - - let matchString = "error: fatalError" - let stdoutMatches = getNumberOfMatches(of: matchString, in: stdout) - let stderrMatches = getNumberOfMatches(of: matchString, in: stderr) - let actualNumMatches = stdoutMatches + stderrMatches - - // AND a fatal error message is printed \(expected) times - XCTAssertEqual( - actualNumMatches, - expected, - [ - "Actual (\(actualNumMatches)) is not as expected (\(expected))", - "stdout: \(stdout.debugDescription)", - "stderr: \(stderr.debugDescription)" - ].joined(separator: "\n") + let error = await #expect(throws: SwiftPMError.self ) { + try await self.execute( + ["--build-tests"], + packagePath: fixturePath,buildSystem: buildSystem, ) } - } - } - -} - - -class BuildCommandNativeTests: BuildCommandTestCases { - - override open var buildSystemProvider: BuildSystemProvider.Kind { - return .native - } + // THEN I expect a failure + guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = try #require(error) else { + Issue.record("Incorrect error was raised.") + return + } - override func testUsage() async throws { - try await super.testUsage() - } + let matchString = "error: fatalError" + let stdoutMatches = getNumberOfMatches(of: matchString, in: stdout) + let stderrMatches = getNumberOfMatches(of: matchString, in: stderr) + let actualNumMatches = stdoutMatches + stderrMatches - override func testBinSymlink() async throws { - try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in - let fullPath = try resolveSymlinks(fixturePath) - let targetPath = try fullPath.appending( - components: ".build", - UserToolchain.default.targetTriple.platformBuildPathComponent - ) - let debugPath = try await self.execute(["--show-bin-path"], packagePath: fullPath).stdout.trimmingCharacters(in: .whitespacesAndNewlines) - XCTAssertEqual(AbsolutePath(debugPath).pathString, targetPath.appending("debug").pathString) - let releasePath = try await self.execute(["-c", "release", "--show-bin-path"], packagePath: fullPath).stdout.trimmingCharacters(in: .whitespacesAndNewlines) - XCTAssertEqual(AbsolutePath(releasePath).pathString, targetPath.appending("release").pathString) + // AND a fatal error message is printed \(expected) times + #expect(actualNumMatches == expected) } } -} - -#if os(macOS) -// Xcode build system tests can only function on macOS -class BuildCommandXcodeTests: BuildCommandTestCases { - override open var buildSystemProvider: BuildSystemProvider.Kind { - return .xcode - } - - override func testUsage() async throws { - try await super.testUsage() - } - - override func testAutomaticParseableInterfacesWithLibraryEvolution() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testNonReachableProductsAndTargetsFunctional() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testCodeCoverage() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - override func testBuildStartMessage() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testBinSymlink() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testSymlink() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testSwiftGetVersion() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testParseableInterfaces() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testProductAndTarget() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testImportOfMissedDepWarning() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testGetTaskAllowEntitlement() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } - - override func testBuildCompleteMessage() async throws { - throw XCTSkip("Test not implemented for xcode build system.") - } } -#endif - -class BuildCommandSwiftBuildTests: BuildCommandTestCases { - - override open var buildSystemProvider: BuildSystemProvider.Kind { - return .swiftbuild - } - - override func testNonReachableProductsAndTargetsFunctional() async throws { - throw XCTSkip("SWBINTTODO: Test failed. This needs to be investigated") - } - - override func testParseableInterfaces() async throws { - try XCTSkipOnWindows(because: "possible long filename issue: needs investigation") - - try await fixture(name: "Miscellaneous/ParseableInterfaces") { fixturePath in - do { - let result = try await build(["--enable-parseable-module-interfaces"], packagePath: fixturePath) - XCTAssertMatch(result.moduleContents, [.regex(#"A[.]swiftmodule[/].*[.]swiftinterface"#)]) - XCTAssertMatch(result.moduleContents, [.regex(#"B[.]swiftmodule[/].*[.]swiftmodule"#)]) - } catch SwiftPMError.executionFailure(_, _, let stderr) { - XCTFail(stderr) - } - } - } - - override func testAutomaticParseableInterfacesWithLibraryEvolution() async throws { - throw XCTSkip("SWBINTTODO: Test failed because of missing 'A.swiftmodule/*.swiftinterface' files") - // TODO: We still need to override this test just like we did for `testParseableInterfaces` above. - } - - override func testBinSymlink() async throws { - try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in - let fullPath = try resolveSymlinks(fixturePath) - let targetPath = try fullPath.appending( - components: ".build", - UserToolchain.default.targetTriple.platformBuildPathComponent - ) - let debugPath = try await self.execute(["--show-bin-path"], packagePath: fullPath).stdout - XCTAssertMatch(AbsolutePath(debugPath).pathString, .regex(targetPath.appending(components: "Products", "Debug").escapedPathString + "(\\-linux|\\-Windows)?")) - let releasePath = try await self.execute(["-c", "release", "--show-bin-path"], packagePath: fullPath).stdout - XCTAssertMatch(AbsolutePath(releasePath).pathString, .regex(targetPath.appending(components: "Products", "Release").escapedPathString + "(\\-linux|\\-Windows)?")) - } - } - - override func testGetTaskAllowEntitlement() async throws { - throw XCTSkip("SWBINTTODO: Test failed because swiftbuild doesn't output precis codesign commands. Once swift run works with swiftbuild the test can be investigated.") - } - override func testCodeCoverage() async throws { - throw XCTSkip("SWBINTTODO: Test failed because of missing plugin support in the PIF builder. This can be reinvestigated after the support is there.") - } - override func testAtMainSupport() async throws { - #if !os(macOS) - throw XCTSkip("SWBINTTODO: File not found or missing libclang errors on non-macOS platforms. This needs to be investigated") - #else - try await super.testAtMainSupport() - #endif - } - - override func testImportOfMissedDepWarning() async throws { - throw XCTSkip("SWBINTTODO: Test fails because the warning message regarding missing imports is expected to be more verbose and actionable at the SwiftPM level with mention of the involved targets. This needs to be investigated. See case targetDiagnostic(TargetDiagnosticInfo) as a message type that may help.") - } - - override func testProductAndTarget() async throws { - throw XCTSkip("SWBINTTODO: Test fails because there isn't a clear warning message about the lib1 being an automatic product and that the default product is being built instead. This needs to be investigated") - } - override func testSwiftGetVersion() async throws { - throw XCTSkip("SWBINTTODO: Test fails because the dummy-swiftc used in the test isn't accepted by swift-build. This needs to be investigated") - } - - override func testSymlink() async throws { - throw XCTSkip("SWBINTTODO: Test fails because of a difference in the build layout. This needs to be updated to the expected path") - } - -#if os(Linux) - override func testIgnoresLinuxMain() async throws { - throw XCTSkip("SWBINTTODO: Swift build doesn't currently ignore Linux main when linking on Linux. This needs further investigation.") - } -#endif - -#if !os(macOS) - override func testBuildStartMessage() async throws { - throw XCTSkip("SWBINTTODO: Swift build produces an error building the fixture for this test.") - } - - override func testSwiftDriverRawOutputGetsNewlines() async throws { - throw XCTSkip("SWBINTTODO: Swift build produces an error building the fixture for this test.") - } -#endif - - override func testBuildSystemDefaultSettings() async throws { - try XCTSkipOnWindows(because: "possible long filename issue: needs investigation") - - try await super.testBuildSystemDefaultSettings() - } - - override func testBuildCompleteMessage() async throws { - try XCTSkipOnWindows(because: "possible long filename issue: needs investigation") - - try await super.testBuildCompleteMessage() - } - -} diff --git a/Tests/FunctionalTests/MacroTests.swift b/Tests/FunctionalTests/MacroTests.swift index ad394a48ad8..edd50144902 100644 --- a/Tests/FunctionalTests/MacroTests.swift +++ b/Tests/FunctionalTests/MacroTests.swift @@ -26,7 +26,7 @@ class MacroTests: XCTestCase { try XCTSkipIf(!localFileSystem.exists(libSwiftSyntaxMacrosPath), "test need `libSwiftSyntaxMacros` to exist in the host toolchain") try fixture(name: "Macros") { fixturePath in - let (stdout, _) = try executeSwiftBuild(fixturePath.appending("MacroPackage"), configuration: .Debug) + let (stdout, _) = try executeSwiftBuild(fixturePath.appending("MacroPackage"), configuration: .debug) XCTAssert(stdout.contains("@__swiftmacro_11MacroClient11fontLiteralfMf_.swift as Font"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } diff --git a/Tests/FunctionalTests/PluginTests.swift b/Tests/FunctionalTests/PluginTests.swift index ccb7fe4853b..074d096baf9 100644 --- a/Tests/FunctionalTests/PluginTests.swift +++ b/Tests/FunctionalTests/PluginTests.swift @@ -29,7 +29,7 @@ final class PluginTests: XCTestCase { try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .Debug, extraArgs: ["--product", "MyLocalTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .debug, extraArgs: ["--product", "MyLocalTool"]) XCTAssert(stdout.contains("Linking MySourceGenBuildTool"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Generating foo.swift from foo.dat"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Linking MyLocalTool"), "stdout:\n\(stdout)") @@ -39,7 +39,7 @@ final class PluginTests: XCTestCase { #if os(macOS) // See https://github.com/swiftlang/swift-package-manager/issues/8416 for errors running build tools on Linux // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .Debug, extraArgs: ["--product", "MyLocalTool", "--build-system", "swiftbuild"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .debug, extraArgs: ["--product", "MyLocalTool", "--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } #endif @@ -63,7 +63,7 @@ final class PluginTests: XCTestCase { try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenClient"), configuration: .Debug, extraArgs: ["--product", "MyTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenClient"), configuration: .debug, extraArgs: ["--product", "MyTool"]) XCTAssert(stdout.contains("Linking MySourceGenBuildTool"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Generating foo.swift from foo.dat"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Linking MyTool"), "stdout:\n\(stdout)") @@ -73,7 +73,7 @@ final class PluginTests: XCTestCase { #if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenClient"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenClient"), configuration: .debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyTool"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } #endif @@ -85,7 +85,7 @@ final class PluginTests: XCTestCase { try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .Debug, extraArgs: ["--product", "MyOtherLocalTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .debug, extraArgs: ["--product", "MyOtherLocalTool"]) XCTAssert(stdout.contains("Compiling MyOtherLocalTool bar.swift"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Compiling MyOtherLocalTool baz.swift"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Linking MyOtherLocalTool"), "stdout:\n\(stdout)") @@ -94,7 +94,7 @@ final class PluginTests: XCTestCase { #if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyOtherLocalTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MySourceGenPlugin"), configuration: .debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyOtherLocalTool"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } #endif @@ -195,7 +195,7 @@ final class PluginTests: XCTestCase { try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ContrivedTestPlugin"), configuration: .Debug, extraArgs: ["--product", "MyLocalTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ContrivedTestPlugin"), configuration: .debug, extraArgs: ["--product", "MyLocalTool"]) XCTAssert(stdout.contains("Linking MySourceGenBuildTool"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Generating foo.swift from foo.dat"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Linking MyLocalTool"), "stdout:\n\(stdout)") @@ -204,7 +204,7 @@ final class PluginTests: XCTestCase { #if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ContrivedTestPlugin"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyLocalTool", "--disable-sandbox"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("ContrivedTestPlugin"), configuration: .debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyLocalTool", "--disable-sandbox"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } #endif @@ -217,14 +217,14 @@ final class PluginTests: XCTestCase { // Only run the test if the environment in which we're running actually supports Swift concurrency (which the plugin APIs require). try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("SandboxTesterPlugin"), configuration: .Debug, extraArgs: ["--product", "MyLocalTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("SandboxTesterPlugin"), configuration: .debug, extraArgs: ["--product", "MyLocalTool"]) XCTAssert(stdout.contains("Linking MyLocalTool"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Build of product 'MyLocalTool' complete!"), "stdout:\n\(stdout)") } // Try again with Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("SandboxTesterPlugin"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyLocalTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("SandboxTesterPlugin"), configuration: .debug, extraArgs: ["--build-system", "swiftbuild", "--product", "MyLocalTool"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } } @@ -236,7 +236,7 @@ final class PluginTests: XCTestCase { // Only run the test if the environment in which we're running actually supports Swift concurrency (which the plugin APIs require). try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MyBinaryToolPlugin"), configuration: .Debug, extraArgs: ["--product", "MyLocalTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("MyBinaryToolPlugin"), configuration: .debug, extraArgs: ["--product", "MyLocalTool"]) XCTAssert(stdout.contains("Linking MyLocalTool"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Build of product 'MyLocalTool' complete!"), "stdout:\n\(stdout)") } @@ -249,7 +249,7 @@ final class PluginTests: XCTestCase { // Only run the test if the environment in which we're running actually supports Swift concurrency (which the plugin APIs require). try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("BinaryToolProductPlugin"), configuration: .Debug, extraArgs: ["--product", "MyLocalTool"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath.appending("BinaryToolProductPlugin"), configuration: .debug, extraArgs: ["--product", "MyLocalTool"]) XCTAssert(stdout.contains("Linking MyLocalTool"), "stdout:\n\(stdout)") XCTAssert(stdout.contains("Build of product 'MyLocalTool' complete!"), "stdout:\n\(stdout)") } @@ -685,7 +685,7 @@ final class PluginTests: XCTestCase { try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins/PluginUsingLocalAndRemoteTool") { path in - let (stdout, stderr) = try await executeSwiftPackage(path.appending("MyLibrary"), configuration: .Debug, extraArgs: ["plugin", "my-plugin"]) + let (stdout, stderr) = try await executeSwiftPackage(path.appending("MyLibrary"), configuration: .debug, extraArgs: ["plugin", "my-plugin"]) XCTAssert(stderr.contains("Linking RemoteTool"), "stdout:\n\(stderr)\n\(stdout)") XCTAssert(stderr.contains("Linking LocalTool"), "stdout:\n\(stderr)\n\(stdout)") XCTAssert(stderr.contains("Linking ImpliedLocalTool"), "stdout:\n\(stderr)\n\(stdout)") @@ -1152,14 +1152,14 @@ final class PluginTests: XCTestCase { try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins") { path in - let (stdout, stderr) = try await executeSwiftPackage(path.appending("PluginsAndSnippets"), configuration: .Debug, extraArgs: ["do-something"]) + let (stdout, stderr) = try await executeSwiftPackage(path.appending("PluginsAndSnippets"), configuration: .debug, extraArgs: ["do-something"]) XCTAssert(stdout.contains("type of snippet target: snippet"), "output:\n\(stderr)\n\(stdout)") } #if !os(Windows) // https://github.com/swiftlang/swift-package-manager/issues/8774 // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins") { path in - let (stdout, stderr) = try await executeSwiftPackage(path.appending("PluginsAndSnippets"), configuration: .Debug, extraArgs: ["--build-system", "swiftbuild", "do-something"]) + let (stdout, stderr) = try await executeSwiftPackage(path.appending("PluginsAndSnippets"), configuration: .debug, extraArgs: ["--build-system", "swiftbuild", "do-something"]) XCTAssert(stdout.contains("type of snippet target: snippet"), "output:\n\(stderr)\n\(stdout)") } #endif @@ -1193,14 +1193,14 @@ final class PluginTests: XCTestCase { for buildSystem in ["native"] { // FIXME: enable swiftbuild testing once pre-build plugins are working // Check that the build fails with a sandbox violation by default. try await fixture(name: "Miscellaneous/Plugins/SandboxViolatingBuildToolPluginCommands") { path in - await XCTAssertAsyncThrowsError(try await executeSwiftBuild(path.appending("MyLibrary"), configuration: .Debug, extraArgs: ["--build-system", buildSystem])) { error in + await XCTAssertAsyncThrowsError(try await executeSwiftBuild(path.appending("MyLibrary"), configuration: .debug, extraArgs: ["--build-system", buildSystem])) { error in XCTAssertMatch("\(error)", .contains("You don’t have permission to save the file “generated” in the folder “MyLibrary”.")) } } // Check that the build succeeds if we disable the sandbox. try await fixture(name: "Miscellaneous/Plugins/SandboxViolatingBuildToolPluginCommands") { path in - let (stdout, stderr) = try await executeSwiftBuild(path.appending("MyLibrary"), configuration: .Debug, extraArgs: ["--build-system", buildSystem, "--disable-sandbox"]) + let (stdout, stderr) = try await executeSwiftBuild(path.appending("MyLibrary"), configuration: .debug, extraArgs: ["--build-system", buildSystem, "--disable-sandbox"]) XCTAssert(stdout.contains("Compiling MyLibrary foo.swift"), "[STDOUT]\n\(stdout)\n[STDERR]\n\(stderr)\n") } } @@ -1281,7 +1281,7 @@ final class PluginTests: XCTestCase { try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, _) = try await executeSwiftBuild( fixturePath.appending(component: "MySourceGenPlugin"), - configuration: .Debug, + configuration: .debug, extraArgs: ["--product", "MyLocalTool", "-Xbuild-tools-swiftc", "-DUSE_CREATE"] ) XCTAssert(stdout.contains("Linking MySourceGenBuildTool"), "stdout:\n\(stdout)") @@ -1294,7 +1294,7 @@ final class PluginTests: XCTestCase { try await fixture(name: "Miscellaneous/Plugins") { fixturePath in let (stdout, stderr) = try await executeSwiftBuild( fixturePath.appending(component: "MySourceGenPlugin"), - configuration: .Debug, + configuration: .debug, extraArgs: ["-v", "--product", "MyLocalTool", "-Xbuild-tools-swiftc", "-DUSE_CREATE", "--build-system", "swiftbuild"] ) XCTAssert(stdout.contains("MySourceGenBuildTool-product"), "stdout:\n\(stdout)\nstderr:\n\(stderr)") @@ -1310,13 +1310,13 @@ final class PluginTests: XCTestCase { try XCTSkipIf(!UserToolchain.default.supportsSwiftConcurrency(), "skipping because test environment doesn't support concurrency") try await fixture(name: "Miscellaneous/Plugins/MySourceGenPluginUsingURLBasedAPI") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath, configuration: .Debug) + let (stdout, _) = try await executeSwiftBuild(fixturePath, configuration: .debug) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } #if os(macOS) // Try again with the Swift Build build system try await fixture(name: "Miscellaneous/Plugins/MySourceGenPluginUsingURLBasedAPI") { fixturePath in - let (stdout, _) = try await executeSwiftBuild(fixturePath, configuration: .Debug, extraArgs: ["--build-system", "swiftbuild"]) + let (stdout, _) = try await executeSwiftBuild(fixturePath, configuration: .debug, extraArgs: ["--build-system", "swiftbuild"]) XCTAssert(stdout.contains("Build complete!"), "stdout:\n\(stdout)") } #endif diff --git a/Tests/FunctionalTests/ResourcesTests.swift b/Tests/FunctionalTests/ResourcesTests.swift index 1e505447c3e..5f21b2e8387 100644 --- a/Tests/FunctionalTests/ResourcesTests.swift +++ b/Tests/FunctionalTests/ResourcesTests.swift @@ -77,12 +77,12 @@ final class ResourcesTests: XCTestCase { #endif let binPath = try AbsolutePath(validating: - await executeSwiftBuild(fixturePath, configuration: .Release, extraArgs: ["--show-bin-path"]).stdout + await executeSwiftBuild(fixturePath, configuration: .release, extraArgs: ["--show-bin-path"]).stdout .trimmingCharacters(in: .whitespacesAndNewlines) ) for execName in executables { - _ = try await executeSwiftBuild(fixturePath, configuration: .Release, extraArgs: ["--product", execName]) + _ = try await executeSwiftBuild(fixturePath, configuration: .release, extraArgs: ["--product", execName]) try await withTemporaryDirectory(prefix: execName) { tmpDirPath in defer { diff --git a/Tests/PackageModelSyntaxTests/ManifestEditTests.swift b/Tests/PackageModelSyntaxTests/ManifestEditTests.swift index 9f2989ef82e..e690deb4daf 100644 --- a/Tests/PackageModelSyntaxTests/ManifestEditTests.swift +++ b/Tests/PackageModelSyntaxTests/ManifestEditTests.swift @@ -100,6 +100,10 @@ class ManifestEditTests: XCTestCase { } func testAddPackageDependencyExistingNoComma() throws { + try XCTSkipOnWindows( + because: "Test appears to hang", + skipPlatformCi: true, + ) try assertManifestRefactor(""" // swift-tools-version: 5.5 let package = Package( diff --git a/Tests/SourceControlTests/GitRepositoryProviderTests.swift b/Tests/SourceControlTests/GitRepositoryProviderTests.swift index cbc86a38f7f..f9960dbc8f7 100644 --- a/Tests/SourceControlTests/GitRepositoryProviderTests.swift +++ b/Tests/SourceControlTests/GitRepositoryProviderTests.swift @@ -19,7 +19,7 @@ import Testing struct GitRepositoryProviderTests { @Test( .bug("https://github.com/swiftlang/swift-package-manager/issues/8564"), - .disabled(if: isSelfHostedCiEnvironment && ProcessInfo.hostOperatingSystem == .windows), + .disabled(if: CiEnvironment.runningInSelfHostedPipeline && ProcessInfo.hostOperatingSystem == .windows), ) func isValidDirectory() throws { try testWithTemporaryDirectory { sandbox in @@ -52,7 +52,7 @@ struct GitRepositoryProviderTests { @Test( .bug("https://github.com/swiftlang/swift-package-manager/issues/8564"), - .disabled(if: isSelfHostedCiEnvironment && ProcessInfo.hostOperatingSystem == .windows), + .disabled(if: CiEnvironment.runningInSelfHostedPipeline && ProcessInfo.hostOperatingSystem == .windows), ) func isValidDirectoryThrowsPrintableError() throws { try testWithTemporaryDirectory { temp in @@ -70,7 +70,7 @@ struct GitRepositoryProviderTests { @Test( .bug("https://github.com/swiftlang/swift-package-manager/issues/8564"), - .disabled(if: isSelfHostedCiEnvironment && ProcessInfo.hostOperatingSystem == .windows), + .disabled(if: CiEnvironment.runningInSelfHostedPipeline && ProcessInfo.hostOperatingSystem == .windows), ) func gitShellErrorIsPrintable() throws { let stdOut = "An error from Git - stdout" @@ -99,7 +99,7 @@ struct GitRepositoryProviderTests { @Test( .bug("https://github.com/swiftlang/swift-package-manager/issues/8564"), - .disabled(if: isSelfHostedCiEnvironment && ProcessInfo.hostOperatingSystem == .windows), + .disabled(if: CiEnvironment.runningInSelfHostedPipeline && ProcessInfo.hostOperatingSystem == .windows), ) func gitShellErrorEmptyStdOut() throws { let stdErr = "An error from Git - stderr" @@ -119,7 +119,7 @@ struct GitRepositoryProviderTests { @Test( .bug("https://github.com/swiftlang/swift-package-manager/issues/8564"), - .disabled(if: isSelfHostedCiEnvironment && ProcessInfo.hostOperatingSystem == .windows), + .disabled(if: CiEnvironment.runningInSelfHostedPipeline && ProcessInfo.hostOperatingSystem == .windows), ) func gitShellErrorEmptyStdErr() throws { let stdOut = "An error from Git - stdout"