Skip to content

fix(testability): restore deterministic parallel Rust tests and the rustfmt baseline (#1343) - #1404

Open
mblua wants to merge 5 commits into
mainfrom
fix/1343-deterministic-rust-baseline-r10
Open

mblua wants to merge 5 commits into
mainfrom
fix/1343-deterministic-rust-baseline-r10

Conversation

@mblua

@mblua mblua commented Aug 17, 2026 •

Copy link
Copy Markdown
Owner

Closes the prerequisite for #1329 AC13.

What this implements

Issue #1343 asks for two things: deterministic parallel Rust workspace tests, and the repository-wide rustfmt baseline. Both are delivered.

Deterministic isolation for cli_test_reset. The cross-process shared-state collision is fixed by a suite guard rather than by serialising the runner. ResetTestCoordinator holds { handle, owned, handle_open, wait_count, release_count, _not_send: PhantomData<Rc<()>> }; the Rc marker makes it !Send + !Sync, so ReleaseMutex can only run on the thread that owns the mutex, by construction rather than by convention. One parameterised constructor performs exactly one CreateMutexW, captures GetLastError in the immediately following statement, builds the guard with owned=false and handle_open=true before any wait, then performs exactly one WaitForSingleObject with a finite 120000 ms timeout. Ownership is taken only for WAIT_OBJECT_0 or WAIT_ABANDONED; every other result closes the handle. complete() releases at most once, closes, preserves both the primary and the secondary error, and leaves both flags false so Drop is a no-op on the normal path. Drop repeats the same cleanup best effort without panicking and emits AC1343_SUITE_CLEANUP_FAILED on failure. The ten active Windows tests acquire the suite first and complete last.

Deterministic Windows regression coverage for the five behaviours the issue names, against the real Win32 primitives and not only against injected adapters:

behaviour where
acquisition reset_mutex_cross_process, reset_test_coordinator_private_handoff
bounded contention and timeout timeout child in reset_test_coordinator_private_handoff, reset_mutex_timeout_closes_unowned_handle
owner abandonment reset_mutex_cross_process kills the holder and asserts the contender observes WAIT_ABANDONED
release complete() paths, reset_mutex_complete_preserves_primary_cleanup_error
successful retry acquire child after the parent releases without closing

The zero-depth probe runs its second acquirer on a fresh thread. A Windows mutex is reentrant for its owning thread, so without that the negative subcase could never produce WAIT_TIMEOUT: it would have passed green while testing nothing.

Repository-wide rustfmt baseline, restored in the parent commit 2c310e7e across exactly the five paths the issue lists, and verified here to hold across the whole workspace.

// SAFETY: proofs on every unsafe site: 8 in src-tauri/src/testability/reset.rs, including the unsafe extern "system" block, and 30 in src-tauri/tests/cli_test_reset.rs. The release and drop proofs state the same-thread ownership argument explicitly, because the !Send marker is what makes it hold. Both files also carry #![deny(clippy::undocumented_unsafe_blocks)]: the lint is allow-by-default, so without it the criterion would be satisfied once and unenforced afterwards, and unsafe site 39 could land uncommented with clippy -D warnings still green. The attribute is module-scoped, and it was measured before adoption: it produces findings only inside these two files and drags nothing else in the workspace red.

Test debt. windows::reset_test_coordinator_child is allowlisted. It is not deferred debt: it runs on every run as a spawned process, and it carries #[ignore] only so libtest does not also run it in-process, where it would contend for the same named mutex as its own parent.

src-tauri/Cargo.toml adds one line, "Win32_System_Pipes", to the existing windows-sys 0.59 feature array. No new dependency, no lockfile delta.

Scope: the delivery plan was cut back to the issue objective

The certified R10 delivery plan accumulated a large verification apparatus around this objective. The user cut it back to what the issue actually asks for. The TCB machinery, the attestation records, PreimplementationTrustAnchorV2, the systemd quarantine manager, the root-view owner/verifier/quarantine chain and the fourteen-role scripts/Invoke-BoundOnce.ps1 are discarded, not deferred, and none of them appears here in any form.

The decision and its three verified findings are recorded on the issue: #1343 (comment)

Verification

Every gate below was executed, not estimated. Toolchain cargo 1.97.1 (c980f4866 2026-06-30), Windows 11, ordinary parallel execution with no --test-threads override anywhere.

At this commit

gate command exit
B-fmt cargo fmt --manifest-path src-tauri/Cargo.toml --all -- --check 0, zero bytes of output
B-check cargo check --manifest-path src-tauri/Cargo.toml --workspace 0
B-clippy cargo clippy --manifest-path src-tauri/Cargo.toml --workspace --all-targets -- -D warnings 0
B-test cargo test --manifest-path src-tauri/Cargo.toml --workspace 0, 179s
B-debt npm run test:debt 0

B-test produced 57 target results, all ok, zero failures: src/lib.rs 3462 passed / 0 failed / 23 ignored, cli_test_reset 10 passed / 0 failed / 1 ignored, and both crates/ members green. B-debt reports 27 ignored Rust tests discovered, 27 allowlisted, 0 unallowlisted, with no stale entries.

The cargo fmt command above spans the whole root workspace, not only the five paths the issue enumerates. Verified with -v: it visits every crate root of all three members, src-tauri/build.rs and both session-bridge binaries included. A separate per-file sweep of all 228 tracked .rs files agrees.

At the unmodified A cut 4f69e6b3

Recorded as observed, in a clean dedicated worktree with a cold target directory.

gate exit note
A-fmt 1 76 hunks, confined to exactly the five paths the issue enumerates and no others
A-check 0
A-clippy 0
A-test 0 57 target results, all ok; src/lib.rs 3455 passed / 0 failed / 23 ignored

A-test passing is recorded as passing. The issue anticipates it: "Exact reruns at the A cut may pass depending on scheduling; no green run disproves the collision and no later-head failure may be relabelled as A evidence." No rerun was attempted to chase a red, and none is claimed. The historical cli_test_reset collision stays diagnostic evidence from a later head, never cut A.

The lint was measured before it was adopted

Adding #![deny(clippy::undocumented_unsafe_blocks)] produces findings only inside the two files that carry it: the first workspace-wide clippy run with the attribute in place emitted exactly 7 errors, all in reset.rs, and cited no other file. A negative control confirms it is live rather than decorative: removing one // SAFETY: comment from cli_test_reset.rs fails clippy with exactly one error naming line 1 as the lint level source.

The merge commit

main moved 66 commits since the A cut, and 9c7c77e5 (#1154) replaced tauri::Builder::default().any_thread() with agentscommander_lib::test_support::test_builder() in the same region of src-tauri/tests/pty_powershell_managed_native.rs that the formatter-only commit reformatted. main was merged in to resolve it, deliberately rather than rebased, so that 8415854e stays an ancestor and remains the reviewed prerequisite commit. The merge resolved exactly one conflict block by taking main's call and keeping the rustfmt-correct wrapping of the following .manage(...); every other file auto-merged.

Gate set re-run on the merged tree: check 0, clippy -D warnings 0, test --workspace 0 in 245s (57 target results all ok, src/lib.rs 3490 passed / 0 failed / 23 ignored, cli_test_reset 10 / 0 / 1), npm run test:debt 0.

cargo fmt --check on the merged tree exits 1, with 145 hunks across 26 files and zero in the five paths this issue covers. Every one of them is pre-existing drift inherited from main, and none is authored by this branch. The number reconciles exactly with an independent measurement at main 8f272a76: 221 hunks over 31 files, minus the 76 in the five baseline paths that this PR fixes. Clearing the other 145 is explicitly outside this issue's Scope, which says to apply rustfmt to the baseline files only, and it is recorded as input to #1401 instead. See below.

Not included

  • No CI cargo fmt --check gate. The repository has none today, so the restored baseline is currently protected by convention only. That is tracked separately rather than turned on inside this PR, because enabling it can redden branches already in flight.
  • One rustfmt deviation exists in crates/terminal-snapshot-renderer/tests/fixtures/diagnostic-failure-harness/failures.rs, a nested fixture crate that declares its own [workspace] and is therefore unreachable by cargo fmt --all. Its blob is unchanged since the A cut, so it is out of scope here.
  • auth::write_registry replaces its registry through ReplaceFileW and fails deterministically when the working-directory path is long enough, which makes the terminal-snapshot acceptance fixture fail to construct. Pre-existing, unrelated to this change, no CI reproduction, tracked separately.

mblua added 3 commits August 13, 2026 21:34
…st-debt entry

Prerequisite B for #1329 AC13. Parent is 2c310e7, the formatter-only and
cross-process-collision commit; this is a single fresh commit, not an amend and
not a reuse of the wip/1343-s1-scaffold preservation commit.

Scope note: the certified R10 delivery plan was cut back to the issue objective
by the user. The TCB machinery, the attestation records,
PreimplementationTrustAnchorV2, the systemd quarantine manager, the root views,
the fourteen roles and scripts/Invoke-BoundOnce.ps1 are discarded, not deferred,
and none of them appears here in any form. Rationale:
#1343 (comment)

Suite guard and Windows matrix (src-tauri/tests/cli_test_reset.rs):
- ResetTestCoordinator { handle, owned, handle_open, wait_count, release_count,
  _not_send: PhantomData<Rc<()>> }. The Rc marker makes the guard !Send + !Sync,
  so ReleaseMutex can only run on the owning thread by construction.
- One parameterised constructor: exactly one CreateMutexW, GetLastError captured
  in the immediately following statement, the guard built with owned=false and
  handle_open=true before any wait, then exactly one WaitForSingleObject with a
  finite 120000 ms timeout. Ownership only for WAIT_OBJECT_0 or WAIT_ABANDONED;
  any other result closes the handle.
- complete() performs at most one ReleaseMutex, closes, preserves the primary
  and secondary errors and leaves both flags false, so Drop is a no-op on the
  normal path. Drop repeats best effort without panicking and emits
  AC1343_SUITE_CLEANUP_FAILED on failure.
- The ten active Windows tests acquire the suite first and complete last.
- Zero-depth probe with both subcases differing only in the initial-owner flag.
  The second acquirer runs on a fresh thread: a Windows mutex is reentrant for
  its owning thread, so without that the negative subcase could never produce
  WAIT_TIMEOUT and would have passed green while testing nothing.

Private mutex, helper and protocol (src-tauri/tests/cli_test_reset.rs):
- reset_test_coordinator_private_handoff creates the nonce-named probe owned,
  runs the timeout child, validates and reaps it, releases without closing, runs
  the acquire child, validates and reaps it, and only then closes.
- Ignored helper windows::reset_test_coordinator_child, launched through
  canonicalize(current_exe()) with the exact argv --ignored --exact
  windows::reset_test_coordinator_child --nocapture --test-threads=1, env_clear
  and only the canonical tuple.
- Closed environment parser running before any Win32 call, rejecting case
  aliases, duplicates, unknown names, NUL, non-ASCII, absence and bad values.
- Child stdout asserted as the closed libtest envelope; child stderr reserved to
  exactly two AC1343_COORD_V1 records over a closed seventeen-key set.

Unsafe proofs (src-tauri/src/testability/reset.rs, src-tauri/tests/cli_test_reset.rs):
- Every unsafe site now carries a // SAFETY: proof: 8 in reset.rs, including the
  unsafe extern "system" block, and 30 in cli_test_reset.rs. The release and
  drop proofs state the same-thread ownership argument explicitly, since the
  !Send marker is what makes it hold.
- Each file also carries #![deny(clippy::undocumented_unsafe_blocks)]. Without
  it the criterion would be satisfied once and unenforced afterwards: the lint
  is allow-by-default, so unsafe site 39 could land uncommented with clippy
  -D warnings still green. The attribute is module-scoped and measured to affect
  only these two files.

Test debt (test-debt.allowlist.json):
- Allowlists windows::reset_test_coordinator_child. It is not deferred debt: it
  runs on every run as a spawned process and carries #[ignore] only so libtest
  does not also run it in-process, where it would contend for the same named
  mutex as its own parent.

src-tauri/Cargo.toml adds only "Win32_System_Pipes" to the existing windows-sys
0.59 feature array. No new dependency and no lockfile delta.
mblua added 2 commits August 17, 2026 13:58
Resolves the single conflict introduced by 9c7c77e (#1154), which replaced
tauri::Builder::default().any_thread() with
agentscommander_lib::test_support::test_builder() in the same region of
src-tauri/tests/pty_powershell_managed_native.rs that the #1343 formatter-only
commit reformatted.

Resolution takes main's test_builder() call and leaves
.manage(MasterToken::new(...)) on one line, which is what rustfmt produces now
that the shorter receiver fits. Nothing else in that file, and no other file,
was resolved by hand: everything else auto-merged.

8415854 remains the reviewed prerequisite commit for #1329 AC13. This merge
exists only to make the branch mergeable and does not change what was reviewed.
`RESET_PROCESS_MUTEX_NAME` was declared unconditionally but read only by
`platform_reset_mutex_wait_adapter`, which is `#[cfg(target_os = "windows")]`.
On any other target the constant is dead code, so `cargo clippy --all-targets
-- -D warnings` promotes the `dead_code` warning to an error and the job exits
101.

Introduced by 2c310e7, which added the reset mutex. It stayed invisible
because `rust-regression-linux` and `rust-regression-macos` did not exist in
`pr-regression-gates.yml` until #1154 added them; this branch only started
running them after merging main.

One attribute, no logic change. The Windows path that actually reads the
constant is unchanged.
@sonarqubecloud

Copy link
Copy Markdown

@mblua

mblua commented Oct 23, 2026

Copy link
Copy Markdown
Owner Author

Heads-up: the required checks on main changed (#3184, PR #3185).

The main ruleset now requires these checks instead of the old names:

  • rust-regression is now rust-regression-windows
  • windows-release-cli-smoke is now release-cli-smoke-windows
  • new: issue-1850-release-windows, issue-1850-release-linux, issue-1850-release-macos and rust-slow-test-windows

This branch still runs the old workflow, so those checks never report here and the PR cannot merge as it is.

What to do when this PR is ready to land: wait until PR #3185 is merged, then bring this branch up to date with main (the ruleset already requires that). The new workflow comes with it and reports the new check names. Resolve any conflict in .github/workflows/pr-regression-gates.yml in favour of main.

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.

1 participant