diff --git a/tests/nip46_e2e.rs b/tests/nip46_e2e.rs index 5e20139..c818e12 100644 --- a/tests/nip46_e2e.rs +++ b/tests/nip46_e2e.rs @@ -345,7 +345,13 @@ async fn nip46_client_handshake_and_sign_against_fake_amber() { // XDG_DATA_HOME is process-global and every test in this binary sets it, // so the lock is held for the WHOLE test: data_dir() re-reads the env on // every save, and a setup-only guard lets parallel tests cross-write. - let _vault_guard = VAULT_ENV_LOCK.lock().unwrap(); + let _vault_guard = VAULT_ENV_LOCK + .lock() + // Poison-tolerant on purpose: this lock only serializes the + // process-global XDG_DATA_HOME. A sibling test that panics while + // holding it must not cascade into PoisonError failures of every + // later test — one real failure should report as ONE failure. + .unwrap_or_else(|e| e.into_inner()); let app = { let tmp = std::env::temp_dir().join(format!("keynectr-e2e-{}", std::process::id())); // data_dir() is $XDG_DATA_HOME/keynectr — the isolation vault must @@ -615,7 +621,13 @@ async fn run_strict_amber( #[allow(clippy::await_holding_lock)] async fn nip46_bunker_connect_params_match_spec_against_strict_amber() { // Whole-body env lock: data_dir() re-reads XDG_DATA_HOME on every save. - let _vault_guard = VAULT_ENV_LOCK.lock().unwrap(); + let _vault_guard = VAULT_ENV_LOCK + .lock() + // Poison-tolerant on purpose: this lock only serializes the + // process-global XDG_DATA_HOME. A sibling test that panics while + // holding it must not cascade into PoisonError failures of every + // later test — one real failure should report as ONE failure. + .unwrap_or_else(|e| e.into_inner()); let app = { let tmp = std::env::temp_dir().join(format!("keynectr-e2e-strict-{}", std::process::id())); let app_dir = tmp.join("keynectr"); @@ -714,6 +726,16 @@ async fn nip46_bunker_connect_params_match_spec_against_strict_amber() { // network-visible profile (what other clients display as the name). // Exercises the real GUI "Publish name" path — Signing::External with // identity validation — against the strict signer. + // Point settings at the in-process relay FIRST: the default relay set is + // the real internet (damus + nostr.band, the latter a known-hanger), so + // leaving it made this assertion a network lottery — it failed whenever + // damus dawdled past the 6s send timeout. The QR test already does this; + // the strict test shipped without it. + { + let mut a = app.lock().await; + a.settings.relays = vec![keynectr::settings::RelayConfig::new(relay_url.clone())]; + a.save_settings().expect("save settings"); + } let (settings, signing) = { let guard = app.lock().await; ( @@ -917,7 +939,13 @@ async fn run_qr_pairing(connect_shape: &'static str) { // Isolated vault + pairing relay; the env lock is held for the whole // helper body (see above) so parallel tests cannot cross-write vaults. - let _vault_guard = VAULT_ENV_LOCK.lock().unwrap(); + let _vault_guard = VAULT_ENV_LOCK + .lock() + // Poison-tolerant on purpose: this lock only serializes the + // process-global XDG_DATA_HOME. A sibling test that panics while + // holding it must not cascade into PoisonError failures of every + // later test — one real failure should report as ONE failure. + .unwrap_or_else(|e| e.into_inner()); let app = { let tmp = std::env::temp_dir().join(format!( "keynectr-e2e-pair-{}-{}", @@ -1073,7 +1101,13 @@ async fn run_qr_pairing(connect_shape: &'static str) { #[tokio::test(flavor = "multi_thread", worker_threads = 4)] #[allow(clippy::await_holding_lock)] async fn nip46_session_restore_redials_and_refuses_wrong_identity() { - let _vault_guard = VAULT_ENV_LOCK.lock().unwrap(); + let _vault_guard = VAULT_ENV_LOCK + .lock() + // Poison-tolerant on purpose: this lock only serializes the + // process-global XDG_DATA_HOME. A sibling test that panics while + // holding it must not cascade into PoisonError failures of every + // later test — one real failure should report as ONE failure. + .unwrap_or_else(|e| e.into_inner()); let app = { let tmp = std::env::temp_dir().join(format!( "keynectr-e2e-restore-{}-{}",