bun test --parallel: send coverage and test results to the coordinator as data, not rendered LCOV/XML

Merged
JA
2mo ago
+1157-1438

What

bun test --parallel workers used to render their own LCOV text and JUnit XML fragments, and the coordinator re-parsed them to merge (line-splitting LCOV and summing DA:/max-ing FNH:, scraping tests=/failures= attributes out of XML). This replaces that with: the child sends the underlying data as binary frames, the parent merges it and runs the one set of writers the serial path already uses.

  • Coverage — the unit is code_coverage::Report (per file: executable/executed line bitsets, line hits, function and basic-block byte ranges + executed bits). Workers encode it with code_coverage::wire (one CoverageFile frame per file). The coordinator folds them per path with MergedReport (hits summed, executed unioned, functions/blocks unioned by byte range, executable lines by the #39930 rule) and prints through print_coverage_reports() — the same function the serial --coverage path now calls. No text/lcov writer in aggregate.rs any more.
  • JUnit — the unit is TestCaseReport (file, describe path, name, status, assertions, duration, line, captured TestFailure). Serial hands it to JunitReporter::record_test_case; a worker appends it to its TestDone frame; the coordinator buffers per file and replays them in file order into its own JunitReporter. Workers never construct a JunitReporter and no XML crosses IPC.

aggregate.rs goes from 441 lines to ~60. Net −200 lines overall.

Behaviour changes

  • Fixes #40586: function coverage is unioned across workers by byte range, so % Funcs/FNH no longer under-report when different workers execute different functions of a file (supersedes #40590 without synthesising FN:/FNDA: names).
  • --parallel --reporter=junit now includes line= attributes and nested describe suites exactly as a serial run does (previously workers had no line numbers). New test asserts the parallel document equals the serial one modulo time/hostname.
  • A file whose worker crashed keeps the test cases it reported before the crash in the JUnit document, plus the synthetic (worker crashed) failure.
  • Text reporter: the last uncovered line range of a file was never printed in Uncovered Line #s (serial and parallel-after-this-change shared that writer); fixed, one snapshot updated.
  • coverageThreshold is now enforced with the lcov-only reporter outside --parallel too (docs previously called this out as unenforced; --parallel already enforced it). Docs updated.
  • --parallel --reporter=junit with zero recorded tests writes no file, matching serial (previously wrote an empty <testsuites>).

Tests

  • test/cli/test/coverage.test.ts: new --parallel merges function coverage across workers (two files rendezvous at import so they must run in different workers; fails on 1.4.0 with FNH:1).
  • test/cli/test/parallel.test.ts: new --parallel --reporter=junit writes the same document as a serial run; threshold test now covers serial + parallel × text + lcov.
  • Existing coverage.test.ts, parallel.test.ts, test/js/junit-reporter/junit.test.js, regression/issue/26851 pass on the debug build.