Repository navigation
test(installer): drive download fixtures on events, not one event-loop turn (HACK-2250) - #858
Conversation
…p turn (HACK-2250) "bounded cancellation refuses uncertain read-error settlement" advanced the fixture clock after a single setTimeout(0). The download opens its target file (real I/O) before it reads, and only then arms the 5 ms cleanup grace on the fixture clock. When open() took longer than one turn, the advance fired nothing, the grace never expired, and the test hung until Bun's 5 s timeout. Its finally never ran, so fetch stayed spied: the next scenario saw two calls and the global-state guard reported fetch replaced. The tests now wait, bounded at 2 s, for the event each step depends on: the cleanup grace armed before advancing 5 ms, the target file open before an inactivity tick, and the five-file sequence's spin loops use the same real-time bound instead of 100 turns. Final settlement is awaited with the same bound, and afterEach restores every spy so a failed test cannot leak fetch into the next one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… clock ticks Review of HACK-2250: the target file can exist before the awaited open() returns its handle, so "file exists, then one turn" still let an inactivity tick land before the download was reading (a false stall). The streams in the transfer-budget and stalled-read fixtures now use highWaterMark 0 and flag pull(), which runs only while the download has a read pending, and each tick waits for that flag, bounded at 2 s. Under 16-way parallel load the previous head failed 2 of 191 runs of the file this way (progress and total); a delay injected after open() creates the file reproduces it every time and passes with this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@codex review |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
Ready for lead: head Ran (Linux, 16 cores)
Not verified
Also fixed in this file: the same "one event-loop turn is enough" assumption in "HTTP transfer budget … progress/total" and "five-file … cleanup". At an intermediate head these failed 2 of 191 runs under load (false stall), and they fail with the injected delays. Test-only; no assertion weakened. |
|
Mac result at 0c33970 (Apple silicon): the four "bounded cancellation" tests pass 200 of 200 runs, and the whole file passes 20 of 20. This PR goes into the next combined Mac batch. 🤖 Generated with Claude Code |
What
tests/python-free-download.test.ts, "bounded cancellation refuses uncertain read-error settlement and preserves the primary failure", hit Bun's 5 s default timeout on hosted macOS shard 1/8 (#853). The next scenario then failedtoHaveBeenCalledTimes(1)with 2, and the global-state guard reportedglobalThis.fetch replaced.What it was really waiting on
The test drove a fake clock after a single
setTimeout(0):transferAttempt(src/lib/release-transfer.ts) awaits a realopen()of the target file before reading. Only after the size failure doessettleCancellationarm the 5 ms grace on the fake clock. Ifopen()takes more than one turn (a loaded runner), the advance fires nothing. The grace is armed afterwards at the new time and never expires, so the download never settles. The test then hangs until the 5 s timeout, and itsfinally { mock.mockRestore() }never runs. The next scenario'sspyOn(globalThis, "fetch")reuses the leaked spy, which already has one call: hence 2, and the guard error.The same assumption (one turn is enough) sat in three sibling tests in this file: "HTTP transfer budget … progress / total" and "five-file … cleanup". They fail the same way when
open()is slow.Fix (test-only)
until(ready, what)drains in a loop with a 2 s real-time bound, well under the 5 s default. A missed step fails withFixture step did not happen within 2000 ms: <what>instead of a timeout.within(promise, what)bounds the final settlement the same way.clock.isArmed(5).FixtureClocknow records each timer's delay; the other timers are 30 and 100 ms.highWaterMark: 0and flagpull(), which runs only while the download is reading. A file-existence check was not enough: the file exists beforeopen()returns its handle (found in review).afterEachcallsmock.restore(), so a test that fails before itsfinallycannot leak thefetchspy into the next test. The existing per-testmockRestore()calls stay.No assertion is weakened or removed.
Validation (Linux, 16 cores)
-t "bounded cancellation"under 16-way parallel loadopen()by 50 msopen()by 200 msopen()creates the filetsc -p packages/cli(it includestests/) andbiome checkpass.Not verified: macOS. The lead runs the 200 on the Mac.
Release signal
test: test-only.Refs HACK-2250.
🤖 Generated with Claude Code