swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.37k stars 10.34k forks source link

Async code resumption bug in tests on Windows #75942

Open MarSe32m opened 1 month ago

MarSe32m commented 1 month ago

Description

When testing async code, i.e. tests that are async, the output is deferred to the exit of the test. See below,

Reproduction

import XCTest

final class swift_test_bugTests: XCTestCase {
    func testAsyncCode() async {
        print("Before yield")
        await Task.yield()
        print("After first yield")

        await withUnsafeContinuation { $0.resume() }
        print("After continuation resumption")

        var start = ContinuousClock.now
        while .now - start < .seconds(1) { }
        print("After first spin")

        await Task.yield()
        print("After second yield")

        start = .now
        while .now - start < .seconds(5) { }
        print("After second spin")
    }
}

Expected behavior

It is expected to print the following:

Before yield
After first yield
After continuation resumption
// After 1 second
After first spin
After second yield
// After 5 seconds
After second spin

Instead nothing is printed for around 6 seconds, after which everything is printed on one go

Before yield
After first yield
After continuation resumption
After first spin
After second yield
After second spin

Environment

Swift version 5.10.1 (swift-5.10.1-RELEASE) Target: x86_64-unknown-windows-msvc

Additional information

If you instead run the program as an executable, i.e.

@main
struct Runner {
    public static func main() async {
        print("Before yield")
        await Task.yield()
        print("After first yield")

        await withUnsafeContinuation { $0.resume() }
        print("After continuation resumption")

        var start = ContinuousClock.now
        while .now - start < .seconds(1) { }
        print("After first spin")

        await Task.yield()
        print("After second yield")

        start = .now
        while .now - start < .seconds(5) { }
        print("After second spin")
    }
}

The expected result appears as described above.

HeMet commented 1 month ago

Maybe it has something to do with https://github.com/swiftlang/swift/issues/72095?