Skip to content

Commit 8676d94

Browse files
committed
[Tests] NFC: Add a way to mock BuildPlan construction
Instead of using unified `buildParameters:` let's switch over to a more fine-grained control over build plan construction and allow setting common driver, linker and other flags but handle destinations internally.
1 parent 07898ee commit 8676d94

11 files changed

+572
-422
lines changed

Sources/Build/BuildPlan/BuildPlan.swift

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -237,28 +237,6 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
237237
/// ObservabilityScope with which to emit diagnostics
238238
let observabilityScope: ObservabilityScope
239239

240-
@available(*, deprecated, renamed: "init(destinationBuildParameters:toolsBuildParameters:graph:)")
241-
public convenience init(
242-
buildParameters: BuildParameters,
243-
graph: ModulesGraph,
244-
additionalFileRules: [FileRuleDescription] = [],
245-
buildToolPluginInvocationResults: [ResolvedModule.ID: [BuildToolPluginInvocationResult]] = [:],
246-
prebuildCommandResults: [ResolvedModule.ID: [PrebuildCommandResult]] = [:],
247-
fileSystem: any FileSystem,
248-
observabilityScope: ObservabilityScope
249-
) throws {
250-
try self.init(
251-
destinationBuildParameters: buildParameters,
252-
toolsBuildParameters: buildParameters,
253-
graph: graph,
254-
additionalFileRules: additionalFileRules,
255-
buildToolPluginInvocationResults: buildToolPluginInvocationResults,
256-
prebuildCommandResults: prebuildCommandResults,
257-
fileSystem: fileSystem,
258-
observabilityScope: observabilityScope
259-
)
260-
}
261-
262240
@available(*, deprecated, renamed: "init(destinationBuildParameters:toolsBuildParameters:graph:fileSystem:observabilityScope:)")
263241
public convenience init(
264242
productsBuildParameters: BuildParameters,

Sources/SPMTestSupport/MockBuildTestHelper.swift

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Basics
1515
@_spi(SwiftPMInternal)
1616
import Build
1717

18+
import struct PackageGraph.ModulesGraph
1819
import struct PackageGraph.ResolvedModule
1920
import struct PackageGraph.ResolvedProduct
2021
import PackageModel
@@ -75,6 +76,7 @@ public let defaultTargetTriple: String = hostTriple.tripleString
7576
#endif
7677

7778
public func mockBuildParameters(
79+
destination: BuildParameters.Destination,
7880
buildPath: AbsolutePath? = nil,
7981
config: BuildConfiguration = .debug,
8082
toolchain: PackageModel.Toolchain = MockToolchain(),
@@ -90,6 +92,7 @@ public func mockBuildParameters(
9092
omitFramePointers: Bool? = nil
9193
) -> BuildParameters {
9294
try! BuildParameters(
95+
destination: destination,
9396
dataPath: buildPath ?? AbsolutePath("/path/to/build").appending(triple.tripleString),
9497
configuration: config,
9598
toolchain: toolchain,
@@ -116,7 +119,10 @@ public func mockBuildParameters(
116119
)
117120
}
118121

119-
public func mockBuildParameters(environment: BuildEnvironment) -> BuildParameters {
122+
public func mockBuildParameters(
123+
destination: BuildParameters.Destination,
124+
environment: BuildEnvironment
125+
) -> BuildParameters {
120126
let triple: Basics.Triple
121127
switch environment.platform {
122128
case .macOS:
@@ -131,9 +137,121 @@ public func mockBuildParameters(environment: BuildEnvironment) -> BuildParameter
131137
fatalError("unsupported platform in tests")
132138
}
133139

134-
return mockBuildParameters(config: environment.configuration ?? .debug, triple: triple)
140+
return mockBuildParameters(
141+
destination: destination,
142+
config: environment.configuration ?? .debug,
143+
triple: triple
144+
)
135145
}
136146

147+
public func mockBuildPlan(
148+
buildPath: AbsolutePath? = nil,
149+
environment: BuildEnvironment,
150+
toolchain: PackageModel.Toolchain = MockToolchain(),
151+
graph: ModulesGraph,
152+
commonFlags: PackageModel.BuildFlags = .init(),
153+
indexStoreMode: BuildParameters.IndexStoreMode = .off,
154+
omitFramePointers: Bool? = nil,
155+
driverParameters: BuildParameters.Driver = .init(),
156+
linkingParameters: BuildParameters.Linking = .init(),
157+
targetSanitizers: EnabledSanitizers = .init(),
158+
fileSystem fs: any FileSystem,
159+
observabilityScope: ObservabilityScope
160+
) throws -> Build.BuildPlan {
161+
try mockBuildPlan(
162+
buildPath: buildPath,
163+
config: environment.configuration ?? .debug,
164+
platform: environment.platform,
165+
toolchain: toolchain,
166+
graph: graph,
167+
commonFlags: commonFlags,
168+
indexStoreMode: indexStoreMode,
169+
omitFramePointers: omitFramePointers,
170+
driverParameters: driverParameters,
171+
linkingParameters: linkingParameters,
172+
targetSanitizers: targetSanitizers,
173+
fileSystem: fs,
174+
observabilityScope: observabilityScope
175+
)
176+
}
177+
178+
public func mockBuildPlan(
179+
buildPath: AbsolutePath? = nil,
180+
config: BuildConfiguration = .debug,
181+
triple: Basics.Triple? = nil,
182+
platform: PackageModel.Platform? = nil,
183+
toolchain: PackageModel.Toolchain = MockToolchain(),
184+
graph: ModulesGraph,
185+
commonFlags: PackageModel.BuildFlags = .init(),
186+
indexStoreMode: BuildParameters.IndexStoreMode = .off,
187+
omitFramePointers: Bool? = nil,
188+
driverParameters: BuildParameters.Driver = .init(),
189+
linkingParameters: BuildParameters.Linking = .init(),
190+
targetSanitizers: EnabledSanitizers = .init(),
191+
fileSystem fs: any FileSystem,
192+
observabilityScope: ObservabilityScope
193+
) throws -> Build.BuildPlan {
194+
let inferredTriple: Basics.Triple
195+
if let platform {
196+
precondition(triple == nil)
197+
198+
inferredTriple = switch platform {
199+
case .macOS:
200+
Triple.x86_64MacOS
201+
case .linux:
202+
Triple.arm64Linux
203+
case .android:
204+
Triple.arm64Android
205+
case .windows:
206+
Triple.windows
207+
default:
208+
fatalError("unsupported platform in tests")
209+
}
210+
} else {
211+
inferredTriple = triple ?? hostTriple
212+
}
213+
214+
let commonDebuggingParameters = BuildParameters.Debugging(
215+
triple: inferredTriple,
216+
shouldEnableDebuggingEntitlement: config == .debug,
217+
omitFramePointers: omitFramePointers
218+
)
219+
220+
var destinationParameters = mockBuildParameters(
221+
destination: .target,
222+
buildPath: buildPath,
223+
config: config,
224+
toolchain: toolchain,
225+
flags: commonFlags,
226+
triple: inferredTriple,
227+
indexStoreMode: indexStoreMode
228+
)
229+
destinationParameters.debuggingParameters = commonDebuggingParameters
230+
destinationParameters.driverParameters = driverParameters
231+
destinationParameters.linkingParameters = linkingParameters
232+
destinationParameters.sanitizers = targetSanitizers
233+
234+
var hostParameters = mockBuildParameters(
235+
destination: .host,
236+
buildPath: buildPath,
237+
config: config,
238+
toolchain: toolchain,
239+
flags: commonFlags,
240+
triple: inferredTriple,
241+
indexStoreMode: indexStoreMode
242+
)
243+
hostParameters.debuggingParameters = commonDebuggingParameters
244+
hostParameters.driverParameters = driverParameters
245+
hostParameters.linkingParameters = linkingParameters
246+
247+
return try BuildPlan(
248+
destinationBuildParameters: destinationParameters,
249+
toolsBuildParameters: hostParameters,
250+
graph: graph,
251+
fileSystem: fs,
252+
observabilityScope: observabilityScope
253+
)
254+
}
137255
enum BuildError: Swift.Error {
138256
case error(String)
139257
}

Tests/BuildTests/BuildOperationTests.swift

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,21 @@ final class BuildOperationTests: XCTestCase {
5454
func testDetectUnexpressedDependencies() throws {
5555
let scratchDirectory = AbsolutePath("/path/to/build")
5656
let triple = hostTriple
57-
let buildParameters = mockBuildParameters(
57+
let targetBuildParameters = mockBuildParameters(
58+
destination: .target,
5859
buildPath: scratchDirectory.appending(triple.tripleString),
5960
shouldDisableLocalRpath: false,
6061
triple: triple
6162
)
6263

6364
let fs = InMemoryFileSystem(files: [
64-
"\(buildParameters.dataPath)/debug/Lunch.build/Lunch.d" : "/Best.framework"
65+
"\(targetBuildParameters.dataPath)/debug/Lunch.build/Lunch.d" : "/Best.framework"
6566
])
6667

6768
let observability = ObservabilitySystem.makeForTesting()
6869
let buildOp = mockBuildOperation(
69-
productsBuildParameters: buildParameters,
70-
toolsBuildParameters: buildParameters,
70+
productsBuildParameters: targetBuildParameters,
71+
toolsBuildParameters: mockBuildParameters(destination: .host, shouldDisableLocalRpath: false),
7172
scratchDirectory: scratchDirectory,
7273
fs: fs, observabilityScope: observability.topScope
7374
)
@@ -120,14 +121,15 @@ final class BuildOperationTests: XCTestCase {
120121

121122
// Perform initial builds for each triple
122123
for triple in triples {
123-
let buildParameters = mockBuildParameters(
124+
let targetBuildParameters = mockBuildParameters(
125+
destination: .target,
124126
buildPath: scratchDirectory.appending(triple.tripleString),
125127
config: .debug,
126128
triple: triple
127129
)
128130
let buildOp = mockBuildOperation(
129-
productsBuildParameters: buildParameters,
130-
toolsBuildParameters: buildParameters,
131+
productsBuildParameters: targetBuildParameters,
132+
toolsBuildParameters: mockBuildParameters(destination: .host),
131133
cacheBuildManifest: false,
132134
packageGraphLoader: { packageGraph },
133135
scratchDirectory: scratchDirectory,
@@ -136,7 +138,7 @@ final class BuildOperationTests: XCTestCase {
136138
// Generate initial llbuild manifest
137139
let _ = try buildOp.getBuildDescription()
138140
// Record the initial llbuild manifest as expected one
139-
llbuildManifestByTriple[triple.tripleString] = try fs.readFileContents(buildParameters.llbuildManifest)
141+
llbuildManifestByTriple[triple.tripleString] = try fs.readFileContents(targetBuildParameters.llbuildManifest)
140142
}
141143

142144
XCTAssertTrue(fs.exists(scratchDirectory.appending("debug.yaml")))
@@ -152,14 +154,15 @@ final class BuildOperationTests: XCTestCase {
152154
// Perform incremental build several times and switch triple for each time
153155
for _ in 0..<4 {
154156
for triple in triples {
155-
let buildParameters = mockBuildParameters(
157+
let targetBuildParameters = mockBuildParameters(
158+
destination: .target,
156159
buildPath: scratchDirectory.appending(triple.tripleString),
157160
config: .debug,
158161
triple: triple
159162
)
160163
let buildOp = mockBuildOperation(
161-
productsBuildParameters: buildParameters,
162-
toolsBuildParameters: buildParameters,
164+
productsBuildParameters: targetBuildParameters,
165+
toolsBuildParameters: mockBuildParameters(destination: .host),
163166
cacheBuildManifest: true,
164167
packageGraphLoader: { packageGraph },
165168
scratchDirectory: scratchDirectory,
@@ -169,7 +172,7 @@ final class BuildOperationTests: XCTestCase {
169172
let _ = try buildOp.getBuildDescription()
170173

171174
// Ensure that llbuild manifest is updated to the expected one
172-
let actualManifest: String = try fs.readFileContents(buildParameters.llbuildManifest)
175+
let actualManifest: String = try fs.readFileContents(targetBuildParameters.llbuildManifest)
173176
let expectedManifest = try XCTUnwrap(llbuildManifestByTriple[triple.tripleString])
174177
XCTAssertEqual(actualManifest, expectedManifest)
175178
}

0 commit comments

Comments
 (0)