From f66825c0d2cb3201456947f68f24c550ae1b1096 Mon Sep 17 00:00:00 2001 From: Sam Khouri Date: Thu, 24 Jul 2025 20:24:30 -0400 Subject: [PATCH 1/2] Run Command: Add SwiftBuild repl support The `swift run --repl` was explicitely using the Native build system. This change modified the `swift run --repl` command to respect the `--build-system ` command line option. The change introduces a new build output request `replArguments`. When provided, the build system is responsible for providing the arguments required for the REPL in the BuildResult. The Swift Run Command will inspect the build repsult for this property. If it's unavailable, the command provides an error indicating repl support is unavailable. A caveat, more work is required to get proper REPL integation with the Package. At the moment, the System Library paths are not provided by the SwiftBuild System when a repl session is requested via the `run` command. Relates to: #8846 issue: rdar://153822861 --- Sources/Build/BuildOperation.swift | 24 +- Sources/Build/BuildPlan/BuildPlan.swift | 5 +- Sources/Commands/SwiftRunCommand.swift | 19 +- Sources/PackageGraph/ModulesGraph.swift | 8 + .../BuildSystem/BuildSystem.swift | 20 +- .../SwiftBuildSupport/SwiftBuildSystem.swift | 97 +- Sources/XCBuildSupport/XcodeBuildSystem.swift | 6 +- .../PackageGraphTester.swift | 196 ++-- .../PackageGraphTesterXCTest.swift | 327 ++++++ .../SwiftTesting+TraitConditional.swift | 11 + Tests/BuildTests/BuildPlanTests.swift | 4 +- Tests/BuildTests/PluginInvocationTests.swift | 2 +- Tests/CommandsTests/RunCommandTests.swift | 2 +- .../CrossCompilationPackageGraphTests.swift | 6 +- .../PackageGraphTests/ModulesGraphTests.swift | 979 ++++++++++-------- Tests/WorkspaceTests/WorkspaceTests.swift | 188 ++-- 16 files changed, 1245 insertions(+), 649 deletions(-) create mode 100644 Sources/_InternalTestSupport/PackageGraphTesterXCTest.swift diff --git a/Sources/Build/BuildOperation.swift b/Sources/Build/BuildOperation.swift index 2b341cc1c2d..90d456fd234 100644 --- a/Sources/Build/BuildOperation.swift +++ b/Sources/Build/BuildOperation.swift @@ -37,8 +37,8 @@ import SwiftDriver #endif package struct LLBuildSystemConfiguration { - let toolsBuildParameters: BuildParameters - let destinationBuildParameters: BuildParameters + fileprivate let toolsBuildParameters: BuildParameters + fileprivate let destinationBuildParameters: BuildParameters let scratchDirectory: AbsolutePath @@ -397,7 +397,11 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS /// Perform a build using the given build description and subset. public func build(subset: BuildSubset, buildOutputs: [BuildOutput]) async throws -> BuildResult { - var result = BuildResult(serializedDiagnosticPathsByTargetName: .failure(StringError("Building was skipped"))) + var result = BuildResult( + serializedDiagnosticPathsByTargetName: .failure(StringError("Building was skipped")), + packageGraph: try await self.getPackageGraph(), + replArguments: nil, + ) guard !self.config.shouldSkipBuilding(for: .target) else { return result @@ -455,10 +459,16 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS ) guard success else { throw Diagnostics.fatalError } - if buildOutputs.contains(.buildPlan) { - result.buildPlan = try buildPlan - } + let buildResultBuildPlan = buildOutputs.contains(.buildPlan) ? try buildPlan : nil + let buildResultReplArgs = buildOutputs.contains(.replArguments) ? try buildPlan.createREPLArguments() : nil + result = BuildResult( + serializedDiagnosticPathsByTargetName: result.serializedDiagnosticPathsByTargetName, + packageGraph: result.packageGraph, + symbolGraph: result.symbolGraph, + buildPlan: buildResultBuildPlan, + replArguments: buildResultReplArgs, + ) var serializedDiagnosticPaths: [String: [AbsolutePath]] = [:] do { for module in try buildPlan.buildModules { @@ -701,7 +711,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS // Create the build plan based on the modules graph and any information from plugins. return try await BuildPlan( - destinationBuildParameters: self.config.destinationBuildParameters, + destinationBuildParameters: self.config.buildParameters(for: .target), toolsBuildParameters: self.config.buildParameters(for: .host), graph: graph, pluginConfiguration: self.pluginConfiguration, diff --git a/Sources/Build/BuildPlan/BuildPlan.swift b/Sources/Build/BuildPlan/BuildPlan.swift index ebf692deea1..a1074cb222e 100644 --- a/Sources/Build/BuildPlan/BuildPlan.swift +++ b/Sources/Build/BuildPlan/BuildPlan.swift @@ -637,13 +637,12 @@ public class BuildPlan: SPMBuildCore.BuildPlan { /// Creates arguments required to launch the Swift REPL that will allow /// importing the modules in the package graph. - public func createREPLArguments() throws -> [String] { + public func createREPLArguments() throws -> CLIArguments { let buildPath = self.toolsBuildParameters.buildPath.pathString var arguments = ["repl", "-I" + buildPath, "-L" + buildPath] // Link the special REPL product that contains all of the library targets. - let replProductName = self.graph.rootPackages[self.graph.rootPackages.startIndex].identity.description + - Product.replProductSuffix + let replProductName = try self.graph.getReplProductName() arguments.append("-l" + replProductName) // The graph should have the REPL product. diff --git a/Sources/Commands/SwiftRunCommand.swift b/Sources/Commands/SwiftRunCommand.swift index 18bdb2f9210..1b6d7448214 100644 --- a/Sources/Commands/SwiftRunCommand.swift +++ b/Sources/Commands/SwiftRunCommand.swift @@ -134,23 +134,24 @@ public struct SwiftRunCommand: AsyncSwiftCommand { // Construct the build operation. // FIXME: We need to implement the build tool invocation closure here so that build tool plugins work with the REPL. rdar://86112934 let buildSystem = try await swiftCommandState.createBuildSystem( - explicitBuildSystem: .native, cacheBuildManifest: false, packageGraphLoader: asyncUnsafeGraphLoader ) // Perform build. - let buildResult = try await buildSystem.build(subset: .allExcludingTests, buildOutputs: [.buildPlan]) - guard let buildPlan = buildResult.buildPlan else { + let buildResult = try await buildSystem.build(subset: .allExcludingTests, buildOutputs: [.replArguments]) + guard let arguments = buildResult.replArguments else { + swiftCommandState.observabilityScope.emit(error: "\(globalOptions.build.buildSystem) build system does not support this command") throw ExitCode.failure } // Execute the REPL. - let arguments = try buildPlan.createREPLArguments() - print("Launching Swift REPL with arguments: \(arguments.joined(separator: " "))") + let interpreterPath = try swiftCommandState.getTargetToolchain().swiftInterpreterPath + swiftCommandState.outputStream.send("Launching Swift (interpreter at \(interpreterPath)) REPL with arguments: \(arguments.joined(separator: " "))\n") + swiftCommandState.outputStream.flush() try self.run( fileSystem: swiftCommandState.fileSystem, - executablePath: swiftCommandState.getTargetToolchain().swiftInterpreterPath, + executablePath: interpreterPath, originalWorkingDirectory: swiftCommandState.originalWorkingDirectory, arguments: arguments ) @@ -197,7 +198,7 @@ public struct SwiftRunCommand: AsyncSwiftCommand { case .run: // Detect deprecated uses of swift run to interpret scripts. if let executable = options.executable, try isValidSwiftFilePath(fileSystem: swiftCommandState.fileSystem, path: executable) { - swiftCommandState.observabilityScope.emit(.runFileDeprecation) + swiftCommandState.observabilityScope.emit(.runFileDeprecation(filePath: executable)) // Redirect execution to the toolchain's swift executable. let swiftInterpreterPath = try swiftCommandState.getTargetToolchain().swiftInterpreterPath // Prepend the script to interpret to the arguments. @@ -364,8 +365,8 @@ public struct SwiftRunCommand: AsyncSwiftCommand { } private extension Basics.Diagnostic { - static var runFileDeprecation: Self { - .warning("'swift run file.swift' command to interpret swift files is deprecated; use 'swift file.swift' instead") + static func runFileDeprecation(filePath: String) -> Self { + .warning("'swift run \(filePath)' command to interpret swift files is deprecated; use 'swift \(filePath)' instead") } } diff --git a/Sources/PackageGraph/ModulesGraph.swift b/Sources/PackageGraph/ModulesGraph.swift index 5c9fe3ced47..77f3f745b38 100644 --- a/Sources/PackageGraph/ModulesGraph.swift +++ b/Sources/PackageGraph/ModulesGraph.swift @@ -285,6 +285,14 @@ public struct ModulesGraph { return result } + + public func getReplProductName() throws -> String { + if self.rootPackages.isEmpty { + throw StringError("Root package does not exist.") + } + return self.rootPackages[self.rootPackages.startIndex].identity.description + + Product.replProductSuffix + } } extension PackageGraphError: CustomStringConvertible { diff --git a/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift b/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift index 9bea61a69ca..0648f288648 100644 --- a/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift +++ b/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift @@ -47,6 +47,7 @@ public enum BuildOutput { // "-emit-extension-block-symbols" // "-emit-synthesized-members" case buildPlan + case replArguments } /// A protocol that represents a build system used by SwiftPM for all build operations. This allows factoring out the @@ -91,15 +92,28 @@ public struct SymbolGraphResult { public let outputLocationForTarget: (String, BuildParameters) -> [String] } +public typealias CLIArguments = [String] + public struct BuildResult { - package init(serializedDiagnosticPathsByTargetName: Result<[String: [AbsolutePath]], Error>, symbolGraph: SymbolGraphResult? = nil, buildPlan: BuildPlan? = nil) { + package init( + serializedDiagnosticPathsByTargetName: Result<[String: [AbsolutePath]], Error>, + packageGraph: ModulesGraph, + symbolGraph: SymbolGraphResult? = nil, + buildPlan: BuildPlan? = nil, + replArguments: CLIArguments? + ) { self.serializedDiagnosticPathsByTargetName = serializedDiagnosticPathsByTargetName + self.packageGraph = packageGraph self.symbolGraph = symbolGraph self.buildPlan = buildPlan + self.replArguments = replArguments } - public var symbolGraph: SymbolGraphResult? - public var buildPlan: BuildPlan? + public let replArguments: CLIArguments? + public let packageGraph: ModulesGraph + public let symbolGraph: SymbolGraphResult? + public let buildPlan: BuildPlan? + public var serializedDiagnosticPathsByTargetName: Result<[String: [AbsolutePath]], Error> } diff --git a/Sources/SwiftBuildSupport/SwiftBuildSystem.swift b/Sources/SwiftBuildSupport/SwiftBuildSystem.swift index 4b88f73498b..63cdd60ccf5 100644 --- a/Sources/SwiftBuildSupport/SwiftBuildSystem.swift +++ b/Sources/SwiftBuildSupport/SwiftBuildSystem.swift @@ -276,6 +276,66 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { self.delegate = delegate } + private func createREPLArguments( + session: SWBBuildServiceSession, + request: SWBBuildRequest + ) async throws -> CLIArguments { + self.outputStream.send("Gathering repl arguments...") + self.outputStream.flush() + + func getUniqueBuildSettingsIncludingDependencies(of targetGuid: [SWBConfiguredTarget], buildSettings: [String]) async throws -> Set { + let dependencyGraph = try await session.computeDependencyGraph( + targetGUIDs: request.configuredTargets.map { SWBTargetGUID(rawValue: $0.guid)}, + buildParameters: request.parameters, + includeImplicitDependencies: true, + ) + var uniquePaths = Set() + for setting in buildSettings { + self.outputStream.send(".") + self.outputStream.flush() + for (target, targetDependencies) in dependencyGraph { + for t in [target] + targetDependencies { + try await session.evaluateMacroAsStringList( + setting, + level: .target(t.rawValue), + buildParameters: request.parameters, + overrides: nil, + ).forEach({ + uniquePaths.insert($0) + }) + } + } + + } + return uniquePaths + } + + // TODO: Need to determine how to get the inlude path of package system library dependencies + let includePaths = try await getUniqueBuildSettingsIncludingDependencies( + of: request.configuredTargets, + buildSettings: [ + "BUILT_PRODUCTS_DIR", + "HEADER_SEARCH_PATHS", + "USER_HEADER_SEARCH_PATHS", + "FRAMEWORK_SEARCH_PATHS", + ] + ) + + let graph = try await self.getPackageGraph() + // Link the special REPL product that contains all of the library targets. + let replProductName: String = try graph.getReplProductName() + + // The graph should have the REPL product. + assert(graph.product(for: replProductName) != nil) + + let arguments = ["repl", "-l\(replProductName)"] + includePaths.map { + "-I\($0)" + } + + self.outputStream.send("Done.\n") + return arguments + } + private func supportedSwiftVersions() throws -> [SwiftLanguageVersion] { // Swift Build should support any of the supported language versions of SwiftPM and the rest of the toolchain SwiftLanguageVersion.supportedSwiftLanguageVersions @@ -283,17 +343,29 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { public func build(subset: BuildSubset, buildOutputs: [BuildOutput]) async throws -> BuildResult { guard !buildParameters.shouldSkipBuilding else { - return BuildResult(serializedDiagnosticPathsByTargetName: .failure(StringError("Building was skipped"))) + return BuildResult( + serializedDiagnosticPathsByTargetName: .failure(StringError("Building was skipped")), + packageGraph: try await self.getPackageGraph(), + replArguments: nil, + ) } try await writePIF(buildParameters: buildParameters) - return try await startSWBuildOperation(pifTargetName: subset.pifTargetName, genSymbolGraph: buildOutputs.contains(.symbolGraph)) + return try await startSWBuildOperation( + pifTargetName: subset.pifTargetName, + genSymbolGraph: buildOutputs.contains(.symbolGraph), + generateReplArguments: buildOutputs.contains(.replArguments), + ) } - private func startSWBuildOperation(pifTargetName: String, genSymbolGraph: Bool) async throws -> BuildResult { + private func startSWBuildOperation( + pifTargetName: String, + genSymbolGraph: Bool, + generateReplArguments: Bool + ) async throws -> BuildResult { let buildStartTime = ContinuousClock.Instant.now - + var replArguments: CLIArguments? return try await withService(connectionMode: .inProcessStatic(swiftbuildServiceEntryPoint)) { service in let derivedDataPath = self.buildParameters.dataPath @@ -418,7 +490,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { case .note: .info case .remark: .debug } - self.observabilityScope.emit(severity: severity, message: message) + self.observabilityScope.emit(severity: severity, message: "\(message)\n") for childDiagnostic in info.childDiagnostics { emitInfoAsDiagnostic(info: childDiagnostic) @@ -502,6 +574,8 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { self.observabilityScope.emit(error: "Unexpected build state") throw Diagnostics.fatalError } + + replArguments = generateReplArguments ? try await self.createREPLArguments(session: session, request: request) : nil } } catch let sessError as SessionFailedError { for diagnostic in sessError.diagnostics { @@ -512,9 +586,16 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { throw error } - return BuildResult(serializedDiagnosticPathsByTargetName: .success(serializedDiagnosticPathsByTargetName), symbolGraph: SymbolGraphResult(outputLocationForTarget: { target, buildParameters in - return ["\(buildParameters.triple.archName)", "\(target).symbolgraphs"] - })) + return BuildResult( + serializedDiagnosticPathsByTargetName: .success(serializedDiagnosticPathsByTargetName), + packageGraph: try await self.getPackageGraph(), + symbolGraph: SymbolGraphResult( + outputLocationForTarget: { target, buildParameters in + return ["\(buildParameters.triple.archName)", "\(target).symbolgraphs"] + } + ), + replArguments: replArguments, + ) } } diff --git a/Sources/XCBuildSupport/XcodeBuildSystem.swift b/Sources/XCBuildSupport/XcodeBuildSystem.swift index 74d89e4271d..9c88c62d662 100644 --- a/Sources/XCBuildSupport/XcodeBuildSystem.swift +++ b/Sources/XCBuildSupport/XcodeBuildSystem.swift @@ -161,7 +161,11 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem { } public func build(subset: BuildSubset, buildOutputs: [BuildOutput]) async throws -> BuildResult { - let buildResult = BuildResult(serializedDiagnosticPathsByTargetName: .failure(StringError("XCBuild does not support reporting serialized diagnostics."))) + let buildResult = BuildResult( + serializedDiagnosticPathsByTargetName: .failure(StringError("XCBuild does not support reporting serialized diagnostics.")), + packageGraph: try await self.getPackageGraph(), + replArguments: nil, + ) guard !buildParameters.shouldSkipBuilding else { return buildResult diff --git a/Sources/_InternalTestSupport/PackageGraphTester.swift b/Sources/_InternalTestSupport/PackageGraphTester.swift index 28c1b7a98d2..fb9a46ea381 100644 --- a/Sources/_InternalTestSupport/PackageGraphTester.swift +++ b/Sources/_InternalTestSupport/PackageGraphTester.swift @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -import XCTest +import Testing import struct Basics.IdentifiableSet @@ -28,73 +28,65 @@ public final class PackageGraphResult { self.graph = graph } - public func check(roots: PackageIdentity..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(graph.rootPackages.map{$0.identity }.sorted(), roots.sorted(), file: file, line: line) + public func check(roots: PackageIdentity..., sourceLocation: SourceLocation = #_sourceLocation) { + #expect(graph.rootPackages.map{$0.identity }.sorted() == roots.sorted(), sourceLocation: sourceLocation) } - public func check(packages: PackageIdentity..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(graph.packages.map {$0.identity }.sorted(), packages.sorted(), file: file, line: line) + public func check(packages: PackageIdentity..., sourceLocation: SourceLocation = #_sourceLocation) { + #expect(graph.packages.map {$0.identity }.sorted() == packages.sorted(), sourceLocation: sourceLocation) } - public func check(modules: String..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( + public func check(modules: String..., sourceLocation: SourceLocation = #_sourceLocation) { + #expect( graph.allModules .filter { $0.type != .test } .map { $0.name } - .sorted(), modules.sorted(), file: file, line: line) + .sorted() == modules.sorted(), sourceLocation: sourceLocation) } - public func check(products: String..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Set(graph.allProducts.map { $0.name }), Set(products), file: file, line: line) + public func check(products: String..., sourceLocation: SourceLocation = #_sourceLocation) { + #expect(Set(graph.allProducts.map { $0.name }) == Set(products), sourceLocation: sourceLocation) } - public func check(reachableTargets: String..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Set(graph.reachableModules.map { $0.name }), Set(reachableTargets), file: file, line: line) + public func check(reachableTargets: String..., sourceLocation: SourceLocation = #_sourceLocation) { + #expect(Set(graph.reachableModules.map { $0.name }) == Set(reachableTargets), sourceLocation: sourceLocation) } - public func check(reachableProducts: String..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Set(graph.reachableProducts.map { $0.name }), Set(reachableProducts), file: file, line: line) + public func check(reachableProducts: String..., sourceLocation: SourceLocation = #_sourceLocation) { + #expect(Set(graph.reachableProducts.map { $0.name }) == Set(reachableProducts), sourceLocation: sourceLocation) } public func check( reachableBuildTargets: String..., in environment: BuildEnvironment, - file: StaticString = #file, - line: UInt = #line + sourceLocation: SourceLocation = #_sourceLocation, ) throws { let targets = Set(try self.reachableBuildTargets(in: environment).map({ $0.name })) - XCTAssertEqual(targets, Set(reachableBuildTargets), file: file, line: line) + #expect(targets == Set(reachableBuildTargets), sourceLocation: sourceLocation) } public func check( reachableBuildProducts: String..., in environment: BuildEnvironment, - file: StaticString = #file, - line: UInt = #line + sourceLocation: SourceLocation = #_sourceLocation, ) throws { let products = Set(try self.reachableBuildProducts(in: environment).map({ $0.name })) - XCTAssertEqual(products, Set(reachableBuildProducts), file: file, line: line) + #expect(products == Set(reachableBuildProducts), sourceLocation: sourceLocation) } public func checkTarget( _ name: String, - file: StaticString = #file, - line: UInt = #line, - body: (ResolvedTargetResult) -> Void - ) { - let target = graph.module(for: name) - - guard let target else { - return XCTFail("Target \(name) not found", file: file, line: line) - } + sourceLocation: SourceLocation = #_sourceLocation, + body: (ResolvedTargetResult) throws -> Void + ) throws { + let target = try #require(graph.module(for: name), "Target \(name) not found", sourceLocation: sourceLocation) - body(ResolvedTargetResult(target)) + try body(ResolvedTargetResult(target)) } package func checkTargets( _ name: String, - file: StaticString = #file, - line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation, body: ([ResolvedTargetResult]) throws -> Void ) rethrows { try body(graph.allModules.filter { $0.name == name }.map(ResolvedTargetResult.init)) @@ -102,37 +94,30 @@ public final class PackageGraphResult { public func checkProduct( _ name: String, - file: StaticString = #file, - line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation, body: (ResolvedProductResult) -> Void - ) { - let product = graph.product(for: name) + ) throws { + let product = try #require(graph.product(for: name), "Product \(name) not found", sourceLocation: sourceLocation) - guard let product else { - return XCTFail("Product \(name) not found", file: file, line: line) - } body(ResolvedProductResult(product)) } package func checkPackage( _ name: String, - file: StaticString = #file, - line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation, body: (ResolvedPackage) -> Void - ) { - guard let package = find(package: .init(stringLiteral: name)) else { - return XCTFail("Product \(name) not found", file: file, line: line) - } - body(package) + ) throws { + let pkg = try #require(find(package: .init(stringLiteral: name)), "Product \(name) not found", sourceLocation: sourceLocation) + body(pkg) } - public func check(testModules: String..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( + public func check(testModules: String..., sourceLocation: SourceLocation = #_sourceLocation) { + #expect( graph.allModules .filter{ $0.type == .test } .map{ $0.name } - .sorted(), testModules.sorted(), file: file, line: line) + .sorted() == testModules.sorted(), sourceLocation: sourceLocation) } public func find(package: PackageIdentity) -> ResolvedPackage? { @@ -164,38 +149,39 @@ public final class ResolvedTargetResult { self.target = target } - public func check(dependencies: String..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Set(dependencies), Set(target.dependencies.map({ $0.name })), file: file, line: line) + public func check(dependencies: String..., sourceLocation: SourceLocation = #_sourceLocation) { + #expect(Set(dependencies) == Set(target.dependencies.map({ $0.name })), sourceLocation: sourceLocation) } - public func check(dependencies: [String], file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Set(dependencies), Set(target.dependencies.map({ $0.name })), file: file, line: line) + public func check(dependencies: [String], sourceLocation: SourceLocation = #_sourceLocation) { + #expect(Set(dependencies) == Set(target.dependencies.map({ $0.name })), sourceLocation: sourceLocation) } public func checkDependency( _ name: String, - file: StaticString = #file, - line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation, body: (ResolvedTargetDependencyResult) -> Void - ) { - guard let dependency = target.dependencies.first(where: { $0.name == name }) else { - return XCTFail("Dependency \(name) not found", file: file, line: line) - } + ) throws { + let dependency = try #require( + target.dependencies.first(where: { $0.name == name }), + "Dependency \(name) not found", + sourceLocation: sourceLocation, + ) body(ResolvedTargetDependencyResult(dependency)) } - public func check(type: Module.Kind, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(type, target.type, file: file, line: line) + public func check(type: Module.Kind, sourceLocation: SourceLocation = #_sourceLocation) { + #expect(type == target.type, sourceLocation: sourceLocation) } - public func checkDeclaredPlatforms(_ platforms: [String: String], file: StaticString = #file, line: UInt = #line) { + public func checkDeclaredPlatforms(_ platforms: [String: String], sourceLocation: SourceLocation = #_sourceLocation) { let targetPlatforms = Dictionary( uniqueKeysWithValues: target.supportedPlatforms.map { ($0.platform.name, $0.version.versionString) } ) - XCTAssertEqual(platforms, targetPlatforms, file: file, line: line) + #expect(platforms == targetPlatforms, sourceLocation: sourceLocation) } - public func checkDerivedPlatforms(_ platforms: [String: String], file: StaticString = #file, line: UInt = #line) { + public func checkDerivedPlatforms(_ platforms: [String: String], sourceLocation: SourceLocation = #_sourceLocation) { let derived = platforms.map { let platform = PlatformRegistry.default.platformByName[$0.key] ?? PackageModel.Platform .custom(name: $0.key, oldestSupportedVersion: $0.value) @@ -204,30 +190,26 @@ public final class ResolvedTargetResult { let targetPlatforms = Dictionary( uniqueKeysWithValues: derived.map { ($0.platform.name, $0.version.versionString) } ) - XCTAssertEqual(platforms, targetPlatforms, file: file, line: line) + #expect(platforms == targetPlatforms, sourceLocation: sourceLocation) } public func checkDerivedPlatformOptions( _ platform: PackageModel.Platform, options: [String], - file: StaticString = #file, - line: UInt = #line + sourceLocation: SourceLocation = #_sourceLocation, ) { let platform = self.target.getSupportedPlatform(for: platform, usingXCTest: target.type == .test) - XCTAssertEqual(platform.options, options, file: file, line: line) + #expect(platform.options == options, sourceLocation: sourceLocation) } package func checkBuildSetting( declaration: BuildSettings.Declaration, assignments: Set?, - file: StaticString = #file, - line: UInt = #line + sourceLocation: SourceLocation = #_sourceLocation, ) { - XCTAssertEqual( - target.underlying.buildSettings.assignments[declaration].flatMap { Set($0) }, - assignments, - file: file, - line: line + #expect( + target.underlying.buildSettings.assignments[declaration].flatMap { Set($0) } == assignments, + sourceLocation: sourceLocation ) } } @@ -239,36 +221,35 @@ public final class ResolvedTargetDependencyResult { self.dependency = dependency } - public func checkConditions(satisfy environment: BuildEnvironment, file: StaticString = #file, line: UInt = #line) { - XCTAssert(dependency.conditions.allSatisfy({ $0.satisfies(environment) }), file: file, line: line) + public func checkConditions(satisfy environment: BuildEnvironment, sourceLocation: SourceLocation = #_sourceLocation) { + #expect(dependency.conditions.allSatisfy({ $0.satisfies(environment) }), sourceLocation: sourceLocation) } public func checkConditions( dontSatisfy environment: BuildEnvironment, - file: StaticString = #file, - line: UInt = #line + sourceLocation: SourceLocation = #_sourceLocation, ) { - XCTAssert(!dependency.conditions.allSatisfy({ $0.satisfies(environment) }), file: file, line: line) + #expect(!dependency.conditions.allSatisfy({ $0.satisfies(environment) }), sourceLocation: sourceLocation) } public func checkTarget( - file: StaticString = #file, - line: UInt = #line, - body: (ResolvedTargetResult) -> Void - ) { + sourceLocation: SourceLocation = #_sourceLocation, + body: (ResolvedTargetResult) throws -> Void + ) throws { guard case let .module(target, _) = self.dependency else { - return XCTFail("Dependency \(dependency) is not a target", file: file, line: line) + Issue.record("Dependency \(dependency) is not a target", sourceLocation: sourceLocation) + return } - body(ResolvedTargetResult(target)) + try body(ResolvedTargetResult(target)) } public func checkProduct( - file: StaticString = #file, - line: UInt = #line, + sourceLocation: SourceLocation = #_sourceLocation, body: (ResolvedProductResult) -> Void ) { guard case let .product(product, _) = self.dependency else { - return XCTFail("Dependency \(dependency) is not a product", file: file, line: line) + Issue.record("Dependency \(dependency) is not a product", sourceLocation: sourceLocation) + return } body(ResolvedProductResult(product)) } @@ -281,43 +262,44 @@ public final class ResolvedProductResult { self.product = product } - public func check(modules: String..., file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Set(modules), Set(product.modules.map({ $0.name })), file: file, line: line) + public func check(modules: String..., sourceLocation: SourceLocation = #_sourceLocation) { + #expect(Set(modules) == Set(product.modules.map({ $0.name })), sourceLocation: sourceLocation) } - public func check(type: ProductType, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(type, product.type, file: file, line: line) + public func check(type: ProductType, sourceLocation: SourceLocation = #_sourceLocation) { + #expect(type == product.type, sourceLocation: sourceLocation) } - public func checkDeclaredPlatforms(_ platforms: [String: String], file: StaticString = #file, line: UInt = #line) { + public func checkDeclaredPlatforms(_ platforms: [String: String], sourceLocation: SourceLocation = #_sourceLocation) { let targetPlatforms = Dictionary(uniqueKeysWithValues: product.supportedPlatforms.map({ ($0.platform.name, $0.version.versionString) })) - XCTAssertEqual(platforms, targetPlatforms, file: file, line: line) + #expect(platforms == targetPlatforms, sourceLocation: sourceLocation) } - public func checkDerivedPlatforms(_ platforms: [String: String], file: StaticString = #file, line: UInt = #line) { + public func checkDerivedPlatforms(_ platforms: [String: String], sourceLocation: SourceLocation = #_sourceLocation) { let derived = platforms.map { let platform = PlatformRegistry.default.platformByName[$0.key] ?? PackageModel.Platform.custom(name: $0.key, oldestSupportedVersion: $0.value) return product.getSupportedPlatform(for: platform, usingXCTest: product.isLinkingXCTest) } let targetPlatforms = Dictionary(uniqueKeysWithValues: derived.map({ ($0.platform.name, $0.version.versionString) })) - XCTAssertEqual(platforms, targetPlatforms, file: file, line: line) + #expect(platforms == targetPlatforms, sourceLocation: sourceLocation) } - public func checkDerivedPlatformOptions(_ platform: PackageModel.Platform, options: [String], file: StaticString = #file, line: UInt = #line) { + public func checkDerivedPlatformOptions(_ platform: PackageModel.Platform, options: [String], sourceLocation: SourceLocation = #_sourceLocation) { let platform = product.getSupportedPlatform(for: platform, usingXCTest: product.isLinkingXCTest) - XCTAssertEqual(platform.options, options, file: file, line: line) + #expect(platform.options == options, sourceLocation: sourceLocation) } public func checkTarget( _ name: String, - file: StaticString = #file, - line: UInt = #line, - body: (ResolvedTargetResult) -> Void - ) { - guard let target = product.modules.first(where: { $0.name == name }) else { - return XCTFail("Target \(name) not found", file: file, line: line) - } - body(ResolvedTargetResult(target)) + sourceLocation: SourceLocation = #_sourceLocation, + body: (ResolvedTargetResult) throws -> Void + ) throws { + let target = try #require( + product.modules.first(where: { $0.name == name }), + "Target \(name) not found", + sourceLocation: sourceLocation, + ) + try body(ResolvedTargetResult(target)) } } diff --git a/Sources/_InternalTestSupport/PackageGraphTesterXCTest.swift b/Sources/_InternalTestSupport/PackageGraphTesterXCTest.swift new file mode 100644 index 00000000000..d2be6488fb6 --- /dev/null +++ b/Sources/_InternalTestSupport/PackageGraphTesterXCTest.swift @@ -0,0 +1,327 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import XCTest + +import struct Basics.IdentifiableSet + +import PackageModel +import PackageGraph + +@available(*, deprecated, message: "Migrate to Swift Testing and use 'PackageGraphTester'") +public func PackageGraphTesterXCTest(_ graph: ModulesGraph, _ result: (PackageGraphResultXCTest) throws -> Void) rethrows { + try result(PackageGraphResultXCTest(graph)) +} + +@available(*, deprecated, message: "Migrate to Swift Testing and use 'PackageGraphResult'") +public final class PackageGraphResultXCTest { + public let graph: ModulesGraph + + public init(_ graph: ModulesGraph) { + self.graph = graph + } + + public func check(roots: PackageIdentity..., file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(graph.rootPackages.map{$0.identity }.sorted(), roots.sorted(), file: file, line: line) + } + + public func check(packages: PackageIdentity..., file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(graph.packages.map {$0.identity }.sorted(), packages.sorted(), file: file, line: line) + } + + public func check(modules: String..., file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( + graph.allModules + .filter { $0.type != .test } + .map { $0.name } + .sorted(), modules.sorted(), file: file, line: line) + } + + public func check(products: String..., file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Set(graph.allProducts.map { $0.name }), Set(products), file: file, line: line) + } + + public func check(reachableTargets: String..., file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Set(graph.reachableModules.map { $0.name }), Set(reachableTargets), file: file, line: line) + } + + public func check(reachableProducts: String..., file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Set(graph.reachableProducts.map { $0.name }), Set(reachableProducts), file: file, line: line) + } + + public func check( + reachableBuildTargets: String..., + in environment: BuildEnvironment, + file: StaticString = #file, + line: UInt = #line + ) throws { + let targets = Set(try self.reachableBuildTargets(in: environment).map({ $0.name })) + XCTAssertEqual(targets, Set(reachableBuildTargets), file: file, line: line) + } + + public func check( + reachableBuildProducts: String..., + in environment: BuildEnvironment, + file: StaticString = #file, + line: UInt = #line + ) throws { + let products = Set(try self.reachableBuildProducts(in: environment).map({ $0.name })) + XCTAssertEqual(products, Set(reachableBuildProducts), file: file, line: line) + } + + public func checkTarget( + _ name: String, + file: StaticString = #file, + line: UInt = #line, + body: (ResolvedTargetResultXCTest) -> Void + ) { + let target = graph.module(for: name) + + guard let target else { + return XCTFail("Target \(name) not found", file: file, line: line) + } + + body(ResolvedTargetResultXCTest(target)) + } + + package func checkTargets( + _ name: String, + file: StaticString = #file, + line: UInt = #line, + body: ([ResolvedTargetResultXCTest]) throws -> Void + ) rethrows { + try body(graph.allModules.filter { $0.name == name }.map(ResolvedTargetResultXCTest.init)) + } + + public func checkProduct( + _ name: String, + file: StaticString = #file, + line: UInt = #line, + body: (ResolvedProductResultXCTest) -> Void + ) { + let product = graph.product(for: name) + + guard let product else { + return XCTFail("Product \(name) not found", file: file, line: line) + } + + body(ResolvedProductResultXCTest(product)) + } + + package func checkPackage( + _ name: String, + file: StaticString = #file, + line: UInt = #line, + body: (ResolvedPackage) -> Void + ) { + guard let package = find(package: .init(stringLiteral: name)) else { + return XCTFail("Product \(name) not found", file: file, line: line) + } + body(package) + } + + public func check(testModules: String..., file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( + graph.allModules + .filter{ $0.type == .test } + .map{ $0.name } + .sorted(), testModules.sorted(), file: file, line: line) + } + + public func find(package: PackageIdentity) -> ResolvedPackage? { + return graph.package(for: package) + } + + private func reachableBuildTargets(in environment: BuildEnvironment) throws -> IdentifiableSet { + let inputTargets = graph.inputPackages.lazy.flatMap { $0.modules } + let recursiveBuildTargetDependencies = try inputTargets + .flatMap { try $0.recursiveDependencies(satisfying: environment) } + .compactMap { $0.module } + return IdentifiableSet(inputTargets).union(recursiveBuildTargetDependencies) + } + + private func reachableBuildProducts(in environment: BuildEnvironment) throws -> IdentifiableSet { + let recursiveBuildProductDependencies = try graph.inputPackages + .lazy + .flatMap { $0.modules } + .flatMap { try $0.recursiveDependencies(satisfying: environment) } + .compactMap { $0.product } + return IdentifiableSet(graph.inputPackages.flatMap { $0.products }).union(recursiveBuildProductDependencies) + } +} + +@available(*, deprecated, message: "Migrate to Swift Testing and use 'ResolvedTargetResult'") +public final class ResolvedTargetResultXCTest { + public let target: ResolvedModule + + init(_ target: ResolvedModule) { + self.target = target + } + + public func check(dependencies: String..., file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Set(dependencies), Set(target.dependencies.map({ $0.name })), file: file, line: line) + } + + public func check(dependencies: [String], file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Set(dependencies), Set(target.dependencies.map({ $0.name })), file: file, line: line) + } + + public func checkDependency( + _ name: String, + file: StaticString = #file, + line: UInt = #line, + body: (ResolvedTargetDependencyResultXCTest) -> Void + ) { + guard let dependency = target.dependencies.first(where: { $0.name == name }) else { + return XCTFail("Dependency \(name) not found", file: file, line: line) + } + body(ResolvedTargetDependencyResultXCTest(dependency)) + } + + public func check(type: Module.Kind, file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(type, target.type, file: file, line: line) + } + + public func checkDeclaredPlatforms(_ platforms: [String: String], file: StaticString = #file, line: UInt = #line) { + let targetPlatforms = Dictionary( + uniqueKeysWithValues: target.supportedPlatforms.map { ($0.platform.name, $0.version.versionString) } + ) + XCTAssertEqual(platforms, targetPlatforms, file: file, line: line) + } + + public func checkDerivedPlatforms(_ platforms: [String: String], file: StaticString = #file, line: UInt = #line) { + let derived = platforms.map { + let platform = PlatformRegistry.default.platformByName[$0.key] ?? PackageModel.Platform + .custom(name: $0.key, oldestSupportedVersion: $0.value) + return self.target.getSupportedPlatform(for: platform, usingXCTest: self.target.type == .test) + } + let targetPlatforms = Dictionary( + uniqueKeysWithValues: derived.map { ($0.platform.name, $0.version.versionString) } + ) + XCTAssertEqual(platforms, targetPlatforms, file: file, line: line) + } + + public func checkDerivedPlatformOptions( + _ platform: PackageModel.Platform, + options: [String], + file: StaticString = #file, + line: UInt = #line + ) { + let platform = self.target.getSupportedPlatform(for: platform, usingXCTest: target.type == .test) + XCTAssertEqual(platform.options, options, file: file, line: line) + } + + package func checkBuildSetting( + declaration: BuildSettings.Declaration, + assignments: Set?, + file: StaticString = #file, + line: UInt = #line + ) { + XCTAssertEqual( + target.underlying.buildSettings.assignments[declaration].flatMap { Set($0) }, + assignments, + file: file, + line: line + ) + } +} + +@available(*, deprecated, message: "Migrate to Swift Testing and use 'ResolvedTargetDependencyResult'") +public final class ResolvedTargetDependencyResultXCTest { + private let dependency: ResolvedModule.Dependency + + init(_ dependency: ResolvedModule.Dependency) { + self.dependency = dependency + } + + public func checkConditions(satisfy environment: BuildEnvironment, file: StaticString = #file, line: UInt = #line) { + XCTAssert(dependency.conditions.allSatisfy({ $0.satisfies(environment) }), file: file, line: line) + } + + public func checkConditions( + dontSatisfy environment: BuildEnvironment, + file: StaticString = #file, + line: UInt = #line + ) { + XCTAssert(!dependency.conditions.allSatisfy({ $0.satisfies(environment) }), file: file, line: line) + } + + public func checkTarget( + file: StaticString = #file, + line: UInt = #line, + body: (ResolvedTargetResultXCTest) -> Void + ) { + guard case let .module(target, _) = self.dependency else { + return XCTFail("Dependency \(dependency) is not a target", file: file, line: line) + } + body(ResolvedTargetResultXCTest(target)) + } + + public func checkProduct( + file: StaticString = #file, + line: UInt = #line, + body: (ResolvedProductResultXCTest) -> Void + ) { + guard case let .product(product, _) = self.dependency else { + return XCTFail("Dependency \(dependency) is not a product", file: file, line: line) + } + body(ResolvedProductResultXCTest(product)) + } +} + +@available(*, deprecated, message: "Migrate to Swift Testing and use 'ResolvedProductResult'") +public final class ResolvedProductResultXCTest { + private let product: ResolvedProduct + + init(_ product: ResolvedProduct) { + self.product = product + } + + public func check(modules: String..., file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Set(modules), Set(product.modules.map({ $0.name })), file: file, line: line) + } + + public func check(type: ProductType, file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(type, product.type, file: file, line: line) + } + + public func checkDeclaredPlatforms(_ platforms: [String: String], file: StaticString = #file, line: UInt = #line) { + let targetPlatforms = Dictionary(uniqueKeysWithValues: product.supportedPlatforms.map({ ($0.platform.name, $0.version.versionString) })) + XCTAssertEqual(platforms, targetPlatforms, file: file, line: line) + } + + public func checkDerivedPlatforms(_ platforms: [String: String], file: StaticString = #file, line: UInt = #line) { + let derived = platforms.map { + let platform = PlatformRegistry.default.platformByName[$0.key] ?? PackageModel.Platform.custom(name: $0.key, oldestSupportedVersion: $0.value) + return product.getSupportedPlatform(for: platform, usingXCTest: product.isLinkingXCTest) + } + let targetPlatforms = Dictionary(uniqueKeysWithValues: derived.map({ ($0.platform.name, $0.version.versionString) })) + XCTAssertEqual(platforms, targetPlatforms, file: file, line: line) + } + + public func checkDerivedPlatformOptions(_ platform: PackageModel.Platform, options: [String], file: StaticString = #file, line: UInt = #line) { + let platform = product.getSupportedPlatform(for: platform, usingXCTest: product.isLinkingXCTest) + XCTAssertEqual(platform.options, options, file: file, line: line) + } + + public func checkTarget( + _ name: String, + file: StaticString = #file, + line: UInt = #line, + body: (ResolvedTargetResultXCTest) -> Void + ) { + guard let target = product.modules.first(where: { $0.name == name }) else { + return XCTFail("Target \(name) not found", file: file, line: line) + } + body(ResolvedTargetResultXCTest(target)) + } +} diff --git a/Sources/_InternalTestSupport/SwiftTesting+TraitConditional.swift b/Sources/_InternalTestSupport/SwiftTesting+TraitConditional.swift index a4c10b613c8..b05539405b4 100644 --- a/Sources/_InternalTestSupport/SwiftTesting+TraitConditional.swift +++ b/Sources/_InternalTestSupport/SwiftTesting+TraitConditional.swift @@ -48,6 +48,17 @@ extension Trait where Self == Testing.ConditionTrait { } } + /// Test required setting ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION define + public static var requiresTargetBasedDependencyResolution: Self { + enabled("enabled as target based dependency resolution is defined") { + #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION + true + #else + false + #endif + } + } + /// Skip test if built by XCode. public static func skipIfXcodeBuilt() -> Self { disabled("Tests built by Xcode") { diff --git a/Tests/BuildTests/BuildPlanTests.swift b/Tests/BuildTests/BuildPlanTests.swift index dacf31e9e0f..75c84a396c3 100644 --- a/Tests/BuildTests/BuildPlanTests.swift +++ b/Tests/BuildTests/BuildPlanTests.swift @@ -3453,7 +3453,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { ) #endif - let graphResult = PackageGraphResult(graph) + let graphResult = PackageGraphResultXCTest(graph) graphResult.check(reachableProducts: "aexec", "BLibrary") graphResult.check(reachableTargets: "ATarget", "BTarget1") #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION @@ -3554,7 +3554,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { ) XCTAssertNoDiagnostics(observability.diagnostics) - let graphResult = PackageGraphResult(graph) + let graphResult = PackageGraphResultXCTest(graph) do { let linuxDebug = BuildEnvironment(platform: .linux, configuration: .debug) diff --git a/Tests/BuildTests/PluginInvocationTests.swift b/Tests/BuildTests/PluginInvocationTests.swift index 84c4ac524c1..63c13ff831b 100644 --- a/Tests/BuildTests/PluginInvocationTests.swift +++ b/Tests/BuildTests/PluginInvocationTests.swift @@ -86,7 +86,7 @@ final class PluginInvocationTests: XCTestCase { // Check the basic integrity before running plugins. XCTAssertNoDiagnostics(observability.diagnostics) - PackageGraphTester(graph) { graph in + PackageGraphTesterXCTest(graph) { graph in graph.check(packages: "Foo") graph.check(modules: "Foo", "FooPlugin", "FooTool", "FooToolLib") graph.checkTarget("Foo") { target in diff --git a/Tests/CommandsTests/RunCommandTests.swift b/Tests/CommandsTests/RunCommandTests.swift index 180be748878..33c66cc1300 100644 --- a/Tests/CommandsTests/RunCommandTests.swift +++ b/Tests/CommandsTests/RunCommandTests.swift @@ -269,7 +269,7 @@ struct RunCommandTests { let cwd = try #require(localFileSystem.currentWorkingDirectory, "Current working directory should not be nil") let (stdout, stderr) = try await execute([filePath, "1", "2"], packagePath: fixturePath, buildSystem: buildSystem) #expect(stdout.contains(#""\#(cwd)" "1" "2""#)) - #expect(stderr.contains("warning: 'swift run file.swift' command to interpret swift files is deprecated; use 'swift file.swift' instead")) + #expect(stderr.contains("warning: 'swift run \(filePath)' command to interpret swift files is deprecated; use 'swift \(filePath)' instead")) } } when: { ProcessInfo.hostOperatingSystem == .windows diff --git a/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift b/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift index 88385d33868..1a46d2509b8 100644 --- a/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift +++ b/Tests/PackageGraphTests/CrossCompilationPackageGraphTests.swift @@ -23,7 +23,7 @@ import XCTest final class CrossCompilationPackageGraphTests: XCTestCase { func testTrivialPackage() throws { let graph = try trivialPackageGraph().graph - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "Pkg") // "SwiftSyntax" is included for both host and target triples and is not pruned on this level result.check(modules: "app", "lib") @@ -42,7 +42,7 @@ final class CrossCompilationPackageGraphTests: XCTestCase { func testMacros() throws { let graph = try macrosPackageGraph().graph - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "swift-firmware", "swift-mmio", "swift-syntax") result.check( modules: "Core", @@ -78,7 +78,7 @@ final class CrossCompilationPackageGraphTests: XCTestCase { func testMacrosTests() throws { let graph = try macrosTestsPackageGraph().graph - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "swift-mmio", "swift-syntax") // "SwiftSyntax" is included for both host and target triples and is not pruned on this level result.check( diff --git a/Tests/PackageGraphTests/ModulesGraphTests.swift b/Tests/PackageGraphTests/ModulesGraphTests.swift index 2a93a6bff22..878d3a47902 100644 --- a/Tests/PackageGraphTests/ModulesGraphTests.swift +++ b/Tests/PackageGraphTests/ModulesGraphTests.swift @@ -2,13 +2,14 @@ // // This source file is part of the Swift open source project // -// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors +// 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 the list of Swift project authors // //===----------------------------------------------------------------------===// +import Foundation import Basics import PackageLoading @@ -19,88 +20,182 @@ import TSCUtility import _InternalTestSupport import PackageModel -import XCTest +import struct PackageGraph.ModulesGraph +import Testing import struct TSCBasic.ByteString -final class ModulesGraphTests: XCTestCase { - func testBasic() throws { - try XCTSkipOnWindows(because: "Possibly related to: https://github.com/swiftlang/swift-package-manager/issues/8511") - let fs = InMemoryFileSystem( - emptyFiles: - "/Foo/Sources/Foo/source.swift", - "/Foo/Sources/Foo/source.swift", - "/Foo/Sources/FooDep/source.swift", - "/Foo/Tests/FooTests/source.swift", - "/Bar/source.swift", - "/Baz/Sources/Baz/source.swift", - "/Baz/Tests/BazTests/source.swift" - ) +@Suite +struct ModulesGraphTests { + + @Suite( + .tags( + Tag.TestSize.small, + ), + ) + struct getReplProductName { + @Test( + "Empty root package throws an error", + ) + func emptyRootPackages() async throws { + let moduleGraph = try ModulesGraph( + rootPackages: [], + packages: IdentifiableSet([ResolvedPackage]()), + dependencies: [], + binaryArtifacts: [:], + ) - let observability = ObservabilitySystem.makeForTesting() - let g = try loadModulesGraph( - fileSystem: fs, - manifests: [ - Manifest.createFileSystemManifest( - displayName: "Foo", - path: "/Foo", - products: [ - ProductDescription(name: "Foo", type: .library(.automatic), targets: ["Foo"]), - ], - targets: [ - TargetDescription(name: "Foo", dependencies: ["FooDep"]), - TargetDescription(name: "FooDep", dependencies: []), - ] - ), - Manifest.createRootManifest( - displayName: "Bar", - path: "/Bar", - dependencies: [ - .localSourceControl(path: "/Foo", requirement: .upToNextMajor(from: "1.0.0")), - ], - products: [ - ProductDescription(name: "Bar", type: .library(.automatic), targets: ["Bar"]), - ], - targets: [ - TargetDescription(name: "Bar", dependencies: ["Foo"], path: "./"), - ] - ), - Manifest.createRootManifest( - displayName: "Baz", - path: "/Baz", - dependencies: [ - .localSourceControl(path: "/Bar", requirement: .upToNextMajor(from: "1.0.0")), - ], - targets: [ - TargetDescription(name: "Baz", dependencies: ["Bar"]), - TargetDescription(name: "BazTests", dependencies: ["Baz"], type: .test), - ] - ), - ], - observabilityScope: observability.topScope - ) + #expect(throws: StringError("Root package does not exist.")) { // Index out of range + let _ = try moduleGraph.getReplProductName() + } + } - XCTAssertNoDiagnostics(observability.diagnostics) - PackageGraphTester(g) { result in - result.check(packages: "Bar", "Foo", "Baz") - result.check(modules: "Bar", "Foo", "Baz", "FooDep") - result.check(testModules: "BazTests") - result.checkTarget("Foo") { result in result.check(dependencies: "FooDep") } - result.checkTarget("Bar") { result in result.check(dependencies: "Foo") } - result.checkTarget("Baz") { result in result.check(dependencies: "Bar") } + @Test( + "Non-empty root package results expected REPL product name", + arguments: 1...5, + ) + func nonEmptyRootPackages( + num: Int, + ) async throws { + // GIVEN a module graph instance with X number of root packages, where the package names are `package_#` + let manifest = Manifest( + displayName: "manifestUT", + packageIdentity: PackageIdentity("manifest_id"), + path: AbsolutePath("/"), + packageKind: .fileSystem(AbsolutePath("/")), + packageLocation: "", + defaultLocalization: nil, + platforms: [], + version: nil, + revision: nil, + toolsVersion: .vNext, + pkgConfig: nil, + providers: nil, + cLanguageStandard: nil, + cxxLanguageStandard: nil, + swiftLanguageVersions: nil, + traits: Set([]), + ) + let rootPackages = (0.. TestingObservability { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Foo/Sources/Foo2/foo.swift", "/Bar/Sources/Bar/bar.swift", "/Bar/Sources/Bar2/bar.swift", @@ -2132,42 +2269,51 @@ final class ModulesGraphTests: XCTestCase { return observability } - func testUnsafeFlagsDisabled() throws { + @Test + func unsafeFlagsDisabled() throws { let observability = try loadUnsafeModulesGraph(toolsVersion: .v6_2) // We have turned off the unsafe flags check - XCTAssertEqual(observability.diagnostics.count, 0) + #expect(observability.diagnostics.count == 0) } + + @Test func testUnsafeFlagsEnabled() throws { let observability = try loadUnsafeModulesGraph(toolsVersion: .v6_1) - XCTAssertEqual(observability.diagnostics.count, 3) - testDiagnostics(observability.diagnostics) { result in + #expect(observability.diagnostics.count == 3) + try testDiagnostics(observability.diagnostics) { result in var expectedMetadata = ObservabilityMetadata() expectedMetadata.moduleName = "Foo2" - let diagnostic1 = result.checkUnordered( + let diagnostic1 = try #require(result.checkUnordered( diagnostic: .contains("the target 'Bar2' in product 'TransitiveBar' contains unsafe build flags"), severity: .error - ) - XCTAssertEqual(diagnostic1?.metadata?.moduleName, "Foo2") - let diagnostic2 = result.checkUnordered( + )) + let diagnostic1_metadata = try #require(diagnostic1.metadata) + #expect(diagnostic1_metadata.moduleName == "Foo2") + + let diagnostic2 = try #require(result.checkUnordered( diagnostic: .contains("the target 'Bar' in product 'Bar' contains unsafe build flags"), severity: .error - ) - XCTAssertEqual(diagnostic2?.metadata?.moduleName, "Foo") - let diagnostic3 = result.checkUnordered( + )) + let diagnostic2_metadata = try #require(diagnostic2.metadata) + #expect(diagnostic2_metadata.moduleName == "Foo") + + let diagnostic3 = try #require(result.checkUnordered( diagnostic: .contains("the target 'Bar2' in product 'Bar' contains unsafe build flags"), severity: .error - ) - XCTAssertEqual(diagnostic3?.metadata?.moduleName, "Foo") + )) + let diagnostic3_metadata = try #require(diagnostic3.metadata) + #expect(diagnostic3_metadata.moduleName == "Foo") } } - func testConditionalTargetDependency() throws { + @Test + func conditionalTargetDependency() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/source.swift", + "/Foo/Sources/Foo/source.swift", "/Foo/Sources/Bar/source.swift", "/Foo/Sources/Baz/source.swift", "/Biz/Sources/Biz/source.swift" @@ -2217,22 +2363,22 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) - PackageGraphTester(graph) { result in + expectNoDiagnostics(observability.diagnostics) + try PackageGraphTester(graph) { result in result.check(modules: "Foo", "Bar", "Baz", "Biz") - result.checkTarget("Foo") { result in + try result.checkTarget("Foo") { result in result.check(dependencies: "Bar", "Baz", "Biz") - result.checkDependency("Bar") { result in + try result.checkDependency("Bar") { result in result.checkConditions(satisfy: .init(platform: .linux, configuration: .debug)) result.checkConditions(satisfy: .init(platform: .linux, configuration: .release)) result.checkConditions(dontSatisfy: .init(platform: .macOS, configuration: .release)) } - result.checkDependency("Baz") { result in + try result.checkDependency("Baz") { result in result.checkConditions(satisfy: .init(platform: .watchOS, configuration: .debug)) result.checkConditions(satisfy: .init(platform: .tvOS, configuration: .debug)) result.checkConditions(dontSatisfy: .init(platform: .tvOS, configuration: .release)) } - result.checkDependency("Biz") { result in + try result.checkDependency("Biz") { result in result.checkConditions(satisfy: .init(platform: .watchOS, configuration: .release)) result.checkConditions(satisfy: .init(platform: .iOS, configuration: .release)) result.checkConditions(dontSatisfy: .init(platform: .iOS, configuration: .debug)) @@ -2242,15 +2388,13 @@ final class ModulesGraphTests: XCTestCase { } } - func testUnreachableProductsSkipped() throws { - #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - #else - try XCTSkipIf(true) - #endif - + @Test( + .requiresTargetBasedDependencyResolution, + ) + func unreachableProductsSkipped() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Root/Sources/Root/Root.swift", + "/Root/Sources/Root/Root.swift", "/Immediate/Sources/ImmediateUsed/ImmediateUsed.swift", "/Immediate/Sources/ImmediateUnused/ImmediateUnused.swift", "/Transitive/Sources/TransitiveUsed/TransitiveUsed.swift", @@ -2338,10 +2482,11 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) } - func testResolvedPackagesStoreIsResilientAgainstDupes() throws { + @Test + func resolvedPackagesStoreIsResilientAgainstDupes() throws { let json = """ { "version": 1, @@ -2374,8 +2519,8 @@ final class ModulesGraphTests: XCTestCase { let packageResolvedFile = AbsolutePath("/Package.resolved") try fs.writeFileContents(packageResolvedFile, string: json) - XCTAssertThrows( - StringError( + #expect( + throws: StringError( "\(packageResolvedFile) file is corrupted or malformed; fix or delete the file to continue: duplicated entry for package \"yams\"" ) ) { @@ -2388,7 +2533,8 @@ final class ModulesGraphTests: XCTestCase { } } - func testResolutionDeterminism() throws { + @Test + func resolutionDeterminism() throws { let fileSystem = InMemoryFileSystem( emptyFiles: [ "/A/Sources/A/A.swift", @@ -2481,10 +2627,11 @@ final class ModulesGraphTests: XCTestCase { } } - func testTargetDependencies_Pre52() throws { + @Test + func targetDependencies_Pre52() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Bar/Sources/Bar/bar.swift" ) @@ -2518,13 +2665,14 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) } - func testTargetDependencies_Pre52_UnknownProduct() throws { + @Test + func targetDependencies_Pre52_UnknownProduct() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Bar/Sources/Bar/bar.swift" ) @@ -2568,10 +2716,11 @@ final class ModulesGraphTests: XCTestCase { } } - func testTargetDependencies_Post52_NamesAligned() throws { + @Test + func targetDependencies_Post52_NamesAligned() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Bar/Sources/Bar/bar.swift" ) @@ -2605,13 +2754,14 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) } - func testTargetDependencies_Post52_UnknownProduct() throws { + @Test + func targetDependencies_Post52_UnknownProduct() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Bar/Sources/Bar/bar.swift" ) @@ -2655,10 +2805,11 @@ final class ModulesGraphTests: XCTestCase { } } - func testTargetDependencies_Post52_ProductPackageNoMatch() throws { + @Test + func targetDependencies_Post52_ProductPackageNoMatch() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Bar/Sources/Bar/bar.swift" ) @@ -2716,15 +2867,16 @@ final class ModulesGraphTests: XCTestCase { manifests: fixedManifests, observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) } } // TODO: remove this when we remove explicit dependency name - func testTargetDependencies_Post52_ProductPackageNoMatch_DependencyExplicitName() throws { + @Test + func targetDependencies_Post52_ProductPackageNoMatch_DependencyExplicitName() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Bar/Sources/Bar/bar.swift" ) @@ -2786,14 +2938,15 @@ final class ModulesGraphTests: XCTestCase { manifests: fixedManifests, observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) } } - func testTargetDependencies_Post52_LocationAndManifestNameDontMatch() throws { + @Test + func targetDependencies_Post52_LocationAndManifestNameDontMatch() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Some-Bar/Sources/Bar/bar.swift" ) @@ -2851,14 +3004,15 @@ final class ModulesGraphTests: XCTestCase { manifests: fixedManifests, observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) } } - func testTargetDependencies_Post52_LocationAndManifestNameDontMatch_ProductPackageDontMatch() throws { + @Test + func targetDependencies_Post52_LocationAndManifestNameDontMatch_ProductPackageDontMatch() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Some-Bar/Sources/Bar/bar.swift" ) @@ -2897,7 +3051,7 @@ final class ModulesGraphTests: XCTestCase { """, severity: .error ) - XCTAssertEqual(diagnostic?.metadata?.packageIdentity, .plain("foo")) + #expect(diagnostic?.metadata?.packageIdentity == .plain("foo")) } } @@ -2917,16 +3071,17 @@ final class ModulesGraphTests: XCTestCase { manifests: fixedManifests, observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) } } // test backwards compatibility 5.2 < 5.4 // TODO: remove this when we remove explicit dependency name - func testTargetDependencies_Post52_LocationAndManifestNameDontMatch_WithDependencyName() throws { + @Test + func targetDependencies_Post52_LocationAndManifestNameDontMatch_WithDependencyName() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Some-Bar/Sources/Bar/bar.swift" ) @@ -2961,16 +3116,16 @@ final class ModulesGraphTests: XCTestCase { let observability = ObservabilitySystem.makeForTesting() _ = try loadModulesGraph(fileSystem: fs, manifests: manifests, observabilityScope: observability.topScope) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) } // test backwards compatibility 5.2 < 5.4 // TODO: remove this when we remove explicit dependency name - func testTargetDependencies_Post52_LocationAndManifestNameDontMatch_ProductPackageDontMatch_WithDependencyName( - ) throws { + @Test + func targetDependencies_Post52_LocationAndManifestNameDontMatch_ProductPackageDontMatch_WithDependencyName() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Some-Bar/Sources/Bar/bar.swift" ) @@ -3013,7 +3168,7 @@ final class ModulesGraphTests: XCTestCase { """, severity: .error ) - XCTAssertEqual(diagnostic?.metadata?.packageIdentity, .plain("foo")) + #expect(diagnostic?.metadata?.packageIdentity == .plain("foo")) } } @@ -3033,13 +3188,14 @@ final class ModulesGraphTests: XCTestCase { manifests: fixedManifests, observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) } } // test backwards compatibility 5.2 < 5.4 // TODO: remove this when we remove explicit dependency name - func testTargetDependencies_Post52_AliasFindsIdentity() throws { + @Test + func targetDependencies_Post52_AliasFindsIdentity() throws { let manifest = try Manifest.createRootManifest( displayName: "Package", path: "/Package", @@ -3068,21 +3224,21 @@ final class ModulesGraphTests: XCTestCase { // Make sure aliases are found properly and do not fall back to pre‐5.2 behavior, leaking across onto other // dependencies. let required = try manifest.dependenciesRequired(for: .everything) - let unrelated = try XCTUnwrap( + let unrelated = try #require( required - .first(where: { $0.nameForModuleDependencyResolutionOnly == "Unrelated" }) - ) + .first(where: { $0.nameForModuleDependencyResolutionOnly == "Unrelated" })) let requestedProducts = unrelated.productFilter - #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION +#if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION // Unrelated should not have been asked for Product, because it should know Product comes from Identity. - XCTAssertFalse(requestedProducts.contains("Product"), "Product requests are leaking.") - #endif + #expect(!requestedProducts.contains("Product"), "Product requests are leaking.") +#endif } - func testPlatforms() throws { + @Test + func platforms() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Sources/foo/module.modulemap", + "/Sources/foo/module.modulemap", "/Sources/bar/bar.swift", "/Sources/cbar/bar.c", "/Sources/cbar/include/bar.h", @@ -3157,9 +3313,9 @@ final class ModulesGraphTests: XCTestCase { customXCTestMinimumDeploymentTargets: customXCTestMinimumDeploymentTargets, observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) - PackageGraphTester(graph) { result in + try PackageGraphTester(graph) { result in let expectedDeclaredPlatforms = [ "macos": "10.14", ] @@ -3170,25 +3326,25 @@ final class ModulesGraphTests: XCTestCase { uniquingKeysWith: { _, rhs in rhs } ) - result.checkTarget("foo") { target in + try result.checkTarget("foo") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) target.checkDerivedPlatformOptions(.macOS, options: ["option1"]) target.checkDerivedPlatformOptions(.iOS, options: []) } - result.checkTarget("bar") { target in + try result.checkTarget("bar") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) target.checkDerivedPlatformOptions(.macOS, options: ["option1"]) target.checkDerivedPlatformOptions(.iOS, options: []) } - result.checkTarget("cbar") { target in + try result.checkTarget("cbar") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) target.checkDerivedPlatformOptions(.macOS, options: ["option1"]) target.checkDerivedPlatformOptions(.iOS, options: []) } - result.checkTarget("test") { target in + try result.checkTarget("test") { target in var expected = expectedDerivedPlatforms for item in [PackageModel.Platform.macOS, .iOS, .tvOS, .watchOS] { expected[item.name] = expectedPlatformsForTests[item]?.versionString @@ -3197,25 +3353,25 @@ final class ModulesGraphTests: XCTestCase { target.checkDerivedPlatformOptions(.macOS, options: ["option1"]) target.checkDerivedPlatformOptions(.iOS, options: []) } - result.checkProduct("foo") { product in + try result.checkProduct("foo") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) product.checkDerivedPlatformOptions(.macOS, options: ["option1"]) product.checkDerivedPlatformOptions(.iOS, options: []) } - result.checkProduct("bar") { product in + try result.checkProduct("bar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) product.checkDerivedPlatformOptions(.macOS, options: ["option1"]) product.checkDerivedPlatformOptions(.iOS, options: []) } - result.checkProduct("cbar") { product in + try result.checkProduct("cbar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) product.checkDerivedPlatformOptions(.macOS, options: ["option1"]) product.checkDerivedPlatformOptions(.iOS, options: []) } - result.checkProduct("multi-target") { product in + try result.checkProduct("multi-target") { product in var expected = expectedDerivedPlatforms for item in [PackageModel.Platform.macOS, .iOS, .tvOS, .watchOS] { expected[item.name] = expectedPlatformsForTests[item]?.versionString @@ -3253,9 +3409,9 @@ final class ModulesGraphTests: XCTestCase { manifests: [manifest], observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) - PackageGraphTester(graph) { result in + try PackageGraphTester(graph) { result in let expectedDeclaredPlatforms = [ "macos": "10.14", "tvos": "12.0", @@ -3267,27 +3423,27 @@ final class ModulesGraphTests: XCTestCase { uniquingKeysWith: { _, rhs in rhs } ) - result.checkTarget("foo") { target in + try result.checkTarget("foo") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - result.checkTarget("bar") { target in + try result.checkTarget("bar") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - result.checkTarget("cbar") { target in + try result.checkTarget("cbar") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - result.checkProduct("foo") { product in + try result.checkProduct("foo") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } - result.checkProduct("bar") { product in + try result.checkProduct("bar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } - result.checkProduct("cbar") { product in + try result.checkProduct("cbar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } @@ -3317,9 +3473,9 @@ final class ModulesGraphTests: XCTestCase { customXCTestMinimumDeploymentTargets: customXCTestMinimumDeploymentTargets, observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) - PackageGraphTester(graph) { result in + try PackageGraphTester(graph) { result in let expectedDeclaredPlatforms = [ "ios": "15.0", ] @@ -3338,15 +3494,15 @@ final class ModulesGraphTests: XCTestCase { expectedDerivedPlatforms["maccatalyst"] = expectedDeclaredPlatforms["ios"] expectedDerivedPlatformsForTests["maccatalyst"] = expectedDeclaredPlatforms["ios"] - result.checkTarget("test") { target in + try result.checkTarget("test") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatformsForTests) } - result.checkTarget("cbar") { target in + try result.checkTarget("cbar") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - result.checkProduct("cbar") { product in + try result.checkProduct("cbar") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } @@ -3354,10 +3510,11 @@ final class ModulesGraphTests: XCTestCase { } } - func testCustomPlatforms() throws { + @Test + func customPlatforms() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Sources/foo/module.modulemap" + "/Sources/foo/module.modulemap" ) let defaultDerivedPlatforms = [ @@ -3396,9 +3553,9 @@ final class ModulesGraphTests: XCTestCase { manifests: [manifest], observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) - PackageGraphTester(graph) { result in + try PackageGraphTester(graph) { result in let expectedDeclaredPlatforms = [ "customos": "1.0", ] @@ -3409,11 +3566,11 @@ final class ModulesGraphTests: XCTestCase { uniquingKeysWith: { _, rhs in rhs } ) - result.checkTarget("foo") { target in + try result.checkTarget("foo") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - result.checkProduct("foo") { product in + try result.checkProduct("foo") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } @@ -3442,9 +3599,9 @@ final class ModulesGraphTests: XCTestCase { manifests: [manifest], observabilityScope: observability.topScope ) - XCTAssertNoDiagnostics(observability.diagnostics) + expectNoDiagnostics(observability.diagnostics) - PackageGraphTester(graph) { result in + try PackageGraphTester(graph) { result in let expectedDeclaredPlatforms = [ "customos": "1.0", "anothercustomos": "2.3", @@ -3456,11 +3613,11 @@ final class ModulesGraphTests: XCTestCase { uniquingKeysWith: { _, rhs in rhs } ) - result.checkTarget("foo") { target in + try result.checkTarget("foo") { target in target.checkDeclaredPlatforms(expectedDeclaredPlatforms) target.checkDerivedPlatforms(expectedDerivedPlatforms) } - result.checkProduct("foo") { product in + try result.checkProduct("foo") { product in product.checkDeclaredPlatforms(expectedDeclaredPlatforms) product.checkDerivedPlatforms(expectedDerivedPlatforms) } @@ -3468,10 +3625,11 @@ final class ModulesGraphTests: XCTestCase { } } - func testDependencyOnUpcomingFeatures() throws { + @Test + func dependencyOnUpcomingFeatures() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/foo.swift", + "/Foo/Sources/Foo/foo.swift", "/Foo/Sources/Foo2/foo.swift", "/Bar/Sources/Bar/bar.swift", "/Bar/Sources/Bar2/bar.swift", @@ -3536,17 +3694,14 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertEqual( - observability.diagnostics.count, - 0, - "unexpected diagnostics: \(observability.diagnostics.map(\.description))" - ) + #expect(observability.diagnostics.count == 0) } - func testCustomNameInPackageDependency() throws { + @Test + func customNameInPackageDependency() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/source.swift", + "/Foo/Sources/Foo/source.swift", "/Bar2/Sources/Bar/source.swift" ) @@ -3580,17 +3735,14 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertEqual( - observability.diagnostics.count, - 0, - "unexpected diagnostics: \(observability.diagnostics.map(\.description))" - ) + #expect(observability.diagnostics.count == 0) } - func testDependencyResolutionWithErrorMessages() throws { + @Test + func dependencyResolutionWithErrorMessages() throws { let fs = InMemoryFileSystem( emptyFiles: - "/aaa/Sources/aaa/main.swift", + "/aaa/Sources/aaa/main.swift", "/zzz/Sources/zzz/source.swift" ) @@ -3641,10 +3793,11 @@ final class ModulesGraphTests: XCTestCase { } } - func testTraits_whenSingleManifest_andDefaultTrait() throws { + @Test + func traits_whenSingleManifest_andDefaultTrait() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/source.swift" + "/Foo/Sources/Foo/source.swift" ) let observability = ObservabilitySystem.makeForTesting() @@ -3669,19 +3822,20 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertEqual(observability.diagnostics.count, 0) + #expect(observability.diagnostics.count == 0) - PackageGraphTester(graph) { result in - result.checkPackage("Foo") { package in - XCTAssertEqual(package.enabledTraits, ["Trait1"]) + try PackageGraphTester(graph) { result in + try result.checkPackage("Foo") { package in + #expect(package.enabledTraits == ["Trait1"]) } } } - func testTraits_whenTraitEnablesOtherTraits() throws { + @Test + func traits_whenTraitEnablesOtherTraits() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Foo/Sources/Foo/source.swift" + "/Foo/Sources/Foo/source.swift" ) let observability = ObservabilitySystem.makeForTesting() @@ -3710,19 +3864,20 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertEqual(observability.diagnostics.count, 0) + #expect(observability.diagnostics.count == 0) - PackageGraphTester(graph) { result in - result.checkPackage("Foo") { package in - XCTAssertEqual(package.enabledTraits, ["Trait1", "Trait2", "Trait3", "Trait4", "Trait5"]) + try PackageGraphTester(graph) { result in + try result.checkPackage("Foo") { package in + #expect(package.enabledTraits == ["Trait1", "Trait2", "Trait3", "Trait4", "Trait5"]) } } } - func testTraits_whenDependencyTraitEnabled() throws { + @Test + func traits_whenDependencyTraitEnabled() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Package1/Sources/Package1Target1/source.swift", + "/Package1/Sources/Package1Target1/source.swift", "/Package2/Sources/Package2Target1/source.swift" ) let observability = ObservabilitySystem.makeForTesting() @@ -3777,23 +3932,24 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertEqual(observability.diagnostics.count, 0) + #expect(observability.diagnostics.count == 0) - PackageGraphTester(graph) { result in - result.checkPackage("Package1") { package in - XCTAssertEqual(package.enabledTraits, ["Package1Trait1"]) - XCTAssertEqual(package.dependencies.count, 1) + try PackageGraphTester(graph) { result in + try result.checkPackage("Package1") { package in + #expect(package.enabledTraits == ["Package1Trait1"]) + #expect(package.dependencies.count == 1) } - result.checkPackage("Package2") { package in - XCTAssertEqual(package.enabledTraits, ["Package2Trait1"]) + try result.checkPackage("Package2") { package in + #expect(package.enabledTraits == ["Package2Trait1"]) } } } - func testTraits_whenTraitEnablesDependencyTrait() throws { + @Test + func traits_whenTraitEnablesDependencyTrait() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Package1/Sources/Package1Target1/source.swift", + "/Package1/Sources/Package1Target1/source.swift", "/Package2/Sources/Package2Target1/source.swift" ) @@ -3850,20 +4006,21 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertEqual(observability.diagnostics.count, 0) + #expect(observability.diagnostics.count == 0) - PackageGraphTester(graph) { result in - result.checkPackage("Package1") { package in - XCTAssertEqual(package.enabledTraits, ["Package1Trait1"]) - XCTAssertEqual(package.dependencies.count, 1) + try PackageGraphTester(graph) { result in + try result.checkPackage("Package1") { package in + #expect(package.enabledTraits == ["Package1Trait1"]) + #expect(package.dependencies.count == 1) } - result.checkPackage("Package2") { package in - XCTAssertEqual(package.enabledTraits, ["Package2Trait1"]) + try result.checkPackage("Package2") { package in + #expect(package.enabledTraits == ["Package2Trait1"]) } } } - func testTraits_whenComplex() throws { + @Test + func traits_whenComplex() throws { let fs = InMemoryFileSystem( emptyFiles: "/Package1/Sources/Package1Target1/source.swift", @@ -4027,14 +4184,14 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertEqual(observability.diagnostics.count, 0) + #expect(observability.diagnostics.count == 0) - PackageGraphTester(graph) { result in - result.checkPackage("Package1") { package in - XCTAssertEqual(package.enabledTraits, ["Package1Trait1", "Package1Trait2"]) - XCTAssertEqual(package.dependencies.count, 3) + try PackageGraphTester(graph) { result in + try result.checkPackage("Package1") { package in + #expect(package.enabledTraits == ["Package1Trait1", "Package1Trait2"]) + #expect(package.dependencies.count == 3) } - result.checkTarget("Package1Target1") { target in + try result.checkTarget("Package1Target1") { target in target.check(dependencies: "Package2Target1", "Package4Target1", "Package5Target1") target.checkBuildSetting( declaration: .SWIFT_ACTIVE_COMPILATION_CONDITIONS, @@ -4045,22 +4202,23 @@ final class ModulesGraphTests: XCTestCase { ] ) } - result.checkPackage("Package2") { package in - XCTAssertEqual(package.enabledTraits, ["Package2Trait1"]) + try result.checkPackage("Package2") { package in + #expect(package.enabledTraits == ["Package2Trait1"]) } - result.checkPackage("Package3") { package in - XCTAssertEqual(package.enabledTraits, ["Package3Trait1"]) + try result.checkPackage("Package3") { package in + #expect(package.enabledTraits == ["Package3Trait1"]) } - result.checkPackage("Package4") { package in - XCTAssertEqual(package.enabledTraits, ["Package4Trait1", "Package4Trait2"]) + try result.checkPackage("Package4") { package in + #expect(package.enabledTraits == ["Package4Trait1", "Package4Trait2"]) } } } - func testTraits_whenPruneDependenciesEnabled() throws { + @Test + func traits_whenPruneDependenciesEnabled() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Package1/Sources/Package1Target1/source.swift", + "/Package1/Sources/Package1Target1/source.swift", "/Package2/Sources/Package2Target1/source.swift", "/Package3/Sources/Package3Target1/source.swift", "/Package4/Sources/Package4Target1/source.swift", @@ -4232,14 +4390,14 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertEqual(observability.diagnostics.count, 0) + #expect(observability.diagnostics.count == 0) - PackageGraphTester(graph) { result in - result.checkPackage("Package1") { package in - XCTAssertEqual(package.enabledTraits, ["Package1Trait3"]) - XCTAssertEqual(package.dependencies.count, 2) + try PackageGraphTester(graph) { result in + try result.checkPackage("Package1") { package in + #expect(package.enabledTraits == ["Package1Trait3"]) + #expect(package.dependencies.count == 2) } - result.checkTarget("Package1Target1") { target in + try result.checkTarget("Package1Target1") { target in target.check(dependencies: "Package2Target1", "Package4Target1") target.checkBuildSetting( declaration: .SWIFT_ACTIVE_COMPILATION_CONDITIONS, @@ -4249,22 +4407,23 @@ final class ModulesGraphTests: XCTestCase { ] ) } - result.checkPackage("Package2") { package in - XCTAssertEqual(package.enabledTraits, []) + try result.checkPackage("Package2") { package in + #expect(package.enabledTraits == []) } - result.checkPackage("Package3") { package in - XCTAssertEqual(package.enabledTraits, []) + try result.checkPackage("Package3") { package in + #expect(package.enabledTraits == []) } - result.checkPackage("Package4") { package in - XCTAssertEqual(package.enabledTraits, ["Package4Trait2"]) + try result.checkPackage("Package4") { package in + #expect(package.enabledTraits == ["Package4Trait2"]) } } } - func testTraits_whenPruneDependenciesEnabledForSomeManifests() throws { + @Test + func traits_whenPruneDependenciesEnabledForSomeManifests() throws { let fs = InMemoryFileSystem( emptyFiles: - "/Package1/Sources/Package1Target1/source.swift", + "/Package1/Sources/Package1Target1/source.swift", "/Package2/Sources/Package2Target1/source.swift", "/Package3/Sources/Package3Target1/source.swift", "/Package4/Sources/Package4Target1/source.swift", @@ -4436,13 +4595,13 @@ final class ModulesGraphTests: XCTestCase { observabilityScope: observability.topScope ) - XCTAssertEqual(observability.diagnostics.count, 0) - PackageGraphTester(graph) { result in - result.checkPackage("Package1") { package in - XCTAssertEqual(package.enabledTraits, ["Package1Trait3"]) - XCTAssertEqual(package.dependencies.count, 2) + #expect(observability.diagnostics.count == 0) + try PackageGraphTester(graph) { result in + try result.checkPackage("Package1") { package in + #expect(package.enabledTraits == ["Package1Trait3"]) + #expect(package.dependencies.count == 2) } - result.checkTarget("Package1Target1") { target in + try result.checkTarget("Package1Target1") { target in target.check(dependencies: "Package2Target1", "Package4Target1") target.checkBuildSetting( declaration: .SWIFT_ACTIVE_COMPILATION_CONDITIONS, @@ -4452,14 +4611,14 @@ final class ModulesGraphTests: XCTestCase { ] ) } - result.checkPackage("Package2") { package in - XCTAssertEqual(package.enabledTraits, []) + try result.checkPackage("Package2") { package in + #expect(package.enabledTraits == []) } - result.checkPackage("Package3") { package in - XCTAssertEqual(package.enabledTraits, []) + try result.checkPackage("Package3") { package in + #expect(package.enabledTraits == []) } - result.checkPackage("Package4") { package in - XCTAssertEqual(package.enabledTraits, ["Package4Trait2"]) + try result.checkPackage("Package4") { package in + #expect(package.enabledTraits == ["Package4Trait2"]) } } } diff --git a/Tests/WorkspaceTests/WorkspaceTests.swift b/Tests/WorkspaceTests/WorkspaceTests.swift index 8d280ffc7c2..667d61aee2f 100644 --- a/Tests/WorkspaceTests/WorkspaceTests.swift +++ b/Tests/WorkspaceTests/WorkspaceTests.swift @@ -94,7 +94,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./Baz", requirement: .exact("1.0.0"), products: .specific(["Baz"])), ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Baz", "Foo", "Quix") result.check(modules: "Bar", "Baz", "Foo", "Quix") @@ -380,7 +380,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo", "Bar"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Bar", "Foo") result.check(packages: "Bar", "Baz", "Foo") result.checkTarget("Foo") { result in result.check(dependencies: "Baz") } @@ -446,7 +446,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo", "Bar", "Overridden/bazzz"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "bar", "Foo", "bazzz") result.check(packages: "bar", "bazzz", "foo") result.checkTarget("Foo") { result in result.check(dependencies: "Baz") } @@ -555,7 +555,7 @@ final class WorkspaceTests: XCTestCase { ), ] ) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "foo-package", "bar-package") result.check(packages: "foo-package", "bar-package") result.checkTarget("FooTarget") { result in result.check(dependencies: "BarProduct") } @@ -610,7 +610,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo", "Baz"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Baz", "Foo") result.check(packages: "Baz", "Foo") result.check(modules: "BazA", "BazB", "Foo") @@ -671,7 +671,7 @@ final class WorkspaceTests: XCTestCase { // Load only Foo right now so Baz is loaded from remote. try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Baz", "Foo") result.check(modules: "Baz", "Foo") @@ -691,7 +691,7 @@ final class WorkspaceTests: XCTestCase { // Now load with Baz as a root package. workspace.delegate.clear() try await workspace.checkPackageGraph(roots: ["Foo", "Baz"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Baz", "Foo") result.check(packages: "Baz", "Foo") result.check(modules: "BazA", "BazB", "Foo") @@ -762,7 +762,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(dependencies: dependencies) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "Bar", "Foo") result.check(modules: "Bar", "Foo") result.checkTarget("Foo") { result in result.check(dependencies: "Bar") } @@ -829,7 +829,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./A", requirement: .exact("1.0.0"), products: .specific(["A"])), ] try await workspace.checkPackageGraph(deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "A", "AA") result.check(modules: "A", "AA") result.checkTarget("A") { result in result.check(dependencies: "AA") } @@ -852,7 +852,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./A", requirement: .exact("1.0.1"), products: .specific(["A"])), ] try await workspace.checkPackageGraph(deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.checkTarget("A") { result in result.check(dependencies: "AA") } } XCTAssertNoDiagnostics(diagnostics) @@ -1515,7 +1515,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["A", "B", "C"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "A", "B", "C") result.check(modules: "A", "B", "C") } @@ -1586,7 +1586,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])), ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -1602,7 +1602,7 @@ final class WorkspaceTests: XCTestCase { XCTAssertNoDiagnostics(diagnostics) } try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -1675,7 +1675,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -1708,7 +1708,7 @@ final class WorkspaceTests: XCTestCase { XCTAssertEqual(expectedChange, change) } try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -1951,7 +1951,7 @@ final class WorkspaceTests: XCTestCase { // Load the graph with one root. try await workspace.checkPackageGraph(roots: ["Root1"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "Foo", "Root1") } XCTAssertNoDiagnostics(diagnostics) @@ -1968,7 +1968,7 @@ final class WorkspaceTests: XCTestCase { // Load the graph with both roots. try await workspace.checkPackageGraph(roots: ["Root1", "Root2"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "Bar", "Foo", "Root1", "Root2") } XCTAssertNoDiagnostics(diagnostics) @@ -2102,7 +2102,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./Bar", requirement: .revision(barRevision), products: .specific(["Bar"])), ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -2149,7 +2149,7 @@ final class WorkspaceTests: XCTestCase { // Load initial version. try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -2213,7 +2213,7 @@ final class WorkspaceTests: XCTestCase { // Load the graph. try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -2223,7 +2223,7 @@ final class WorkspaceTests: XCTestCase { try fs.removeFileTree(workspace.getOrCreateWorkspace().location.repositoriesCheckoutsDirectory) try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -2400,7 +2400,7 @@ final class WorkspaceTests: XCTestCase { // Load the graph. try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: .plain("Root")) result.check(packages: .plain("bar"), .plain("foo"), .plain("Root")) } @@ -2508,7 +2508,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: .plain("Root")) result.check(packages: .plain("root"), .plain("Foo")) } @@ -2617,7 +2617,7 @@ final class WorkspaceTests: XCTestCase { // Load the graph and edit foo. try await workspace.checkPackageGraph(deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "Foo") } XCTAssertNoDiagnostics(diagnostics) @@ -2711,7 +2711,7 @@ final class WorkspaceTests: XCTestCase { ] // Load the graph. try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -2841,7 +2841,7 @@ final class WorkspaceTests: XCTestCase { // Load the graph. try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -2855,7 +2855,7 @@ final class WorkspaceTests: XCTestCase { .fileSystem(path: "./Foo", products: .specific(["Foo"])), ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Bar", "Root") } @@ -2905,7 +2905,7 @@ final class WorkspaceTests: XCTestCase { // Initial resolution. try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Bar", "Foo") } @@ -2999,7 +2999,7 @@ final class WorkspaceTests: XCTestCase { // Load the graph. try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -3129,7 +3129,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"], deps: []) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "Bar", "Foo", "Root") } } @@ -3154,7 +3154,7 @@ final class WorkspaceTests: XCTestCase { // reload graph after "external" change try await workspace.checkPackageGraph(roots: ["Root"], deps: []) { graph, _ in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "Bar", "Foo", "Root") } } @@ -3268,7 +3268,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Bar", "Baz", "Foo") result.check(modules: "Bar", "Baz", "Foo") @@ -3346,7 +3346,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Foo") result.check(modules: "Foo") @@ -3394,7 +3394,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Bar", "Foo") } @@ -3448,7 +3448,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Foo") result.check(modules: "Foo") @@ -3502,7 +3502,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./Foo", requirement: .branch("develop"), products: .specific(["Foo"])), ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -3571,7 +3571,7 @@ final class WorkspaceTests: XCTestCase { .fileSystem(path: "./Foo", products: .specific(["Foo"])), ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -3651,7 +3651,7 @@ final class WorkspaceTests: XCTestCase { .fileSystem(path: "./Foo", products: .specific(["Foo"])), ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -3720,7 +3720,7 @@ final class WorkspaceTests: XCTestCase { .fileSystem(path: "./Foo", products: .specific(["Foo"])), ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -3799,7 +3799,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Foo", "Root") } @@ -4266,7 +4266,7 @@ final class WorkspaceTests: XCTestCase { do { try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -4296,7 +4296,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.closeWorkspace(resetResolvedFile: false) // run resolution again, now it should rely on the resolved file try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -4322,7 +4322,7 @@ final class WorkspaceTests: XCTestCase { // run resolution again, but change requirements try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -4347,7 +4347,7 @@ final class WorkspaceTests: XCTestCase { try fs.writeFileContents(rootManifestPath, string: manifestContent) // run resolution again, now it should rely on the resolved file try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -4372,7 +4372,7 @@ final class WorkspaceTests: XCTestCase { ] // run resolution again, but change requirements try await workspace.checkPackageGraph(roots: ["Root"], dependencies: changedDeps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Baz", "Foo", "Root") } @@ -4395,7 +4395,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.closeWorkspace(resetResolvedFile: false) // run resolution again, but change requirements back to original try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -4418,7 +4418,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.closeWorkspace(resetResolvedFile: false) // run resolution again, now it should rely on the resolved file try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -4439,7 +4439,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.closeWorkspace(resetResolvedFile: true) // run resolution again try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -4542,7 +4542,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "BarMirror", "BazMirror", "Foo", "Dep") result.check(modules: "Bar", "Baz", "Foo", "Dep") @@ -4646,7 +4646,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "BarMirror", "Foo", "Dep") result.check(modules: "Bar", "Foo", "Dep") @@ -4734,7 +4734,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "bar-mirror", "baz-mirror", "foo", "dep") result.check(modules: "Bar", "Baz", "Foo", "Dep") @@ -4840,7 +4840,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "bar-mirror", "foo", "dep") result.check(modules: "Bar", "Foo", "Dep") @@ -4911,7 +4911,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "org.bar-mirror", "baz", "foo") result.check(modules: "Bar", "Baz", "Foo") @@ -4981,7 +4981,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "bar-mirror", "org.baz", "foo") result.check(modules: "Bar", "Baz", "Foo") @@ -5098,7 +5098,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -5128,7 +5128,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "Bar", "Foo", "Root") } @@ -5701,7 +5701,7 @@ final class WorkspaceTests: XCTestCase { ) try await workspace.checkPackageGraph(roots: ["Foo"]) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Bar", "Baz", "Foo") result.checkTarget("Foo") { result in result.check(dependencies: "Bar", "Baz") } @@ -11840,7 +11840,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "bar", "baz", "foo", "Root", "qux") let package = result.find(package: "foo") XCTAssertEqual(package?.manifest.packageLocation, "https://github.com/org/foo.git") @@ -11982,7 +11982,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "bar", "baz", "foo", "Root") let package = result.find(package: "foo") XCTAssertEqual(package?.manifest.packageLocation, "git@github.com:org/foo.git") @@ -12125,7 +12125,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "bar", "foo", "Root") let package = result.find(package: "foo") XCTAssertEqual(package?.manifest.packageLocation, "git@github.com:org/foo.git") @@ -12147,7 +12147,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root2"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "bar", "baz", "foo", "Root2") let package = result.find(package: "foo") XCTAssertEqual(package?.manifest.packageLocation, "git@github.com:org/foo.git") @@ -12242,7 +12242,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "foo", "Root") let package = result.find(package: "foo") XCTAssertEqual(package?.manifest.packageLocation, "https://github.com/org/foo.git") @@ -12267,7 +12267,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root2"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "foo", "Root2") let package = result.find(package: "foo") XCTAssertEqual(package?.manifest.packageLocation, "git@github.com:org/foo.git") @@ -12396,7 +12396,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "bar", "foo", "Root") let package = result.find(package: "foo") XCTAssertEqual(package?.manifest.packageLocation, "https://github.com/org/foo.git") @@ -12427,7 +12427,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root2"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(packages: "bar", "foo", "Root2") let package = result.find(package: "foo") XCTAssertEqual(package?.manifest.packageLocation, "git@github.com:org/foo.git") @@ -12625,7 +12625,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["Root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "bar", "foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -12834,7 +12834,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["MyPackage"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "MyPackage") result.check(packages: "Bar", "Foo", "MyPackage") result.check(modules: "Foo", "Bar", "MyTarget1", "MyTarget2") @@ -12967,7 +12967,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["MyPackage"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "MyPackage") result.check(packages: "Bar", "Baz", "Foo", "MyPackage") result.check(modules: "Foo", "Bar", "Baz", "MyTarget1", "MyTarget2") @@ -13084,7 +13084,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["MyPackage"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "MyPackage") result.check(packages: "org.bar", "org.foo", "mypackage") result.check(modules: "Foo", "Bar", "MyTarget1", "MyTarget2") @@ -13217,7 +13217,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["MyPackage"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "MyPackage") result.check(packages: "org.bar", "org.baz", "org.foo", "mypackage") result.check(modules: "Foo", "Bar", "Baz", "MyTarget1", "MyTarget2") @@ -13333,7 +13333,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -13421,7 +13421,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -13444,7 +13444,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -13467,7 +13467,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -13529,7 +13529,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.foo", "Root") result.check(modules: "FooTarget", "RootTarget") @@ -13746,7 +13746,7 @@ final class WorkspaceTests: XCTestCase { ) } - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -13770,7 +13770,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -13793,7 +13793,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -13909,7 +13909,7 @@ final class WorkspaceTests: XCTestCase { severity: .warning ) } - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -13932,7 +13932,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -14181,7 +14181,7 @@ final class WorkspaceTests: XCTestCase { ) } } - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -14204,7 +14204,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -14469,7 +14469,7 @@ final class WorkspaceTests: XCTestCase { ) } } - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.baz", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "BazTarget", "RootTarget") @@ -14497,7 +14497,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["root"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.baz", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "BazTarget", "RootTarget") @@ -14757,7 +14757,7 @@ final class WorkspaceTests: XCTestCase { severity: .warning ) } - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -14787,7 +14787,7 @@ final class WorkspaceTests: XCTestCase { severity: .warning ) } - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Root") result.check(packages: "org.bar", "org.foo", "Root") result.check(modules: "FooTarget", "BarTarget", "RootTarget") @@ -14880,7 +14880,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(url: bazURL, requirement: .exact("1.0.0")), ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Baz", "Foo") result.check(modules: "Bar", "Baz", "Foo") @@ -15423,7 +15423,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["MyPackage"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in guard let foo = result.find(package: "org.foo") else { return XCTFail("missing package") } @@ -15495,7 +15495,7 @@ final class WorkspaceTests: XCTestCase { try await workspace.checkPackageGraph(roots: ["MyPackage"]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in XCTAssertNotNil(result.find(package: "org.foo"), "missing package") } } @@ -15709,7 +15709,7 @@ final class WorkspaceTests: XCTestCase { PackageIdentity.plain("org.bar"): XCTUnwrap(actualMetadata.signature?.signedBy), ]) { graph, diagnostics in XCTAssertNoDiagnostics(diagnostics) - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in XCTAssertNotNil(result.find(package: "ecorp.bar"), "missing package") XCTAssertNil(result.find(package: "org.bar"), "unexpectedly present package") } @@ -15875,7 +15875,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Baz", "Foo") result.check(modules: "Bar", "Baz", "Foo") @@ -15962,7 +15962,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Baz", "Foo", "Boo") result.check(modules: "Bar", "Baz", "Boo", "Foo") @@ -16041,7 +16041,7 @@ final class WorkspaceTests: XCTestCase { ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Baz", "Foo") result.check(modules: "Bar", "Baz", "Foo") @@ -16122,7 +16122,7 @@ final class WorkspaceTests: XCTestCase { .sourceControl(path: "./Boo", requirement: .exact("1.0.0"), products: .specific(["Boo"])), ] try await workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in - PackageGraphTester(graph) { result in + PackageGraphTesterXCTest(graph) { result in result.check(roots: "Foo") result.check(packages: "Baz", "Boo", "Foo") result.check(modules: "Bar", "Baz", "Boo", "Foo") From f0d1b7f9efca056391a8fa0eda95d80366e33c58 Mon Sep 17 00:00:00 2001 From: Sam Khouri Date: Wed, 30 Jul 2025 12:56:19 -0400 Subject: [PATCH 2/2] Update based on PR feedback --- Sources/Build/BuildOperation.swift | 2 -- Sources/SPMBuildCore/BuildSystem/BuildSystem.swift | 3 --- Sources/SwiftBuildSupport/SwiftBuildSystem.swift | 2 -- Sources/XCBuildSupport/XcodeBuildSystem.swift | 1 - 4 files changed, 8 deletions(-) diff --git a/Sources/Build/BuildOperation.swift b/Sources/Build/BuildOperation.swift index 90d456fd234..f162c921030 100644 --- a/Sources/Build/BuildOperation.swift +++ b/Sources/Build/BuildOperation.swift @@ -399,7 +399,6 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS public func build(subset: BuildSubset, buildOutputs: [BuildOutput]) async throws -> BuildResult { var result = BuildResult( serializedDiagnosticPathsByTargetName: .failure(StringError("Building was skipped")), - packageGraph: try await self.getPackageGraph(), replArguments: nil, ) @@ -464,7 +463,6 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS result = BuildResult( serializedDiagnosticPathsByTargetName: result.serializedDiagnosticPathsByTargetName, - packageGraph: result.packageGraph, symbolGraph: result.symbolGraph, buildPlan: buildResultBuildPlan, replArguments: buildResultReplArgs, diff --git a/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift b/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift index 0648f288648..490950234b1 100644 --- a/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift +++ b/Sources/SPMBuildCore/BuildSystem/BuildSystem.swift @@ -97,20 +97,17 @@ public typealias CLIArguments = [String] public struct BuildResult { package init( serializedDiagnosticPathsByTargetName: Result<[String: [AbsolutePath]], Error>, - packageGraph: ModulesGraph, symbolGraph: SymbolGraphResult? = nil, buildPlan: BuildPlan? = nil, replArguments: CLIArguments? ) { self.serializedDiagnosticPathsByTargetName = serializedDiagnosticPathsByTargetName - self.packageGraph = packageGraph self.symbolGraph = symbolGraph self.buildPlan = buildPlan self.replArguments = replArguments } public let replArguments: CLIArguments? - public let packageGraph: ModulesGraph public let symbolGraph: SymbolGraphResult? public let buildPlan: BuildPlan? diff --git a/Sources/SwiftBuildSupport/SwiftBuildSystem.swift b/Sources/SwiftBuildSupport/SwiftBuildSystem.swift index 63cdd60ccf5..6adea73edfa 100644 --- a/Sources/SwiftBuildSupport/SwiftBuildSystem.swift +++ b/Sources/SwiftBuildSupport/SwiftBuildSystem.swift @@ -345,7 +345,6 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { guard !buildParameters.shouldSkipBuilding else { return BuildResult( serializedDiagnosticPathsByTargetName: .failure(StringError("Building was skipped")), - packageGraph: try await self.getPackageGraph(), replArguments: nil, ) } @@ -588,7 +587,6 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem { return BuildResult( serializedDiagnosticPathsByTargetName: .success(serializedDiagnosticPathsByTargetName), - packageGraph: try await self.getPackageGraph(), symbolGraph: SymbolGraphResult( outputLocationForTarget: { target, buildParameters in return ["\(buildParameters.triple.archName)", "\(target).symbolgraphs"] diff --git a/Sources/XCBuildSupport/XcodeBuildSystem.swift b/Sources/XCBuildSupport/XcodeBuildSystem.swift index 9c88c62d662..11f12615e66 100644 --- a/Sources/XCBuildSupport/XcodeBuildSystem.swift +++ b/Sources/XCBuildSupport/XcodeBuildSystem.swift @@ -163,7 +163,6 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem { public func build(subset: BuildSubset, buildOutputs: [BuildOutput]) async throws -> BuildResult { let buildResult = BuildResult( serializedDiagnosticPathsByTargetName: .failure(StringError("XCBuild does not support reporting serialized diagnostics.")), - packageGraph: try await self.getPackageGraph(), replArguments: nil, )