Skip to content

test: eliminate Windows background-terminal process-test flakes in the full suite #304

Description

@yxr-2025

Problem

scripts/run-tests.mjs discovers every Node test file and passes all of them to one invocation:

node --test --experimental-strip-types <all .test.ts files>

Node executes test files concurrently by default. The background-terminals manager tests are different from ordinary unit tests: on Windows they create real process trees, invoke and await taskkill, observe settlement callbacks, poll descendant liveness, and clean up OS resources. When other test files are creating or terminating processes at the same time, Windows scheduling and process-tree cleanup become timing-sensitive.

This produces intermittent failures around the same 3.3-3.8 second teardown window even though the affected tests are stable in isolation.

Reproduction evidence

Observed on Windows with Node v24.12.0 and Bun 1.4.0:

  • Each affected test passes when run alone.
  • The three affected tests pass when run together.
  • The entire tests/extensions/background-terminals directory passes with --test-concurrency=1.
  • An unmodified bun run test reproduced the failure on the first run:
    • kill settles a never-exiting process... passed in about 3.32 s.
    • concurrent overlapping multi-id kills... failed in about 3.60 s.
    • taskkill terminates a Windows descendant process tree passed in about 3.62 s.
  • The exact three-test selection then passed 3/3 at about 3.25-3.30 s each.
  • Serial execution of the complete background-terminals directory passed: 89 passed, 4 skipped, 0 failed.

The failures only appear under full-suite cross-file concurrency. This rules out .gitattributes, line-ending policy, and the assertions in those three tests as the primary cause.

Why this harms the whole repository

This is a test-infrastructure reliability problem, not a local inconvenience:

  • False CI failures block unrelated changes. Any contributor can receive a red build even when their change does not touch background terminals or process management.
  • Flakes hide real regressions. Once rerunning CI becomes normal, developers cannot tell whether a process-lifecycle failure is infrastructure noise or a genuine runtime bug.
  • Debugging time is wasted in the wrong layer. The failure points at settlement, kill, or descendant assertions, encouraging investigation of production code and test assertions even though the trigger is suite-level scheduling.
  • Windows contributors pay a disproportionate cost. The affected path uses real Windows process-tree semantics and taskkill /T, so the default full-suite topology makes their development loop less trustworthy.
  • Release and prepublish validation become unreliable. prepublishOnly depends on bun run test; an intermittent infrastructure failure can delay or discourage releases.
  • Failed runs can take much longer to settle. In one reproduction the Node test process stopped producing output after the failure and required interruption, increasing the cost beyond a simple retry.

A green test suite must mean the code passed, and a red suite must provide actionable evidence. The current behavior violates that contract.

Proposed direction

Keep ordinary Node test files parallel, but isolate the real-process Windows tests from cross-file contention. Possible implementations include:

  1. Run the background-terminals real-process test group in a separate serial Node invocation, while keeping the rest of the suite parallel.
  2. Add a Windows-specific concurrency policy in scripts/run-tests.mjs if a narrower grouping is not practical.
  3. Split OS-process integration tests from fast unit tests so the runner can apply concurrency deliberately instead of globally.

The narrowest option that preserves fast parallel execution for unrelated tests is preferable. The fix should live in test infrastructure rather than weakening teardown bounds or adding retries to the assertions, because those changes would mask the scheduling problem.

Acceptance criteria

  • Repeated full bun run test runs on Windows do not intermittently fail the affected process-lifecycle tests.
  • The real-process background-terminals tests do not overlap with unrelated Node test files in a way that changes their settlement or descendant-cleanup timing.
  • Existing teardown bounds and behavioral assertions remain intact.
  • Non-Windows and ordinary unit-test parallelism is preserved where practical.
  • The test-runner policy is covered by a focused test or documented clearly enough to prevent accidental regression.

Expected result

After this is fixed, contributors should get deterministic local and CI results, process-lifecycle failures should become trustworthy signals again, Windows validation should stop penalizing unrelated changes, and releases should no longer depend on retrying a flaky full-suite run. The repository keeps the speed benefit of parallel tests without sacrificing correctness for the small subset that exercises real OS process trees.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions