test(control_plane): fix flaky env-var data race in unit tests - #318
Merged
Merged
Conversation
…x flake control_plane unit tests mutate process-global env (ASAP_EDGE_FUSED, ASAP_AGENT_MEMORY_LIMIT_MIB, USE_TYPED_STAGE_SPLIT) via set_var/remove_var. cargo test runs #[test] fns in parallel threads in a single process, so the three previously-independent module-local mutexes did not serialize against each other: concurrent setenv/unsetenv calls (documented as unsound) raced, and env-reading tests (e.g. the mvp46_* routing assertions) transiently observed a writer's ASAP_EDGE_FUSED=1, yielding nondeterministic failures. Centralize a single crate-wide test_support::env_lock() mutex plus an RAII EnvVarGuard (set/unset on construct, restore prior value on drop) in lib.rs. Every unit test that reads or writes a process-global env var now serializes behind that one lock, regardless of module. Production code is unchanged; this is a test-hygiene fix. main.rs keeps its own guard (separate test binary, already internally consistent). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
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.
Summary
control_planeunit tests mutate process-global environment viastd::env::set_var/std::env::remove_var.cargo testruns#[test]/#[tokio::test]functions on parallel threads within a single process, so these mutations raced:replan::tests::TYPED_ENV_GUARD,emit::stage_config::tests::MEMORY_LIMIT_ENV_LOCK) did not serialize against each other. Concurrentsetenv/unsetenv(documented as unsound in a multithreaded program) raced on the one global environ table.mvp46_*routing-shape assertions) held no lock, so they could transiently observe a concurrent writer'sASAP_EDGE_FUSED=1and assert against the wrong (fused vs. routing) emit shape.Result: nondeterministic failures depending on thread scheduling (reproduced reliably: 6 / 2 / 4 random
mvp46_*failures across three full--libruns before the fix).The racy variables are
ASAP_EDGE_FUSED,ASAP_AGENT_MEMORY_LIMIT_MIB, andUSE_TYPED_STAGE_SPLIT(the originally-filedASAP_EDGE_FUSED-only framing was incomplete).Fix
#[cfg(test)] test_supportmodule inlib.rsexposing one sharedenv_lock()mutex plus an RAIIEnvVarGuard(set/unseton construct, restore the prior value on drop — panic-safe).emit/stage_config.rs,emit/mod.rs,emit/trait_def.rs,replan.rs). The three old per-module locks are removed.main.rskeeps its own guard (it is a separate test binary and is already internally consistent).No new dependency added (reuses the existing
static Mutexpattern the crate already used in three places, now unified into one).Test plan
cargo test -p control_plane --libx5 —769 passed; 0 failedevery run (was flaky before).cargo test -p control_plane(lib + bin) x3 —769+28passed, no failures.cargo build -p control_planeclean.cargo clippy -p control_plane --lib --tests— no new warnings from the changed files (pre-existing unused-import /vec_init_then_pushlints in untouched production code remain).🤖 Generated with Claude Code