fix(test-runner): make runs cancellable, deadlock-free, and bounded - #735
Open
beruro wants to merge 5 commits into
Open
fix(test-runner): make runs cancellable, deadlock-free, and bounded#735beruro wants to merge 5 commits into
beruro wants to merge 5 commits into
Conversation
beruro
marked this pull request as ready for review
August 7, 2026 14:23
beruro
force-pushed
the
junyu/fix-test-runner-lifecycle
branch
from
August 10, 2026 04:04
2efe460 to
668102e
Compare
beruro
force-pushed
the
junyu/fix-test-runner-lifecycle
branch
from
August 10, 2026 05:47
44ab60e to
4bb09b6
Compare
Pre-commit hook ran. Total eslint: 5, total circular: 0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Test runs in the WorkStation Testing tab could not actually be stopped, could deadlock while draining child output, and could grow memory without bound. The frontend stop action cleared UI state without signalling the backend, command and runner layers generated different run ids, cancellation was not observed by the child lifecycle, stdout and stderr were drained sequentially, and both streams accumulated into unbounded strings.
The test event wire shape also emitted snake_case variant fields while the frontend expects camelCase, so run_started could arrive without a usable runId.
Solution
The branch now uses one canonical run id from command registration through every event and summary, with a drop guard that always deregisters the run. Cancellation is backed by CancellationToken and terminates the process tree: Unix uses a dedicated process group with TERM, a bounded grace period, then KILL; Windows uses taskkill tree termination plus start_kill.
Stdout and stderr are drained concurrently in chunk-based tasks with a 16 MiB tail bound per stream and explicit truncation state. Cancelled runs emit run_cancelled and resolve with a partial summary marked cancelled. Per-variant camelCase serialization pins the frontend wire contract.
The frontend stop action now resolves the active run, invokes stop_tests, and updates state only after backend confirmation. Pure lifecycle transitions cover stale parallel-run events and no-op stop attempts.
Current develop is merged into the branch. Develop's relocation of the test-runner hook into the WorkStation module is preserved while retaining the lifecycle changes.
Potential risks
Rollback is a normal revert of this PR. It changes no persistence schema and requires no data recovery.
Verification
Merged current
developatb9331da7einto the branch in merge commit8ec95dbc9. GitHub now reports the PR as mergeable. Relative to currentdevelop, the PR remains 16 files with 1,138 additions and 148 deletions; the test-runner hook change follows its new WorkStation path.cargo test -p test_runnerfromsrc-tauri: 28/28 passed, including stderr-flood no-deadlock, bounded capture, process-group kill with grandchild verification, pre-cancelled token, canonical-id event ordering, wire-format pinning, and registry/RunGuard lifecycle coverage.cargo clippy -p test_runner --all-targets -- -D warningsfromsrc-tauri: passed with no warnings.pnpm vitest run src/services/test/__tests__/testRunLifecycle.test.ts: 11/11 passed.pnpm typecheck: passed.git diff --cached origin/develop --checkbefore the merge commit: passed.8ec95dbc9; Frontend, Rust, and attribution checks were queued/in progress at the time of this update.The merge commit used
--no-verifybecause lint-staged expands a merge index to hundreds of files imported fromdevelopand attempted to format unrelated base files. Those hook-generated edits were removed, the 16-file PR diff was revalidated, and the focused lint, typecheck, frontend tests, Rust tests, and Rust clippy commands above all passed.Effects: none added or modified (React
useEffectsurface untouched;useTestRunneronly re-typesstopTests).