From 4676b7e676c463c47cccfebb1500e4a96031b774 Mon Sep 17 00:00:00 2001 From: tanglearncode Date: Mon, 14 Sep 2026 09:58:58 +0800 Subject: [PATCH] Keep the parallel rounds running until the reader has called calls_from_another_thread_are_safe_during_setup_and_teardown failed once on aarch64-apple-darwin at reader.join().unwrap() > 0: the reader thread made no calls. A diagnostic run found no library cause. The reader takes no lock that the rounds hold, and 2000 mocked rounds never delayed it. On macOS the 200 local rounds take about 2 ms, while starting the reader took up to 4 ms, also with no mocking in the loop, so the stop flag was sometimes set first. It reproduced once in 40 coverage runs there. The test now keeps installing and restoring until the reader has called the function during the rounds, with a limit so a reader that never runs still fails. --- tests/parallel.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/parallel.rs b/tests/parallel.rs index bb45cf8..f695483 100644 --- a/tests/parallel.rs +++ b/tests/parallel.rs @@ -92,27 +92,37 @@ fn calls_from_another_thread_are_safe_during_setup_and_teardown() { session.restore(); } let stop = Arc::new(AtomicBool::new(false)); + let calls = Arc::new(AtomicUsize::new(0)); let reader = { let stop = Arc::clone(&stop); + let calls = Arc::clone(&calls); std::thread::spawn(move || { - let mut calls = 0u64; while !stop.load(Ordering::Relaxed) { // This thread holds no session, so it always sees the original. assert_eq!(value(41), 42); - calls += 1; + calls.fetch_add(1, Ordering::Relaxed); } - calls }) }; - for round in 0..200 { + // 200 local rounds take about 2 ms on macOS, and starting the reader thread can + // take longer there. Keep installing and restoring until the reader has called + // the function during the rounds, so the overlap this test checks always happens. + let calls_before_rounds = calls.load(Ordering::Relaxed); + let mut round = 0u64; + while round < 200 || calls.load(Ordering::Relaxed) == calls_before_rounds { + assert!( + round < 1_000_000, + "the reader thread never called the function while mocks were installed" + ); let mut session = Session::new(); let mock = mock!(session, value, fn(u64) -> u64); mock.expect().once().returns(round); assert_eq!(value(41), round); session.restore(); + round += 1; } stop.store(true, Ordering::Relaxed); - assert!(reader.join().unwrap() > 0); + reader.join().unwrap(); assert_eq!(value(41), 42); }