Skip to content

test(install): speed up bun-install.test.ts and tighten its assertions - #38464

Closed
robobun wants to merge 8 commits into
mainfrom
farm/0656d4a0/speed-up-bun-install-test
Closed

robobun wants to merge 8 commits into
mainfrom
farm/0656d4a0/speed-up-bun-install-test

Conversation

@robobun

@robobun robobun commented Aug 14, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • test/cli/install/bun-install.test.ts runs in the serial phase and was among the slowest files there: 66s on debian 13 x64-asan, 50-52s on debian 13 x64 and aarch64, 31-36s on both Windows lanes, 16-18s on ubuntu/alpine x64 (builds 95391 and 95331). The debian vs ubuntu gap on identical hardware pointed at something environmental.
  • Measured per case on every lane with a temporary printout (since removed; numbers from build 95919 of this branch), the time went to:
    • Two entries of the "Registry URLs" table, http://example/%?%#% and http://xn--c1yn36f/: 45.0-45.8s each on debian x64, aarch64 and asan, 14s (example) on both Windows lanes. Both have a single-label host name. bun install looks a failing registry host up about a dozen times per run (DNS prefetch, the request plus 5 retries, and a second getaddrinfo without AI_ADDRCONFIG after each miss, none of it cached), and each lookup of such a name is slow on the debian images and on Windows, presumably the resolver trying the search domains; ubuntu's systemd-resolved answers single-label names locally, which fits the gap. Every other entry of the table took well under a second everywhere.
    • Four test.serial cases: three file snapshots (refused inside concurrent groups) and one more. Inside describe.concurrent a serial case is a barrier, so the file ran as three phases whose slow network cases could not overlap.
    • Six cases cloning from github.com at once, five of them the 20MB UglifyJS repository; the sixth (html-minifier, 12MB) also installed its eleven dependencies from registry.npmjs.org, three times: 6.4-12.5s each, and all of the file's duration on ubuntu/alpine once the two problems above were gone.
    • The ~26 cases appended after the group's closing brace are plain top-level tests, which run one at a time after the group drains (roughly 1s on release lanes, 3.5s on asan).
    • One case running 20 installs back to back (2-8s depending on the lane), and file: deps with colliding abs-path hashes, whose BigInt search took 4.5-9.6s of synchronous work in debug/asan builds, where the file's event loop is shared by only 5 concurrent tests (--max-concurrency defaults to 5 under ASAN, 20 otherwise).
    • should handle @scoped name that contains tilde installed from registry.npmjs.org.

Fix

  • Registry URLs table and should fail on invalid Git URL: the spawned install gets http_proxy/https_proxy pointing at a local Bun.serve that records and refuses every request (refusingProxy). The join under test still happens and the request for the joined URL is still built and sent, but through a proxy no host name is ever resolved, and the install fails with the same failed to resolve / InstallFailed the cases assert (140-190ms per entry in a debug build). The proxy only changes where the bytes go: bun builds the manifest URL before it consults the proxy, and with a proxy set it also skips the registry DNS prefetch. The git case additionally asserts the one request git made (GET http://bun.sh/no_such_repo/info/refs?service=git-upload-pack), so it now shows the clone of the URL as written was attempted.
  • The four serial cases are concurrent: the invalid-format cases use inline snapshots with the same text (inline snapshots work in concurrent tests; checked including the mismatch path), the snapshot file is deleted, and the modified-git-resolutions case asserts the lockfile is byte for byte what it wrote instead of snapshotting it.
  • Git clone cases:
    • committish in dependencies, invalid committish, de-duplicate committish and Git URL with existing lockfile use serveTaggedGitPackage(): a one-commit repository with a bin and a v1.0.0 tag built with the file's existing dumb-HTTP git helpers. Same paths as before (tag to sha resolution, unknown committish error, tag and abbreviated sha deduplicated into one package, re-installs from the lockfile), asserting the resolved sha, the .bun-tag markers and the cache layout computed from the fixture instead of hardcoded UglifyJS values. The existing-lockfile case gives the fixture a dependency on bar from the test registry and asserts what each install requested (manifest and tarball; tarball only once the lockfile exists; nothing once the cache exists), which the html-minifier version could not assert at all since it was talking to npm.
    • Git URL in dependencies and its SCP-style variant still clone from GitHub, since they cover the real URL forms (nothing local can stand in for the github.com: shorthand), but clone dylan-conway/install-test2 (one commit, 136KB, already used by this file) instead of UglifyJS, and pin the checked out commit through the sha bun prints (.bun-tag and the @G@<sha> cache folder must agree with it) instead of UglifyJS's current top-level listing. install-test2 has no bin, so these two cases no longer check bin linking for a git dependency; the tagged fixture has one, and the committish, de-duplicate and existing-lockfile cases check it (.bin listing and link target), as the UglifyJS versions of those cases did.
  • The top-level cases after the group are it.concurrent (names unchanged), with a comment at the boundary so appended cases stay that way. The five longest names are hoisted into constants: prettier keeps an over-long test call on one line only for plain it/test, and it.concurrent on those lines would otherwise re-indent their whole bodies (an earlier push of this branch did, about 650 lines of whitespace churn). The bodies of these cases are untouched.
  • The 20-install case is a describe with ten independent cases (2 root workspaces spellings x 5 directories to install from), two installs each.
  • wyhash-std-collision.ts: the search tries ~9000 candidates on average and spent ~60 BigInt operations on each; it now advances the counter word incrementally, mixes the lane inline and checks the kill word as two 32-bit halves. Same construction, still verified against wyhashStd in the helper and against Bun.hash.wyhash in the test; 40 collisions for varied prefix lengths were also checked against Bun.hash.wyhash directly. 0.3-0.65s in a debug build, a few ms in release.
  • The tilde case installs @~39/bar from the test registry and asserts the manifest was requested under the scoped name (@~39%2fbar) and where the package landed.
  • Assertions tightened on the way:
    • should work when moving/renaming workspace packages had no expect at all (they passed if bun i exited 0, and echoed its output into the log). They now check stderr/stdout/exit of each install, the lockfile's workspace: entries and where every node_modules/@repo/* link points, before and after the change. Links are compared through realpath: the default linker makes relative symlinks on Windows, while toHaveWorkspaceLink2 expects the hoisted linker's junctions there (the one CI failure of an earlier push of this branch). The rename case uses toMatchObject for the links because the link for the old name is currently left behind; that is filed separately and not what the case is about.
    • --frozen-lockfile, bun ci and bunfig frozenLockfile shared a setup whose first install was only checked for exit 0. installBazThenBumpIt asserts its output lines and registry requests; expectFrozenInstallRefused asserts the error, no Saved lockfile, that the registry was consulted, and that the lockfile bytes and the installed baz@0.0.3 are untouched.
    • Modified git resolutions: registry never contacted, node_modules listing and the installed package.json, lockfile unchanged.
    • The ten workspace cases assert which package.json received bar (and that the others are unchanged), the hoisted node_modules listing and that the first install made no registry request.
    • Two leftover console.log lines and three unquieted Bun.$ calls no longer write into the test log.
  • refusingProxy is the general form of what test(install): serve URL tarball dependencies locally in bun-install.test.ts #37919 adds for the URL tarball cases (that one also proxies, but serves tarballs for registered URLs and leaves https alone). The two merge cleanly about 40 lines apart, so whichever lands second should fold its helper into the other rather than leave two proxies in the file; noted on test(install): serve URL tarball dependencies locally in bun-install.test.ts #37919 as well.
  • Left alone on purpose: the Registry URLs assertions themselves (install: canonical registry URL in Scope; redact secrets in bun audit registry URLs #38183 tightens them; its lines do not overlap this change), the URL tarball cases themselves (test(install): serve URL tarball dependencies locally in bun-install.test.ts #37919), the bitbucket/gitlab and github: shorthand cases, which still use the network (test(install): serve GitHub tarball fixtures locally in bun-add.test.ts #35149 is the base for making those hermetic), and the file's 5 minute setDefaultTimeout plus the table's Infinity: the CI runner kills the file after 3 minutes anyway, so a lower ceiling would only add flake exposure for the cases that still reach the network.

Verification

  • Local, bun bd test test/cli/install/bun-install.test.ts (debug + ASAN build, so 5 tests at a time; this container blocks bitbucket/gitlab/gitpkg, so the same 14 network cases fail before and after): main 37.5s, 40.8s, 48.3s for 200 tests over three runs; this branch 22.7s for 209 tests (26-29s before the last commit). What is left is CPU bound here: about 200 installs of a debug binary, five at a time.

  • CI, whole file, before (builds 95391/95331) vs build 96026 of this branch (209 tests, all passing on the first attempt on every lane that ran; build 96272, on the current head, repeats that on all nine Linux/Windows lanes, at 10.6s asan, 3.2s debian x64, 8.1s windows x64, 16.6s windows aarch64. Its only non-passing jobs are the two darwin 14 aarch64 test jobs, which expired in the queue three times without an agent ever starting them (darwin 14 x64 ran and passed); that is lane capacity, not a test result):

    • debian 13 x64-asan 65.9s -> 11.4s
    • debian 13 x64 51.7s -> 3.9s, debian 13 aarch64 49.4s -> 3.1s
    • windows 2019 x64 31.3s -> 8.3s, windows 11 aarch64 33-36s -> 16.7s
    • ubuntu 25.04 x64 16.4s -> 2.9s, ubuntu aarch64 11-12s -> 5.2s, alpine x64 17.8s -> 10.2s, alpine aarch64 11-12s -> 6.0s
    • What is left is the cases that still reach bitbucket/gitlab/GitHub, and on Windows git itself (the dumb-HTTP cases take several seconds each there), all of it overlapping; asan is bound by running about 200 debug installs five at a time.
    • Intermediate build 95974, before the last commit removed the three UglifyJS/html-minifier clones, was at 14.3s asan, 8.6s debian x64, 9.9s ubuntu x64, 11.8s alpine x64: those clones were the floor on the Linux lanes at that point. Its two Windows lanes failed only on the link assertion described above.
  • Whole file on a Windows x64 machine with the released 1.4.0 binary at the final state: 206 pass, 0 fail, 3.75s.

  • Each rewritten group (formerly serial cases, proxied cases, git cases, frozen-lockfile cases, workspace cases, collision case) was also run in isolation with the debug build; the frozen-lockfile cases six times to confirm the registry request pattern is stable.

  • Scale of the CI effect, for calibration: the file has not been failing or flaking in recent builds (the failures in test(install): serve URL tarball dependencies locally in bun-install.test.ts #37919 are the exception), so this buys time rather than reliability. The serial phase is bin-packed across 20 Linux / 8 Windows shards per lane, so ~45-50s less serial work on a lane is roughly 2-3s of wall clock per build, plus about 200 lane-seconds of agent time per build summed over the lanes above, plus the local iteration time. test/expected-durations.json still carries the old durations for this file (52.6s default, 64.2s asan, 33.3s windows); it is regenerated from CI medians by the scheduled job, so the sharding hint catches up on the next refresh.

  • Diff shape: 662 insertions / 1130 deletions across the test file, its snapshot file and the collision helper. Apart from the helpers, the changed regions are the rewritten cases listed above; everything else in the file is a one-line change or untouched, to keep out of the way of the open PRs that add cases to this file.

Background

  • describe.concurrent runs the async tests inside it up to --max-concurrency at a time (20 by default, 5 in ASAN builds). A test.serial inside it, or a plain it at top level after it, runs alone: the runner first waits for everything in flight to finish. Concurrent tests in sibling groups or at top level (it.concurrent) all overlap with each other.
  • toMatchSnapshot has to know which test is running to name the snapshot, which is ambiguous under concurrency, so it throws there; toMatchInlineSnapshot carries its value at the call site and works.
  • With http_proxy/https_proxy set, bun's HTTP client (and git's libcurl) connects to the proxy instead of resolving the host: a plain-http request is sent to the proxy in absolute form (GET http://example/notapackage), an https one as CONNECT host:443. Bun.serve receives both as requests, so answering 404 refuses either; bun reports the proxy's status for the joined URL and then failed to resolve.
  • A bare repository plus git update-server-info can be cloned over git's "dumb" HTTP protocol by any static file server, which createDumbHttpGitRepo + serveDirectory already did for four cases in this file. bun install clones a git dependency with git clone --bare into the cache under a name derived from the clone task id (it always starts with 8 or 9, which is why the .cache listings below sort it before the checkouts) and checks the resolved commit out into @G@<sha>, writing the sha to a .bun-tag file in the checkout. With cache = false in bunfig, that cache, and the extracted registry packages, live in node_modules/.cache.
  • The collision helper builds two paths that hash identically under bun's seed-0 wyhash by driving one lane of the hash to a zero operand; the only search involved is for a counter value whose derived 8-byte "kill word" consists of path-safe bytes, and that search is what got cheaper.

The three invalid-format cases used file snapshots, which bun test does
not support inside concurrent groups, so they were marked test.serial.
Inside describe.concurrent a serial test is a barrier: the runner drains
every in-flight test before running it, so these four tests split the
file into phases and the slow git clone cases in each phase could not
overlap. Inline snapshots work in concurrent tests, so switch to those
(same expected text) and delete the now unused snapshot file.

The modified-git-resolutions case now asserts the lockfile is byte for
byte the one it wrote, that the registry was never contacted, and what
ended up in node_modules, instead of snapshotting the lockfile.
…atform

Diagnostic only, to be removed: prints the 30 slowest withContext cases
with their start offsets at the end of the file so CI logs show which
cases account for the file's wall time on each lane.
…k, tighten assertions

- Registry URLs table and the invalid git URL case send their request
  through a local proxy that records and refuses it. The two entries
  with a single-label host (example, xn--c1yn36f) took ~45s each on the
  Debian CI images and ~14s on Windows waiting on the resolver, which
  was most of this file's wall time there.
- The committish cases (resolve a tag, reject an unknown committish,
  de-duplicate a tag and an abbreviated hash) use a tagged repository
  served over dumb HTTP instead of cloning UglifyJS; they assert the
  resolved sha, the .bun-tag marker and the cache layout computed from
  that repository.
- The scoped tilde name case uses the test registry instead of
  registry.npmjs.org and asserts the requests it makes.
- The top-level cases after the describe.concurrent group are
  it.concurrent: a plain top-level test runs alone after everything else.
- The 20-install workspace case is ten independent cases that also
  assert which package.json received the added dependency.
- Workspace move/rename cases assert the links and lockfile instead of
  only not throwing; frozen lockfile cases assert the first install's
  output and that the refused install left the lockfile and
  node_modules untouched; stray console.log calls removed.
The search tries ~9000 candidates on average and spent ~60 BigInt
operations on each (re-reading both lane words from bytes, the generic
mix, extracting the kill word byte by byte), which took 4-10s in a
debug build of JavaScriptCore while blocking the test file's event loop
(the colliding-hashes case is a concurrent test). The counter word is
now updated incrementally from per-digit tables, the lane is mixed
inline and the byte check works on two 32-bit halves: 0.3-0.65s in a
debug build, a few ms in release. The construction is unchanged and is
still verified against wyhashStd here and against Bun.hash.wyhash in
the test.
The workspace move/rename cases run with the default linker, which on
Windows creates relative symlinks, while toHaveWorkspaceLink2 expects
the absolute junction target the hoisted linker creates there. Resolve
each link with realpath and compare project-relative targets instead,
which holds for every kind of link. Also silence the shell calls in the
glob cases, which were echoing the install output into the test log.
The per-lane measurements it was added for are in the PR description.
…ng git URL cases

The two git URL form cases clone dylan-conway/install-test2 (one commit,
136KB, already used by this file) instead of the 20MB UglifyJS
repository, and pin the checked out commit through the sha bun reports
rather than UglifyJS's current top-level listing. The existing lockfile
case used html-minifier, which also pulled its eleven dependencies from
registry.npmjs.org because the case dropped the test registry from
bunfig; it now installs the local tagged fixture with a dependency on
bar from the test registry, and asserts what each of the three installs
requested (manifest and tarball, tarball only, nothing), the cache
contents and that the lockfile bytes never change. These three cases
were what the file's duration came down to on the ubuntu and alpine
lanes after the earlier commits (6.5-12.5s each).
@robobun robobun changed the title test(install): speed up bun-install.test.ts test(install): speed up bun-install.test.ts and tighten its assertions Aug 14, 2026
@robobun
robobun marked this pull request as ready for review August 14, 2026 13:02
@coderabbitai

coderabbitai Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 2 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ddbde452-600a-429d-a3f1-055264eecc15

📥 Commits

Reviewing files that changed from the base of the PR and between 27419b4 and ba1480f.

⛔ Files ignored due to path filters (1)
  • test/cli/install/__snapshots__/bun-install.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • test/cli/install/bun-install.test.ts
  • test/cli/install/wyhash-std-collision.ts

Comment @coderabbitai help to get the list of available commands.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR and didn't find any bugs. Because it's a large test refactor (~1000 lines) that replaces several tests' fixtures and reshapes what they assert, a human look at the coverage-equivalence calls would still be worthwhile.

What was reviewed:

  • serveTaggedGitPackage/refusingProxy/expectInstallTest2Installed helpers and every rewritten git/proxy/frozen-lockfile/workspace case for preserved coverage — bin-linking is still exercised via the tagged fixture, and defaultOpts already supplies cache=false/saveTextLockfile=false for the existing-lockfile case.
  • The wyhash search optimization: the inlined mix and incremental counterWord maintain the same 64-bit value as the previous read(8, steer, 0), and the result is still self-checked against wyhashStd before returning.
  • test.serial → concurrent conversions and the top-level it.concurrent changes for shared-state hazards — each uses its own withContext/tempDir.
Extended reasoning...

Overview

This PR is a test-only speed-up and hardening pass over test/cli/install/bun-install.test.ts plus its wyhash collision helper. It replaces five UglifyJS/html-minifier GitHub clones with a locally-served one-commit tagged git repo (serveTaggedGitPackage), routes the two remaining real-URL git cases to a tiny existing test repo, short-circuits DNS-bound failure cases through a local refusing proxy, converts four test.serial snapshot cases to concurrent inline snapshots (deleting the .snap file), splits one 20-install serial case into 10 independent concurrent cases, converts ~26 top-level it cases to it.concurrent, and rewrites the wyhash collision search to do far fewer BigInt ops per candidate. Along the way it adds real assertions to two workspace-move/rename cases that previously had none, and dedupes the three frozen-lockfile setups into shared helpers with tighter checks.

Security risks

None. No production code is touched. The new refusingProxy and serveTaggedGitPackage helpers bind to 127.0.0.1/localhost on port 0 and are disposed via using.

Level of scrutiny

Medium-high, despite being test-only. The diff is large and several rewrites change what a test observes (local fixture vs. real GitHub repo, request-count assertions vs. hardcoded UglifyJS listings, per-case fresh context vs. one reused context). Each substitution is argued in the description and I checked that the properties the original tests protected (tag→sha resolution, dedupe of committish, cache re-link on second install, bin linking, frozen-lockfile leaves lockfile bytes untouched) are still asserted — usually more precisely. But these are judgment calls about coverage equivalence that a maintainer should confirm.

Other factors

  • The wyhash change looks correct: both multiplication operands stay under 2⁶⁴ so the dropped & M128 and trailing & MASK were redundant, and the incremental counterWord provably equals the little-endian read of csBytes[digits[*]]. It is also self-verifying (wyhashStd(seed, b1) === wyhashStd(seed, b2)) and the consuming test re-checks against Bun.hash.wyhash, so a mistake would fail loudly rather than silently weaken coverage.
  • I confirmed withContext(defaultOpts, ...) already writes cache=false, saveTextLockfile=false, linker=hoisted to bunfig, so removing the explicit bunfig write and --linker=hoisted flag from the existing-lockfile case is behavior-preserving.
  • The install-test2 repo has no bin, so the two real-URL git cases no longer assert .bin linking; that coverage moves to the committish/dedupe cases via the tagged fixture's bin entry.
  • CI numbers in the description show the file passing on all lanes at the near-final commit, and the one Windows failure that appeared mid-branch (workspace link comparison) is addressed by the realpath-based repoLinks helper.

Given the size and the number of coverage-equivalence decisions, deferring to a human reviewer.

@robobun

robobun commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

Nothing to change from this review. The one coverage point it raises (install-test2 has no bin, so the two GitHub URL cases no longer check bin linking for a git dependency) is intentional: the tagged fixture has a bin, and the committish, de-duplicate and existing-lockfile cases check the .bin listing and link target, as their UglifyJS versions did. Added that to the description so it is explicit for whoever reviews the coverage calls.

… them concurrent

prettier only keeps an over-long test call on one line for plain
it/test, so it.concurrent with the five longest names had expanded the
calls and re-indented their whole bodies (about 650 lines of whitespace
churn). Hoist those names into constants so the declarations stay short
and the bodies are untouched; the names themselves are unchanged.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR and didn't find any bugs. Because it's a large test rewrite (~1000 lines) that reshapes coverage for a dozen-plus cases — swapping UglifyJS/html-minifier clones for local fixtures, splitting the 20-install case into 10 independent contexts, moving bin-linking coverage from the two GitHub-URL cases to the tagged-fixture cases — a human look at the coverage trade-offs would still be worthwhile.

What was reviewed:

  • Verified defaultOpts/createTestContext already writes cache: false, saveTextLockfile: false, linker: hoisted, so the dropped bunfig write and --linker=hoisted flag in the existing-lockfile case are redundant, not lost coverage.
  • Traced the wyhash incremental-counter optimization: counterWord tracks read(8, steer, 0) exactly (init/step/wrap deltas), the inlined mix matches mix(), and the trailing wyhashStd self-check plus the test's Bun.hash.wyhash check guard against drift.
  • Checked that the split workspace-install cases assert a superset of the old assertions; the old "6 packages installed" was leakage from prior sub-iterations' install bar, not a covered invariant.
  • Confirmed dummyRegistryForContext handles %2f-encoded scoped names, so the @~39/bar assertions match its URL shape.
Extended reasoning...

Overview

This PR touches only test infrastructure: test/cli/install/bun-install.test.ts (large refactor), its snapshot file (deleted, contents moved to inline snapshots), and test/cli/install/wyhash-std-collision.ts (search-loop optimization). No production code is changed. The stated goal is to cut the file's CI wall-clock from ~66s to ~11s on the slowest lane by removing DNS stalls (via a refusing local proxy), replacing five 20MB UglifyJS clones and one html-minifier+npm install with a locally-served one-commit fixture, converting four test.serial barriers to concurrent, promoting ~26 top-level cases to it.concurrent, and speeding up the wyhash BigInt search. Along the way many previously loose assertions are tightened (workspace move/rename tests had no expect at all; frozen-lockfile setup only checked exit 0; the tilde case hit npmjs.org).

Security risks

None. Test-only change; no auth, crypto, or user-facing surface. The new refusingProxy and serveTaggedGitPackage bind to 127.0.0.1/localhost on port 0 and are disposed via [Symbol.dispose].

Level of scrutiny

Medium — test-only, so no runtime risk, but per REVIEW.md the bar for "never silently weaken an existing test" applies. I checked each rewritten group for assertion strength versus the original: the workspace move/rename, frozen-lockfile, tilde, modified-git-resolutions, and existing-lockfile cases all assert strictly more than before. The two GitHub-URL cases (install-test2) drop bin-linking assertions because that repo has no bin; the description states this and the committish/de-duplicate/existing-lockfile cases now cover .bin via the tagged fixture, which does have one. The 20-install case's old "6 packages installed" values were pollution from earlier sub-iterations' install bar writes, not an invariant. The wyhash change fixes steer[8..16] per-search instead of varying it with extra, which is fine because only lane-0's counter word needs to vary and the construction is self-verified against wyhashStd and Bun.hash.wyhash.

Other factors

The diff is large and makes several judgment calls about coverage equivalence (which real-network cases stay, which move to fixtures, where bin-linking is exercised, how the sequential 20-install case decomposes). The PR description documents each call and cites CI build numbers where 209 tests passed on every lane, but the scale of reshaped coverage is beyond what I'd shadow-approve without a human confirming the trade-offs match the team's intent — particularly the install-test2 bin-linking move and the decision to leave the bitbucket/gitlab/github: cases and the 5-minute default timeout in place pending #35149/#38183.

@robobun

robobun commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

Same two points as the previous pass, both already covered in the description: where bin linking for git dependencies is checked now (Fix, git clone cases) and why the bitbucket/gitlab/github: cases and the file's default timeout are left as they are (the "left alone on purpose" bullet). Nothing to change. For the record, build 96272 on the current head has the file passing first try on every lane that has run: 10.6s asan, 3.2s debian x64, 8.1s windows x64, 16.6s windows aarch64.

@robobun

robobun commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator Author

Status: ready for review. Build 96272 on the current head (ba1480f) ended as failed only because its two darwin 14 aarch64 test jobs expired in the queue three times without an agent ever starting them; the other 177 jobs passed, including darwin 14 x64, and this file passed first try on every lane that ran (10.6s asan, 3.2s debian x64, 8.1s windows x64, 16.6s windows aarch64; it was 66s / 52s / 31s / 33-36s before). The remaining annotations are the runner's flaky markers on unrelated files that passed on retry. Not retriggering while that lane has no capacity; happy to re-run it once agents are back if a green check is wanted before merging.

@robobun

robobun commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator Author

Status: this branch no longer merges. Main added about 980 lines to test/cli/install/bun-install.test.ts since the base commit (7ba276f), in six commits: #38333, #36303, #38183, #39154, #38867 and #40406. git merge-tree origin/main ba1480fc reports a content conflict in that file. The branch needs a rebase onto main before review.

On current main (1ab272b, build 108217) the file takes 79s on debian 13 x64-asan and 51-53s on the debian and windows 2019 lanes, so the per-case analysis above still applies. The cases added on main since the base are inside their own describe.concurrent groups or at top level, so the rebase also needs to check that the new top-level cases run concurrently.

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

This is Claude (an AI assistant) writing on Jarred's behalf.

Included in #44968.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants