Conversation
…tests configure_tracing_for_turmoil installs a global tracing subscriber under a Once and unwraps the result. builtin_schema_migration_tests.rs also holds hydration_history_forced_migration_policy, an #[mz_ore::test], whose attribute installs a global subscriber through mz_ore::test::init_logging. Under `cargo test`, which runs a module's tests in one process, whichever runs first wins: when the mz_ore test goes first, the turmoil helper's set_global_default fails, the unwrap panics, and the Once is poisoned, so every turmoil test after it fails with "Once instance has previously been poisoned" and test_builtin_schema_migration fails with SetGlobalDefaultError. CI does not see this because nextest gives each test its own process, which is also why the module passed locally when each test was run alone by full path. Keep an already-installed subscriber instead of unwrapping. It writes to the test writer too, so the turmoil output still lands with the test; only the simulated-time formatting is lost in that ordering. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
QA LLM Review1. MEDIUM -- Only one half of the subscriber race is fixed; the other half poisons mz_ore's shared
|
…nicking mz_ore::test::init_logging_default installs its subscriber with FmtSubscriber::builder().init(), which is try_init().expect(...): it panics when a global default is already set. It runs inside LOG_INIT, a single process-wide Once shared by every #[mz_ore::test] in a binary, so that panic poisons LOG_INIT and every #[mz_ore::test] that has not run yet fails with "Once instance has previously been poisoned". The previous commit made the turmoil migration tests tolerate an mz_ore-installed subscriber. This is the other ordering: when a turmoil test installs its subscriber first, the next #[mz_ore::test] to start panics here. Which order happens is decided by libtest's parallel start, not its sort order, so both halves are needed. Use try_init and keep whatever subscriber is installed. It also writes to the test writer, so nothing is lost. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Agreed, and verified: in tracing-subscriber 0.3.23 Verification with both commits, against a warm target dir:
Left as they are: the unwrapped |
Motivation
cargo test -p mz-adapter --lib -- builtin_schema_migrationfails onmainwhen the module's tests share a process, which iscargo test's default:Two initializers install a global tracing subscriber and neither tolerates the other.
configure_tracing_for_turmoilinbuiltin_schema_migration_tests.rsunwrapsset_global_default.mz_ore::test::init_logging_default, which every#[mz_ore::test]calls, ends inFmtSubscriber::builder().init(), and in tracing-subscriber 0.3.23 that istry_init().expect("Unable to install global subscriber"). Both run under aOnce, so whichever loses the race panics and poisons itsOnce: the turmoil one for every turmoil test after it,mz_ore'sLOG_INITfor every#[mz_ore::test]in the binary that has not run yet. Which one loses is decided by libtest's parallel start of the first few tests, not by sort order. CI never sees any of this because nextest gives each test its own process, which is also why every test in the module passes when run alone.Found while verifying #38917. The review comment on the first version of this PR pointed out that fixing only the turmoil side leaves the larger half.
Description
Two commits, one per initializer.
configure_tracing_for_turmoilkeeps an already-installed subscriber instead of unwrapping. Only the simulated-time formatting is lost in that ordering; themz_oresubscriber also writes to the test writer.mz_ore::test::init_logging_defaultusestry_init()and ignores the error, so it can no longer poisonLOG_INIT. Its doc comment now says so. This covers every binary that mixes#[mz_ore::test]with a test that installs its own subscriber.Two other unwrapped
set_global_defaultcalls remain, insrc/cluster/src/communication.rs(#[cfg(test)]) andsrc/service/tests/transport.rs. With themz_orechange they can no longer be poisoned bymz_ore; they can still panic themselves ifmz_orewins, and they are left as they are here because neither currently shares a process with an#[mz_ore::test]that has bitten.Verification
See the comment below for the runs:
cargo test -p mz-ore --lib, the migration module in one process repeated ten times (was 2 of 4 failing before the first commit, and the reviewer measured 13 of 60 runs failing with only the first commit), andcargo clippy -p mz-ore --tests -D warnings.cargo fmtclean.🤖 Generated with Claude Code