Files
deno/cli/ops
d1152a1bac fix(test): abort with a message when a test exits with sanitizeExit disabled (#34491)
## Summary

Follow-up to #22515 / fixes #22516.

Previously, when a test set `sanitizeExit: false`, we treated the exit
sanitizer as completely disabled — a test calling `Deno.exit()`
terminated the process immediately. Because the test reporter's
stdout/stderr is buffered and flushed asynchronously through a channel,
this could drop output and produce flaky test runs. #22515 had to
comment out a node-compat test (`should allow exit`) precisely because
of this unreliable flushing.

This PR makes the exit handler always present during tests, with
behavior depending on `sanitizeExit`:

- **`sanitizeExit: true` (default)** — unchanged. An exit attempt fails
the current test (and a non-zero exit code set during a test fails it
too), and the remaining tests keep running.
- **`sanitizeExit: false`** — instead of silently terminating the
process, the test run is **aborted with a message**. The worker hands
the exit code to the reporter, which prints a message, reliably flushes
all buffered output, and then exits the process with the requested code.

Example output:

```
running 2 tests from ./main.ts
exit ...
------- output -------
output before exit
----- output end -----

warning A test called Deno.exit(42) while the exit sanitizer was disabled (sanitizeExit: false). Aborting the test run.

The following tests were pending:

exit => ./main.ts:1:6
```

(process exits with code 42)

## Implementation

- New `op_test_event_exit` op sends a new `TestEvent::Exit(code)` to the
reporter (which forces a stdio sync/flush first), then parks the worker
so user code can't keep running while the process is torn down.
- `report_tests` handles `TestEvent::Exit` much like
`TestEvent::Sigint`: it reports the pending tests, flushes the report,
and exits the process with the given code. A `report_exit` method was
added to the `TestReporter` trait (pretty/dot/tap/junit/compound).
- `op_test_event_exit` is added to the `NOT_IMPORTED_OPS` allowlist in
`99_main.js` so it stays available on `Deno.core.ops` (where the other
`deno_test` ops live).

## Tests

- New spec test `test/exit_sanitizer_disabled` covering the
abort-with-message + reliable-flush behavior and exit code propagation.
- Re-enables the `should allow exit` node-compat test that #22515
disabled, updating its expected output and exit code (123).
- Verified the default `sanitizeExit: true` behavior
(`test/exit_sanitizer`) is unchanged.

Closes denoland/orchid#282

---------

Co-authored-by: divybot <divybot@users.noreply.github.com>
Co-authored-by: Divy Srivastava <me@littledivy.com>
2026-05-29 17:35:15 +05:30
..
…
2026-05-01 13:07:44 +02:00
…