Skip to content

Commit

Permalink
Fix async XCTest execution on Darwin when the runner's main is `a…
Browse files Browse the repository at this point in the history
…sync`.

There is what appears to be a strange bug on Darwin platforms here. If the calling context (e.g., `main`) is `async` and there are any `async` tests in the suite to be run, calling `XCTestSuite.run()` will cause the test process to terminate abnormally with the error "freed pointer was not the last allocation" out of the Swift runtime. We "avoid" (work around) this by wrapping the call in a detached task and then awaiting its result. The task must be detached so that we don't block the main actor, which the tests may also be depending on.

PiperOrigin-RevId: 662944537
  • Loading branch information
allevato authored and swiple-rules-gardener committed Aug 14, 2024
1 parent 722ec91 commit d7f555d
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 6 deletions.
18 changes: 14 additions & 4 deletions tools/test_discoverer/ObjcTestPrinter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,22 @@ struct ObjcTestPrinter {
let description: String
}
static func run() throws {
static func run() async throws {
try loadXCTest()
XCTestObservationCenter.shared.addTestObserver(BazelXMLTestObserver.default)
var testCollector = try ShardingFilteringTestCollector()
let shardedSuite = testCollector.shard(XCTestSuite.default)
shardedSuite.run()
// There is what appears to be a strange bug on Darwin platforms here. If the calling
// context (e.g., `main`) is `async` and there are any `async` tests in the suite to be
// run, calling `shardedSuite.run()` below will cause the test process to terminate
// abnormally with the error "freed pointer was not the last allocation" out of the Swift
// runtime. We "avoid" (work around) this by wrapping the call in a detached task and then
// awaiting its result. The task must be detached so that we don't block the main actor,
// which the tests may also be depending on.
_ = try await Task.detached {
var testCollector = try ShardingFilteringTestCollector()
let shardedSuite = testCollector.shard(XCTestSuite.default)
shardedSuite.run()
}.value
}
private static func loadXCTest() throws {
Expand Down
4 changes: 2 additions & 2 deletions tools/test_discoverer/TestDiscoverer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ struct TestDiscoverer: ParsableCommand {
\(availabilityAttribute)
@main
struct Main {
static func main() {
static func main() async {
do {
try XCTestRunner.run()
try await XCTestRunner.run()
try XUnitTestRecorder.shared.writeXML()
guard !XUnitTestRecorder.shared.hasFailure else {
Expand Down

1 comment on commit d7f555d

@brentleyjones
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.