fix(tests): prevent realtime overflow flakes on busy runners (#163731)

The fake realtime audio device resumed preparation after a two-second semaphore timeout, allowing frames before overflow had fenced playback on busy CI runners. Hold preparation and frame gates until the test explicitly releases them, including failure cleanup. Production behavior, signal deadlines, exactly-one-stop and zero-frame assertions remain unchanged.

Validated a delayed baseline failure and repaired pass, a failing negative control removing production overflow stop, 30 repetitions of all nine production-fixture tests, and the full 73-test RealtimeTalk/PCM suite. Independent Codex autoreview found no actionable P0-P2 findings.
This commit is contained in:
Peter Steinberger 2026-10-02 12:21:39 -07:00 • committed by GitHub
parent c1b973aec1
commit 9d2360bd90
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -13,6 +13,8 @@ final class RealtimeRelayDevice: @unchecked Sendable {
let scheduled = RealtimeRelayTestSignal<Int>(timeoutSeconds: 5)
let prepared = RealtimeRelayTestSignal<Void>(timeoutSeconds: 5)
let stopped = RealtimeRelayTestSignal<Int>(timeoutSeconds: 5)
// Tests own gate release, with deferred cleanup on failure.
// A timeout would let the device resume before the stop under test.
let prepareGate: DispatchSemaphore?
let frameGate: DispatchSemaphore?
@ -31,7 +33,7 @@ final class RealtimeRelayDevice: @unchecked Sendable {
func prepare(_: Double) {
self.prepared.send(())
if let prepareGate { _ = prepareGate.wait(timeout: .now() + 2) }
self.prepareGate?.wait()
}
func schedule(_ data: Data, _: Double, completion: @escaping @Sendable () -> Void) {
@ -41,7 +43,7 @@ final class RealtimeRelayDevice: @unchecked Sendable {
return self.storedFrames.count
}
self.scheduled.send(count)
if let frameGate { _ = frameGate.wait(timeout: .now() + 2) }
self.frameGate?.wait()
}
func stop() {