tmux-amq/tests/test_cleanup.py
tegwick 92881b6b56
Some checks failed
tamq-ci / test (push) Failing after 6s
feat: add readable duplex messaging
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a03397-4d51-7fd1-8ff2-946eb22ea2bc
2026-08-25 19:26:27 +02:00

190 lines
6.1 KiB
Python

from pathlib import Path
import os
import socket
from tamq.cleanup import SHIM_MARKER, cleanup_runtime
from tamq.cli import main
from tamq.store import Store
class FakeManager:
def __init__(self, command_dir: Path):
self.command_dir = command_dir
self.identity = (42, "tmux-amq-42-test")
self.commands = []
def _existing_session_identity(self):
return self.identity
def _run(self, *args, check=True):
self.commands.append(args)
if args[0] == "show-options":
return str(self.command_dir)
if args[0] == "kill-session":
self.identity = None
return ""
def configure_paths(tmp_path, monkeypatch):
state = tmp_path / "state"
runtime = tmp_path / "runtime"
runtime.mkdir()
monkeypatch.setenv("TAMQ_STATE_DIR", str(state))
monkeypatch.setenv("XDG_RUNTIME_DIR", str(runtime))
monkeypatch.setenv("TAMQ_SOCKET", str(runtime / "tamq.sock"))
monkeypatch.setenv("TMUX_TMPDIR", str(tmp_path / "tmux"))
return state, runtime
def test_cleanup_is_dry_run_then_removes_only_owned_runtime(
tmp_path, monkeypatch
):
state, runtime = configure_paths(tmp_path, monkeypatch)
command_dir = state / "commands" / "tamq"
command_dir.mkdir(parents=True)
generated = command_dir / "To:audit-core:"
generated.write_text(f"#!/bin/sh\n{SHIM_MARKER}\n", encoding="utf-8")
unrelated = command_dir / "keep-me"
unrelated.write_text("operator file\n", encoding="utf-8")
binary = command_dir / "binary"
binary.write_bytes(b"\xff\x00\x80")
for name in ("tamq.sock", "tamq.pid", "tamq.lock"):
(runtime / name).write_text("stale\n", encoding="utf-8")
tmux_socket_dir = tmp_path / "tmux" / f"tmux-{os.getuid()}"
tmux_socket_dir.mkdir(parents=True)
stale_tmux_socket = tmux_socket_dir / "tamq-old-test"
socket_handle = socket.socket(socket.AF_UNIX)
socket_handle.bind(str(stale_tmux_socket))
socket_handle.close()
live_tmux_socket = tmux_socket_dir / "tamq-live-test"
live_socket_handle = socket.socket(socket.AF_UNIX)
live_socket_handle.bind(str(live_tmux_socket))
live_socket_handle.listen()
store = Store(state / "tamq.sqlite3")
message_id = store.add("a", "b", "preserve me")
store.register_endpoint("ep", 42, "tamq", ["a", "b"])
assert store.claim(message_id, "ep") is not None
store.close()
manager = FakeManager(command_dir)
async def not_running():
return False
monkeypatch.setattr("tamq.cleanup.ping", not_running)
stopped = []
dry_run = cleanup_runtime(
apply=False,
manager=manager,
stop_service=lambda: stopped.append(True),
)
assert dry_run["managed_session"] is True
assert dry_run["active_endpoints"] == 1
assert dry_run["leases"] == 1
assert dry_run["history_preserved"] == 1
assert dry_run["stale_tmux_socket_count"] == 1
assert generated.exists()
assert (runtime / "tamq.sock").exists()
assert stale_tmux_socket.exists()
assert manager.identity is not None
applied = cleanup_runtime(
apply=True,
manager=manager,
stop_service=lambda: stopped.append(True),
)
assert applied["errors"] == []
assert stopped == []
assert manager.identity is None
assert not generated.exists()
assert unrelated.exists()
assert binary.exists()
assert not any((runtime / name).exists() for name in ("tamq.sock", "tamq.pid", "tamq.lock"))
assert not stale_tmux_socket.exists()
assert live_tmux_socket.exists()
reopened = Store(state / "tamq.sqlite3")
assert len(reopened.list()) == 1
assert reopened.endpoints() == []
assert reopened.db.execute("SELECT COUNT(*) FROM leases").fetchone()[0] == 0
reopened.close()
repeated = cleanup_runtime(
apply=True,
manager=manager,
stop_service=lambda: stopped.append(True),
)
assert repeated["errors"] == []
assert unrelated.exists()
live_socket_handle.close()
live_tmux_socket.unlink()
def test_cleanup_refuses_unverified_running_service(tmp_path, monkeypatch):
state, runtime = configure_paths(tmp_path, monkeypatch)
(runtime / "tamq.pid").write_text("41", encoding="utf-8")
manager = FakeManager(state / "commands" / "tamq")
async def running():
return True
async def request(_payload):
return {"ok": True, "pid": 42}
monkeypatch.setattr("tamq.cleanup.ping", running)
monkeypatch.setattr("tamq.cleanup.request", request)
stopped = []
report = cleanup_runtime(
apply=True,
manager=manager,
stop_service=lambda: stopped.append(True),
)
assert report["errors"] == ["refusing to stop an unverified service PID"]
assert stopped == []
assert manager.identity is not None
def test_cleanup_stops_verified_service_before_removing_runtime(
tmp_path, monkeypatch
):
state, runtime = configure_paths(tmp_path, monkeypatch)
(runtime / "tamq.pid").write_text("42", encoding="utf-8")
manager = FakeManager(state / "commands" / "tamq")
liveness = iter((True, False))
async def ping():
return next(liveness)
async def request(_payload):
return {"ok": True, "pid": 42}
monkeypatch.setattr("tamq.cleanup.ping", ping)
monkeypatch.setattr("tamq.cleanup.request", request)
stopped = []
report = cleanup_runtime(
apply=True,
manager=manager,
stop_service=lambda: stopped.append(42) or 42,
)
assert report["errors"] == []
assert stopped == [42]
assert manager.identity is None
assert not (runtime / "tamq.pid").exists()
def test_cleanup_cli_is_dry_run_by_default(monkeypatch, capsys):
calls = []
def cleanup_runtime(**kwargs):
calls.append(kwargs)
return {"errors": [], "apply": kwargs["apply"]}
monkeypatch.setattr("tamq.cli.cleanup_runtime", cleanup_runtime)
assert main(["cleanup", "--session", "test-session"]) == 0
assert calls[0]["apply"] is False
assert calls[0]["session"] == "test-session"
assert '"apply": false' in capsys.readouterr().out
assert main(["cleanup", "--yes"]) == 0
assert calls[1]["apply"] is True