"""AZ-328 — ``FilelockFileLockFactory`` real-filelock smoke tests.""" from __future__ import annotations from pathlib import Path import pytest from gps_denied_onboard.components.c12_operator_tooling import ( FilelockFileLockFactory, LockTimeout, ) class TestFilelockFileLockFactory: def test_acquire_and_release(self, tmp_path: Path) -> None: factory = FilelockFileLockFactory() lock_path = tmp_path / ".c12.lock" with factory.try_lock(lock_path, timeout_s=1.0): # Re-acquire from the same process with a tight timeout — # filelock is reentrant by holder process, so this MAY succeed # without raising; what we care about is that the basic # acquire/release contract works. assert lock_path.exists() # Lock file may persist on POSIX (it's the rendezvous file) # but it should now be released and re-acquirable. with factory.try_lock(lock_path, timeout_s=1.0): pass def test_concurrent_lock_raises_lock_timeout(self, tmp_path: Path) -> None: # filelock IS process-aware, so two SEPARATE FileLock objects # against the same path from the same process WILL contend on # POSIX — verify the timeout path raises our LockTimeout. from filelock import FileLock as RealFileLock lock_path = tmp_path / ".c12.lock" held = RealFileLock(str(lock_path)) held.acquire(timeout=1.0) try: factory = FilelockFileLockFactory() with pytest.raises(LockTimeout) as exc_info: # Tight timeout — the held lock must NOT be released by # this assertion path or the test loses meaning. with factory.try_lock(lock_path, timeout_s=0.05): pass # pragma: no cover assert exc_info.value.path == lock_path assert exc_info.value.timeout_s == 0.05 finally: held.release() def test_creates_parent_directory(self, tmp_path: Path) -> None: factory = FilelockFileLockFactory() nested = tmp_path / "nested" / "deeper" / ".c12.lock" with factory.try_lock(nested, timeout_s=1.0): assert nested.parent.is_dir()