From fd361fb35e35f860b1055dbc71941ec602c29e33 Mon Sep 17 00:00:00 2001 From: archipelago Date: Sun, 19 Jul 2026 02:01:58 -0400 Subject: [PATCH] test(update): serialize the apply_update regression tests Both tests take the global single-flight UPDATE_OP_LOCK; run concurrently by the test harness, one saw the other's lock and failed with 'another update operation is already running' instead of its expected refusal. A shared test mutex makes them mutually exclusive deterministically. Co-Authored-By: Claude Fable 5 --- core/archipelago/src/update.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/archipelago/src/update.rs b/core/archipelago/src/update.rs index c08476e5..3e6e22f3 100644 --- a/core/archipelago/src/update.rs +++ b/core/archipelago/src/update.rs @@ -2565,8 +2565,14 @@ mod tests { assert!(!persisted.update_in_progress); } + /// apply_update takes the global single-flight UPDATE_OP_LOCK, so tests + /// that call it must not run concurrently — one would see the other's + /// lock and fail with "another update operation is already running". + static APPLY_TEST_SERIAL: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(()); + #[tokio::test] async fn test_apply_refuses_unmarked_staging() { + let _serial = APPLY_TEST_SERIAL.lock().await; // Regression: .198 v1.7.103 bricking — apply ran against a staging // dir that a concurrent download was still filling. Without the // .download-complete marker, apply must refuse before touching @@ -2586,6 +2592,7 @@ mod tests { #[tokio::test] async fn test_apply_refuses_staged_bytes_that_mismatch_manifest() { + let _serial = APPLY_TEST_SERIAL.lock().await; // Marker present (a complete download once existed) but the staged // bytes no longer match the manifest — apply must re-verify and // refuse rather than install whatever is on disk.