ui_test_lock.rs 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839
  1. //! Process-global lock serializing the two Playwright UI test suites (the
  2. //! web dashboard's `ui_playwright_checks` and the report viewer's
  3. //! `report_playwright_checks`). Both launch a chromium instance via deno;
  4. //! running them concurrently on the same machine flakes (browser
  5. //! contention), so `make check` serializes them through this guard.
  6. //!
  7. //! The guard is acquired inside `spawn_blocking` closures (blocking
  8. //! context, no await held) — see the callers in `web/tests.rs` and
  9. //! `report/ui_tests.rs`.
  10. #![cfg(test)]
  11. use std::sync::{Mutex, MutexGuard, PoisonError};
  12. pub static PLAYWRIGHT_LOCK: Mutex<()> = Mutex::new(());
  13. /// Serializes the tests that change the process cwd (`set_current_dir`) with
  14. /// the tests that read cwd-relative state (`./config.toml`, the recipe search
  15. /// order). Cargo runs test functions in parallel threads of one process, so a
  16. /// chdir in one test would otherwise re-point the others mid-flight. A tokio
  17. /// mutex (not std) because the holders await their HTTP round-trips.
  18. fn cwd_mutex() -> &'static tokio::sync::Mutex<()> {
  19. static LOCK: std::sync::OnceLock<tokio::sync::Mutex<()>> = std::sync::OnceLock::new();
  20. LOCK.get_or_init(|| tokio::sync::Mutex::new(()))
  21. }
  22. /// Acquire the cwd lock; held until the guard is dropped.
  23. pub async fn cwd_guard() -> tokio::sync::MutexGuard<'static, ()> {
  24. cwd_mutex().lock().await
  25. }
  26. /// Acquire the Playwright session lock; held until the guard is dropped.
  27. /// Tolerates a poisoned lock (a panicked holder) — the browser is the
  28. /// shared resource, not the lock's payload.
  29. pub fn playwright_session() -> MutexGuard<'static, ()> {
  30. PLAYWRIGHT_LOCK
  31. .lock()
  32. .unwrap_or_else(PoisonError::into_inner)
  33. }