test(desktop): serialize archive tests against the egress registry

The merge unites main's identity-archive tests, which transitively admit
an owner-identity egress lease through submit_event/signing_keys, with
this branch's owner_identity_egress tests, which latch the process-global
registry into Draining/Indeterminate. Neither parent had both test sets.

The archive tests serialized only on the rate-limit TEST_SERIAL, not the
EGRESS_REGISTRY_TEST_LOCK the egress tests use, so a concurrent egress
test's drain window leaked in and refused the signer — a reproducible
"owner-identity egress is draining" / empty-snapshot failure under the
full parallel lib run, passing in isolation.

Hold EGRESS_REGISTRY_TEST_LOCK and reset the registry in the three
egress-touching archive tests, matching the module's own guard idiom and
the TEST_SERIAL-first lock order of the egress admission tests.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
Duncan
2026-08-19 16:51:11 -04:00
parent eeca9e78ca
commit 557c05645f

View File

@@ -649,12 +649,22 @@ mod tests {
/// RED-on-revert: restore `fetch_archived_pubkeys` to read the override for
/// each leg (`fetch_relay_self` + `query_relay`) and this returns B's pubkey.
#[tokio::test]
#[allow(clippy::await_holding_lock)] // EGRESS_REGISTRY_TEST_LOCK serialises parallel tests
async fn archived_fetch_never_crosses_relays_mid_flight() {
use crate::app_state::build_app_state;
use crate::relay_admission::{reset_rate_limit_gate, TEST_SERIAL};
use axum::{routing::get, routing::post, Json, Router};
let _serial = TEST_SERIAL.lock().await;
// The archive fetch signs through `signing_keys`, gated by the
// process-global egress registry, so serialise against it too — not
// just the rate-limit `TEST_SERIAL`. Without this a concurrent egress
// test's `Draining`/`Indeterminate` window leaks in and refuses the
// signer. Order matches the egress admission tests: TEST_SERIAL first.
let _egress_guard = crate::owner_identity_egress::EGRESS_REGISTRY_TEST_LOCK
.lock()
.unwrap_or_else(|e| e.into_inner());
crate::owner_identity_egress::reset_registry_for_test();
reset_rate_limit_gate();
// Build a loopback relay that advertises `relay_keys` as its NIP-11
@@ -764,11 +774,21 @@ mod tests {
/// this pins the archive command's callback independently of unarchive.
#[cfg(not(target_os = "windows"))]
#[tokio::test]
#[allow(clippy::await_holding_lock)] // EGRESS_REGISTRY_TEST_LOCK serialises parallel tests
async fn archive_core_fires_regen_only_on_accepted_submit() {
use crate::app_state::build_app_state;
use crate::relay_admission::{reset_rate_limit_gate, TEST_SERIAL};
let _serial = TEST_SERIAL.lock().await;
// The submit path admits an owner-identity egress lease, gated by the
// process-global egress registry, so serialise against it too — not
// just the rate-limit `TEST_SERIAL`. Without this a concurrent egress
// test's `Draining`/`Indeterminate` window leaks in and refuses the
// submit. Order matches the egress admission tests: TEST_SERIAL first.
let _egress_guard = crate::owner_identity_egress::EGRESS_REGISTRY_TEST_LOCK
.lock()
.unwrap_or_else(|e| e.into_inner());
crate::owner_identity_egress::reset_registry_for_test();
reset_rate_limit_gate();
let state = build_app_state();
@@ -814,11 +834,21 @@ mod tests {
/// independently, not just the shared `submit_then_regenerate`.
#[cfg(not(target_os = "windows"))]
#[tokio::test]
#[allow(clippy::await_holding_lock)] // EGRESS_REGISTRY_TEST_LOCK serialises parallel tests
async fn unarchive_core_fires_regen_only_on_accepted_submit() {
use crate::app_state::build_app_state;
use crate::relay_admission::{reset_rate_limit_gate, TEST_SERIAL};
let _serial = TEST_SERIAL.lock().await;
// The submit path admits an owner-identity egress lease, gated by the
// process-global egress registry, so serialise against it too — not
// just the rate-limit `TEST_SERIAL`. Without this a concurrent egress
// test's `Draining`/`Indeterminate` window leaks in and refuses the
// submit. Order matches the egress admission tests: TEST_SERIAL first.
let _egress_guard = crate::owner_identity_egress::EGRESS_REGISTRY_TEST_LOCK
.lock()
.unwrap_or_else(|e| e.into_inner());
crate::owner_identity_egress::reset_registry_for_test();
reset_rate_limit_gate();
let state = build_app_state();