From f4d3244eb93d9c5cbc52193c94922c2efb5fa95c Mon Sep 17 00:00:00 2001 From: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Date: Wed, 7 Oct 2026 06:53:53 -0400 Subject: [PATCH] test(relay): run startup_steps, telemetry and config tests in CI The new startup_steps::tests and the telemetry/config log-capture tests ran in no CI lane: just test-unit selects buzz-relay lib tests by module and none of these modules were listed. Add them to the infra-free relay stanza (anchoring ^config:: so it does not also pick up nip_fi_config) and mirror them in scripts/run-tests.sh, single-threaded for the two env-mutating modules because libtest shares one process. Also correct the tracing_dispatch_lock doc: the thread_window failure Postgres test installs a dispatcher without the lock too. Signed-off-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> --- Justfile | 6 +++++- crates/buzz-relay/src/test_support.rs | 5 +++-- scripts/run-tests.sh | 13 +++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Justfile b/Justfile index ca84a49590..bd45b1cc07 100644 --- a/Justfile +++ b/Justfile @@ -481,8 +481,12 @@ test-unit: # (JWKS source + refresh-loop composition), which `--lib` cannot reach # because they live in the binary target; the nested # `tests::postgres_tests::` stays in the PostgreSQL lane. + # The fourth clause adds the startup step timers (startup_steps) and the + # env- and log-capture tests in telemetry and config. All three modules + # are infra-free; config parses env into a struct and never connects. + # `^config::` is anchored so it does not also select nip_fi_config. cargo nextest run -p buzz-relay --lib --bin buzz-relay \ - -E 'test(/^api::admin::/) + test(/^handlers::channel_authz::/) + test(/^handlers::moderation_authz::/) + test(/^handlers::side_effects::tests::/) + test(/^storage_sweep::tests::/) + test(/^nip_fi_core::tests::/) + test(/^nip_fi_http::tests::/) + test(/^nip_fi_config::tests::/) + test(/^readiness::tests::/) + test(/^router::tests::/) + test(/^api::parse_query_tests::/) + test(/^api::git::transport::off_mode_precedence_tests::/) + test(/^audio::join::tests::/) + test(/^audio::handler::tests::/) + test(/^nip_fi_gate::tests::/) + test(/^nip_fi_session::tests::/) + test(/^nip_fi_shadow::tests::/) + test(/^nip_fi_shadow_session::tests::/) + test(=state::tests::neither_a_confirmed_inactive_community_nor_a_failed_lookup_admits_the_socket) + test(=handlers::req::tests::timed_out_historical_read_deregisters_before_closed) + test(=handlers::req::tests::superseded_timeout_leaves_replacement_intact) + test(=handlers::req::tests::search_claim_retires_live_and_yields_to_replacement) + test(=handlers::req::tests::concurrent_claims_and_stale_teardowns_keep_the_last_owner) + test(=handlers::req::tests::timeout_closed_is_emitted_before_a_replacement_can_claim) + test(=handlers::req::tests::revoke_then_replacement_keeps_replacement_whole) + test(=handlers::req::tests::claims_after_connection_cleanup_are_refused) + test(=handlers::req::tests::dropped_terminal_frame_cancels_connection) + test(=handlers::req::tests::revoke_dropped_terminal_frame_cancels_connection) + (kind(bin) & (test(/^tests::/) + test(/^composition_tests::/) + test(/^env_filter_tests::/)) - test(/^tests::postgres_tests::/))' + -E 'test(/^api::admin::/) + test(/^handlers::channel_authz::/) + test(/^handlers::moderation_authz::/) + test(/^handlers::side_effects::tests::/) + test(/^storage_sweep::tests::/) + test(/^nip_fi_core::tests::/) + test(/^nip_fi_http::tests::/) + test(/^nip_fi_config::tests::/) + test(/^readiness::tests::/) + test(/^router::tests::/) + test(/^api::parse_query_tests::/) + test(/^api::git::transport::off_mode_precedence_tests::/) + test(/^audio::join::tests::/) + test(/^audio::handler::tests::/) + test(/^nip_fi_gate::tests::/) + test(/^nip_fi_session::tests::/) + test(/^nip_fi_shadow::tests::/) + test(/^nip_fi_shadow_session::tests::/) + test(/^startup_steps::tests::/) + test(/^telemetry::tests::/) + test(/^config::tests::/) + test(=state::tests::neither_a_confirmed_inactive_community_nor_a_failed_lookup_admits_the_socket) + test(=handlers::req::tests::timed_out_historical_read_deregisters_before_closed) + test(=handlers::req::tests::superseded_timeout_leaves_replacement_intact) + test(=handlers::req::tests::search_claim_retires_live_and_yields_to_replacement) + test(=handlers::req::tests::concurrent_claims_and_stale_teardowns_keep_the_last_owner) + test(=handlers::req::tests::timeout_closed_is_emitted_before_a_replacement_can_claim) + test(=handlers::req::tests::revoke_then_replacement_keeps_replacement_whole) + test(=handlers::req::tests::claims_after_connection_cleanup_are_refused) + test(=handlers::req::tests::dropped_terminal_frame_cancels_connection) + test(=handlers::req::tests::revoke_dropped_terminal_frame_cancels_connection) + (kind(bin) & (test(/^tests::/) + test(/^composition_tests::/) + test(/^env_filter_tests::/)) - test(/^tests::postgres_tests::/))' # Note on audio::join::tests scope: the full suite is infra-free (no DB, # no Redis). The infra-free audio/FI regression witnesses — bootstrap # ordering barrier, CommitConfirmed arm, pending-close invisibility, diff --git a/crates/buzz-relay/src/test_support.rs b/crates/buzz-relay/src/test_support.rs index 2209bc21f0..b6d786de6f 100644 --- a/crates/buzz-relay/src/test_support.rs +++ b/crates/buzz-relay/src/test_support.rs @@ -6,8 +6,9 @@ const DEFAULT_DATABASE_URL: &str = "postgres://buzz:buzz_dev@localhost:5432/buzz /// process-wide from whichever dispatchers are live when it is first hit or /// rebuilt, so a parallel test's dispatcher (or a thread with none) can enable /// or disable another test's callsites. Not reentrant; take it once per test. -/// `router.rs`'s async otel-export test installs a dispatcher without it, -/// because the guard would be held across `.await`. +/// Two async tests install a dispatcher without it, because the guard would be +/// held across `.await`: `router.rs`'s otel-export test and +/// `api/bridge/thread_window/postgres_tests/failure_postgres_tests.rs`. pub(crate) fn tracing_dispatch_lock() -> std::sync::MutexGuard<'static, ()> { static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); LOCK.lock().unwrap_or_else(|poisoned| poisoned.into_inner()) diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index f89fb8c3ee..d4aa073dd8 100755 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -203,6 +203,19 @@ run_unit_tests() { run_test_step "buzz-relay NIP-FI shadow session tests" \ cargo test -p buzz-relay --lib nip_fi_shadow_session::tests:: -- --nocapture + run_test_step "buzz-relay startup step tests" \ + cargo test -p buzz-relay --lib startup_steps::tests:: -- --nocapture + + # telemetry and config tests mutate process env. libtest runs one process + # with many threads (nextest, used by `just test-unit`, isolates each test), + # so run them single-threaded here. `--skip` keeps the substring filter + # `config::tests::` from also selecting nip_fi_config, which runs above. + run_test_step "buzz-relay telemetry tests" \ + cargo test -p buzz-relay --lib telemetry::tests:: -- --test-threads=1 --nocapture + + run_test_step "buzz-relay config tests" \ + cargo test -p buzz-relay --lib config::tests:: -- --skip nip_fi_config:: --test-threads=1 --nocapture + # Mirror the NIP-FI (S3) stanza from `just test-unit`: module filters, then # each exact name. Keep this list in step with that stanza's `test(=...)`s. run_test_step "buzz-relay NIP-FI config tests" \