test: remove three fixture races from intermittently failing app-host tests
Three app-host tests that failed intermittently in main's full suite (#15488) raced their own fixtures, not the product. Each now waits for the condition it depends on instead of a fixed delay or ordering the scheduler doesn't guarantee. Each assertion checks the same thing as before.
SSHStartupManualReconnectTests/directSignalInterruptsPersistentAttachAuthenticationBackoff()(run 36645415013, Cocoa error 260).- The fake
sleepwrote itsreadymarker before its PID file. The test waits forready, then reads the PID file. - A fixture descheduled between the two writes left no PID file.
- The fixture now writes the PID first. The file stays at 913 lines.
- The fake
BrowserOmnibarPerformanceSupportTests/testSuggestionRefreshSchedulerInvalidatesQueuedRefreshOnCancel(run 36623504600, 1 s timeout withnil).- After the debounce clock advances, the refresh task has to hop from the clock actor back to the main actor before it checks its generation and emits.
- Two
Task.yield()calls cannot order that hop beforecancelPendingRefresh(). When the cancel won, nothing was emitted. - The listener now waits for the emission itself, then cancels and asserts that the emitted generation is rejected.
TerminalPlainTextPasteStartupTests/clipboardRestorationAfterNativePaste()(run 36645415013, trial 0 received no bytes after the 20 s receipt wait).- A 600 ms sleep stood in for "the prewarmed plain-text reader has started". A slow launch through the fixture's wrapper on a loaded runner outlasted it, so trial 0 missed the sender's 100 ms clipboard restore.
- The fixture now waits until the reader was prewarmed at init and has served one read.
- The final
launches == ["text"]assertion still holds, because the readiness read reuses the same reader.
Evidence
The proofs use app-host-test-rerun.yml with the app build from full-suite run 36685498203 (478e3232b):
- SSH, deterministic red/green. Both runs add a 1 s delay between the fixture's two writes, for the proof only; it isn't committed.
- Original order: run 36710919348 failed 3 of 3 with the CI error,
Cocoa error 260: The file "backoff-pid" couldn't be opened because there is no such file. - Fixed order: run 36710923192 passed 3 of 3. That job's red status comes from an artifact upload timeout after the tests (
Failed to CreateArtifact: ETIMEDOUT).
- Original order: run 36710919348 failed 3 of 3 with the CI error,
- All three fixes, 20 iterations each: run 36713674088 passed 20 of 20 for each test: the omnibar XCTest ran 20 iterations, and the SSH and paste tests ran 20 each in Swift Testing.
SSH startup suite: first exec in a fresh app host
This PR's admission lane runs SSHStartupManualReconnectTests first in a fresh app host. Its first test, failedVMStartupClosesAfterDismissalWithoutImplicitReconnect, failed there twice: the dismissal prompt never appeared within the 3 s wait, and then the cleanup timed out.
- What the fleet logs show. The unified logs of both minis (
log show) have the cause. syspolicyd held the first new executable the app host ran, the rewritten VM launcher script, before assessing it: 6.3 s on cmuxs-mac-mini-3 and 13.5 s on cmux10s. The kernel then loggedASP: Sleep interruptedandSecurity policy would not allow processfor the launcher, still waiting in exec when the cleanup signalled it. - Why only the first test. The app host's later new files were assessed in 0.1โ0.3 s. Main's shards pass because earlier suites absorb that one-time stall.
- Fix. Every shell fixture now exits at once when
CMUX_TEST_PRIME_EXECis set, and is run that way as soon as it is written, like the Claude, Hermes and Pi wrapper fixtures. The rewritten launcher gets the same guard ahead of its self-delete, and the terminal-teardown test primes its copy of it. No wait, budget or assertion changes.writeShellFilemoves to the fixtures file, so the suite file stays within its 913-line budget; it is now 908 lines. - Evidence. Run 36722931614 ran the whole suite first in a fresh app host on cmuxs-mac-mini-3, the Mac of the second failure, 5 iterations, plus the omnibar test.
- Everything passed: 65 of 65 Swift Testing runs and 5 of 5 omnibar iterations.
- The first iteration of
failedVMStartupClosesAfterDismissalWithoutImplicitReconnecttook 6.58 s and later ones 0.76โ0.78 s. The stall still happens, but in the untimed priming step instead of the 3 s wait.
The omnibar test also now asserts that the emitted refresh is accepted before the cancel, so a gate that rejects every refresh no longer passes it.
Changelog
- none
๐ค Generated with Claude Code