from __future__ import annotations import os import threading import time from pathlib import Path import pytest from packetstation import cli, worker def test_version(capsys: pytest.CaptureFixture[str], monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setenv("PS_BUILD", "abc123") assert cli.main(["version"]) == 0 assert "build abc123" in capsys.readouterr().out def test_worker_healthcheck(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: beat = tmp_path / "beat" monkeypatch.setenv("WORKER_BEAT_FILE", str(beat)) assert cli.main(["healthcheck", "worker"]) == 1 worker.touch(beat) assert cli.main(["healthcheck", "worker"]) == 0 old = time.time() - 120 os.utime(beat, (old, old)) assert cli.main(["healthcheck", "worker"]) == 1 def test_app_healthcheck_down() -> None: # Nothing listens on 8000 in tests (or something unrelated does): either way not a crash assert cli.main(["healthcheck", "app"]) in (0, 1) def test_worker_loop_touches_and_stops(tmp_path: Path) -> None: beat = tmp_path / "sub" / "beat" stop = threading.Event() t = threading.Thread(target=worker.run, args=(beat, "t"), kwargs={"stop": stop, "interval": 0.05}) t.start() deadline = time.time() + 5 while not beat.exists() and time.time() < deadline: time.sleep(0.01) stop.set() t.join(5) assert beat.exists() and not t.is_alive() def test_migrate_reports_bad_secret( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] ) -> None: monkeypatch.setenv("PG_MIGRATE_PASSWORD_FILE", str(tmp_path / "missing")) assert cli.main(["migrate"]) == 2 assert "PG_MIGRATE_PASSWORD_FILE" in capsys.readouterr().err