From 334f36ce25d5d5a606a16710490809db7bacad0b Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 5 Jul 2026 18:09:59 +0000 Subject: [PATCH] test(punktfunk1): serialize in-process-host tests (shared admission table) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reconnect-preempt (b53710d, preempt_same_identity) reads the process-global admission table and signals same-identity live sessions. The three in-process-host tests each bind a fixed loopback port and share that ONE table, so running them concurrently let one test's connection preempt + close another's live session — an intermittent `next_au: Closed` in c_abi_connection_roundtrip (surfaced under full-workspace load; a lucky pass hid it at b53710d). Serialize them on a poison-tolerant lock. Test-isolation only — in production a host is one process with unique client certs, so same-identity preempt is correct. Full workspace `cargo test` now green (18 suites, 3× clean). Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/punktfunk-host/src/punktfunk1.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/punktfunk-host/src/punktfunk1.rs b/crates/punktfunk-host/src/punktfunk1.rs index 88a3460..b320cf8 100644 --- a/crates/punktfunk-host/src/punktfunk1.rs +++ b/crates/punktfunk-host/src/punktfunk1.rs @@ -3982,10 +3982,18 @@ mod tests { /// End-to-end through the C ABI — the exact contract platform clients (Swift) link: /// in-process punktfunk/1 host, `punktfunk_connect` (TOFU → pinned reconnect) → /// `punktfunk_connection_next_au` pulls verified frames → `punktfunk_connection_send_input` + /// In-process-host tests each spin up a host on a fixed loopback port and share the process-global + /// admission table, so they must NOT run concurrently: a same-identity connection in one test would + /// fire the reconnect-preempt (`preempt_same_identity`) against another test's live session and + /// close it. Serialize them on this lock. Poison-tolerant (`into_inner`) so a failing test doesn't + /// cascade a poison error into the others. + static SESSION_TEST_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); + /// enqueues → `punktfunk_connection_close`. Three sequential sessions against ONE host /// process prove the persistent listener, and a wrong pin is rejected. #[test] fn c_abi_connection_roundtrip() { + let _serial = SESSION_TEST_LOCK.lock().unwrap_or_else(|p| p.into_inner()); use punktfunk_core::abi::{ punktfunk_connect, punktfunk_connection_close, punktfunk_connection_mode, punktfunk_connection_send_input, @@ -4174,6 +4182,7 @@ mod tests { /// admitted to a session with no PIN and no reconnect. #[test] fn delegated_approval_admits_after_knock() { + let _serial = SESSION_TEST_LOCK.lock().unwrap_or_else(|p| p.into_inner()); use punktfunk_core::client::NativeClient; use punktfunk_core::quic::endpoint; @@ -4285,6 +4294,7 @@ mod tests { /// identity gets a session on a pairing-required host; an anonymous client does not. #[test] fn pairing_ceremony_and_gate() { + let _serial = SESSION_TEST_LOCK.lock().unwrap_or_else(|p| p.into_inner()); use punktfunk_core::client::NativeClient; use punktfunk_core::quic::endpoint;