"""Unit tests for daemon PID file management.""" from __future__ import annotations import os from pathlib import Path import pytest from pyra.daemon.pid import PidFile, PidFileError, resolve_pid_path def test_write_creates_file(tmp_path: Path) -> None: p = PidFile(tmp_path / "daemon.pid") p.write() assert (tmp_path / "daemon.pid").exists() assert int((tmp_path / "daemon.pid").read_text().strip()) == os.getpid() def test_read_returns_none_when_absent(tmp_path: Path) -> None: p = PidFile(tmp_path / "daemon.pid") assert p.read() is None def test_read_returns_pid_when_present(tmp_path: Path) -> None: pid_file = tmp_path / "daemon.pid" pid_file.write_text("12345") p = PidFile(pid_file) assert p.read() == 12345 def test_read_returns_none_on_bad_content(tmp_path: Path) -> None: pid_file = tmp_path / "daemon.pid" pid_file.write_text("not-a-number") p = PidFile(pid_file) assert p.read() is None def test_is_stale_false_for_self(tmp_path: Path) -> None: p = PidFile(tmp_path / "daemon.pid") p.write() assert not p.is_stale() def test_is_stale_true_for_dead_pid(tmp_path: Path) -> None: pid_file = tmp_path / "daemon.pid" pid_file.write_text("999999999") # unrealistically large PID p = PidFile(pid_file) assert p.is_stale() def test_is_stale_false_when_file_absent(tmp_path: Path) -> None: p = PidFile(tmp_path / "daemon.pid") assert not p.is_stale() def test_remove_deletes_file(tmp_path: Path) -> None: p = PidFile(tmp_path / "daemon.pid") p.write() p.remove() assert not (tmp_path / "daemon.pid").exists() def test_remove_is_idempotent(tmp_path: Path) -> None: p = PidFile(tmp_path / "daemon.pid") p.remove() # must not raise def test_context_manager_writes_and_removes(tmp_path: Path) -> None: pid_file = tmp_path / "daemon.pid" p = PidFile(pid_file) with p: assert pid_file.exists() assert int(pid_file.read_text().strip()) == os.getpid() assert not pid_file.exists() def test_write_raises_when_live_pid_exists(tmp_path: Path) -> None: p = PidFile(tmp_path / "daemon.pid") p.write() # writes self PID (which is alive) p2 = PidFile(tmp_path / "daemon.pid") with pytest.raises(PidFileError): p2.write() def test_write_succeeds_over_stale_pid(tmp_path: Path) -> None: pid_file = tmp_path / "daemon.pid" pid_file.write_text("999999999") # stale p = PidFile(pid_file) p.write() # should not raise assert int(pid_file.read_text().strip()) == os.getpid() def test_resolve_pid_path_expands_tilde() -> None: result = resolve_pid_path("~/.pyra/daemon.pid") assert not str(result).startswith("~") assert result.is_absolute() def test_resolve_pid_path_absolute_unchanged(tmp_path: Path) -> None: path = tmp_path / "daemon.pid" result = resolve_pid_path(str(path)) assert result == path