Skip to content

Tests: make the warm-recorder tests headless-runner-safe - #142

Closed
claude[bot] wants to merge 1 commit into
claude/airpods-lag-diagnosis-63h108from
test/warm-tests-runner-fix
Closed

Tests: make the warm-recorder tests headless-runner-safe#142
claude[bot] wants to merge 1 commit into
claude/airpods-lag-diagnosis-63h108from
test/warm-tests-runner-fix

Conversation

@claude

@claude claude Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Requested by Dylan Fox · Slack thread

Fixes the red CI that #141's tests caused on #133.

What broke on the runner: the three tests in MicCaptureWarmTests.swift that call production warmUp() / scheduleRewarm() reach prepareWarmRecorder()'s AudioRoute.currentInput() — a CoreAudio HAL query — on a headless macos-26 runner with no input device. Result in run 31747352994: 3 expectation failures (lines 27, 29, 53), plus at least one CoreAudio call that blocked, pinning the cooperative pool and starving the whole parallel swift-testing process — 72 unrelated in-flight tests never finished and the job hit its 30-minute timeout (the suite's .timeLimit can't fire once the pool is pinned). The re-warm test's unbounded while … { await Task.yield() } wait guaranteed nothing shorter than the job timeout could end it.

What this changes (tests only, no production code):

  • The warmUp / bring-up-window guard assertions now drive through the proven installWarmRecorder(boundTo:) seam and direct state setters; production warmUp() and scheduleRewarm() appear only on their refusal paths, which return before the device read.
  • The re-warm test is reworked to pin the overtaken-re-warm no-op; its one remaining wait is deadline-bounded (500 ms) and cancellation-aware, so a regression fails fast instead of wedging.
  • A new test covers armPreparedRecorderExpiry directly, recouping countdown-arming coverage the prepare path used to reach.
  • The header comment no longer claims the prepare path is "reachable in CI" — prepareWarmRecorder()'s success path is exercised only on hardware.
  • The three seam-driven tests that already passed on the runner are unchanged.

Coverage impact gets measured by this PR's own check run (last full measure without any warm tests: 87.37% against the 88% gate).


Generated by Claude Code

The three tests driving production warmUp() / scheduleRewarm() reached
prepareWarmRecorder()'s AudioRoute.currentInput() — a CoreAudio HAL query —
on a runner with no input device: 3 expectation failures, plus at least one
blocked CoreAudio call that pinned the cooperative pool and wedged the whole
parallel test process into the job's 30-minute timeout (the suite's
.timeLimit can't fire once the pool is pinned). The re-warm test's unbounded
'while ... { await Task.yield() }' wait made sure nothing shorter than the
job timeout could end it.

Rework those three to drive the same guard logic through the proven
installWarmRecorder(boundTo:) seam and direct state setters: warmUp() and
scheduleRewarm() now appear only on their refusal paths, which return before
the device read. The one remaining wait is deadline-bounded (500 ms) and
cancellation-aware. Add a direct armPreparedRecorderExpiry test to keep line
coverage of the countdown arming that the prepare path used to reach. The
three seam-driven tests that already passed on the runner are unchanged.
Tests only; no production changes. prepareWarmRecorder()'s success path is
now exercised only on hardware, and the header comment says so instead of
claiming CI reachability.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CNFeP9D8k1HJ1piwyidUv3
@claude

claude Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Alex fixed these himself in d378778 — closing.


Generated by Claude Code

@claude claude Bot closed this Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant