Skip to content

Commit 4e772a8

Browse files
committed
Attach the build transcript and path to the build description to the test at the end of BuildOperationTester.checkBuild().
We can do this now that Swift Testing support attachments. Also give callers of checkBuild() the opportunity to opt out of adding these attachments, and have BuildTaskBehaviorTests.stressConcurrentCancellation() do so, as its particular nature can sometimes crash the tests when adding attachments.
1 parent a94b27b commit 4e772a8

File tree

2 files changed

+16
-15
lines changed

2 files changed

+16
-15
lines changed

Sources/SWBTestSupport/BuildOperationTester.swift

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,12 +1414,16 @@ package final class BuildOperationTester {
14141414
}
14151415

14161416
/// Construct the tasks for the given build parameters, and test the result.
1417-
@discardableResult package func checkBuild<T>(_ name: String? = nil, parameters: BuildParameters? = nil, runDestination: SWBProtocol.RunDestinationInfo?, buildRequest inputBuildRequest: BuildRequest? = nil, buildCommand: BuildCommand? = nil, schemeCommand: SchemeCommand? = .launch, persistent: Bool = false, serial: Bool = false, buildOutputMap: [String:String]? = nil, signableTargets: Set<String> = [], signableTargetInputs: [String: ProvisioningTaskInputs] = [:], clientDelegate: (any ClientDelegate)? = nil, sourceLocation: SourceLocation = #_sourceLocation, body: (BuildResults) async throws -> T) async throws -> T {
1418-
try await checkBuild(name, parameters: parameters, runDestination: runDestination, buildRequest: inputBuildRequest, buildCommand: buildCommand, schemeCommand: schemeCommand, persistent: persistent, serial: serial, buildOutputMap: buildOutputMap, signableTargets: signableTargets, signableTargetInputs: signableTargetInputs, clientDelegate: clientDelegate, sourceLocation: sourceLocation, body: body, performBuild: { try await $0.buildWithTimeout() })
1417+
///
1418+
/// This variant of `checkBuild()` differs from the main versiion in these ways:
1419+
/// - Does not have a `operationBuildRequest` parameter.
1420+
/// - Has a default value of the `performBuild` parameter which performs a nortmal build.
1421+
@discardableResult package func checkBuild<T>(_ name: String? = nil, parameters: BuildParameters? = nil, runDestination: SWBProtocol.RunDestinationInfo?, buildRequest inputBuildRequest: BuildRequest? = nil, buildCommand: BuildCommand? = nil, schemeCommand: SchemeCommand? = .launch, persistent: Bool = false, serial: Bool = false, buildOutputMap: [String:String]? = nil, signableTargets: Set<String> = [], signableTargetInputs: [String: ProvisioningTaskInputs] = [:], attachBuildArifacts: Bool = true, clientDelegate: (any ClientDelegate)? = nil, sourceLocation: SourceLocation = #_sourceLocation, body: (BuildResults) async throws -> T) async throws -> T {
1422+
try await checkBuild(name, parameters: parameters, runDestination: runDestination, buildRequest: inputBuildRequest, buildCommand: buildCommand, schemeCommand: schemeCommand, persistent: persistent, serial: serial, buildOutputMap: buildOutputMap, signableTargets: signableTargets, signableTargetInputs: signableTargetInputs, attachBuildArifacts: attachBuildArifacts, clientDelegate: clientDelegate, sourceLocation: sourceLocation, body: body, performBuild: { try await $0.buildWithTimeout() })
14191423
}
14201424

14211425
/// Construct the tasks for the given build parameters, and test the result.
1422-
@discardableResult package func checkBuild<T>(_ name: String? = nil, parameters: BuildParameters? = nil, runDestination: RunDestinationInfo?, buildRequest inputBuildRequest: BuildRequest? = nil, operationBuildRequest: BuildRequest? = nil, buildCommand: BuildCommand? = nil, schemeCommand: SchemeCommand? = .launch, persistent: Bool = false, serial: Bool = false, buildOutputMap: [String:String]? = nil, signableTargets: Set<String> = [], signableTargetInputs: [String: ProvisioningTaskInputs] = [:], clientDelegate: (any ClientDelegate)? = nil, sourceLocation: SourceLocation = #_sourceLocation, body: (BuildResults) async throws -> T, performBuild: @escaping (any BuildSystemOperation) async throws -> Void) async throws -> T {
1426+
@discardableResult package func checkBuild<T>(_ name: String? = nil, parameters: BuildParameters? = nil, runDestination: SWBProtocol.RunDestinationInfo?, buildRequest inputBuildRequest: BuildRequest? = nil, operationBuildRequest: BuildRequest? = nil, buildCommand: BuildCommand? = nil, schemeCommand: SchemeCommand? = .launch, persistent: Bool = false, serial: Bool = false, buildOutputMap: [String:String]? = nil, signableTargets: Set<String> = [], signableTargetInputs: [String: ProvisioningTaskInputs] = [:], attachBuildArifacts: Bool = true, clientDelegate: (any ClientDelegate)? = nil, sourceLocation: SourceLocation = #_sourceLocation, body: (BuildResults) async throws -> T, performBuild: @escaping (any BuildSystemOperation) async throws -> Void) async throws -> T {
14231427
try await checkBuildDescription(parameters, runDestination: runDestination, buildRequest: inputBuildRequest, buildCommand: buildCommand, schemeCommand: schemeCommand, persistent: persistent, serial: serial, signableTargets: signableTargets, signableTargetInputs: signableTargetInputs, clientDelegate: clientDelegate) { results throws in
14241428
// Check that there are no duplicate task identifiers - it is a fatal error if there are, unless `continueBuildingAfterErrors` is set.
14251429
var tasksByTaskIdentifier: [TaskIdentifier: Task] = [:]
@@ -1476,19 +1480,14 @@ package final class BuildOperationTester {
14761480
// Check the results.
14771481
let results = try BuildResults(core: core, workspace: workspace, buildDescriptionResults: results, tasksByTaskIdentifier: delegate.tasksByTaskIdentifier.merging(delegate.dynamicTasksByTaskIdentifier, uniquingKeysWith: { a, b in a }), fs: fs, events: events, dynamicTaskDependencies: dynamicDependencies, buildDatabasePath: persistent ? results.buildDescription.buildDatabasePath : nil)
14781482

1479-
/*@MainActor func addAttachments() {
1480-
// TODO: This `runActivity` call should be wider in scope, but this would significantly complicate the code flow due to threading requirements without having async/await.
1481-
XCTContext.runActivity(named: "Execute Build Operation" + (name.map({ " \"\($0)\"" }) ?? "")) { activity in
1482-
// TODO: <rdar://59432231> Longer term, we should find a way to share code with CoreQualificationTester, which has a number of APIs for emitting build operation debug info.
1483-
activity.attach(name: "Build Transcript", string: results.buildTranscript)
1484-
if localFS.exists(results.buildDescription.packagePath) {
1485-
activity.attach(name: "Build Description", from: results.buildDescription.packagePath)
1486-
}
1483+
// TODO: <rdar://59432231> Longer term, we should find a way to share code with CoreQualificationTester, which has a number of APIs for emitting build operation debug info.
1484+
if attachBuildArifacts {
1485+
Attachment.record(results.buildTranscript, named: "Build Transcript" + (name.map({ " for Build Operation \"\($0)\"" }) ?? ""))
1486+
if localFS.exists(results.buildDescription.packagePath) {
1487+
Attachment.record(results.buildDescription.packagePath.str, named: "Build Description" + (name.map({ " for Build Operation \"\($0)\"" }) ?? ""))
14871488
}
14881489
}
14891490

1490-
await addAttachments()*/
1491-
14921491
defer {
14931492
let validationResults = results.validate(sourceLocation: sourceLocation)
14941493

Tests/SWBBuildSystemTests/BuildTaskBehaviorTests.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,16 @@ fileprivate struct BuildTaskBehaviorTests: CoreBasedTests {
229229
let startBuilds = WaitCondition()
230230
let buildsDone = WaitCondition()
231231

232+
// The threads this test spawns to run the build can outlive the lifetime of the test itself, so it passed attachBuildArifacts = false since if that happens then the test might crash because the reporter needed to add the attachments will no longer exist.
233+
232234
// build1 cancels immediately
233235
_Concurrency.Task<Void, Never> {
234236
do {
235237
let (tester, _, _) = try await self.createBuildOperationTesterForCancellation(temporaryDirectory: temporaryDirectory, contents: "")
236238

237239
tester.userPreferences = prefs
238240

239-
try await tester.checkBuild(runDestination: .host, body: { results in
241+
try await tester.checkBuild(runDestination: .host, attachBuildArifacts: false, body: { results in
240242
results.checkCapstoneEvents(last: .buildCancelled)
241243
}) { operation in
242244
build1Ready.signal()
@@ -264,7 +266,7 @@ fileprivate struct BuildTaskBehaviorTests: CoreBasedTests {
264266

265267
tester.userPreferences = prefs
266268

267-
try await tester.checkBuild(runDestination: .host, body: { results in
269+
try await tester.checkBuild(runDestination: .host, attachBuildArifacts: false, body: { results in
268270
#expect(results.events.first! == .buildStarted)
269271

270272
let waitTask = try #require(results.getTask(.matchRule(["wait"])))

0 commit comments

Comments
 (0)