diff --git a/Package.swift b/Package.swift index d641b133ea6..ac0af785b98 100644 --- a/Package.swift +++ b/Package.swift @@ -815,11 +815,17 @@ let package = Package( "Archiver/Inputs/invalid_archive.tar.gz", "Archiver/Inputs/invalid_archive.zip", "processInputs/long-stdout-stderr", + "processInputs/long-stdout-stderr.bat", "processInputs/exit4", + "processInputs/exit4.bat", "processInputs/simple-stdout-stderr", + "processInputs/simple-stdout-stderr.bat", "processInputs/deadlock-if-blocking-io", + "processInputs/deadlock-if-blocking-io.bat", "processInputs/echo", + "processInputs/echo.bat", "processInputs/in-to-out", + "processInputs/in-to-out.bat", ] ), .testTarget( diff --git a/Sources/Basics/Concurrency/AsyncProcess.swift b/Sources/Basics/Concurrency/AsyncProcess.swift index 9868b5a1324..8b6c86b42dc 100644 --- a/Sources/Basics/Concurrency/AsyncProcess.swift +++ b/Sources/Basics/Concurrency/AsyncProcess.swift @@ -387,6 +387,20 @@ package final class AsyncProcess { self.loggingHandler = loggingHandler ?? AsyncProcess.loggingHandler } + package convenience init( + args: [String], + environment: Environment = .current, + outputRedirection: OutputRedirection = .collect, + loggingHandler: LoggingHandler? = .none + ) { + self.init( + arguments: args, + environment: environment, + outputRedirection: outputRedirection, + loggingHandler: loggingHandler + ) + } + package convenience init( args: String..., environment: Environment = .current, diff --git a/Sources/Commands/SwiftRunCommand.swift b/Sources/Commands/SwiftRunCommand.swift index 21c455edd55..ff8db0d3a94 100644 --- a/Sources/Commands/SwiftRunCommand.swift +++ b/Sources/Commands/SwiftRunCommand.swift @@ -274,7 +274,8 @@ public struct SwiftRunCommand: AsyncSwiftCommand { // If the executable is implicit, search through root products. let rootExecutables = graph.rootPackages .flatMap { $0.products } - .filter { $0.type == .executable || $0.type == .snippet } + // The type checker slows down significantly when ProductTypes arent explicitly typed. + .filter { $0.type == ProductType.executable || $0.type == ProductType.snippet } .map { $0.name } // Error out if the package contains no executables. diff --git a/Sources/PackageDescription/PackageDependency.swift b/Sources/PackageDescription/PackageDependency.swift index 594736e558c..dd654c5b37a 100644 --- a/Sources/PackageDescription/PackageDependency.swift +++ b/Sources/PackageDescription/PackageDependency.swift @@ -511,7 +511,6 @@ extension Package.Dependency { /// ``` /// /// - Parameters: - /// - name: The name of the package, or nil to deduce it from the URL. /// - url: The valid Git URL of the package. /// - range: The custom version range requirement. /// @@ -534,7 +533,6 @@ extension Package.Dependency { /// ``` /// /// - Parameters: - /// - name: The name of the package, or nil to deduce it from the URL. /// - url: The valid Git URL of the package. /// - range: The custom version range requirement. /// - traits: The trait configuration of this dependency. Defaults to enabling the default traits. @@ -585,7 +583,6 @@ extension Package.Dependency { /// ``` /// /// - Parameters: - /// - name: The name of the package, or `nil` to deduce it from the URL. /// - url: The valid Git URL of the package. /// - range: The closed version range requirement. /// @@ -608,7 +605,6 @@ extension Package.Dependency { /// ``` /// /// - Parameters: - /// - name: The name of the package, or `nil` to deduce it from the URL. /// - url: The valid Git URL of the package. /// - range: The closed version range requirement. /// - traits: The trait configuration of this dependency. Defaults to enabling the default traits. @@ -788,7 +784,6 @@ extension Package.Dependency { /// Adds a remote package dependency given a version requirement. /// /// - Parameters: - /// - name: The name of the package, or nil to deduce it from the URL. /// - url: The valid Git URL of the package. /// - requirement: A dependency requirement. See static methods on `Package.Dependency.Requirement` for available options. /// diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/BuildSettingCondition.md b/Sources/PackageDescription/PackageDescription.docc/Curation/BuildSettingCondition.md index 6b0ad810888..ffc550fe605 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/BuildSettingCondition.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/BuildSettingCondition.md @@ -6,5 +6,6 @@ - ``when(platforms:)`` - ``when(configuration:)`` -- ``when(platforms:configuration:)-2991l`` - ``when(platforms:configuration:)-475co`` +- ``when(platforms:configuration:traits:)`` +- ``when(platforms:configuration:)-2991l`` diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Dependency.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Dependency.md index 95c3faa2ab4..f3f06defc8a 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Dependency.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Dependency.md @@ -5,20 +5,52 @@ ### Creating a Package Dependency - ``package(name:path:)`` +- ``package(name:path:traits:)`` +- ``package(path:)`` +- ``package(path:traits:)`` - ``package(url:from:)`` - ``package(url:_:)-2ys47`` - ``package(url:_:)-1r6rc`` - ``package(url:branch:)`` - ``package(url:revision:)`` - ``package(url:exact:)`` -- ``package(path:)`` +- ``package(url:exact:traits:)`` +- ``package(url:_:traits:)-(_,Range,_)`` +- ``package(url:_:traits:)-(_,ClosedRange,_)`` +- ``package(url:branch:traits:)`` +- ``package(url:from:traits:)`` +- ``package(url:revision:traits:)`` +- ``package(id:_:)-(_,Range)`` +- ``package(id:_:)-(_,ClosedRange)`` +- ``package(id:_:traits:)-(_,Range,_)`` +- ``package(id:_:traits:)-(_,ClosedRange,_)`` +- ``package(id:exact:)`` +- ``package(id:exact:traits:)`` +- ``package(id:from:)`` +- ``package(id:from:traits:)`` +- ``package(name:url:_:)-(String?,_,_)`` +- ``package(name:url:_:)-(_,_,Range)`` +- ``package(name:url:_:)-(_,_,ClosedRange)`` +- ``package(name:url:branch:)`` +- ``package(name:url:from:)`` +- ``package(name:url:revision:)`` +- ``package(url:_:)-(_,Package.Dependency.Requirement)`` +- ``name`` +- ``url`` ### Declaring Requirements - ``requirement-swift.property`` - ``Requirement-swift.enum`` +- ``traits`` +- ``Trait`` +- ``RegistryRequirement`` +- ``SourceControlRequirement`` ### Describing a Package Dependency +- ``name`` +- ``url`` - ``kind-swift.property`` +- ``Kind`` - ``Version`` diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/CLanguageStandard-hash.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/CLanguageStandard-hash.md index a789334c7b2..389328ca47f 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/CLanguageStandard-hash.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/CLanguageStandard-hash.md @@ -6,4 +6,4 @@ Hashes the C language standard by feeding the item into the given hasher. -- Parameter into: The hasher. +- Parameter hasher: The hasher. diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/CXXLanguageStandard-hash.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/CXXLanguageStandard-hash.md index 04bfff2d8c2..69a2a9c22df 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/CXXLanguageStandard-hash.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/CXXLanguageStandard-hash.md @@ -6,4 +6,4 @@ Hashes the C++ language standard by feeding the item into the given hasher. -- Parameter into: The hasher. +- Parameter hasher: The hasher. diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/LanguageTag-hash.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/LanguageTag-hash.md index caabf6fa08a..e1d3b4ad1aa 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/LanguageTag-hash.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/LanguageTag-hash.md @@ -6,4 +6,4 @@ Hashes the language tag by feeding the item into the given hasher. -- Parameter into: The hasher. +- Parameter hasher: The hasher. diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Library-LibraryType-hash.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Library-LibraryType-hash.md index ffb2b9f70a3..942f7c31a25 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Library-LibraryType-hash.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Library-LibraryType-hash.md @@ -11,4 +11,4 @@ Implement this method to conform to the Hashable protocol. The components used f > Important: > Never call finalize() on hasher. Doing so may become a compile-time error in the future. -- Parameter into: The hasher to use when combining the components of this instance. +- Parameter hasher: The hasher to use when combining the components of this instance. diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Resource-Localization-hash.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Resource-Localization-hash.md index aa34c1b2923..ee48715c910 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Resource-Localization-hash.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Resource-Localization-hash.md @@ -6,4 +6,4 @@ Hashes the localization by feeding the item into the given hasher. -- Parameter into: The hasher. +- Parameter hasher: The hasher. diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Target-TargetType-hash.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Target-TargetType-hash.md index cd8203cc945..c08d320b785 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Target-TargetType-hash.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Extensions/Target-TargetType-hash.md @@ -6,6 +6,6 @@ Hashes the target type by feeding the item into the given hasher. -- Parameter into: The hasher. +- Parameter hasher: The hasher. diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/LanguageTag.md b/Sources/PackageDescription/PackageDescription.docc/Curation/LanguageTag.md index bb00e985638..d8b1f564b50 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/LanguageTag.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/LanguageTag.md @@ -4,7 +4,6 @@ ### Creating a Language Tag -- ``init(_:)`` - - ``init(stringLiteral:)`` - @@ -13,7 +12,6 @@ ### Describing a Language Tag -- ``tag`` - ``description`` ### Hashing diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Package.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Package.md index f85d1e97751..284f38751a2 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Package.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Package.md @@ -4,7 +4,13 @@ ### Creating a Package +- ``Package/init(name:defaultLocalization:platforms:pkgConfig:providers:products:dependencies:targets:swiftLanguageModes:cLanguageStandard:cxxLanguageStandard:)`` +- ``Package/init(name:defaultLocalization:platforms:pkgConfig:providers:products:traits:dependencies:targets:swiftLanguageModes:cLanguageStandard:cxxLanguageStandard:)`` - ``Package/init(name:defaultLocalization:platforms:pkgConfig:providers:products:dependencies:targets:swiftLanguageVersions:cLanguageStandard:cxxLanguageStandard:)`` +- ``Package/init(name:platforms:pkgConfig:providers:products:dependencies:targets:swiftLanguageVersions:cLanguageStandard:cxxLanguageStandard:)`` +- ``Package/init(name:pkgConfig:providers:products:dependencies:targets:swiftLanguageVersions:cLanguageStandard:cxxLanguageStandard:)-(_,_,_,_,_,_,[Int]?,_,_)`` +- ``Package/init(name:pkgConfig:providers:products:dependencies:targets:swiftLanguageVersions:cLanguageStandard:cxxLanguageStandard:)-(_,_,_,_,_,_,[SwiftVersion]?,_,_)`` + ### Naming the Package @@ -37,6 +43,11 @@ - ``Package/pkgConfig`` - ``Package/providers`` +### Configuring Traits + +- ``Package/traits`` +- ``Trait`` + ### Declaring Package Dependencies - ``Package/dependencies`` @@ -44,9 +55,11 @@ ### Declaring Supported Languages +- ``SwiftLanguageMode`` - ``SwiftVersion`` - ``CLanguageStandard`` - ``CXXLanguageStandard`` +- ``Package/swiftLanguageModes`` - ``Package/swiftLanguageVersions`` - ``Package/cLanguageStandard`` - ``Package/cxxLanguageStandard`` diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Platform.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Platform.md index f694781bc66..25466890bc5 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Platform.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Platform.md @@ -9,10 +9,12 @@ - ``macOS`` - ``tvOS`` - ``watchOS`` +- ``visionOS`` - ``macCatalyst`` - ``driverKit`` - ``android`` - ``linux`` +- ``freebsd`` - ``openbsd`` - ``wasi`` - ``windows`` diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Resource.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Resource.md index 1535ff8d5b3..8279f56e422 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Resource.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Resource.md @@ -7,3 +7,4 @@ - ``process(_:localization:)`` - ``Localization`` - ``copy(_:)`` +- ``embedInCode(_:)`` diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/SupportedPlatforms.md b/Sources/PackageDescription/PackageDescription.docc/Curation/SupportedPlatforms.md index e30d3c1b50b..b4062a595ab 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/SupportedPlatforms.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/SupportedPlatforms.md @@ -51,15 +51,10 @@ - - ``DriverKitVersion`` -### Supporting Linux - -- - -### Type methods +### Supporting Custom Platforms - ``custom(_:versionString:)`` ### Operator Functions - ``!=(_:_:)`` -- ``==(_:_:)`` diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/SwiftVersion.md b/Sources/PackageDescription/PackageDescription.docc/Curation/SwiftVersion.md deleted file mode 100644 index 760c6c7b481..00000000000 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/SwiftVersion.md +++ /dev/null @@ -1,11 +0,0 @@ -# ``PackageDescription/SwiftVersion`` - -## Topics - -### Enumeration Cases - -- ``v3`` -- ``v4`` -- ``v4_2`` -- ``v5`` -- ``version(_:)`` diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Target-Dependency.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Target-Dependency.md index e8616f0e280..27b3e78d2e4 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Target-Dependency.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Target-Dependency.md @@ -4,22 +4,14 @@ ### Creating a Target Dependency +- ``product(name:package:moduleAliases:condition:)`` - ``product(name:package:condition:)`` - ``product(name:package:)-fp0j`` - ``product(name:package:)-2nako`` -- ``product(name:package:moduleAliases:)`` -- ``product(name:package:moduleAliases:condition:)`` +- ``productItem(name:package:condition:)`` - ``target(name:condition:)`` - ``target(name:)`` - ``byName(name:condition:)`` - ``byName(name:)`` - ``TargetDependencyCondition`` - ``init(stringLiteral:)`` -- ``init(extendedGraphemeClusterLiteral:)`` -- ``init(unicodeScalarLiteral:)`` - -### Identifying related types - -- ``ExtendedGraphemeClusterLiteralType`` -- ``StringLiteralType`` -- ``UnicodeScalarLiteralType`` diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Target-TargetDependencyCondition.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Target-TargetDependencyCondition.md index 36c8b139722..2a39614a69e 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Target-TargetDependencyCondition.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Target-TargetDependencyCondition.md @@ -5,4 +5,6 @@ ### Creating a Dependency Condition - ``when(platforms:)-5bxhc`` +- ``when(traits:)`` +- ``when(platforms:traits:)`` - ``when(platforms:)-4djh6`` diff --git a/Sources/PackageDescription/PackageDescription.docc/Curation/Target.md b/Sources/PackageDescription/PackageDescription.docc/Curation/Target.md index 33507e4f3b4..a68bcc6c27b 100644 --- a/Sources/PackageDescription/PackageDescription.docc/Curation/Target.md +++ b/Sources/PackageDescription/PackageDescription.docc/Curation/Target.md @@ -30,11 +30,29 @@ ### Creating an Executable Target -- ``executableTarget(name:dependencies:path:exclude:sources:resources:publicHeadersPath:cSettings:cxxSettings:swiftSettings:linkerSettings:)`` +- ``executableTarget(name:dependencies:path:exclude:sources:resources:publicHeadersPath:packageAccess:cSettings:cxxSettings:swiftSettings:linkerSettings:plugins:)`` - ``executableTarget(name:dependencies:path:exclude:sources:resources:publicHeadersPath:cSettings:cxxSettings:swiftSettings:linkerSettings:plugins:)`` +- ``executableTarget(name:dependencies:path:exclude:sources:resources:publicHeadersPath:cSettings:cxxSettings:swiftSettings:linkerSettings:)`` + +### Creating a Regular Target + +- ``target(name:dependencies:path:exclude:sources:resources:publicHeadersPath:packageAccess:cSettings:cxxSettings:swiftSettings:linkerSettings:plugins:)`` +- ``target(name:dependencies:path:exclude:sources:resources:publicHeadersPath:cSettings:cxxSettings:swiftSettings:linkerSettings:plugins:)`` +- ``target(name:dependencies:path:exclude:sources:resources:publicHeadersPath:cSettings:cxxSettings:swiftSettings:linkerSettings:)`` +- ``target(name:dependencies:path:exclude:sources:publicHeadersPath:cSettings:cxxSettings:swiftSettings:linkerSettings:)`` +- ``target(name:dependencies:path:exclude:sources:publicHeadersPath:)`` + +### Creating a Test Target + +- ``testTarget(name:dependencies:path:exclude:sources:resources:packageAccess:cSettings:cxxSettings:swiftSettings:linkerSettings:plugins:)`` +- ``testTarget(name:dependencies:path:exclude:sources:resources:cSettings:cxxSettings:swiftSettings:linkerSettings:plugins:)`` +- ``testTarget(name:dependencies:path:exclude:sources:resources:cSettings:cxxSettings:swiftSettings:linkerSettings:)`` +- ``testTarget(name:dependencies:path:exclude:sources:cSettings:cxxSettings:swiftSettings:linkerSettings:)`` +- ``testTarget(name:dependencies:path:exclude:sources:)`` ### Creating a Plugin Target +- ``plugin(name:capability:dependencies:path:exclude:sources:packageAccess:)`` - ``plugin(name:capability:dependencies:path:exclude:sources:)`` - ``pluginCapability-swift.property`` - ``PluginCapability-swift.enum`` @@ -61,6 +79,7 @@ - ``SwiftSetting`` - ``LinkerSetting`` - ``PluginUsage`` +- ``packageAccess`` ### Describing the Target Type diff --git a/Sources/PackageDescription/PackageDescription.swift b/Sources/PackageDescription/PackageDescription.swift index 261fca0cc81..edc7b18cdf4 100644 --- a/Sources/PackageDescription/PackageDescription.swift +++ b/Sources/PackageDescription/PackageDescription.swift @@ -171,6 +171,7 @@ public final class Package { /// - pkgConfig: The name to use for C modules. If present, the Swift /// Package Manager searches for a `.pc` file to get the /// additional flags required for a system target. + /// - providers: The system package providers that this package uses. /// - products: The list of products that this package makes available for clients to use. /// - dependencies: The list of package dependencies. /// - targets: The list of targets that are part of this package. @@ -211,6 +212,7 @@ public final class Package { /// - pkgConfig: The name to use for C modules. If present, the Swift /// Package Manager searches for a `.pc` file to get the /// additional flags required for a system target. + /// - providers: The system package providers that this package uses. /// - products: The list of products that this package makes available for clients to use. /// - dependencies: The list of package dependencies. /// - targets: The list of targets that are part of this package. diff --git a/Sources/PackageDescription/Version+StringLiteralConvertible.swift b/Sources/PackageDescription/Version+StringLiteralConvertible.swift index 58dbc187e39..c3d01faf20c 100644 --- a/Sources/PackageDescription/Version+StringLiteralConvertible.swift +++ b/Sources/PackageDescription/Version+StringLiteralConvertible.swift @@ -13,7 +13,7 @@ extension Version: ExpressibleByStringLiteral { /// Initializes a version struct with the provided string literal. /// - /// - Parameter version: A string literal to use for creating a new version struct. + /// - Parameter value: A string literal to use for creating a new version struct. public init(stringLiteral value: String) { if let version = Version(value) { self = version @@ -29,7 +29,7 @@ extension Version: ExpressibleByStringLiteral { /// Initializes a version struct with the provided extended grapheme cluster. /// - /// - Parameter version: An extended grapheme cluster to use for creating a new + /// - Parameter value: An extended grapheme cluster to use for creating a new /// version struct. public init(extendedGraphemeClusterLiteral value: String) { self.init(stringLiteral: value) @@ -37,7 +37,7 @@ extension Version: ExpressibleByStringLiteral { /// Initializes a version struct with the provided Unicode string. /// - /// - Parameter version: A Unicode string to use for creating a new version struct. + /// - Parameter value: A Unicode string to use for creating a new version struct. public init(unicodeScalarLiteral value: String) { self.init(stringLiteral: value) } @@ -45,7 +45,7 @@ extension Version: ExpressibleByStringLiteral { extension Version: LosslessStringConvertible { /// Initializes a version struct with the provided version string. - /// - Parameter version: A version string to use for creating a new version struct. + /// - Parameter versionString: A version string to use for creating a new version struct. public init?(_ versionString: String) { // SemVer 2.0.0 allows only ASCII alphanumerical characters and "-" in the version string, except for "." and "+" as delimiters. ("-" is used as a delimiter between the version core and pre-release identifiers, but it's allowed within pre-release and metadata identifiers as well.) // Alphanumerics check will come later, after each identifier is split out (i.e. after the delimiters are removed). diff --git a/Sources/PackageDescription/Version.swift b/Sources/PackageDescription/Version.swift index 09b9b214da7..b777a241919 100644 --- a/Sources/PackageDescription/Version.swift +++ b/Sources/PackageDescription/Version.swift @@ -59,11 +59,11 @@ public struct Version: Sendable { /// - minor: The minor version number. /// - patch: The patch version number. /// - prereleaseIdentifiers: The pre-release identifier. - /// - buildMetaDataIdentifiers: Build metadata that identifies a build. + /// - buildMetadataIdentifiers: Build metadata that identifies a build. /// /// - Precondition: `major >= 0 && minor >= 0 && patch >= 0`. /// - Precondition: `prereleaseIdentifiers` can contain only ASCII alpha-numeric characters and "-". - /// - Precondition: `buildMetaDataIdentifiers` can contain only ASCII alpha-numeric characters and "-". + /// - Precondition: `buildMetadataIdentifiers` can contain only ASCII alpha-numeric characters and "-". public init( _ major: Int, _ minor: Int, diff --git a/Sources/SwiftBuildSupport/PIFBuilder.swift b/Sources/SwiftBuildSupport/PIFBuilder.swift index cb6866018ae..667e943b0ba 100644 --- a/Sources/SwiftBuildSupport/PIFBuilder.swift +++ b/Sources/SwiftBuildSupport/PIFBuilder.swift @@ -100,7 +100,8 @@ public final class PIFBuilder { func generatePIF( prettyPrint: Bool = true, preservePIFModelStructure: Bool = false, - printPIFManifestGraphviz: Bool = false + printPIFManifestGraphviz: Bool = false, + buildParameters: BuildParameters ) throws -> String { #if canImport(SwiftBuild) let encoder = prettyPrint ? JSONEncoder.makeWithDefaults() : JSONEncoder() @@ -109,7 +110,7 @@ public final class PIFBuilder { encoder.userInfo[.encodeForSwiftBuild] = true } - let topLevelObject = try self.construct() + let topLevelObject = try self.constructPIF(buildParameters: buildParameters) // Sign the PIF objects before encoding it for Swift Build. try PIF.sign(workspace: topLevelObject.workspace) @@ -138,7 +139,7 @@ public final class PIFBuilder { private var cachedPIF: PIF.TopLevelObject? /// Constructs a `PIF.TopLevelObject` representing the package graph. - private func construct() throws -> PIF.TopLevelObject { + private func constructPIF(buildParameters: BuildParameters) throws -> PIF.TopLevelObject { try memoize(to: &self.cachedPIF) { guard let rootPackage = self.graph.rootPackages.only else { if self.graph.rootPackages.isEmpty { @@ -163,6 +164,7 @@ public final class PIFBuilder { buildToolPluginResultsByTargetName: [:], createDylibForDynamicProducts: self.parameters.shouldCreateDylibForDynamicProducts, packageDisplayVersion: package.manifest.displayName, + fileSystem: self.fileSystem, observabilityScope: self.observabilityScope ) @@ -174,7 +176,9 @@ public final class PIFBuilder { projects.append( try buildAggregateProject( packagesAndProjects: packagesAndProjects, - observabilityScope: observabilityScope + observabilityScope: observabilityScope, + modulesGraph: graph, + buildParameters: buildParameters ) ) @@ -197,7 +201,7 @@ public final class PIFBuilder { packageGraph: ModulesGraph, fileSystem: FileSystem, observabilityScope: ObservabilityScope, - preservePIFModelStructure: Bool + preservePIFModelStructure: Bool, ) throws -> String { let parameters = PIFBuilderParameters(buildParameters, supportedSwiftVersions: []) let builder = Self( @@ -206,7 +210,7 @@ public final class PIFBuilder { fileSystem: fileSystem, observabilityScope: observabilityScope ) - return try builder.generatePIF(preservePIFModelStructure: preservePIFModelStructure) + return try builder.generatePIF(preservePIFModelStructure: preservePIFModelStructure, buildParameters: buildParameters) } } @@ -306,7 +310,9 @@ fileprivate final class PackagePIFBuilderDelegate: PackagePIFBuilder.BuildDelega fileprivate func buildAggregateProject( packagesAndProjects: [(package: ResolvedPackage, project: ProjectModel.Project)], - observabilityScope: ObservabilityScope + observabilityScope: ObservabilityScope, + modulesGraph: ModulesGraph, + buildParameters: BuildParameters ) throws -> ProjectModel.Project { precondition(!packagesAndProjects.isEmpty) @@ -367,6 +373,13 @@ fileprivate func buildAggregateProject( // conflicts with those from "PACKAGE-TARGET:Foo-dynamic". continue } + + if let resolvedModule = modulesGraph.module(for: target.name) { + guard modulesGraph.isInRootPackages(resolvedModule, satisfying: buildParameters.buildEnvironment) else { + // Disconnected target, possibly due to platform when condition that isn't satisfied + continue + } + } aggregateProject[keyPath: allIncludingTestsTargetKeyPath].common.addDependency( on: target.id, diff --git a/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift b/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift index e1689c1b086..b0273deb5a3 100644 --- a/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift +++ b/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift @@ -12,16 +12,16 @@ import Foundation +import protocol TSCBasic.FileSystem import struct TSCUtility.Version import struct Basics.AbsolutePath import struct Basics.Diagnostic -import let Basics.localFileSystem import struct Basics.ObservabilityMetadata -import class Basics.ObservabilityScope -import class Basics.ObservabilitySystem import struct Basics.RelativePath import struct Basics.SourceControlURL +import class Basics.ObservabilityScope +import class Basics.ObservabilitySystem import class Basics.ThreadSafeArrayStore import enum PackageModel.BuildConfiguration @@ -440,13 +440,13 @@ extension PackageGraph.ResolvedModule { } /// Relative path of the module-map file, if any (*only* applies to C-language modules). - var moduleMapFileRelativePath: RelativePath? { + func moduleMapFileRelativePath(fileSystem: FileSystem) -> RelativePath? { guard let clangModule = self.underlying as? ClangModule else { return nil } let moduleMapFileAbsolutePath = clangModule.moduleMapPath // Check whether there is actually a modulemap at the specified path. // FIXME: Feels wrong to do file system access at this level —— instead, libSwiftPM's TargetBuilder should do that? - guard localFileSystem.isFile(moduleMapFileAbsolutePath) else { return nil } + guard fileSystem.isFile(moduleMapFileAbsolutePath) else { return nil } let moduleMapFileRelativePath = moduleMapFileAbsolutePath.relative(to: clangModule.sources.root) return try! RelativePath(validating: moduleMapFileRelativePath.pathString) @@ -612,6 +612,7 @@ extension SystemLibraryModule { /// Returns pkgConfig result for a system library target. func pkgConfig( package: PackageGraph.ResolvedPackage, + fileSystem: FileSystem, observabilityScope: ObservabilityScope ) throws -> (cFlags: [String], libs: [String]) { let diagnostics = ThreadSafeArrayStore() @@ -651,7 +652,7 @@ extension SystemLibraryModule { for: self, pkgConfigDirectories: [], brewPrefix: brewPrefix, - fileSystem: localFileSystem, + fileSystem: fileSystem, observabilityScope: pkgConfigParsingScope ) guard let pkgConfigResult else { return emptyPkgConfig } diff --git a/Sources/SwiftBuildSupport/PackagePIFBuilder+Plugins.swift b/Sources/SwiftBuildSupport/PackagePIFBuilder+Plugins.swift index 3934f30984e..2f89010bfc9 100644 --- a/Sources/SwiftBuildSupport/PackagePIFBuilder+Plugins.swift +++ b/Sources/SwiftBuildSupport/PackagePIFBuilder+Plugins.swift @@ -12,9 +12,10 @@ import Foundation -import struct Basics.AbsolutePath -import let Basics.localFileSystem +import protocol TSCBasic.FileSystem + import enum Basics.Sandbox +import struct Basics.AbsolutePath import struct Basics.SourceControlURL #if canImport(SwiftBuild) @@ -123,10 +124,10 @@ extension PackagePIFBuilder { } /// Applies the sandbox profile to the given command line, and return the modified command line. - public func apply(to command: [String]) throws -> [String] { + public func apply(to command: [String], fileSystem: FileSystem) throws -> [String] { try Sandbox.apply( command: command, - fileSystem: localFileSystem, + fileSystem: fileSystem, strictness: self.strictness, writableDirectories: self.writableDirectories, readOnlyDirectories: self.readOnlyDirectories diff --git a/Sources/SwiftBuildSupport/PackagePIFBuilder.swift b/Sources/SwiftBuildSupport/PackagePIFBuilder.swift index ba854b1f461..001ff5c5437 100644 --- a/Sources/SwiftBuildSupport/PackagePIFBuilder.swift +++ b/Sources/SwiftBuildSupport/PackagePIFBuilder.swift @@ -12,20 +12,22 @@ import Foundation +import protocol TSCBasic.FileSystem + import struct Basics.AbsolutePath import struct Basics.SourceControlURL +import struct Basics.Diagnostic +import struct Basics.ObservabilityMetadata +import class Basics.ObservabilityScope import class PackageModel.Manifest import class PackageModel.Package +import class PackageModel.Product import struct PackageModel.Platform import struct PackageModel.PlatformVersion -import class PackageModel.Product -import enum PackageModel.ProductType import struct PackageModel.Resource +import enum PackageModel.ProductType -import struct Basics.Diagnostic -import struct Basics.ObservabilityMetadata -import class Basics.ObservabilityScope import struct PackageGraph.ModulesGraph import struct PackageGraph.ResolvedModule import struct PackageGraph.ResolvedPackage @@ -169,6 +171,9 @@ public final class PackagePIFBuilder { /// Package display version, if any (i.e., it can be a version, branch or a git ref). let packageDisplayVersion: String? + /// The file system to read from. + let fileSystem: FileSystem + /// Whether to suppress warnings from compilers, linkers, and other build tools for package dependencies. private var suppressWarningsForPackageDependencies: Bool { UserDefaults.standard.bool(forKey: "SuppressWarningsForPackageDependencies", defaultValue: true) @@ -191,6 +196,7 @@ public final class PackagePIFBuilder { buildToolPluginResultsByTargetName: [String: BuildToolPluginInvocationResult], createDylibForDynamicProducts: Bool = false, packageDisplayVersion: String?, + fileSystem: FileSystem, observabilityScope: ObservabilityScope ) { self.package = resolvedPackage @@ -200,6 +206,7 @@ public final class PackagePIFBuilder { self.buildToolPluginResultsByTargetName = buildToolPluginResultsByTargetName self.createDylibForDynamicProducts = createDylibForDynamicProducts self.packageDisplayVersion = packageDisplayVersion + self.fileSystem = fileSystem self.observabilityScope = observabilityScope } diff --git a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift index 028c9e537ea..e766c3f4725 100644 --- a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift +++ b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift @@ -377,7 +377,7 @@ extension PackagePIFProjectBuilder { // We only need to impart this to C clients. impartedSettings[.OTHER_CFLAGS] = ["-fmodule-map-file=\(moduleMapFile)", "$(inherited)"] - } else if sourceModule.moduleMapFileRelativePath == nil { + } else if sourceModule.moduleMapFileRelativePath(fileSystem: self.pifBuilder.fileSystem) == nil { // Otherwise, this is a C library module and we generate a modulemap if one is already not provided. if case .umbrellaHeader(let path) = sourceModule.moduleMapType { log(.debug, "\(package.name).\(sourceModule.name) generated umbrella header") @@ -423,7 +423,7 @@ extension PackagePIFProjectBuilder { .spm_mangledToBundleIdentifier() settings[.EXECUTABLE_NAME] = executableName settings[.CLANG_ENABLE_MODULES] = "YES" - settings[.GENERATE_MASTER_OBJECT_FILE] = "NO" + settings[.GENERATE_PRELINK_OBJECT_FILE] = "NO" settings[.STRIP_INSTALLED_PRODUCT] = "NO" // Macros build as executables, so they need slightly different @@ -824,6 +824,7 @@ extension PackagePIFProjectBuilder { let settings: ProjectModel.BuildSettings = self.package.underlying.packageBaseBuildSettings let pkgConfig = try systemLibrary.pkgConfig( package: self.package, + fileSystem: self.pifBuilder.fileSystem, observabilityScope: pifBuilder.observabilityScope ) diff --git a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift index 1b8648f1622..c37a6e6f3b9 100644 --- a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift +++ b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift @@ -460,7 +460,7 @@ struct PackagePIFProjectBuilder { ) { var commandLine = [command.executable] + command.arguments if let sandbox = command.sandboxProfile, !pifBuilder.delegate.isPluginExecutionSandboxingDisabled { - commandLine = try! sandbox.apply(to: commandLine) + commandLine = try! sandbox.apply(to: commandLine, fileSystem: self.pifBuilder.fileSystem) } self.project[keyPath: targetKeyPath].customTasks.append( diff --git a/Sources/SwiftBuildSupport/SwiftBuildSystem.swift b/Sources/SwiftBuildSupport/SwiftBuildSystem.swift index 38d3272beaf..79e8b6567ea 100644 --- a/Sources/SwiftBuildSupport/SwiftBuildSystem.swift +++ b/Sources/SwiftBuildSupport/SwiftBuildSystem.swift @@ -239,7 +239,8 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { let pifBuilder = try await getPIFBuilder() let pif = try pifBuilder.generatePIF( - printPIFManifestGraphviz: buildParameters.printPIFManifestGraphviz + printPIFManifestGraphviz: buildParameters.printPIFManifestGraphviz, + buildParameters: buildParameters ) try self.fileSystem.writeIfChanged(path: buildParameters.pifManifest, string: pif) diff --git a/Sources/_InternalTestSupport/MockWorkspace.swift b/Sources/_InternalTestSupport/MockWorkspace.swift index 4b1d516f9f0..3349eb60f91 100644 --- a/Sources/_InternalTestSupport/MockWorkspace.swift +++ b/Sources/_InternalTestSupport/MockWorkspace.swift @@ -185,12 +185,14 @@ public final class MockWorkspace { private func create() async throws { // Remove the sandbox if present. - try self.fileSystem.removeFileTree(self.sandbox) + if self.fileSystem.exists(self.sandbox) { + try self.fileSystem.removeFileTree(self.sandbox) + } // Create directories. try self.fileSystem.createDirectory(self.sandbox, recursive: true) - try self.fileSystem.createDirectory(self.rootsDir) - try self.fileSystem.createDirectory(self.packagesDir) + try self.fileSystem.createDirectory(self.rootsDir, recursive: true) + try self.fileSystem.createDirectory(self.packagesDir, recursive: true) var manifests: [MockManifestLoader.Key: Manifest] = [:] diff --git a/Sources/_InternalTestSupport/Process.swift b/Sources/_InternalTestSupport/Process.swift new file mode 100644 index 00000000000..72c501aedc4 --- /dev/null +++ b/Sources/_InternalTestSupport/Process.swift @@ -0,0 +1,49 @@ +/* + This source file is part of the Swift.org open source project + + Copyright (c) 2014 - 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 Swift project authors + */ + +public import Foundation + +public enum OperatingSystem: Hashable, Sendable { + case macOS + case windows + case linux + case android + case unknown +} + +extension ProcessInfo { + #if os(macOS) + public static let hostOperatingSystem = OperatingSystem.macOS + #elseif os(Linux) + public static let hostOperatingSystem = OperatingSystem.linux + #elseif os(Windows) + public static let hostOperatingSystem = OperatingSystem.windows + #else + public static let hostOperatingSystem = OperatingSystem.unknown + #endif + + #if os(Windows) + public static let EOL = "\r\n" + #else + public static let EOL = "\n" + #endif + + #if os(Windows) + public static let exeSuffix = ".exe" + #else + public static let exeSuffix = "" + #endif + + #if os(Windows) + public static let batSuffix = ".bat" + #else + public static let batSuffix = "" + #endif +} diff --git a/Sources/_InternalTestSupport/XCTAssertHelpers.swift b/Sources/_InternalTestSupport/XCTAssertHelpers.swift index 9bdbd3e475e..1eb619ee1c5 100644 --- a/Sources/_InternalTestSupport/XCTAssertHelpers.swift +++ b/Sources/_InternalTestSupport/XCTAssertHelpers.swift @@ -46,7 +46,7 @@ public func XCTAssertEqual (_ lhs:(T,U), _ rhs:(T,U), public func XCTSkipIfCI(file: StaticString = #filePath, line: UInt = #line) throws { // TODO: is this actually the right variable now? - if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] != nil { + if isInCiEnvironment { throw XCTSkip("Skipping because the test is being run on CI", file: file, line: line) } } @@ -268,3 +268,21 @@ public struct CommandExecutionError: Error { public let stdout: String public let stderr: String } + +/// Skips the test if running on a platform which lacks the ability for build tasks to set a working directory due to lack of requisite system API. +/// +/// Presently, relevant platforms include Amazon Linux 2 and OpenBSD. +/// +/// - seealso: https://github.com/swiftlang/swift-package-manager/issues/8560 +public func XCTSkipIfWorkingDirectoryUnsupported() throws { + func unavailable() throws { + throw XCTSkip("Thread-safe process working directory support is unavailable on this platform.") + } + #if os(Linux) + if FileManager.default.contents(atPath: "/etc/system-release").map({ String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" }) ?? false { + try unavailable() + } + #elseif os(OpenBSD) + try unavailable() + #endif +} diff --git a/Sources/_InternalTestSupport/misc.swift b/Sources/_InternalTestSupport/misc.swift index 0cc73af222d..baf6a186abf 100644 --- a/Sources/_InternalTestSupport/misc.swift +++ b/Sources/_InternalTestSupport/misc.swift @@ -39,6 +39,8 @@ 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 + /// Test helper utility for executing a block with a temporary directory. public func testWithTemporaryDirectory( function: StaticString = #function, @@ -294,7 +296,7 @@ public func skipOnWindowsAsTestCurrentlyFails(because reason: String? = nil) thr } else { failureCause = "" } - throw XCTSkip("Test fails on windows\(failureCause)") + throw XCTSkip("Skipping tests on windows\(failureCause)") #endif } diff --git a/Tests/BasicsTests/AsyncProcessTests.swift b/Tests/BasicsTests/AsyncProcessTests.swift index 8ffb8bc7f7d..6f27f3ca7ba 100644 --- a/Tests/BasicsTests/AsyncProcessTests.swift +++ b/Tests/BasicsTests/AsyncProcessTests.swift @@ -22,56 +22,48 @@ import class TSCBasic.Thread import func TSCBasic.withTemporaryFile import func TSCTestSupport.withCustomEnv -final class AsyncProcessTests: XCTestCase { - #if os(Windows) - let executableExt = ".exe" - #else - let executableExt = "" - #endif +#if os(Windows) +let catExecutable = "type" +#else +let catExecutable = "cat" +#endif - func testBasics() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "missingExecutableProgram(program: "echo.exe")" - """) +final class AsyncProcessTests: XCTestCase { + let echoExecutableArgs = getAsyncProcessArgs(executable: "echo") + let catExecutableArgs = getAsyncProcessArgs(executable: catExecutable) - do { - let process = AsyncProcess(args: "echo\(executableExt)", "hello") + func testBasicsProcess() throws { + let process = AsyncProcess(arguments: echoExecutableArgs + ["hello"]) try process.launch() let result = try process.waitUntilExit() - XCTAssertEqual(try result.utf8Output(), "hello\n") + XCTAssertEqual(try result.utf8Output(), "hello\(ProcessInfo.EOL)") XCTAssertEqual(result.exitStatus, .terminated(code: 0)) XCTAssertEqual(result.arguments, process.arguments) - } + } - do { - let process = AsyncProcess(scriptName: "exit4") + func testBasicsScript() throws { + let process = AsyncProcess(scriptName: "exit4\(ProcessInfo.batSuffix)") try process.launch() let result = try process.waitUntilExit() XCTAssertEqual(result.exitStatus, .terminated(code: 4)) - } } func testPopenBasic() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "missingExecutableProgram(program: "echo.exe")" - """) - // Test basic echo. - XCTAssertEqual(try AsyncProcess.popen(arguments: ["echo\(executableExt)", "hello"]).utf8Output(), "hello\n") + XCTAssertEqual(try AsyncProcess.popen(arguments: echoExecutableArgs + ["hello"]).utf8Output(), "hello\(ProcessInfo.EOL)") } func testPopenWithBufferLargerThanAllocated() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "missingExecutableProgram(program: "cat.exe")" - """) // Test buffer larger than that allocated. try withTemporaryFile { file in let count = 10000 let stream = BufferedOutputByteStream() stream.send(Format.asRepeating(string: "a", count: count)) try localFileSystem.writeFileContents(file.path, bytes: stream.bytes) - let outputCount = try AsyncProcess.popen(args: "cat\(executableExt)", file.path.pathString).utf8Output().count - XCTAssert(outputCount == count) + let actualStreamCount = stream.bytes.count + XCTAssertTrue(actualStreamCount == count, "Actual stream count (\(actualStreamCount)) is not as exxpected (\(count))") + let outputCount = try AsyncProcess.popen(arguments: catExecutableArgs + [file.path.pathString]).utf8Output().count + XCTAssert(outputCount == count, "Actual count (\(outputCount)) is not as expected (\(count))") } } @@ -122,18 +114,14 @@ final class AsyncProcessTests: XCTestCase { XCTAssertTrue(output.hasPrefix(answer)) } - func testCheckNonZeroExit() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "missingExecutableProgram(program: "echo.exe")" - """) - + func testCheckNonZeroExit() async throws { do { - let output = try AsyncProcess.checkNonZeroExit(args: "echo\(executableExt)", "hello") - XCTAssertEqual(output, "hello\n") + let output = try await AsyncProcess.checkNonZeroExit(args: echoExecutableArgs + ["hello"]) + XCTAssertEqual(output, "hello\(ProcessInfo.EOL)") } do { - let output = try AsyncProcess.checkNonZeroExit(scriptName: "exit4") + let output = try await AsyncProcess.checkNonZeroExit(scriptName: "exit4\(ProcessInfo.batSuffix)") XCTFail("Unexpected success \(output)") } catch AsyncProcessResult.Error.nonZeroExit(let result) { XCTAssertEqual(result.exitStatus, .terminated(code: 4)) @@ -142,17 +130,13 @@ final class AsyncProcessTests: XCTestCase { @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) func testCheckNonZeroExitAsync() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "missingExecutableProgram(program: "echo.exe")" - """) - do { - let output = try await AsyncProcess.checkNonZeroExit(args: "echo\(executableExt)", "hello") - XCTAssertEqual(output, "hello\n") + let output = try await AsyncProcess.checkNonZeroExit(args: echoExecutableArgs + ["hello"]) + XCTAssertEqual(output, "hello\(ProcessInfo.EOL)") } do { - let output = try await AsyncProcess.checkNonZeroExit(scriptName: "exit4") + let output = try await AsyncProcess.checkNonZeroExit(scriptName: "exit4\(ProcessInfo.batSuffix)") XCTFail("Unexpected success \(output)") } catch AsyncProcessResult.Error.nonZeroExit(let result) { XCTAssertEqual(result.exitStatus, .terminated(code: 4)) @@ -160,7 +144,7 @@ final class AsyncProcessTests: XCTestCase { } func testFindExecutable() throws { - try skipOnWindowsAsTestCurrentlyFails(because: "Assertion failure when trying to find ls executable") + try skipOnWindowsAsTestCurrentlyFails(because: "https://github.com/swiftlang/swift-package-manager/issues/8547: Assertion failure when trying to find ls executable") try testWithTemporaryDirectory { tmpdir in // This process should always work. @@ -171,11 +155,16 @@ final class AsyncProcessTests: XCTestCase { // Create a local nonexecutable file to test. let tempExecutable = tmpdir.appending(component: "nonExecutableProgram") - try localFileSystem.writeFileContents(tempExecutable, bytes: """ + #if os(Windows) + let exitScriptContent = ByteString("EXIT /B") + #else + let exitScriptContent = ByteString(""" #!/bin/sh exit """) + #endif + try localFileSystem.writeFileContents(tempExecutable, bytes: exitScriptContent) try withCustomEnv(["PATH": tmpdir.pathString]) { XCTAssertEqual(AsyncProcess.findExecutable("nonExecutableProgram"), nil) @@ -206,11 +195,7 @@ final class AsyncProcessTests: XCTestCase { } func testThreadSafetyOnWaitUntilExit() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "missingExecutableProgram(program: "echo.exe")" - """) - - let process = AsyncProcess(args: "echo\(executableExt)", "hello") + let process = AsyncProcess(args: echoExecutableArgs + ["hello"]) try process.launch() var result1 = "" @@ -229,17 +214,13 @@ final class AsyncProcessTests: XCTestCase { t1.join() t2.join() - XCTAssertEqual(result1, "hello\n") - XCTAssertEqual(result2, "hello\n") + XCTAssertEqual(result1, "hello\(ProcessInfo.EOL)") + XCTAssertEqual(result2, "hello\(ProcessInfo.EOL)") } @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) func testThreadSafetyOnWaitUntilExitAsync() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "missingExecutableProgram(program: "echo.exe")" - """) - - let process = AsyncProcess(args: "echo\(executableExt)", "hello") + let process = AsyncProcess(args: echoExecutableArgs + ["hello"]) try process.launch() let t1 = Task { @@ -253,46 +234,38 @@ final class AsyncProcessTests: XCTestCase { let result1 = try await t1.value let result2 = try await t2.value - XCTAssertEqual(result1, "hello\n") - XCTAssertEqual(result2, "hello\n") + XCTAssertEqual(result1, "hello\(ProcessInfo.EOL)") + XCTAssertEqual(result2, "hello\(ProcessInfo.EOL)") } func testStdin() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "Error Domain=NSCocoaErrorDomain Code=3584 "(null)"UserInfo={NSUnderlyingError=Error Domain=org.swift.Foundation.WindowsError Code=193 "(null)"}" - """) - var stdout = [UInt8]() - let process = AsyncProcess(scriptName: "in-to-out", outputRedirection: .stream(stdout: { stdoutBytes in + let process = AsyncProcess(scriptName: "in-to-out\(ProcessInfo.batSuffix)", outputRedirection: .stream(stdout: { stdoutBytes in stdout += stdoutBytes }, stderr: { _ in })) let stdinStream = try process.launch() - stdinStream.write("hello\n") + stdinStream.write("hello\(ProcessInfo.EOL)") stdinStream.flush() try stdinStream.close() try process.waitUntilExit() - XCTAssertEqual(String(decoding: stdout, as: UTF8.self), "hello\n") + XCTAssertEqual(String(decoding: stdout, as: UTF8.self), "hello\(ProcessInfo.EOL)") } func testStdoutStdErr() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "Error Domain=NSCocoaErrorDomain Code=3584 "(null)"UserInfo={NSUnderlyingError=Error Domain=org.swift.Foundation.WindowsError Code=193 "(null)"}" - """) - // A simple script to check that stdout and stderr are captured separatly. do { - let result = try AsyncProcess.popen(scriptName: "simple-stdout-stderr") - XCTAssertEqual(try result.utf8Output(), "simple output\n") - XCTAssertEqual(try result.utf8stderrOutput(), "simple error\n") + let result = try AsyncProcess.popen(scriptName: "simple-stdout-stderr\(ProcessInfo.batSuffix)") + XCTAssertEqual(try result.utf8Output(), "simple output\(ProcessInfo.EOL)") + XCTAssertEqual(try result.utf8stderrOutput(), "simple error\(ProcessInfo.EOL)") } // A long stdout and stderr output. do { - let result = try AsyncProcess.popen(scriptName: "long-stdout-stderr") + let result = try AsyncProcess.popen(scriptName: "long-stdout-stderr\(ProcessInfo.batSuffix)") let count = 16 * 1024 XCTAssertEqual(try result.utf8Output(), String(repeating: "1", count: count)) XCTAssertEqual(try result.utf8stderrOutput(), String(repeating: "2", count: count)) @@ -300,7 +273,7 @@ final class AsyncProcessTests: XCTestCase { // This script will block if the streams are not read. do { - let result = try AsyncProcess.popen(scriptName: "deadlock-if-blocking-io") + let result = try AsyncProcess.popen(scriptName: "deadlock-if-blocking-io\(ProcessInfo.batSuffix)") let count = 16 * 1024 XCTAssertEqual(try result.utf8Output(), String(repeating: "1", count: count)) XCTAssertEqual(try result.utf8stderrOutput(), String(repeating: "2", count: count)) @@ -309,20 +282,16 @@ final class AsyncProcessTests: XCTestCase { @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) func testStdoutStdErrAsync() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "Error Domain=NSCocoaErrorDomain Code=3584 "(null)"UserInfo={NSUnderlyingError=Error Domain=org.swift.Foundation.WindowsError Code=193 "(null)"}" - """) - // A simple script to check that stdout and stderr are captured separatly. do { - let result = try await AsyncProcess.popen(scriptName: "simple-stdout-stderr") - XCTAssertEqual(try result.utf8Output(), "simple output\n") - XCTAssertEqual(try result.utf8stderrOutput(), "simple error\n") + let result = try await AsyncProcess.popen(scriptName: "simple-stdout-stderr\(ProcessInfo.batSuffix)") + XCTAssertEqual(try result.utf8Output(), "simple output\(ProcessInfo.EOL)") + XCTAssertEqual(try result.utf8stderrOutput(), "simple error\(ProcessInfo.EOL)") } // A long stdout and stderr output. do { - let result = try await AsyncProcess.popen(scriptName: "long-stdout-stderr") + let result = try await AsyncProcess.popen(scriptName: "long-stdout-stderr\(ProcessInfo.batSuffix)") let count = 16 * 1024 XCTAssertEqual(try result.utf8Output(), String(repeating: "1", count: count)) XCTAssertEqual(try result.utf8stderrOutput(), String(repeating: "2", count: count)) @@ -330,7 +299,7 @@ final class AsyncProcessTests: XCTestCase { // This script will block if the streams are not read. do { - let result = try await AsyncProcess.popen(scriptName: "deadlock-if-blocking-io") + let result = try await AsyncProcess.popen(scriptName: "deadlock-if-blocking-io\(ProcessInfo.batSuffix)") let count = 16 * 1024 XCTAssertEqual(try result.utf8Output(), String(repeating: "1", count: count)) XCTAssertEqual(try result.utf8stderrOutput(), String(repeating: "2", count: count)) @@ -338,45 +307,51 @@ final class AsyncProcessTests: XCTestCase { } func testStdoutStdErrRedirected() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "Error Domain=NSCocoaErrorDomain Code=3584 "(null)"UserInfo={NSUnderlyingError=Error Domain=org.swift.Foundation.WindowsError Code=193 "(null)"}" - """) - // A simple script to check that stdout and stderr are captured in the same location. do { let process = AsyncProcess( - scriptName: "simple-stdout-stderr", + scriptName: "simple-stdout-stderr\(ProcessInfo.batSuffix)", outputRedirection: .collect(redirectStderr: true) ) try process.launch() let result = try process.waitUntilExit() - XCTAssertEqual(try result.utf8Output(), "simple error\nsimple output\n") - XCTAssertEqual(try result.utf8stderrOutput(), "") + #if os(Windows) + let expectedStdout = "simple output\(ProcessInfo.EOL)" + let expectedStderr = "simple error\(ProcessInfo.EOL)" + #else + let expectedStdout = "simple error\(ProcessInfo.EOL)simple output\(ProcessInfo.EOL)" + let expectedStderr = "" + #endif + XCTAssertEqual(try result.utf8Output(), expectedStdout) + XCTAssertEqual(try result.utf8stderrOutput(), expectedStderr) } // A long stdout and stderr output. do { let process = AsyncProcess( - scriptName: "long-stdout-stderr", + scriptName: "long-stdout-stderr\(ProcessInfo.batSuffix)", outputRedirection: .collect(redirectStderr: true) ) try process.launch() let result = try process.waitUntilExit() let count = 16 * 1024 - XCTAssertEqual(try result.utf8Output(), String(repeating: "12", count: count)) - XCTAssertEqual(try result.utf8stderrOutput(), "") + #if os(Windows) + let expectedStdout = String(repeating: "1", count: count) + let expectedStderr = String(repeating: "2", count: count) + #else + let expectedStdout = String(repeating: "12", count: count) + let expectedStderr = "" + #endif + XCTAssertEqual(try result.utf8Output(), expectedStdout) + XCTAssertEqual(try result.utf8stderrOutput(), expectedStderr) } } func testStdoutStdErrStreaming() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "Error Domain=NSCocoaErrorDomain Code=3584 "(null)"UserInfo={NSUnderlyingError=Error Domain=org.swift.Foundation.WindowsError Code=193 "(null)"}" - """) - var stdout = [UInt8]() var stderr = [UInt8]() - let process = AsyncProcess(scriptName: "long-stdout-stderr", outputRedirection: .stream(stdout: { stdoutBytes in + let process = AsyncProcess(scriptName: "long-stdout-stderr\(ProcessInfo.batSuffix)", outputRedirection: .stream(stdout: { stdoutBytes in stdout += stdoutBytes }, stderr: { stderrBytes in stderr += stderrBytes @@ -390,13 +365,9 @@ final class AsyncProcessTests: XCTestCase { } func testStdoutStdErrStreamingRedirected() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "Error Domain=NSCocoaErrorDomain Code=3584 "(null)"UserInfo={NSUnderlyingError=Error Domain=org.swift.Foundation.WindowsError Code=193 "(null)"}" - """) - var stdout = [UInt8]() var stderr = [UInt8]() - let process = AsyncProcess(scriptName: "long-stdout-stderr", outputRedirection: .stream(stdout: { stdoutBytes in + let process = AsyncProcess(scriptName: "long-stdout-stderr\(ProcessInfo.batSuffix)", outputRedirection: .stream(stdout: { stdoutBytes in stdout += stdoutBytes }, stderr: { stderrBytes in stderr += stderrBytes @@ -405,15 +376,18 @@ final class AsyncProcessTests: XCTestCase { try process.waitUntilExit() let count = 16 * 1024 - XCTAssertEqual(String(bytes: stdout, encoding: .utf8), String(repeating: "12", count: count)) - XCTAssertEqual(stderr, []) + #if os(Windows) + let expectedStdout = String(repeating: "1", count: count) + let expectedStderr = String(repeating: "2", count: count) + #else + let expectedStdout = String(repeating: "12", count: count) + let expectedStderr = "" + #endif + XCTAssertEqual(String(bytes: stdout, encoding: .utf8), expectedStdout) + XCTAssertEqual(String(bytes: stderr, encoding: .utf8), expectedStderr) } func testWorkingDirectory() throws { - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "missingExecutableProgram(program: "cat.exe")" - """) - guard #available(macOS 10.15, *) else { // Skip this test since it's not supported in this OS. return @@ -435,14 +409,14 @@ final class AsyncProcessTests: XCTestCase { try localFileSystem.writeFileContents(childPath, bytes: ByteString("child")) do { - let process = AsyncProcess(arguments: ["cat\(executableExt)", "file"], workingDirectory: tempDirPath) + let process = AsyncProcess(arguments: catExecutableArgs + ["file"], workingDirectory: tempDirPath) try process.launch() let result = try process.waitUntilExit() XCTAssertEqual(try result.utf8Output(), "parent") } do { - let process = AsyncProcess(arguments: ["cat", "file"], workingDirectory: childPath.parentDirectory) + let process = AsyncProcess(arguments: catExecutableArgs + ["file"], workingDirectory: childPath.parentDirectory) try process.launch() let result = try process.waitUntilExit() XCTAssertEqual(try result.utf8Output(), "child") @@ -453,15 +427,13 @@ final class AsyncProcessTests: XCTestCase { func testAsyncStream() async throws { // rdar://133548796 try XCTSkipIfCI() - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "Error Domain=NSCocoaErrorDomain Code=3584 "(null)"UserInfo={NSUnderlyingError=Error Domain=org.swift.Foundation.WindowsError Code=193 "(null)"}" - """) + try skipOnWindowsAsTestCurrentlyFails(because: "https://github.com/swiftlang/swift-package-manager/issues/8547: 'swift test' was hanging.") let (stdoutStream, stdoutContinuation) = AsyncProcess.ReadableStream.makeStream() let (stderrStream, stderrContinuation) = AsyncProcess.ReadableStream.makeStream() let process = AsyncProcess( - scriptName: "echo\(executableExt)", + scriptName: "echo\(ProcessInfo.batSuffix)", outputRedirection: .stream { stdoutContinuation.yield($0) } stderr: { @@ -474,14 +446,14 @@ final class AsyncProcessTests: XCTestCase { group.addTask { var counter = 0 - stdin.write("Hello \(counter)\n") + stdin.write("Hello \(counter)\(ProcessInfo.EOL)") stdin.flush() for await output in stdoutStream { - XCTAssertEqual(output, .init("Hello \(counter)\n".utf8)) + XCTAssertEqual(output, .init("Hello \(counter)\(ProcessInfo.EOL)".utf8)) counter += 1 - stdin.write(.init("Hello \(counter)\n".utf8)) + stdin.write(.init("Hello \(counter)\(ProcessInfo.EOL)".utf8)) stdin.flush() } @@ -513,22 +485,21 @@ final class AsyncProcessTests: XCTestCase { func testAsyncStreamHighLevelAPI() async throws { // rdar://133548796 try XCTSkipIfCI() - try skipOnWindowsAsTestCurrentlyFails(because: """ - threw error "Error Domain=NSCocoaErrorDomain Code=3584 "(null)"UserInfo={NSUnderlyingError=Error Domain=org.swift.Foundation.WindowsError Code=193 "(null)"}" - """) + try skipOnWindowsAsTestCurrentlyFails(because: "https://github.com/swiftlang/swift-package-manager/issues/8547: 'swift test' was hanging.") let result = try await AsyncProcess.popen( - scriptName: "echo\(executableExt)", + scriptName: "echo\(ProcessInfo.batSuffix)", // maps to 'processInputs/echo' script stdout: { stdin, stdout in var counter = 0 - stdin.write("Hello \(counter)\n") + stdin.write("Hello \(counter)\(ProcessInfo.EOL)") stdin.flush() for await output in stdout { - XCTAssertEqual(output, .init("Hello \(counter)\n".utf8)) + + XCTAssertEqual(output, .init("Hello \(counter)\(ProcessInfo.EOL)".utf8)) counter += 1 - stdin.write(.init("Hello \(counter)\n".utf8)) + stdin.write(.init("Hello \(counter)\(ProcessInfo.EOL)".utf8)) stdin.flush() } @@ -561,12 +532,25 @@ extension AsyncProcess { outputRedirection: OutputRedirection = .collect ) { self.init( - arguments: [Self.script(scriptName)] + arguments, + arguments: getAsyncProcessArgs(executable: AsyncProcess.script(scriptName)) + arguments, environment: .current, outputRedirection: outputRedirection ) } + @discardableResult + fileprivate static func checkNonZeroExit( + args: [String], + environment: Environment = .current, + loggingHandler: LoggingHandler? = .none + ) async throws -> String { + try await self.checkNonZeroExit( + arguments: args, + environment: environment, + loggingHandler: loggingHandler + ) + } + @available(*, noasync) fileprivate static func checkNonZeroExit( scriptName: String, @@ -600,7 +584,7 @@ extension AsyncProcess { environment: Environment = .current, loggingHandler: LoggingHandler? = .none ) throws -> AsyncProcessResult { - try self.popen(arguments: [self.script(scriptName)], environment: .current, loggingHandler: loggingHandler) + try self.popen(arguments: getAsyncProcessArgs(executable: self.script(scriptName)), environment: .current, loggingHandler: loggingHandler) } @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) @@ -610,7 +594,7 @@ extension AsyncProcess { environment: Environment = .current, loggingHandler: LoggingHandler? = .none ) async throws -> AsyncProcessResult { - try await self.popen(arguments: [self.script(scriptName)], environment: .current, loggingHandler: loggingHandler) + try await self.popen(arguments: getAsyncProcessArgs(executable: self.script(scriptName)), environment: .current, loggingHandler: loggingHandler) } fileprivate static func popen( @@ -618,6 +602,15 @@ extension AsyncProcess { stdout: @escaping AsyncProcess.DuplexStreamHandler, stderr: AsyncProcess.ReadableStreamHandler? = nil ) async throws -> AsyncProcessResult { - try await self.popen(arguments: [self.script(scriptName)], stdoutHandler: stdout, stderrHandler: stderr) + try await self.popen(arguments: getAsyncProcessArgs(executable: self.script(scriptName)), stdoutHandler: stdout, stderrHandler: stderr) } } + +fileprivate func getAsyncProcessArgs(executable: String) -> [String] { + #if os(Windows) + let args = ["cmd.exe", "/c", executable] + #else + let args = [executable] + #endif + return args +} diff --git a/Tests/BasicsTests/FileSystem/InMemoryFilesSystemTests.swift b/Tests/BasicsTests/FileSystem/InMemoryFilesSystemTests.swift new file mode 100644 index 00000000000..b34f869896f --- /dev/null +++ b/Tests/BasicsTests/FileSystem/InMemoryFilesSystemTests.swift @@ -0,0 +1,236 @@ +/* + This source file is part of the Swift.org 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 Swift project authors + */ + +import Basics +import struct TSCBasic.ByteString +import struct TSCBasic.FileSystemError + +import Testing +import _InternalTestSupport + +#if os(Linux) +let isLinux = true +#else +let isLinux = false +#endif + +// Comment out the Swift Testing test until we figure out why the Linux Smoke Test +// is crashing +// struct InMemoryFileSystemTests { +// @Test( +// arguments: [ +// ( +// path: "/", +// recurvise: true, +// expectedFiles: [ +// (p: "/", shouldExist: true), +// ], +// expectError: false +// ), +// ( +// path: "/tmp", +// recurvise: true, +// expectedFiles: [ +// (p: "/", shouldExist: true), +// (p: "/tmp", shouldExist: true), +// ], +// expectError: false +// ), +// ( +// path: "/tmp/ws", +// recurvise: true, +// expectedFiles: [ +// (p: "/", shouldExist: true), +// (p: "/tmp", shouldExist: true), +// (p: "/tmp/ws", shouldExist: true), +// ], +// expectError: false +// ), +// ( +// path: "/tmp/ws", +// recurvise: false, +// expectedFiles: [ +// (p: "/", shouldExist: true), +// (p: "/tmp", shouldExist: true), +// (p: "/tmp/ws", shouldExist: true), +// ], +// expectError: true +// ), +// ] +// ) +// func creatingDirectoryCreatesInternalFiles( +// path: String, +// recursive: Bool, +// expectedFiles: [(String, Bool) ], +// expectError: Bool +// ) async throws { +// let fs = InMemoryFileSystem() +// let pathUnderTest = AbsolutePath(path) + +// func errorMessage(_ pa: AbsolutePath, _ exists: Bool) -> String { +// return "Path '\(pa) \(exists ? "should exists, but doesn't" : "should not exist, but does.")" +// } + +// try withKnownIssue { +// try fs.createDirectory(pathUnderTest, recursive: recursive) + +// for (p, shouldExist) in expectedFiles { +// let expectedPath = AbsolutePath(p) +// #expect(fs.exists(expectedPath) == shouldExist, "\(errorMessage(expectedPath, shouldExist))") +// } +// } when: { +// expectError +// } +// } + + +// @Test( +// arguments: [ +// "/", +// "/tmp", +// "/tmp/", +// "/something/ws", +// "/something/ws/", +// "/what/is/this", +// "/what/is/this/", +// ] +// ) +// func callingCreateDirectoryOnAnExistingDirectoryIsSuccessful(path: String) async throws { +// let root = AbsolutePath(path) +// let fs = InMemoryFileSystem() + +// #expect(throws: Never.self) { +// try fs.createDirectory(root, recursive: true) +// } + +// #expect(throws: Never.self) { +// try fs.createDirectory(root.appending("more"), recursive: true) +// } +// } + +// struct writeFileContentsTests { + +// @Test +// func testWriteFileContentsSuccessful() async throws { +// // GIVEN we have a filesytstem +// let fs = InMemoryFileSystem() +// // and a path +// let pathUnderTest = AbsolutePath("/myFile.zip") +// let expectedContents = ByteString([0xAA, 0xBB, 0xCC]) + +// // WHEN we write contents to the file +// try fs.writeFileContents(pathUnderTest, bytes: expectedContents) + +// // THEN we expect the file to exist +// #expect(fs.exists(pathUnderTest), "Path \(pathUnderTest.pathString) does not exists when it should") +// } + +// @Test +// func testWritingAFileWithANonExistingParentDirectoryFails() async throws { +// // GIVEN we have a filesytstem +// let fs = InMemoryFileSystem() +// // and a path +// let pathUnderTest = AbsolutePath("/tmp/myFile.zip") +// let expectedContents = ByteString([0xAA, 0xBB, 0xCC]) + +// // WHEN we write contents to the file +// // THEn we expect an error to occus +// try withKnownIssue { +// try fs.writeFileContents(pathUnderTest, bytes: expectedContents) +// } + +// // AND we expect the file to not exist +// #expect(!fs.exists(pathUnderTest), "Path \(pathUnderTest.pathString) does exists when it should not") +// } + +// @Test +// func errorOccursWhenWritingToRootDirectory() async throws { +// // GIVEN we have a filesytstem +// let fs = InMemoryFileSystem() +// // and a path +// let pathUnderTest = AbsolutePath("/") +// let expectedContents = ByteString([0xAA, 0xBB, 0xCC]) + +// // WHEN we write contents to the file +// // THEN we expect an error to occur +// try withKnownIssue { +// try fs.writeFileContents(pathUnderTest, bytes: expectedContents) +// } + +// } + +// @Test +// func testErrorOccursIfParentIsNotADirectory() async throws { +// // GIVEN we have a filesytstem +// let fs = InMemoryFileSystem() +// // AND an existing file +// let aFile = AbsolutePath("/foo") +// try fs.writeFileContents(aFile, bytes: "") + +// // AND a the path under test that has an existing file as a parent +// let pathUnderTest = aFile.appending("myFile") +// let expectedContents = ByteString([0xAA, 0xBB, 0xCC]) + +// // WHEN we write contents to the file +// // THEN we expect an error to occur +// withKnownIssue { +// try fs.writeFileContents(pathUnderTest, bytes: expectedContents) +// } + +// } +// } + + +// struct testReadFileContentsTests { +// @Test +// func readingAFileThatDoesNotExistsRaisesAnError()async throws { +// // GIVEN we have a filesystem +// let fs = InMemoryFileSystem() + +// // WHEN we read a non-existing file +// // THEN an error occurs +// try withKnownIssue { +// let _ = try fs.readFileContents("/file/does/not/exists") +// } +// } + +// @Test +// func readingExistingFileReturnsExpectedContents() async throws { +// // GIVEN we have a filesytstem +// let fs = InMemoryFileSystem() +// // AND a file a path +// let pathUnderTest = AbsolutePath("/myFile.zip") +// let expectedContents = ByteString([0xAA, 0xBB, 0xCC]) +// try fs.writeFileContents(pathUnderTest, bytes: expectedContents) + +// // WHEN we read contents if the file +// let actualContents = try fs.readFileContents(pathUnderTest) + +// // THEN the actual contents should match the expected to match the +// #expect(actualContents == expectedContents, "Actual is not as expected") +// } + +// @Test +// func readingADirectoryFailsWithAnError() async throws { +// // GIVEN we have a filesytstem +// let fs = InMemoryFileSystem() +// // AND a file a path +// let pathUnderTest = AbsolutePath("/myFile.zip") +// let expectedContents = ByteString([0xAA, 0xBB, 0xCC]) +// try fs.writeFileContents(pathUnderTest, bytes: expectedContents) + +// // WHEN we read the contents of a directory +// // THEN we expect a failure to occur +// withKnownIssue { +// let _ = try fs.readFileContents(pathUnderTest.parentDirectory) +// } +// } +// } +// } diff --git a/Tests/BasicsTests/Serialization/SerializedJSONTests.swift b/Tests/BasicsTests/Serialization/SerializedJSONTests.swift index b499a4eb1dc..db3ab32e95d 100644 --- a/Tests/BasicsTests/Serialization/SerializedJSONTests.swift +++ b/Tests/BasicsTests/Serialization/SerializedJSONTests.swift @@ -34,7 +34,7 @@ final class SerializedJSONTests: XCTestCase { } func testPathInterpolationFailsOnWindows() throws { - try skipOnWindowsAsTestCurrentlyFails(because: "Expectations are not met") + try skipOnWindowsAsTestCurrentlyFails(because: "Expectations are not met. Possibly related to https://github.com/swiftlang/swift-package-manager/issues/8511") #if os(Windows) var path = try AbsolutePath(validating: #"\\?\C:\Users"#) diff --git a/Tests/BasicsTests/processInputs/deadlock-if-blocking-io.bat b/Tests/BasicsTests/processInputs/deadlock-if-blocking-io.bat new file mode 100644 index 00000000000..28438667ac8 --- /dev/null +++ b/Tests/BasicsTests/processInputs/deadlock-if-blocking-io.bat @@ -0,0 +1,2 @@ +@echo off +python %~dp0deadlock-if-blocking-io \ No newline at end of file diff --git a/Tests/BasicsTests/processInputs/echo.bat b/Tests/BasicsTests/processInputs/echo.bat new file mode 100644 index 00000000000..e954bbcdd16 --- /dev/null +++ b/Tests/BasicsTests/processInputs/echo.bat @@ -0,0 +1,2 @@ +@echo off +python %~dp0echo \ No newline at end of file diff --git a/Tests/BasicsTests/processInputs/exit4.bat b/Tests/BasicsTests/processInputs/exit4.bat new file mode 100644 index 00000000000..9f3929bdf9d --- /dev/null +++ b/Tests/BasicsTests/processInputs/exit4.bat @@ -0,0 +1 @@ +EXIT /B 4 \ No newline at end of file diff --git a/Tests/BasicsTests/processInputs/in-to-out.bat b/Tests/BasicsTests/processInputs/in-to-out.bat new file mode 100644 index 00000000000..dbf639c3fe7 --- /dev/null +++ b/Tests/BasicsTests/processInputs/in-to-out.bat @@ -0,0 +1,2 @@ +@echo off +python %~dp0in-to-out \ No newline at end of file diff --git a/Tests/BasicsTests/processInputs/long-stdout-stderr.bat b/Tests/BasicsTests/processInputs/long-stdout-stderr.bat new file mode 100644 index 00000000000..57aaf420f21 --- /dev/null +++ b/Tests/BasicsTests/processInputs/long-stdout-stderr.bat @@ -0,0 +1,2 @@ +@echo off +python %~dp0long-stdout-stderr \ No newline at end of file diff --git a/Tests/BasicsTests/processInputs/simple-stdout-stderr.bat b/Tests/BasicsTests/processInputs/simple-stdout-stderr.bat new file mode 100644 index 00000000000..4e1d389ee12 --- /dev/null +++ b/Tests/BasicsTests/processInputs/simple-stdout-stderr.bat @@ -0,0 +1,2 @@ +@echo off +python %~dp0simple-stdout-stderr \ No newline at end of file diff --git a/Tests/BuildTests/BuildPlanTests.swift b/Tests/BuildTests/BuildPlanTests.swift index f3d9a2a74de..5c9ac3c9ce9 100644 --- a/Tests/BuildTests/BuildPlanTests.swift +++ b/Tests/BuildTests/BuildPlanTests.swift @@ -7069,14 +7069,11 @@ class BuildPlanSwiftBuildTests: BuildPlanTestCase { } override func testPackageNameFlag() async throws { + try XCTSkipIfWorkingDirectoryUnsupported() #if os(Windows) throw XCTSkip("Skip until there is a resolution to the partial linking with Windows that results in a 'subsystem must be defined' error.") #endif - #if os(Linux) - if FileManager.default.contents(atPath: "/etc/system-release").map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false { - throw XCTSkip("Skipping Swift Build testing on Amazon Linux because of platform issues.") - } // Linking error: "/usr/bin/ld.gold: fatal error: -pie and -static are incompatible". // Tracked by GitHub issue: https://github.com/swiftlang/swift-package-manager/issues/8499 throw XCTSkip("Skipping Swift Build testing on Linux because of linking issues.") diff --git a/Tests/BuildTests/BuildSystemDelegateTests.swift b/Tests/BuildTests/BuildSystemDelegateTests.swift index 8e07b6a3d1a..ea844efc800 100644 --- a/Tests/BuildTests/BuildSystemDelegateTests.swift +++ b/Tests/BuildTests/BuildSystemDelegateTests.swift @@ -30,7 +30,7 @@ final class BuildSystemDelegateTests: XCTestCase { } func testFilterNonFatalCodesignMessages() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: "Package fails to build when the test is being executed") + try skipOnWindowsAsTestCurrentlyFails(because: "https://github.com/swiftlang/swift-package-manager/issues/8540: Package fails to build when the test is being executed") try XCTSkipIf(!UserToolchain.default.supportsSDKDependentTests(), "skipping because test environment doesn't support this test") // Note: we can re-use the `TestableExe` fixture here since we just need an executable. diff --git a/Tests/CommandsTests/BuildCommandTests.swift b/Tests/CommandsTests/BuildCommandTests.swift index 16e7d45f501..a91357a4147 100644 --- a/Tests/CommandsTests/BuildCommandTests.swift +++ b/Tests/CommandsTests/BuildCommandTests.swift @@ -859,12 +859,7 @@ class BuildCommandSwiftBuildTests: BuildCommandTestCases { } override func testParseableInterfaces() async throws { - #if os(Linux) - if FileManager.default.contents(atPath: "/etc/system-release") - .map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false { - throw XCTSkip("https://github.com/swiftlang/swift-package-manager/issues/8545: Test currently fails on Amazon Linux 2") - } - #endif + try XCTSkipIfWorkingDirectoryUnsupported() try await fixture(name: "Miscellaneous/ParseableInterfaces") { fixturePath in do { let result = try await build(["--enable-parseable-module-interfaces"], packagePath: fixturePath) @@ -944,11 +939,7 @@ class BuildCommandSwiftBuildTests: BuildCommandTestCases { #endif override func testBuildSystemDefaultSettings() async throws { - #if os(Linux) - if FileManager.default.contents(atPath: "/etc/system-release").map( { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ) ?? false { - throw XCTSkip("Skipping SwiftBuild testing on Amazon Linux because of platform issues.") - } - #endif + try XCTSkipIfWorkingDirectoryUnsupported() if ProcessInfo.processInfo.environment["SWIFTPM_NO_SWBUILD_DEPENDENCY"] != nil { throw XCTSkip("SWIFTPM_NO_SWBUILD_DEPENDENCY is set so skipping because SwiftPM doesn't have the swift-build capability built inside.") @@ -958,11 +949,7 @@ class BuildCommandSwiftBuildTests: BuildCommandTestCases { } override func testBuildCompleteMessage() async throws { - #if os(Linux) - if FileManager.default.contents(atPath: "/etc/system-release").map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false { - throw XCTSkip("Skipping Swift Build testing on Amazon Linux because of platform issues.") - } - #endif + try XCTSkipIfWorkingDirectoryUnsupported() try await super.testBuildCompleteMessage() } diff --git a/Tests/CommandsTests/PackageCommandTests.swift b/Tests/CommandsTests/PackageCommandTests.swift index 876dfa4c9e4..cb2a1cef77a 100644 --- a/Tests/CommandsTests/PackageCommandTests.swift +++ b/Tests/CommandsTests/PackageCommandTests.swift @@ -3906,11 +3906,8 @@ class PackageCommandSwiftBuildTests: PackageCommandTestCase { #if !os(macOS) override func testCommandPluginTestingCallbacks() async throws { -#if os(Linux) - if FileManager.default.contents(atPath: "/etc/system-release").map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false { - throw XCTSkip("Skipping Swift Build testing on Amazon Linux because of platform issues.") - } -#endif + try XCTSkipIfWorkingDirectoryUnsupported() + try await super.testCommandPluginTestingCallbacks() } #endif diff --git a/Tests/FunctionalTests/MiscellaneousTests.swift b/Tests/FunctionalTests/MiscellaneousTests.swift index dd39ab65f0c..c06e2f76dc2 100644 --- a/Tests/FunctionalTests/MiscellaneousTests.swift +++ b/Tests/FunctionalTests/MiscellaneousTests.swift @@ -665,4 +665,15 @@ final class MiscellaneousTestCase: XCTestCase { XCTAssertEqual(errors, [], "unexpected errors: \(errors)") } } + + func testRootPackageWithConditionalsSwiftBuild() async throws { +#if os(Linux) + if FileManager.default.contents(atPath: "/etc/system-release").map { String(decoding: $0, as: UTF8.self) == "Amazon Linux release 2 (Karoo)\n" } ?? false { + throw XCTSkip("Skipping Swift Build testing on Amazon Linux because of platform issues.") + } +#endif + try await fixture(name: "Miscellaneous/RootPackageWithConditionals") { path in + _ = try await SwiftPM.Build.execute(["--build-system=swiftbuild"], packagePath: path, env: ["SWIFT_DRIVER_SWIFTSCAN_LIB" : "/this/is/a/bad/path"]) + } + } } diff --git a/Tests/PackageGraphTests/ModulesGraphTests.swift b/Tests/PackageGraphTests/ModulesGraphTests.swift index 02b3a907834..ac2f5e68469 100644 --- a/Tests/PackageGraphTests/ModulesGraphTests.swift +++ b/Tests/PackageGraphTests/ModulesGraphTests.swift @@ -25,7 +25,7 @@ import struct TSCBasic.ByteString final class ModulesGraphTests: XCTestCase { func testBasic() throws { - try skipOnWindowsAsTestCurrentlyFails() + try skipOnWindowsAsTestCurrentlyFails(because: "Possibly related to: https://github.com/swiftlang/swift-package-manager/issues/8511") let fs = InMemoryFileSystem( emptyFiles: "/Foo/Sources/Foo/source.swift", diff --git a/Tests/PackageLoadingTests/PackageBuilderTests.swift b/Tests/PackageLoadingTests/PackageBuilderTests.swift index c57b2da08cb..6a71f526a8c 100644 --- a/Tests/PackageLoadingTests/PackageBuilderTests.swift +++ b/Tests/PackageLoadingTests/PackageBuilderTests.swift @@ -564,7 +564,7 @@ final class PackageBuilderTests: XCTestCase { } func testTestManifestSearch() throws { - try skipOnWindowsAsTestCurrentlyFails() + try skipOnWindowsAsTestCurrentlyFails(because: "possibly related to https://github.com/swiftlang/swift-package-manager/issues/8511") let fs = InMemoryFileSystem(emptyFiles: "/pkg/foo.swift", diff --git a/Tests/PackageModelTests/PackageModelTests.swift b/Tests/PackageModelTests/PackageModelTests.swift index 8c7f5f3b184..9d230b286d5 100644 --- a/Tests/PackageModelTests/PackageModelTests.swift +++ b/Tests/PackageModelTests/PackageModelTests.swift @@ -17,7 +17,6 @@ import Basics import func TSCBasic.withTemporaryFile import XCTest -import _InternalTestSupport // for skipOnWindowsAsTestCurrentlyFails import struct TSCBasic.ByteString @@ -160,10 +159,7 @@ final class PackageModelTests: XCTestCase { } func testDetermineSwiftCompilers() throws { - try skipOnWindowsAsTestCurrentlyFails() - let fs = localFileSystem - try withTemporaryFile { _ in try withTemporaryDirectory(removeTreeOnDeinit: true) { tmp in // When swiftc is not in the toolchain bin directory, UserToolchain // should find it in the system PATH search paths in the order they @@ -175,10 +171,17 @@ final class PackageModelTests: XCTestCase { // Create a directory with two swiftc binaries in it. let binDirs = ["bin1", "bin2"].map { tmp.appending($0) } + #if os(Windows) + let exeSuffix = ".exe" + #else + let exeSuffix = "" + #endif + let expectedExecuable = "swiftc\(exeSuffix)" // Files that end with .exe are considered executable on Windows. for binDir in binDirs { try fs.createDirectory(binDir) - let binFile = binDir.appending("swiftc") + let binFile = binDir.appending(expectedExecuable) try fs.writeFileContents(binFile, bytes: ByteString(Self.tinyPEBytes)) + XCTAssertTrue(fs.exists(binFile), "File '\(binFile)' does not exist when it should") #if !os(Windows) try fs.chmod(.executable, path: binFile, options: []) #endif @@ -193,8 +196,7 @@ final class PackageModelTests: XCTestCase { ) // The first swiftc in the search paths should be chosen. - XCTAssertEqual(compilers.compile, binDirs.first?.appending("swiftc")) + XCTAssertEqual(compilers.compile, binDirs.first?.appending(expectedExecuable)) } - } } } diff --git a/Tests/QueryEngineTests/QueryEngineTests.swift b/Tests/QueryEngineTests/QueryEngineTests.swift index 840bff4d4e4..c87f59820ed 100644 --- a/Tests/QueryEngineTests/QueryEngineTests.swift +++ b/Tests/QueryEngineTests/QueryEngineTests.swift @@ -100,7 +100,7 @@ private struct Expression: CachingQuery { final class QueryEngineTests: XCTestCase { func testFilePathHashing() throws { - try skipOnWindowsAsTestCurrentlyFails() + try skipOnWindowsAsTestCurrentlyFails(because: "https://github.com/swiftlang/swift-package-manager/issues/8541") let path = "/root" diff --git a/Tests/WorkspaceTests/WorkspaceTests.swift b/Tests/WorkspaceTests/WorkspaceTests.swift index bb479d83893..a2f06d441d1 100644 --- a/Tests/WorkspaceTests/WorkspaceTests.swift +++ b/Tests/WorkspaceTests/WorkspaceTests.swift @@ -43,8 +43,6 @@ final class WorkspaceTests: XCTestCase { // } func testBasics() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -339,8 +337,6 @@ final class WorkspaceTests: XCTestCase { } func testMultipleRootPackages() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -398,8 +394,6 @@ final class WorkspaceTests: XCTestCase { } func testRootPackagesOverride() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -462,8 +456,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateRootPackages() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -501,8 +493,6 @@ final class WorkspaceTests: XCTestCase { /// Test that the explicit name given to a package is not used as its identity. func testExplicitPackageNameIsNotUsedAsPackageIdentity() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -560,7 +550,7 @@ final class WorkspaceTests: XCTestCase { roots: ["foo-package", "bar-package"], dependencies: [ .localSourceControl( - path: "/tmp/ws/pkgs/bar-package", + path: "\(sandbox)/pkgs/bar-package", requirement: .upToNextMajor(from: "1.0.0") ), ] @@ -576,8 +566,6 @@ final class WorkspaceTests: XCTestCase { /// Test that the remote repository is not resolved when a root package with same name is already present. func testRootAsDependency1() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -633,14 +621,12 @@ final class WorkspaceTests: XCTestCase { await workspace.checkManagedDependencies { result in result.check(notPresent: "baz") } - XCTAssertNoMatch(workspace.delegate.events, [.equal("fetching package: /tmp/ws/pkgs/Baz")]) + XCTAssertNoMatch(workspace.delegate.events, [.equal("fetching package: \(sandbox)/pkgs/Baz")]) XCTAssertNoMatch(workspace.delegate.events, [.equal("will resolve dependencies")]) } /// Test that a root package can be used as a dependency when the remote version was resolved previously. func testRootAsDependency2() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -728,8 +714,6 @@ final class WorkspaceTests: XCTestCase { } func testGraphRootDependencies() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -791,9 +775,8 @@ final class WorkspaceTests: XCTestCase { } } - func testCanResolveWithIncompatiblePackages() async throws { - try skipOnWindowsAsTestCurrentlyFails() + func testCanResolveWithIncompatiblePackages() async throws { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -896,8 +879,6 @@ final class WorkspaceTests: XCTestCase { } func testResolverCanHaveError() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -959,8 +940,6 @@ final class WorkspaceTests: XCTestCase { } func testPrecomputeResolution_empty() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") @@ -1006,8 +985,6 @@ final class WorkspaceTests: XCTestCase { } func testPrecomputeResolution_newPackages() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") @@ -1069,8 +1046,6 @@ final class WorkspaceTests: XCTestCase { } func testPrecomputeResolution_requirementChange_versionToBranch() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") @@ -1139,8 +1114,6 @@ final class WorkspaceTests: XCTestCase { } func testPrecomputeResolution_requirementChange_versionToRevision() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let cPath = RelativePath("C") @@ -1192,8 +1165,6 @@ final class WorkspaceTests: XCTestCase { } func testPrecomputeResolution_requirementChange_localToBranch() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") @@ -1261,8 +1232,6 @@ final class WorkspaceTests: XCTestCase { } func testPrecomputeResolution_requirementChange_versionToLocal() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") @@ -1330,8 +1299,6 @@ final class WorkspaceTests: XCTestCase { } func testPrecomputeResolution_requirementChange_branchToLocal() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") @@ -1400,8 +1367,6 @@ final class WorkspaceTests: XCTestCase { } func testPrecomputeResolution_other() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") @@ -1471,8 +1436,6 @@ final class WorkspaceTests: XCTestCase { } func testPrecomputeResolution_notRequired() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let bPath = RelativePath("B") @@ -1538,8 +1501,6 @@ final class WorkspaceTests: XCTestCase { } func testLoadingRootManifests() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -1564,8 +1525,6 @@ final class WorkspaceTests: XCTestCase { } func testUpdate() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -1667,8 +1626,6 @@ final class WorkspaceTests: XCTestCase { } func testUpdateDryRun() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -1740,7 +1697,7 @@ final class WorkspaceTests: XCTestCase { .updated(.init(requirement: .version(Version("1.5.0")), products: .everything)) #endif - let path = AbsolutePath("/tmp/ws/pkgs/Foo") + let path = sandbox.appending(components: ["pkgs","Foo"]) let expectedChange = ( PackageReference.localSourceControl(identity: PackageIdentity(path: path), path: path), stateChange @@ -1764,8 +1721,6 @@ final class WorkspaceTests: XCTestCase { } func testPartialUpdate() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -1870,8 +1825,6 @@ final class WorkspaceTests: XCTestCase { } func testCleanAndReset() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -1951,10 +1904,8 @@ final class WorkspaceTests: XCTestCase { } func testDependencyManifestLoading() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") - let fs = InMemoryFileSystem() + let fs: InMemoryFileSystem = InMemoryFileSystem() let workspace = try await MockWorkspace( sandbox: sandbox, @@ -2032,8 +1983,6 @@ final class WorkspaceTests: XCTestCase { } func testDependencyManifestsOrder() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2103,8 +2052,6 @@ final class WorkspaceTests: XCTestCase { } func testBranchAndRevision() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2148,7 +2095,7 @@ final class WorkspaceTests: XCTestCase { ) // Get some revision identifier of Bar. - let bar = RepositorySpecifier(path: "/tmp/ws/pkgs/Bar") + let bar = RepositorySpecifier(path: "\(sandbox)/pkgs/Bar") let barRevision = workspace.repositoryProvider.specifierMap[bar]!.revisions[0] // We request Bar via revision. @@ -2169,8 +2116,6 @@ final class WorkspaceTests: XCTestCase { } func testResolve() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2244,8 +2189,6 @@ final class WorkspaceTests: XCTestCase { } func testDeletedCheckoutDirectory() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2291,9 +2234,8 @@ final class WorkspaceTests: XCTestCase { } } - func testMinimumRequiredToolsVersionInDependencyResolution() async throws { - try skipOnWindowsAsTestCurrentlyFails() + func testMinimumRequiredToolsVersionInDependencyResolution() async throws { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2335,8 +2277,6 @@ final class WorkspaceTests: XCTestCase { } func testToolsVersionRootPackages() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2415,9 +2355,8 @@ final class WorkspaceTests: XCTestCase { } } - func testEditDependency() async throws { - try skipOnWindowsAsTestCurrentlyFails() + func testEditDependency() async throws { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2504,7 +2443,7 @@ final class WorkspaceTests: XCTestCase { } // Edit bar at a custom path and branch (ToT). - let barPath = AbsolutePath("/tmp/ws/custom/bar") + let barPath = sandbox.appending(components: ["custom", "bar"]) await workspace.checkEdit(packageIdentity: "bar", path: barPath, checkoutBranch: "dev") { diagnostics in XCTAssertNoDiagnostics(diagnostics) } @@ -2526,8 +2465,6 @@ final class WorkspaceTests: XCTestCase { } func testUnsafeFlagsInEditedPackage() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2580,7 +2517,7 @@ final class WorkspaceTests: XCTestCase { XCTAssertNoDiagnostics(diagnostics) } - let editedFooPath = AbsolutePath("/tmp/ws/Foo") + let editedFooPath = sandbox.appending("Foo") await workspace.checkEdit(packageIdentity: "Foo", path: editedFooPath) { diagnostics in XCTAssertNoDiagnostics(diagnostics) } @@ -2591,8 +2528,6 @@ final class WorkspaceTests: XCTestCase { } func testMissingEditCanRestoreOriginalCheckout() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2656,8 +2591,6 @@ final class WorkspaceTests: XCTestCase { } func testCanUneditRemovedDependencies() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2732,8 +2665,6 @@ final class WorkspaceTests: XCTestCase { } func testDependencyResolutionWithEdit() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2855,8 +2786,6 @@ final class WorkspaceTests: XCTestCase { } func testPrefetchingWithOverridenPackage() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -2942,8 +2871,6 @@ final class WorkspaceTests: XCTestCase { // Test that changing a particular dependency re-resolves the graph. func testChangeOneDependency() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3030,8 +2957,6 @@ final class WorkspaceTests: XCTestCase { } func testResolutionFailureWithEditedDependency() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3100,6 +3025,11 @@ final class WorkspaceTests: XCTestCase { workspace.manifestLoader.manifests[editedFooKey] = manifest } + } + func testResolutionFailureWithEditedDependencyWithABadGraph() async throws { + let sandbox = AbsolutePath("/tmp/ws/") + let fs = InMemoryFileSystem() + // Try resolving a bad graph. let deps: [MockDependency] = [ .sourceControl(path: "./Bar", requirement: .exact("1.1.0"), products: .specific(["Bar"])), @@ -3152,8 +3082,6 @@ final class WorkspaceTests: XCTestCase { } func testStateModified() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3245,8 +3173,6 @@ final class WorkspaceTests: XCTestCase { } func testSkipUpdate() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3296,8 +3222,6 @@ final class WorkspaceTests: XCTestCase { } func testLocalDependencyBasics() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3375,9 +3299,8 @@ final class WorkspaceTests: XCTestCase { } } - func testLocalDependencyTransitive() async throws { - try skipOnWindowsAsTestCurrentlyFails() + func testLocalDependencyTransitive() async throws { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3440,8 +3363,6 @@ final class WorkspaceTests: XCTestCase { } func testLocalDependencyWithPackageUpdate() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3506,8 +3427,6 @@ final class WorkspaceTests: XCTestCase { } func testMissingLocalDependencyDiagnostic() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3548,8 +3467,6 @@ final class WorkspaceTests: XCTestCase { } func testRevisionVersionSwitch() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3619,8 +3536,6 @@ final class WorkspaceTests: XCTestCase { } func testLocalVersionSwitch() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3690,8 +3605,6 @@ final class WorkspaceTests: XCTestCase { } func testLocalLocalSwitch() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3764,8 +3677,6 @@ final class WorkspaceTests: XCTestCase { // Test that switching between two same local packages placed at // different locations works correctly. func testDependencySwitchLocalWithSameIdentity() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3843,8 +3754,6 @@ final class WorkspaceTests: XCTestCase { // Test that switching between two remote packages at // different locations works correctly. func testDependencySwitchRemoteWithSameIdentity() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3923,8 +3832,6 @@ final class WorkspaceTests: XCTestCase { } func testResolvedFileUpdate() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -3980,15 +3887,12 @@ final class WorkspaceTests: XCTestCase { } func testResolvedFileSchemeToolsVersion() async throws { - try skipOnWindowsAsTestCurrentlyFails() - - let fs = InMemoryFileSystem() - for pair in [ (ToolsVersion.v5_2, ToolsVersion.v5_2), (ToolsVersion.v5_6, ToolsVersion.v5_6), (ToolsVersion.v5_2, ToolsVersion.v5_6), ] { + let fs = InMemoryFileSystem() let sandbox = AbsolutePath("/tmp/ws/") let workspace = try await MockWorkspace( sandbox: sandbox, @@ -4045,16 +3949,16 @@ final class WorkspaceTests: XCTestCase { let minToolsVersion = [pair.0, pair.1].min()! let expectedSchemeVersion = minToolsVersion >= .v5_6 ? 2 : 1 + let actualSchemeVersion = try workspace.getOrCreateWorkspace().resolvedPackagesStore.load().schemeVersion() XCTAssertEqual( - try workspace.getOrCreateWorkspace().resolvedPackagesStore.load().schemeVersion(), - expectedSchemeVersion + actualSchemeVersion, + expectedSchemeVersion, + "Actual scheme version (\(actualSchemeVersion)) is not as expected (\(expectedSchemeVersion)). Pair 0 (\(pair.0)) pair 1 (\(pair.1))" ) } } func testResolvedFileStableCanonicalLocation() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -4297,8 +4201,6 @@ final class WorkspaceTests: XCTestCase { } func testPreferResolvedFileWhenExists() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -4554,21 +4456,19 @@ final class WorkspaceTests: XCTestCase { } } } + } - // util - func checkPinnedVersion(pin: ResolvedPackagesStore.ResolvedPackage, version: Version) { - switch pin.state { - case .version(let pinnedVersion, _): - XCTAssertEqual(pinnedVersion, version) - default: - XCTFail("non-version pin \(pin.state)") - } + // util + func checkPinnedVersion(pin: ResolvedPackagesStore.ResolvedPackage, version: Version) { + switch pin.state { + case .version(let pinnedVersion, _): + XCTAssertEqual(pinnedVersion, version) + default: + XCTFail("non-version pin \(pin.state)") } } func testPackageSimpleMirrorPath() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -4661,8 +4561,6 @@ final class WorkspaceTests: XCTestCase { } func testPackageMirrorPath() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -4766,8 +4664,6 @@ final class WorkspaceTests: XCTestCase { } func testPackageSimpleMirrorURL() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -4857,8 +4753,6 @@ final class WorkspaceTests: XCTestCase { } func testPackageMirrorURL() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -4964,8 +4858,6 @@ final class WorkspaceTests: XCTestCase { } func testPackageMirrorURLToRegistry() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5036,8 +4928,6 @@ final class WorkspaceTests: XCTestCase { } func testPackageMirrorRegistryToURL() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5111,8 +5001,6 @@ final class WorkspaceTests: XCTestCase { // file for a transitive dependency whose URL is later changed to // something else, while keeping the same package identity. func testTransitiveDependencySwitchWithSameIdentity() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5266,8 +5154,6 @@ final class WorkspaceTests: XCTestCase { } func testForceResolveToResolvedVersions() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5394,8 +5280,6 @@ final class WorkspaceTests: XCTestCase { } func testForceResolveToResolvedVersionsDuplicateLocalDependency() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5447,8 +5331,6 @@ final class WorkspaceTests: XCTestCase { } func testForceResolveWithNoResolvedFile() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5506,8 +5388,6 @@ final class WorkspaceTests: XCTestCase { } func testForceResolveToResolvedVersionsLocalPackage() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5549,8 +5429,6 @@ final class WorkspaceTests: XCTestCase { } func testForceResolveToResolvedVersionsLocalPackageInAdditionalDependencies() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5652,8 +5530,6 @@ final class WorkspaceTests: XCTestCase { } func testRevisionDepOnLocal() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5712,8 +5588,6 @@ final class WorkspaceTests: XCTestCase { } func testRootPackagesOverrideBasenameMismatch() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5764,8 +5638,6 @@ final class WorkspaceTests: XCTestCase { } func testManagedDependenciesNotCaseSensitive() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5860,8 +5732,6 @@ final class WorkspaceTests: XCTestCase { } func testUnsafeFlags() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5942,8 +5812,6 @@ final class WorkspaceTests: XCTestCase { } func testUnsafeFlagsInFoundation() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -5993,8 +5861,6 @@ final class WorkspaceTests: XCTestCase { } func testEditDependencyHadOverridableConstraints() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -6096,8 +5962,6 @@ final class WorkspaceTests: XCTestCase { } func testTargetBasedDependency() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -6206,8 +6070,6 @@ final class WorkspaceTests: XCTestCase { } func testLocalArchivedArtifactExtractionHappyPath() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -6312,17 +6174,17 @@ final class WorkspaceTests: XCTestCase { try fs.writeFileContents(bFrameworkArchivePath, bytes: ByteString([0xB0])) // Ensure that the artifacts do not exist yet - XCTAssertFalse(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/A/A1.xcframework"))) - XCTAssertFalse(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/A/A2.artifactbundle"))) - XCTAssertFalse(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/B/B.xcframework"))) + XCTAssertFalse(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "A", "A1.xcframework"]))) + XCTAssertFalse(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "A", "A2", "artifactbundle"]))) + XCTAssertFalse(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "B", "B", "xcframework"]))) try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) // Ensure that the artifacts have been properly extracted - XCTAssertTrue(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/a/A1/A1.xcframework"))) - XCTAssertTrue(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/a/A2/A2.artifactbundle"))) - XCTAssertTrue(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/b/B/B.xcframework"))) + XCTAssertTrue(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "a", "A1", "A1.xcframework"]))) + XCTAssertTrue(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "a", "A2", "A2.artifactbundle"]))) + XCTAssertTrue(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "b", "B", "B.xcframework"]))) // Ensure that the original archives have been untouched XCTAssertTrue(fs.exists(a1FrameworkArchivePath)) @@ -6331,15 +6193,15 @@ final class WorkspaceTests: XCTestCase { // Ensure that the temporary folders have been properly created XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A1"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A2"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/b/B"), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), + sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), ]) // Ensure that the temporary directories have been removed - XCTAssertTrue(try! fs.getDirectoryContents(AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A1")).isEmpty) - XCTAssertTrue(try! fs.getDirectoryContents(AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A2")).isEmpty) - XCTAssertTrue(try! fs.getDirectoryContents(AbsolutePath("/tmp/ws/.build/artifacts/extract/b/B")).isEmpty) + XCTAssertTrue(try! fs.getDirectoryContents(sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"])).isEmpty) + XCTAssertTrue(try! fs.getDirectoryContents(sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"])).isEmpty) + XCTAssertTrue(try! fs.getDirectoryContents(sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"])).isEmpty) } await workspace.checkManagedArtifacts { result in @@ -6378,8 +6240,6 @@ final class WorkspaceTests: XCTestCase { // It ensures that all the appropriate clean-up operations are executed, and the workspace // contains the correct set of managed artifacts after the transition. func testLocalArchivedArtifactSourceTransitionPermutations() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -6595,31 +6455,31 @@ final class WorkspaceTests: XCTestCase { XCTAssertTrue(fs.exists(a4FrameworkArchivePath)) // Ensure that the new artifacts have been properly extracted - XCTAssertTrue(try fs.exists(AbsolutePath(validating: "/tmp/ws/.build/artifacts/a/A1/\(a1FrameworkName)"))) + XCTAssertTrue(try fs.exists(AbsolutePath(validating: "\(sandbox)/.build/artifacts/a/A1/\(a1FrameworkName)"))) XCTAssertTrue( try fs .exists( - AbsolutePath(validating: "/tmp/ws/.build/artifacts/a/A3/\(a3FrameworkName)/local-archived") + AbsolutePath(validating: "\(sandbox)/.build/artifacts/a/A3/\(a3FrameworkName)/local-archived") ) ) XCTAssertTrue( try fs - .exists(AbsolutePath(validating: "/tmp/ws/.build/artifacts/a/A4/\(a4FrameworkName)/remote")) + .exists(AbsolutePath(validating: "\(sandbox)/.build/artifacts/a/A4/\(a4FrameworkName)/remote")) ) // Ensure that the old artifacts have been removed - XCTAssertFalse(try fs.exists(AbsolutePath(validating: "/tmp/ws/.build/artifacts/a/A2/\(a2FrameworkName)"))) + XCTAssertFalse(try fs.exists(AbsolutePath(validating: "\(sandbox)/.build/artifacts/a/A2/\(a2FrameworkName)"))) XCTAssertFalse( try fs - .exists(AbsolutePath(validating: "/tmp/ws/.build/artifacts/a/A3/\(a3FrameworkName)/remote")) + .exists(AbsolutePath(validating: "\(sandbox)/.build/artifacts/a/A3/\(a3FrameworkName)/remote")) ) XCTAssertFalse( try fs .exists( - AbsolutePath(validating: "/tmp/ws/.build/artifacts/a/A4/\(a4FrameworkName)/local-archived") + AbsolutePath(validating: "\(sandbox)/.build/artifacts/a/A4/\(a4FrameworkName)/local-archived") ) ) - XCTAssertFalse(try fs.exists(AbsolutePath(validating: "/tmp/ws/.build/artifacts/a/A5/\(a5FrameworkName)"))) + XCTAssertFalse(try fs.exists(AbsolutePath(validating: "\(sandbox)/.build/artifacts/a/A5/\(a5FrameworkName)"))) } await workspace.checkManagedArtifacts { result in @@ -6651,10 +6511,8 @@ final class WorkspaceTests: XCTestCase { } func testLocalArchivedArtifactNameDoesNotMatchTargetName() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") - let fs = InMemoryFileSystem() + let fs: InMemoryFileSystem = InMemoryFileSystem() // create a dummy xcframework directory from the request archive let archiver = MockArchiver(handler: { archiver, archivePath, destinationPath, completion in @@ -6712,8 +6570,6 @@ final class WorkspaceTests: XCTestCase { } func testLocalArchivedArtifactExtractionError() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -6765,8 +6621,6 @@ final class WorkspaceTests: XCTestCase { } func testLocalArchiveDoesNotMatchTargetName() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -6843,8 +6697,6 @@ final class WorkspaceTests: XCTestCase { ////// STAET ATDIN func testLocalArchivedArtifactChecksumChange() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -6928,7 +6780,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, _ in // Ensure that only the artifact archive with the changed checksum has been extracted XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/A1"), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), ]) } @@ -6949,8 +6801,6 @@ final class WorkspaceTests: XCTestCase { } func testLocalArchivedArtifactStripFirstComponent() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -7024,17 +6874,17 @@ final class WorkspaceTests: XCTestCase { try fs.writeFileContents(archivesPath.appending("nested2.zip"), bytes: ByteString([0x3])) // ensure that the artifacts do not exist yet - XCTAssertFalse(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/root/flat/flat.xcframework"))) - XCTAssertFalse(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/root/nested/nested.artifactbundle"))) - XCTAssertFalse(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/root/nested2/nested2.xcframework"))) + XCTAssertFalse(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root", "flat", "flat.xcframework"]))) + XCTAssertFalse(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root", "nested", "nested.artifactbundle"]))) + XCTAssertFalse(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root", "nested2", "nested2.xcframework"]))) try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/root"))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root"]))) XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/flat"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/nested"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/nested2"), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "flat"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested2"]), ]) } @@ -7061,9 +6911,7 @@ final class WorkspaceTests: XCTestCase { } func testLocalArtifactHappyPath() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - - let sandbox = AbsolutePath("/tmp/ws/") + let sandbox = AbsolutePath("/tmp/ws") let fs = InMemoryFileSystem() let workspace = try await MockWorkspace( @@ -7115,8 +6963,6 @@ final class WorkspaceTests: XCTestCase { } func testLocalArtifactDoesNotExist() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -7146,13 +6992,13 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.checkUnordered( diagnostic: .contains( - "local binary target 'A1' at '\(AbsolutePath("/tmp/ws/roots/Root/XCFrameworks/incorrect.xcframework"))' does not contain a binary artifact." + "local binary target 'A1' at '\(sandbox.appending(components: ["roots", "Root", "XCFrameworks", "incorrect.xcframework"]))' does not contain a binary artifact." ), severity: .error ) result.checkUnordered( diagnostic: .contains( - "local binary target 'A2' at '\(AbsolutePath("/tmp/ws/roots/Root/ArtifactBundles/incorrect.artifactbundle"))' does not contain a binary artifact." + "local binary target 'A2' at '\(sandbox.appending(components: ["roots", "Root", "ArtifactBundles", "incorrect.artifactbundle"]))' does not contain a binary artifact." ), severity: .error ) @@ -7161,8 +7007,6 @@ final class WorkspaceTests: XCTestCase { } func testArtifactDownloadHappyPath() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let downloads = ThreadSafeKeyValueStore() @@ -7284,8 +7128,8 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/a"))) - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/b"))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "a"]))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "b"]))) XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ "https://a.com/a1.zip", "https://a.com/a2.zip", @@ -7297,9 +7141,9 @@ final class WorkspaceTests: XCTestCase { ByteString([0xB0]).hexadecimalRepresentation, ]) XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A1"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A2"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/b/B"), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), + sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), ]) XCTAssertEqual( downloads.map(\.value).sorted(), @@ -7352,8 +7196,6 @@ final class WorkspaceTests: XCTestCase { } func testArtifactDownloadWithPreviousState() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let downloads = ThreadSafeKeyValueStore() @@ -7581,14 +7423,14 @@ final class WorkspaceTests: XCTestCase { severity: .error ) } - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/b"))) - XCTAssert(fs.exists(AbsolutePath("/tmp/ws/.build/artifacts/a/A1/A1.xcframework"))) - XCTAssert(fs.exists(AbsolutePath("/tmp/ws/.build/artifacts/a/A2/A2.xcframework"))) - XCTAssert(!fs.exists(AbsolutePath("/tmp/ws/.build/artifacts/a/A3/A3.xcframework"))) - XCTAssert(!fs.exists(AbsolutePath("/tmp/ws/.build/artifacts/a/A4/A4.xcframework"))) - XCTAssert(!fs.exists(AbsolutePath("/tmp/ws/.build/artifacts/a/A5/A5.xcframework"))) - XCTAssert(fs.exists(AbsolutePath("/tmp/ws/pkgs/a/XCFrameworks/A7.xcframework"))) - XCTAssert(!fs.exists(AbsolutePath("/tmp/ws/.build/artifacts/Foo"))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "b"]))) + XCTAssert(fs.exists(sandbox.appending(components: [".build", "artifacts", "a", "A1", "A1.xcframework"]))) + XCTAssert(fs.exists(sandbox.appending(components: [".build", "artifacts", "a", "A2", "A2.xcframework"]))) + XCTAssert(!fs.exists(sandbox.appending(components: [".build", "artifacts", "a", "A3", "A3.xcframework"]))) + XCTAssert(!fs.exists(sandbox.appending(components: [".build", "artifacts", "a", "A4", "A4.xcframework"]))) + XCTAssert(!fs.exists(sandbox.appending(components: [".build", "artifacts", "a", "A5", "A5.xcframework"]))) + XCTAssert(fs.exists(sandbox.appending(components: ["pkgs", "a", "XCFrameworks", "A7.xcframework"]))) + XCTAssert(!fs.exists(sandbox.appending(components: [".build", "artifacts", "Foo"]))) XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ "https://a.com/a2.zip", "https://a.com/a3.zip", @@ -7602,10 +7444,10 @@ final class WorkspaceTests: XCTestCase { ByteString([0xB0]).hexadecimalRepresentation, ]) XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A2"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A3"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A7"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/b/B"), + sandbox.appending(components: [".build", "artifacts", "extract","a", "A2"]), + sandbox.appending(components: [".build", "artifacts", "extract","a", "A3"]), + sandbox.appending(components: [".build", "artifacts", "extract","a", "A7"]), + sandbox.appending(components: [".build", "artifacts", "extract","b", "B"]), ]) XCTAssertEqual( downloads.map(\.value).sorted(), @@ -7662,8 +7504,6 @@ final class WorkspaceTests: XCTestCase { } func testArtifactDownloadTwice() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let downloads = ThreadSafeArrayStore<(URL, AbsolutePath)>() @@ -7740,7 +7580,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/root"))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root"]))) XCTAssertEqual(workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), [ ByteString([0xA1]).hexadecimalRepresentation, ]) @@ -7750,7 +7590,7 @@ final class WorkspaceTests: XCTestCase { "https://a.com/a1.zip", ]) XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/A1"), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), ]) XCTAssertEqual( downloads.map(\.1).sorted(), @@ -7765,7 +7605,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/root"))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root"]))) XCTAssertEqual(workspace.checksumAlgorithm.hashes.map(\.hexadecimalRepresentation).sorted(), [ ByteString([0xA1]).hexadecimalRepresentation, ByteString([0xA1]).hexadecimalRepresentation, @@ -7776,8 +7616,8 @@ final class WorkspaceTests: XCTestCase { "https://a.com/a1.zip", "https://a.com/a1.zip", ]) XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/A1"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/A1"), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), ]) XCTAssertEqual( downloads.map(\.1).sorted(), @@ -7786,8 +7626,6 @@ final class WorkspaceTests: XCTestCase { } func testArtifactDownloadServerError() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let fs = InMemoryFileSystem() let sandbox = AbsolutePath("/tmp/ws/") try fs.createDirectory(sandbox, recursive: true) @@ -7841,8 +7679,8 @@ final class WorkspaceTests: XCTestCase { } // make sure artifact downloaded is deleted - XCTAssertTrue(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/root"))) - XCTAssertFalse(fs.exists(AbsolutePath("/tmp/ws/.build/artifacts/root/a.zip"))) + XCTAssertTrue(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root"]))) + XCTAssertFalse(fs.exists(sandbox.appending(components: [".build", "artifacts", "root", "a.zip"]))) // make sure the cached artifact is also deleted let artifactCacheKey = artifactUrl.spm_mangledToC99ExtendedIdentifier() @@ -7858,8 +7696,6 @@ final class WorkspaceTests: XCTestCase { } func testArtifactDownloaderOrArchiverError() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -7884,7 +7720,7 @@ final class WorkspaceTests: XCTestCase { } let archiver = MockArchiver(handler: { _, _, destinationPath, completion in - XCTAssertEqual(destinationPath.parentDirectory, AbsolutePath("/tmp/ws/.build/artifacts/extract/root/A2")) + XCTAssertEqual(destinationPath.parentDirectory, sandbox.appending(components: [".build", "artifacts", "extract", "root", "A2"])) completion(.failure(DummyError())) }) @@ -7946,9 +7782,8 @@ final class WorkspaceTests: XCTestCase { } } - func testDownloadedArtifactNotAnArchiveError() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) + func testDownloadedArtifactNotAnArchiveError() async throws { let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -8057,8 +7892,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactInvalid() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -8130,8 +7963,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactDoesNotMatchTargetName() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -8207,11 +8038,14 @@ final class WorkspaceTests: XCTestCase { } func testArtifactChecksum() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) + try skipOnWindowsAsTestCurrentlyFails(because: #""" + threw error "\tmp\ws doesn't exist in file system" because there is an issue with InMemoryFileSystem readFileContents(...) on Windows + """#) let fs = InMemoryFileSystem() try fs.createMockToolchain() let sandbox = AbsolutePath("/tmp/ws/") + try fs.createDirectory(sandbox, recursive: true) let checksumAlgorithm = MockHashAlgorithm() @@ -8281,8 +8115,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactChecksumChange() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -8335,8 +8167,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactChecksumChangeURLChange() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -8428,8 +8258,6 @@ final class WorkspaceTests: XCTestCase { } func testArtifactDownloadAddsAcceptHeader() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let acceptHeaders = ThreadSafeBox([String]()) @@ -8506,8 +8334,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactNoCache() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let downloads = ThreadSafeBox(0) @@ -8597,8 +8423,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactCache() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let downloads = ThreadSafeBox(0) @@ -8703,8 +8527,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactTransitive() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let downloads = ThreadSafeKeyValueStore() @@ -8845,7 +8667,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/a"))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "a"]))) XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ "https://a.com/a.zip", ]) @@ -8853,7 +8675,7 @@ final class WorkspaceTests: XCTestCase { ByteString([0xA]).hexadecimalRepresentation, ]) XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A"), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A"]), ]) XCTAssertEqual( downloads.map(\.value).sorted(), @@ -8875,8 +8697,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactArchiveExists() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() // this relies on internal knowledge of the destination path construction @@ -8989,8 +8809,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactConcurrency() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -9103,8 +8921,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadedArtifactStripFirstComponent() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() let downloads = ThreadSafeKeyValueStore() @@ -9211,7 +9027,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/root"))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "root"]))) XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ "https://a.com/flat.zip", "https://a.com/nested.zip", @@ -9223,9 +9039,9 @@ final class WorkspaceTests: XCTestCase { ByteString([0x03]).hexadecimalRepresentation, ]) XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/flat"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/nested"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/nested2"), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "flat"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "nested2"]), ]) XCTAssertEqual( downloads.map(\.value).sorted(), @@ -9265,10 +9081,8 @@ final class WorkspaceTests: XCTestCase { } func testArtifactMultipleExtensions() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") - let fs = InMemoryFileSystem() + let fs: InMemoryFileSystem = InMemoryFileSystem() let downloads = ThreadSafeKeyValueStore() // returns a dummy zipfile for the requested artifact @@ -9359,8 +9173,8 @@ final class WorkspaceTests: XCTestCase { ByteString([0xA2]).hexadecimalRepresentation, ]) XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/A1"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/root/A2"), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "root", "A2"]), ]) XCTAssertEqual( downloads.map(\.value).sorted(), @@ -9391,8 +9205,6 @@ final class WorkspaceTests: XCTestCase { } func testLoadRootPackageWithBinaryDependencies() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -9437,8 +9249,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadArchiveIndexFilesHappyPath() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() try fs.createMockToolchain() @@ -9606,8 +9416,8 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/a"))) - XCTAssert(fs.isDirectory(AbsolutePath("/tmp/ws/.build/artifacts/b"))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "a"]))) + XCTAssert(fs.isDirectory(sandbox.appending(components: [".build", "artifacts", "b"]))) XCTAssertEqual(downloads.map(\.key.absoluteString).sorted(), [ "https://a.com/a1.zip", "https://a.com/a2/a2.zip", @@ -9626,9 +9436,9 @@ final class WorkspaceTests: XCTestCase { ).map(\.hexadecimalRepresentation).sorted() ) XCTAssertEqual(archiver.extractions.map(\.destinationPath.parentDirectory).sorted(), [ - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A1"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/a/A2"), - AbsolutePath("/tmp/ws/.build/artifacts/extract/b/B"), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A1"]), + sandbox.appending(components: [".build", "artifacts", "extract", "a", "A2"]), + sandbox.appending(components: [".build", "artifacts", "extract", "b", "B"]), ]) XCTAssertEqual( downloads.map(\.value).sorted(), @@ -9681,8 +9491,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadArchiveIndexServerError() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -9725,8 +9533,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadArchiveIndexFileBadChecksum() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() try fs.createMockToolchain() @@ -9793,8 +9599,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadArchiveIndexFileChecksumChanges() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -9845,8 +9649,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadArchiveIndexFileBadArchivesChecksum() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() try fs.createMockToolchain() @@ -9954,8 +9756,6 @@ final class WorkspaceTests: XCTestCase { } func testDownloadArchiveIndexFileArchiveNotFound() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() try fs.createMockToolchain() @@ -10028,10 +9828,9 @@ final class WorkspaceTests: XCTestCase { } func testDownloadArchiveIndexTripleNotFound() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() + try fs.createMockToolchain() let hostToolchain = try UserToolchain.mockHostToolchain(fs) @@ -10100,8 +9899,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateDependencyIdentityWithNameAtRoot() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10163,7 +9960,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: "Conflicting identity for utility: dependency '/tmp/ws/pkgs/bar/utility' and dependency '/tmp/ws/pkgs/foo/utility' both point to the same package identity 'utility'.", + diagnostic: "Conflicting identity for utility: dependency '\(CanonicalPackageLocation(sandbox.pathString))/pkgs/bar/utility' and dependency '\(CanonicalPackageLocation(sandbox.pathString))/pkgs/foo/utility' both point to the same package identity 'utility'.", severity: .error ) } @@ -10171,8 +9968,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateDependencyIdentityWithoutNameAtRoot() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10225,8 +10020,9 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( - diagnostic: "Conflicting identity for utility: dependency '/tmp/ws/pkgs/bar/utility' and dependency '/tmp/ws/pkgs/foo/utility' both point to the same package identity 'utility'.", + diagnostic: "Conflicting identity for utility: dependency '\(tmpDirCanonicalPackageLocation)/pkgs/bar/utility' and dependency '\(tmpDirCanonicalPackageLocation)/pkgs/foo/utility' both point to the same package identity 'utility'.", severity: .error ) } @@ -10234,8 +10030,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateExplicitDependencyName_AtRoot() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10305,8 +10099,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateManifestNameAtRoot() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10362,8 +10154,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateManifestName_ExplicitProductPackage_AtRoot() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10419,8 +10209,6 @@ final class WorkspaceTests: XCTestCase { } func testManifestNameAndIdentityConflict_AtRoot_Pre52() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10476,8 +10264,6 @@ final class WorkspaceTests: XCTestCase { } func testManifestNameAndIdentityConflict_AtRoot_Post52_Incorrect() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10542,8 +10328,6 @@ final class WorkspaceTests: XCTestCase { } func testManifestNameAndIdentityConflict_AtRoot_Post52_Correct() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10599,8 +10383,6 @@ final class WorkspaceTests: XCTestCase { } func testManifestNameAndIdentityConflict_ExplicitDependencyNames_AtRoot() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10665,8 +10447,6 @@ final class WorkspaceTests: XCTestCase { } func testManifestNameAndIdentityConflict_ExplicitDependencyNames_ExplicitProductPackage_AtRoot() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10731,8 +10511,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateTransitiveIdentityWithNames() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10813,8 +10591,9 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( - diagnostic: "Conflicting identity for utility: dependency '/tmp/ws/pkgs/other/utility' and dependency '/tmp/ws/pkgs/foo/utility' both point to the same package identity 'utility'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->/tmp/ws/pkgs/bar->/tmp/ws/pkgs/other/utility (B) /tmp/ws/roots/root->/tmp/ws/pkgs/foo/utility. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency.", + diagnostic: "Conflicting identity for utility: dependency '\(tmpDirCanonicalPackageLocation)/pkgs/other/utility' and dependency '\(tmpDirCanonicalPackageLocation)/pkgs/foo/utility' both point to the same package identity 'utility'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->\(tmpDirCanonicalPackageLocation)/pkgs/bar->\(tmpDirCanonicalPackageLocation)/pkgs/other/utility (B) \(tmpDirCanonicalPackageLocation)/roots/root->\(tmpDirCanonicalPackageLocation)/pkgs/foo/utility. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency.", severity: .error ) } @@ -10822,9 +10601,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateTransitiveIdentityMultiplePossibleChains() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #""" - threw error "\tmp\ws doesn't exist in file system" - """#) let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -10969,22 +10745,26 @@ final class WorkspaceTests: XCTestCase { ] ) + let sandboxCanonicalPackageLocation: CanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in result.check( - diagnostic: "Conflicting identity for glass: dependency '/tmp/ws/pkgs/tempered/glass' and dependency '/tmp/ws/pkgs/standard/glass' both point to the same package identity 'glass'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->/tmp/ws/pkgs/house->/tmp/ws/pkgs/premium_window->/tmp/ws/pkgs/tempered/glass (B) /tmp/ws/roots/root->/tmp/ws/pkgs/shack->/tmp/ws/pkgs/standard/glass. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency.", + diagnostic: "Conflicting identity for glass: dependency '\(sandboxCanonicalPackageLocation)/pkgs/tempered/glass' and dependency '\(sandboxCanonicalPackageLocation)/pkgs/standard/glass' both point to the same package identity 'glass'. The dependencies are introduced through the following chains: (A) \(sandboxCanonicalPackageLocation)/roots/root->\(sandboxCanonicalPackageLocation)/pkgs/house->\(sandboxCanonicalPackageLocation)/pkgs/premium_window->\(sandboxCanonicalPackageLocation)/pkgs/tempered/glass (B) \(sandboxCanonicalPackageLocation)/roots/root->\(sandboxCanonicalPackageLocation)/pkgs/shack->\(sandboxCanonicalPackageLocation)/pkgs/standard/glass. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency.", severity: .error ) } } try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in testPartialDiagnostics(diagnostics, minSeverity: .debug) { result in + let prefix1 = sandbox.appending(components: ["pkgs", "tempered", "glass"]) result.checkUnordered( - diagnostic: .contains("Conflicting identity for glass: chains of dependencies for /tmp/ws/pkgs/tempered/glass: [[/tmp/ws/roots/root, /tmp/ws/pkgs/house, /tmp/ws/pkgs/premium_window, /tmp/ws/pkgs/tempered/glass]]"), + diagnostic: .contains("Conflicting identity for glass: chains of dependencies for \(prefix1): [[\(sandboxCanonicalPackageLocation)/roots/root, \(sandboxCanonicalPackageLocation)/pkgs/house, \(sandboxCanonicalPackageLocation)/pkgs/premium_window, \(sandboxCanonicalPackageLocation)/pkgs/tempered/glass]]"), severity: .debug ) + + let prefix2 = sandbox.appending(components: ["pkgs", "standard", "glass"]) result.checkUnordered( - diagnostic: .contains("Conflicting identity for glass: chains of dependencies for /tmp/ws/pkgs/standard/glass: [[/tmp/ws/roots/root, /tmp/ws/pkgs/shack, /tmp/ws/pkgs/standard/glass], [/tmp/ws/roots/root, /tmp/ws/pkgs/house, /tmp/ws/pkgs/budget_window, /tmp/ws/pkgs/standard/glass]]"), + diagnostic: .contains("Conflicting identity for glass: chains of dependencies for \(prefix2): [[\(sandboxCanonicalPackageLocation)/roots/root, \(sandboxCanonicalPackageLocation)/pkgs/shack, \(sandboxCanonicalPackageLocation)/pkgs/standard/glass], [\(sandboxCanonicalPackageLocation)/roots/root, \(sandboxCanonicalPackageLocation)/pkgs/house, \(sandboxCanonicalPackageLocation)/pkgs/budget_window, \(sandboxCanonicalPackageLocation)/pkgs/standard/glass]]"), severity: .debug ) } @@ -10992,10 +10772,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateIdentityDependenciesMultipleRoots() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #""" - threw error "\tmp\ws doesn't exist in file system" - """#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11068,12 +10844,16 @@ final class WorkspaceTests: XCTestCase { testPartialDiagnostics(diagnostics, minSeverity: .debug) { result in // Order of roots processing is not deterministic. To make the test less brittle, we check debug // output of individual conflicts instead of a summarized error message. + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) + let prefix = sandbox.appending(components: ["pkgs", "standing", "water"]) result.checkUnordered( - diagnostic: .contains("Conflicting identity for water: chains of dependencies for /tmp/ws/pkgs/standing/water: [[/tmp/ws/roots/lake, /tmp/ws/pkgs/standing/water]]"), + diagnostic: .contains("Conflicting identity for water: chains of dependencies for \(prefix): [[\(tmpDirCanonicalPackageLocation)/roots/lake, \(tmpDirCanonicalPackageLocation)/pkgs/standing/water]]"), severity: .debug ) + + let prefix2 = sandbox.appending(components: ["pkgs", "flowing", "water"]) result.checkUnordered( - diagnostic: .contains("Conflicting identity for water: chains of dependencies for /tmp/ws/pkgs/flowing/water: [[/tmp/ws/roots/river, /tmp/ws/pkgs/flowing/water]]"), + diagnostic: .contains("Conflicting identity for water: chains of dependencies for \(prefix2): [[\(tmpDirCanonicalPackageLocation)/roots/river, \(tmpDirCanonicalPackageLocation)/pkgs/flowing/water]]"), severity: .debug ) } @@ -11081,8 +10861,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateTransitiveIdentityWithoutNames() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11153,8 +10931,9 @@ final class WorkspaceTests: XCTestCase { // we will escalate this to an error in a few versions to tighten up the validation try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( - diagnostic: "Conflicting identity for utility: dependency '/tmp/ws/pkgs/other-foo/utility' and dependency '/tmp/ws/pkgs/foo/utility' both point to the same package identity 'utility'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->/tmp/ws/pkgs/bar->/tmp/ws/pkgs/other-foo/utility (B) /tmp/ws/roots/root->/tmp/ws/pkgs/foo/utility. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency. This will be escalated to an error in future versions of SwiftPM.", + diagnostic: "Conflicting identity for utility: dependency '\(tmpDirCanonicalPackageLocation)/pkgs/other-foo/utility' and dependency '\(tmpDirCanonicalPackageLocation)/pkgs/foo/utility' both point to the same package identity 'utility'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->\(tmpDirCanonicalPackageLocation)/pkgs/bar->\(tmpDirCanonicalPackageLocation)/pkgs/other-foo/utility (B) \(tmpDirCanonicalPackageLocation)/roots/root->\(tmpDirCanonicalPackageLocation)/pkgs/foo/utility. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency. This will be escalated to an error in future versions of SwiftPM.", severity: .warning ) // FIXME: rdar://72940946 @@ -11168,8 +10947,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateTransitiveIdentitySimilarURLs1() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11245,8 +11022,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateTransitiveIdentitySimilarURLs2() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11322,8 +11097,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateTransitiveIdentityGitHubURLs1() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11399,8 +11172,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateTransitiveIdentityGitHubURLs2() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11479,8 +11250,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateTransitiveIdentityUnfamiliarURLs() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11557,8 +11326,9 @@ final class WorkspaceTests: XCTestCase { // we will escalate this to an error in a few versions to tighten up the validation try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( - diagnostic: "Conflicting identity for foo: dependency 'github.com/foo-moved/foo' and dependency 'github.com/foo/foo' both point to the same package identity 'foo'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->/tmp/ws/pkgs/bar->github.com/foo-moved/foo (B) /tmp/ws/roots/root->github.com/foo/foo. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency. This will be escalated to an error in future versions of SwiftPM.", + diagnostic: "Conflicting identity for foo: dependency 'github.com/foo-moved/foo' and dependency 'github.com/foo/foo' both point to the same package identity 'foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->\(tmpDirCanonicalPackageLocation)/pkgs/bar->github.com/foo-moved/foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->github.com/foo/foo. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency. This will be escalated to an error in future versions of SwiftPM.", severity: .warning ) } @@ -11566,8 +11336,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateTransitiveIdentityWithSimilarURLs() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11690,8 +11458,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateNestedTransitiveIdentityWithNames() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11775,8 +11541,9 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { _, diagnostics in testDiagnostics(diagnostics) { result in + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( - diagnostic: "Conflicting identity for utility: dependency '/tmp/ws/pkgs/other/utility' and dependency '/tmp/ws/pkgs/foo/utility' both point to the same package identity 'utility'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->/tmp/ws/pkgs/foo/utility->/tmp/ws/pkgs/bar->/tmp/ws/pkgs/other/utility (B) /tmp/ws/roots/root->/tmp/ws/pkgs/foo/utility. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency.", + diagnostic: "Conflicting identity for utility: dependency '\(tmpDirCanonicalPackageLocation)/pkgs/other/utility' and dependency '\(tmpDirCanonicalPackageLocation)/pkgs/foo/utility' both point to the same package identity 'utility'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->\(tmpDirCanonicalPackageLocation)/pkgs/foo/utility->\(tmpDirCanonicalPackageLocation)/pkgs/bar->\(tmpDirCanonicalPackageLocation)/pkgs/other/utility (B) \(tmpDirCanonicalPackageLocation)/roots/root->\(tmpDirCanonicalPackageLocation)/pkgs/foo/utility. If there are multiple chains that lead to the same dependency, only the first chain is shown here. To see all chains use debug output option. To resolve the conflict, coordinate with the maintainer of the package that introduces the conflicting dependency.", severity: .error ) } @@ -11784,8 +11551,6 @@ final class WorkspaceTests: XCTestCase { } func testDuplicateNestedTransitiveIdentityWithoutNames() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11870,8 +11635,6 @@ final class WorkspaceTests: XCTestCase { } func testRootPathConflictsWithTransitiveIdentity() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -11947,8 +11710,6 @@ final class WorkspaceTests: XCTestCase { } func testDeterministicURLPreference() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -12110,8 +11871,6 @@ final class WorkspaceTests: XCTestCase { } func testDeterministicURLPreferenceWithRoot() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -12251,8 +12010,6 @@ final class WorkspaceTests: XCTestCase { } func testCanonicalURLWithPreviousManagedState() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -12415,8 +12172,6 @@ final class WorkspaceTests: XCTestCase { } func testCanonicalURLChanges() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -12530,8 +12285,6 @@ final class WorkspaceTests: XCTestCase { } func testCanonicalURLChangesWithTransitiveDependencies() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -12698,8 +12451,6 @@ final class WorkspaceTests: XCTestCase { } func testCycleRoot() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -12816,8 +12567,6 @@ final class WorkspaceTests: XCTestCase { } func testResolutionBranchAndVersion() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -13030,8 +12779,6 @@ final class WorkspaceTests: XCTestCase { } func testBasicResolutionFromSourceControl() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -13138,8 +12885,6 @@ final class WorkspaceTests: XCTestCase { } func testBasicTransitiveResolutionFromSourceControl() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -13284,8 +13029,6 @@ final class WorkspaceTests: XCTestCase { } func testBasicResolutionFromRegistry() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -13392,8 +13135,6 @@ final class WorkspaceTests: XCTestCase { } func testBasicTransitiveResolutionFromRegistry() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -13538,8 +13279,6 @@ final class WorkspaceTests: XCTestCase { } func testTransitiveResolutionFromRegistryWithByNameDependencies() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -13620,8 +13359,6 @@ final class WorkspaceTests: XCTestCase { // no dups func testResolutionMixedRegistryAndSourceControl1() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -13752,8 +13489,6 @@ final class WorkspaceTests: XCTestCase { } func testTransitiveResolutionFromRegistryWithDifferentPackageNameCasing() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -13819,8 +13554,6 @@ final class WorkspaceTests: XCTestCase { // duplicate package at root level func testResolutionMixedRegistryAndSourceControl2() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -13920,8 +13653,6 @@ final class WorkspaceTests: XCTestCase { // mixed graph root --> dep1 scm // --> dep2 scm --> dep1 registry func testResolutionMixedRegistryAndSourceControl3() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -14011,9 +13742,10 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in testDiagnostics(diagnostics) { result in + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( diagnostic: .contains(""" - dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->git/org/bar->org.foo (B) /tmp/ws/roots/root->git/org/foo. + dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. """), severity: .warning ) @@ -14085,8 +13817,6 @@ final class WorkspaceTests: XCTestCase { // mixed graph root --> dep1 scm // --> dep2 registry --> dep1 registry func testResolutionMixedRegistryAndSourceControl4() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -14176,9 +13906,10 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in testDiagnostics(diagnostics) { result in + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( diagnostic: .contains(""" - dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->org.bar->org.foo (B) /tmp/ws/roots/root->git/org/foo. + dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. """), severity: .warning ) @@ -14225,8 +13956,6 @@ final class WorkspaceTests: XCTestCase { // mixed graph root --> dep1 scm // --> dep2 scm --> dep1 registry incompatible version func testResolutionMixedRegistryAndSourceControl5() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -14352,8 +14081,6 @@ final class WorkspaceTests: XCTestCase { // mixed graph root --> dep1 registry // --> dep2 registry --> dep1 scm func testResolutionMixedRegistryAndSourceControl6() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -14442,10 +14169,11 @@ final class WorkspaceTests: XCTestCase { workspace.sourceControlToRegistryDependencyTransformation = .identity try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) testDiagnostics(diagnostics) { result in result.check( diagnostic: .contains(""" - dependency 'git/org/foo' and dependency 'org.foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->org.bar->git/org/foo (B) /tmp/ws/roots/root->org.foo. + dependency 'git/org/foo' and dependency 'org.foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->git/org/foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->org.foo. """), severity: .warning ) @@ -14500,8 +14228,6 @@ final class WorkspaceTests: XCTestCase { // mixed graph root --> dep1 registry // --> dep2 registry --> dep1 scm incompatible version func testResolutionMixedRegistryAndSourceControl7() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -14627,8 +14353,6 @@ final class WorkspaceTests: XCTestCase { // mixed graph root --> dep1 registry --> dep3 scm // --> dep2 registry --> dep3 registry func testResolutionMixedRegistryAndSourceControl8() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -14734,9 +14458,10 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in testDiagnostics(diagnostics) { result in + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) result.check( diagnostic: .contains(""" - dependency 'git/org/baz' and dependency 'org.baz' both point to the same package identity 'org.baz'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->org.foo->git/org/baz (B) /tmp/ws/roots/root->org.bar->org.baz. + dependency 'git/org/baz' and dependency 'org.baz' both point to the same package identity 'org.baz'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.foo->git/org/baz (B) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.baz. """), severity: .warning ) @@ -14799,8 +14524,6 @@ final class WorkspaceTests: XCTestCase { // mixed graph root --> dep1 registry --> dep3 scm // --> dep2 registry --> dep3 registry incompatible version func testResolutionMixedRegistryAndSourceControl9() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -14942,9 +14665,8 @@ final class WorkspaceTests: XCTestCase { // mixed graph root --> dep1 scm branch // --> dep2 registry --> dep1 registry func testResolutionMixedRegistryAndSourceControl10() async throws { - try skipOnWindowsAsTestCurrentlyFails() - - let sandbox = AbsolutePath("/tmp/ws/") + let sandbox: AbsolutePath = AbsolutePath("/tmp/ws/") + let tmpDirCanonicalPackageLocation = CanonicalPackageLocation(sandbox.pathString) let fs = InMemoryFileSystem() let workspace = try await MockWorkspace( @@ -15035,7 +14757,7 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check( diagnostic: .contains(""" - dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->org.bar->org.foo (B) /tmp/ws/roots/root->git/org/foo. + dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. """), severity: .warning ) @@ -15065,7 +14787,7 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check( diagnostic: .contains(""" - dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) /tmp/ws/roots/root->org.bar->org.foo (B) /tmp/ws/roots/root->git/org/foo. + dependency 'org.foo' and dependency 'git/org/foo' both point to the same package identity 'org.foo'. The dependencies are introduced through the following chains: (A) \(tmpDirCanonicalPackageLocation)/roots/root->org.bar->org.foo (B) \(tmpDirCanonicalPackageLocation)/roots/root->git/org/foo. """), severity: .warning ) @@ -15091,8 +14813,6 @@ final class WorkspaceTests: XCTestCase { } func testCustomPackageContainerProvider() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -15122,7 +14842,7 @@ final class WorkspaceTests: XCTestCase { customRetrievalPath: .root ) - let fooPath = AbsolutePath("/tmp/ws/Foo") + let fooPath = sandbox.appending("Foo") let fooPackageReference = PackageReference(identity: PackageIdentity(path: fooPath), kind: .root(fooPath)) let fooContainer = MockPackageContainer(package: fooPackageReference) @@ -15182,8 +14902,6 @@ final class WorkspaceTests: XCTestCase { } func testRegistryMissingConfigurationErrors() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -15233,12 +14951,10 @@ final class WorkspaceTests: XCTestCase { testDiagnostics(diagnostics) { result in result.check(diagnostic: .equal("no registry configured for 'org' scope"), severity: .error) } - } + } } func testRegistryReleasesServerErrors() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -15324,8 +15040,6 @@ final class WorkspaceTests: XCTestCase { } func testRegistryReleaseChecksumServerErrors() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -15413,8 +15127,6 @@ final class WorkspaceTests: XCTestCase { } func testRegistryManifestServerErrors() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -15502,8 +15214,6 @@ final class WorkspaceTests: XCTestCase { } func testRegistryDownloadServerErrors() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -15591,8 +15301,6 @@ final class WorkspaceTests: XCTestCase { } func testRegistryArchiveErrors() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -15655,8 +15363,6 @@ final class WorkspaceTests: XCTestCase { } func testRegistryMetadata() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -15739,8 +15445,6 @@ final class WorkspaceTests: XCTestCase { } func testRegistryDefaultRegistryConfiguration() async throws { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -15807,9 +15511,9 @@ final class WorkspaceTests: XCTestCase { metadata: [String: RegistryReleaseMetadata], mirrors: DependencyMirrors? = nil ) async throws -> MockWorkspace { - try skipOnWindowsAsTestCurrentlyFails() - let sandbox = AbsolutePath("/tmp/ws/") + // let sandbox = AbsolutePath.root.appending("swiftpm-tests-can-be-deleted/tmp/ws") + let sandbox = AbsolutePath.root.appending(components: ["swiftpm-tests-can-be-deleted", "tmp", "ws"]) let fs = InMemoryFileSystem() return try await MockWorkspace( @@ -16105,8 +15809,6 @@ final class WorkspaceTests: XCTestCase { } func testTraitConfigurationExists_NoDefaultTraits() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -16195,8 +15897,6 @@ final class WorkspaceTests: XCTestCase { } func testTraitConfigurationExists_WithDefaultTraits() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -16285,8 +15985,6 @@ final class WorkspaceTests: XCTestCase { } func testTraitConfiguration_WithPrunedDependencies() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem() @@ -16365,8 +16063,6 @@ final class WorkspaceTests: XCTestCase { } func testNoTraitConfiguration_WithDefaultTraits() async throws { - try skipOnWindowsAsTestCurrentlyFails(because: #"\tmp\ws doesn't exist in file system"#) - let sandbox = AbsolutePath("/tmp/ws/") let fs = InMemoryFileSystem()