from __future__ import annotations import os from pathlib import Path import pytest from k1link.device_plugins.xgrids_k1.archive import discover_legacy_viewer_sessions from k1link.sessions import ActiveSessionLease, recover_stale_active_session_marker from k1link.sessions import active as active_session_module def test_active_session_lease_hides_live_evidence_until_release(tmp_path: Path) -> None: sessions = tmp_path / "sessions" session = sessions / "20260717T011050Z_viewer_live" lease = ActiveSessionLease.acquire(sessions, session) try: session.mkdir() capture = session / "captures" / "mqtt_live" capture.mkdir(parents=True) (capture / "mqtt.raw.k1mqtt").write_bytes(b"K1MQTT\x00unfinished") candidates = discover_legacy_viewer_sessions(sessions) assert candidates == () assert recover_stale_active_session_marker(sessions) is False finally: lease.release() assert not (sessions / ".current_session").exists() candidates = discover_legacy_viewer_sessions(sessions) assert len(candidates) == 1 assert candidates[0].session_id == session.name assert candidates[0].replayable is False def test_startup_recovery_removes_only_an_unlocked_stale_marker(tmp_path: Path) -> None: sessions = tmp_path / "sessions" sessions.mkdir() marker = sessions / ".current_session" marker.write_text("20260717T011050Z_viewer_live\n", encoding="utf-8") assert recover_stale_active_session_marker(sessions) is True assert not marker.exists() assert recover_stale_active_session_marker(sessions) is False def test_active_session_release_retries_unlink_without_dropping_lock( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: sessions = tmp_path / "sessions" session = sessions / "20260812T231000Z_viewer_live" lease = ActiveSessionLease.acquire(sessions, session) marker = sessions / ".current_session" original_unlink = Path.unlink attempts = 0 def fail_once(path: Path, *args: object, **kwargs: object) -> None: nonlocal attempts if path == marker and attempts == 0: attempts += 1 raise OSError("injected marker unlink failure") original_unlink(path, *args, **kwargs) monkeypatch.setattr(Path, "unlink", fail_once) with pytest.raises(OSError, match="injected marker unlink failure"): lease.release() assert marker.exists() assert lease._released is False # noqa: SLF001 os.fstat(lease._descriptor) # noqa: SLF001 assert recover_stale_active_session_marker(sessions) is False lease.release() assert lease._released is True # noqa: SLF001 assert not marker.exists() def test_active_session_release_retries_directory_fsync_after_unlink( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: sessions = tmp_path / "sessions" session = sessions / "20260812T231100Z_viewer_live" lease = ActiveSessionLease.acquire(sessions, session) original_fsync = active_session_module._fsync_directory_strict attempts = 0 def fail_once(path: Path) -> None: nonlocal attempts if attempts == 0: attempts += 1 raise OSError("injected directory fsync failure") original_fsync(path) monkeypatch.setattr(active_session_module, "_fsync_directory_strict", fail_once) with pytest.raises(OSError, match="injected directory fsync failure"): lease.release() assert lease._marker_removed is True # noqa: SLF001 assert lease._released is False # noqa: SLF001 os.fstat(lease._descriptor) # noqa: SLF001 lease.release() lease.release() assert lease._released is True # noqa: SLF001