Skip to content

test: stop quarantining whole files for one broken case - #33952

Merged
Jarred-Sumner merged 4 commits into
mainfrom
claude/expectations-honor-kind
Jul 11, 2026
Merged

Jarred-Sumner merged 4 commits into
mainfrom
claude/expectations-honor-kind

Conversation

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

The mechanism

An entry in test/expectations.txt removes the whole file from the run. getRelevantTests (scripts/runner.node.mjs) filters on the platform modifier and never reads the kind — [ FAIL ], [ SKIP ], [ CRASH ], [ FLAKY ], [ LEAK ], [ TIMEOUT ] are all the same thing. There is no "run it and expect failure" mode.

So quarantining one broken case silently deletes that file's entire coverage, and nothing ever reports it. Several entries turned out to be stale — the thing they quarantined had been fixed, and no one could tell, because the file wasn't running.

Restored

Verified with the debug (ASAN) build.

file was now why it was dark
test/bundler/native-plugin.test.ts 0 running 18 pass, 1 skip 1 real failure, ASAN-only
test/js/node/child_process/child_process.test.ts 0 on ASAN 43 pass stale
test/js/bun/shell/bunshell.test.ts 0 on ASAN 388 pass stale
test/cli/run/run-crash-handler.test.ts 0 running 9 pass stale
test/bundler/cli.test.ts 0 on ASAN runs stale
test/js/bun/util/reportError.test.ts 0 on ASAN 2 pass stale
test/cli/create/create-jsx.test.ts 0 running runs CI-only failure that no longer reproduces

native-plugin's one real failure is ASAN-only: the plugin dereferences null on purpose, and ASAN traps the SEGV and aborts before Bun's crash handler can print the plugin name. It is now skipIf(win32 || isASAN) — the broken test is quarantined, not the file.

Also

  • Dropped 5 entries naming files that do not exist.
  • Rewrote the header to state what the runner does, and to say: skip the broken test in the file, not the file.

Not fixed here

test/js/bun/spawn/spawn-maxbuf.test.ts stays quarantined. It is not flaky — it fails deterministically (5/5 runs). Two causes:

  1. Wall-clock bounds (toBeLessThan(100)) that a debug/ASAN build cannot meet — it measured 108ms.
  2. A real one: Bun.spawn with timeout kills the direct child, but reading proc.stdout afterwards blocks for the child's full lifetime.
exited after 127 ms, signal: SIGHUP
stdout read after 4957 ms, bytes: 0     <-- the full `sleep 5`

bun exec sleep 5 → the shell spawns sleep, which inherits the stdout pipe's write end. Killing the shell leaves sleep holding it, so the stream never EOFs. proc.exited resolves; the stream does not. Whether killSignal should reach the process group is a product decision, so I left it alone.

An entry in test/expectations.txt removes the FILE from the run — the kind
(FAIL/SKIP/CRASH/FLAKY) is parsed but never read, so there is no
"expect failure" mode. Quarantining one case deletes the file's whole
coverage, and nobody finds out, because a skipped file reports nothing.

Verified with the debug (ASAN) build, per file:

  native-plugin.test.ts     18 tests dark for 1 real failure. That failure
                            is ASAN-only: the plugin null-derefs on purpose
                            and ASAN traps the SEGV before the crash handler
                            can print the name. Skip that case under ASAN
                            (it already skips on Windows) -> 18 pass, 1 skip.
  run-crash-handler.test.ts 9 pass, 0 fail. Entry was stale.
  reportError.test.ts       2 pass under ASAN. Entry was stale.
  child_process.test.ts     43 pass under ASAN. Entry was stale.
  bunshell.test.ts          388 pass under ASAN. Entry was stale.
  bundler/cli.test.ts       no debug-log failures under ASAN. Entry was stale.
  create-jsx.test.ts        7 pass locally; the entry names a CI-only build
                            failure that no longer reproduces. Removed - if
                            CI disagrees it will say so, which is the point.

Also drop 5 entries naming files that do not exist, and rewrite the header
to say what the runner actually does, so the next person quarantines the
broken TEST rather than the file.

spawn-maxbuf.test.ts stays quarantined: it is not flaky, it fails
deterministically, and the cause is a real behavior question (below).
@robobun

robobun commented Jul 11, 2026 •

Copy link
Copy Markdown
Collaborator
Updated 9:54 PM PT - Jul 10th, 2026

@Jarred-Sumner, your commit 4e7cef3 is building: #71851

@coderabbitai

coderabbitai Bot commented Jul 11, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 9 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: 7d354d7f-7da8-4651-88fb-aab08537efd9

📥 Commits

Reviewing files that changed from the base of the PR and between aaace0d and 54c2a15.

📒 Files selected for processing (1)
  • test/no-validate-leaksan.txt

Walkthrough

Changes

The PR updates platform-specific test skipping, documents a native-plugin validation exclusion, and revises expectation guidance while removing obsolete broken-test, ASAN, and HTTP/2 skip entries.

Test stability

Layer / File(s) Summary
Native plugin crash-test conditions
test/bundler/native-plugin.test.ts, test/no-validate-exceptions.txt
The plugin-crash test skips on Windows, ASAN, and musl, and the native plugin test is excluded from validateExceptionChecks=1 with explanatory comments.
Windows create-test handling
test/cli/create/create-jsx.test.ts
The auto-install dependency test is marked as a Windows todo because the expected dependency output is not printed there.
Expectation guidance and quarantine cleanup
test/expectations.txt
Updates entry-authoring guidance and removes resolved broken-test, ASAN, and HTTP/2 timeout skip entries.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: quarantining a broken case instead of entire files.
Description check ✅ Passed The description explains the change and verification, but it does not follow the template headings exactly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

Beyond the inline nit, I verified: the 6 removed entries (5× test/js/node/test/sequential/test-http2-* + test-inspector-enabled.js) point to files that do not exist on disk; the new header's claim that getRelevantTests never reads the expectation kind is accurate (scripts/runner.node.mjs:2086-2091 destructures expectations but uses only modifiers); and the "match by SUBSTRING" claim matches isMatch at line 2052. Worth waiting on build #71732 before merge — the 7 un-quarantined files were verified on one local ASAN build, not the full platform matrix.

Extended reasoning...

This PR un-quarantines 7 test files and removes 6 stale entries, based on local debug/ASAN verification. The header rewrite and runner-behavior claims check out against the source. The only risk is a re-quarantined file failing on a platform the author did not run (Windows, macOS, musl); that is answerable only by the pending CI build, not code inspection. The inline nit about the skip comment misdescribing raise(SIGSEGV) as a null-deref is minor and non-blocking. No production code is touched.

Comment thread test/bundler/native-plugin.test.ts Outdated
Build 71732 ran these files for the first time. What the blanket entries
were hiding, and what each needs:

native-plugin.test.ts
  ASAN     Its napi addon's Init() calls napi_create_function and then
           napi_set_named_property without checking the status in between,
           like most real addons. validateExceptionChecks simulates a throw
           in every scope, so the second call trips at the napi boundary.
           Added to no-validate-exceptions.txt, which keeps the file RUNNING
           on the ASAN lane instead of skipped.
  musl     Every test passes (19/19). The job fails only because the
           "plugin crashes" test segfaults on purpose and the agent writes a
           core, which the runner counts as a failure. Skip that one test.
  Windows  beforeAll builds the addon with node-gyp and the agents have no
           ClangCL toolset (MSB8020), so nothing in the file can run. This
           one is a real whole-file skip, with the reason written down.

create-jsx.test.ts
  Windows  12 of 13 tests are already todo there; the last one asserts on an
           "--only-missing install" line `bun create` never prints on
           Windows. Marked todoIf(isWindows).

Net: native-plugin runs on darwin, glibc linux, and ASAN (18 pass, 1 skip);
create-jsx runs everywhere.

@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.

LGTM — test-infra only, restores coverage that stale quarantine entries were hiding. The follow-up commit tightened the native-plugin skip comment to "segfaults on purpose" (accurate) and folded in what CI surfaced (musl core-dump, Windows ClangCL, validateExceptionChecks). Verified the six dropped expectations.txt entries (5× sequential/test-http2-*, test-inspector-enabled.js) reference files that do not exist on disk, and isASAN/isMusl are real harness.ts exports.

Extended reasoning...

Overview

Test-infrastructure cleanup touching four files, zero production code:

  • test/expectations.txt — rewrites the header to document that entries remove the whole file regardless of kind, drops ~12 stale/nonexistent entries, and narrows the native-plugin.test.ts quarantine from all-platforms to [ WINDOWS ] only.
  • test/bundler/native-plugin.test.ts — one test's skipIf widened from win32 to win32 || isASAN || isMusl with a per-platform comment.
  • test/cli/create/create-jsx.test.ts — one test gated todoIf(isWindows).
  • test/no-validate-exceptions.txt — adds native-plugin.test.ts (napi fixture's unchecked napi_* status between calls trips the simulated-throw checker).

Net effect: ~460 previously-dark test cases across 7 files re-enter the CI matrix.

Security risks

None. No runtime, parser, network, crypto, or install code touched. Changes are limited to CI test-selection metadata and skipIf/todoIf guards in test files.

Level of scrutiny

Low. The failure mode of getting this wrong is bounded and self-correcting: an incorrectly un-quarantined file turns CI red on the affected platform, which is immediately visible. There is no silent-corruption risk. The PR already went through one CI round — commit aaace0db exists specifically to fold in what build #71761's predecessor surfaced (musl agent core-dump accounting, Windows node-gyp toolchain, exception-check validation), which is evidence the loop was closed.

Other factors

  • I spot-checked the "files that do not exist" claim: none of test/js/node/test/sequential/test-http2-{timeout-large-write,timeout-large-write-file,max-session-memory,ping-flood,settings-flood}.js or test/js/node/test/parallel/test-inspector-enabled.js exist on disk, so removing those entries is a no-op for the runner and pure hygiene.
  • isASAN and isMusl are both exported from test/harness.ts, so the new imports resolve.
  • My earlier nit about the skip comment's "dereferences null" wording was addressed — it now reads "segfaults on purpose", which matches raise(SIGSEGV) in native_plugin.cc. The alternative .env(bunEnv) fix I floated was explicitly speculative for CI; keeping the skip is the conservative choice and still nets +18 tests in that file.
  • The rewritten expectations.txt header is factually consistent with getRelevantTests in scripts/runner.node.mjs (substring match, kind ignored) and gives future contributors the right guidance.

With the exception-check exemption in place the file now passes on the ASAN
lane (18 pass, 0 fail) and then aborts at exit: LeakSanitizer reports a direct
8-byte leak from Bun's own dlopen path. BunProcess.cpp allocates a
NapiModuleMeta and hands it to a NapiExternal with no finalizer, right under a
comment saying "TODO: think about the finalizer here / currently we do not
dealloc napi modules". So the meta is never freed.

That is a real leak, but fixing it means changing napi module lifetime, which
does not belong in a test-quarantine cleanup. Exempt the file from the leak
check so its 18 tests run on ASAN, and leave the leak reported.

@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.

LGTM — test-infra only, net effect is restoring coverage that stale quarantine entries had silently disabled. The comment wording nit from my earlier pass was addressed (now "segfaults on purpose").

What was reviewed:

  • Verified the 5 removed sequential/test-http2-* entries and test-inspector-enabled.js reference files that no longer exist on disk.
  • Confirmed isMusl is exported from harness.ts; the widened skipIf and todoIf(isWindows) still net-gain coverage vs. the prior whole-file quarantines.
  • Checked the new no-validate-exceptions.txt / no-validate-leaksan.txt entries only relax sanitizer modes for a file that was previously not running at all.
Extended reasoning...

Overview

This PR touches only test-infrastructure files: test/expectations.txt (removes ~12 stale/nonexistent entries, rewrites the header to document that entries remove whole files, adds a Windows-scoped entry for native-plugin), two test files (narrows whole-file quarantines to per-test skipIf/todoIf), and adds native-plugin.test.ts to the two no-validate lists with commented rationale. No runtime, native, or bundler code is modified.

Security risks

None. The diff is confined to CI test-selection metadata and test skip conditions. No auth, crypto, network, or user-facing code paths are touched.

Level of scrutiny

Low-to-moderate. The change is mechanically simple (deleting text-file lines, adding || isASAN || isMusl to a skip condition, wrapping one test in todoIf(isWindows)), and the blast radius is bounded to CI green/red. The real verification is the CI matrix itself, and the commit history shows three rounds of CI-driven fixups already applied (aaace0db, 54c2a15d) after the initial un-quarantine, so the author has already iterated against the full matrix. I spot-checked that the removed sequential/test-http2-* and test-inspector-enabled.js entries reference files that do not exist on disk, matching the PR's "5 nonexistent entries" claim.

Other factors

My earlier review left one nit — the skip comment inaccurately said "dereferences null" when native_plugin.cc actually calls raise(SIGSEGV). The thread is resolved and the comment now reads "segfaults on purpose", which is accurate. The author did not take the speculative .env(bunEnv)-instead-of-skip suggestion, but that was explicitly flagged as unproven for CI and non-blocking; skipIf(isASAN) on one test is strictly better than the prior whole-file quarantine, so there is no regression. The new no-validate-* entries only relax sanitizer modes for a file that previously wasn't running at all, so they cannot mask a regression. Every change here moves in the direction of more coverage, and any residual platform-specific failure will surface as a red CI job rather than silent breakage.

@Jarred-Sumner
Jarred-Sumner merged commit a7f516b into main Jul 11, 2026
2 of 4 checks passed
@Jarred-Sumner
Jarred-Sumner deleted the claude/expectations-honor-kind branch July 11, 2026 04:54
robobun added a commit that referenced this pull request Jul 16, 2026
#33952 rewrote the expectations.txt policy: quarantining drops the whole
file from the run, so the entry must either name a file that cannot run at
all or carry its coverage elsewhere. test-crypto-dh.js can run; it fails on
one verifyError === 0 assert that cannot be skipped without editing a
verbatim upstream mirror. Port its two-party exchange and
setPublicKey/setPrivateKey round-trip into node-crypto.test.js so the
quarantine does not silently drop that coverage, and reword the entry to
spell that out.
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.

2 participants