Files

71 lines
2.0 KiB
Swift

import Testing
import XCTest
@MainActor
struct BoundedTestWaitTests {
@Test func missingPhaseStopsTheBodyAndDrainsItsTask() async throws {
let entered = XCTestExpectation(description: "worker entered")
let gate = RuleRuntimeDelayGate(started: entered)
var exited = false
var continued = false
let task = Task {
try? await gate.wait()
exited = true
}
try await requireTestPhase([entered])
await #expect(throws: TestWaitError.self) {
try await withTestTask(
task, release: { gate.resume() },
body: {
try await requireTestPhase(
[XCTestExpectation(description: "phase never reached")], timeout: 0.02)
continued = true
})
}
#expect(!continued)
#expect(exited)
}
@Test func missingConditionHasADeadline() async {
await #expect(throws: TestWaitError.self) {
try await requireTestCondition("never true", timeout: .milliseconds(20)) { false }
}
}
@Test func cancelledConditionWaitStops() async {
let task = Task {
withUnsafeCurrentTask { $0?.cancel() }
try await requireTestCondition("never true") { false }
}
await #expect(throws: CancellationError.self) { try await task.value }
}
@Test func asyncGateTimesOutWithoutBlockingAWorker() async {
let gate = TestAsyncGate(onTimeout: {})
#expect(await gate.wait(timeout: .milliseconds(20)) == false)
}
@Test func asyncGateRemembersEarlyAndRepeatedRelease() async {
let gate = TestAsyncGate()
gate.release()
gate.release()
#expect(await gate.wait(timeout: .zero))
}
@Test func asyncGateReleasesEveryWorker() async throws {
let gate = TestAsyncGate()
let entered = XCTestExpectation(description: "workers entered")
entered.expectedFulfillmentCount = 4
let workers = (0..<4).map { _ in
Task.detached {
entered.fulfill()
return await gate.wait()
}
}
try await requireTestPhase([entered])
gate.release()
gate.release()
for worker in workers { #expect(await worker.value) }
}
}