From 1792eab55d4bd0f290c8d6199e4e30b6278babc3 Mon Sep 17 00:00:00 2001 From: tech Date: Thu, 21 May 2026 13:07:15 +0800 Subject: [PATCH] test: add integration tests for full tunnel lifecycle --- tests/integration/test_lifecycle.py | 36 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/tests/integration/test_lifecycle.py b/tests/integration/test_lifecycle.py index 7198671..4bc684b 100644 --- a/tests/integration/test_lifecycle.py +++ b/tests/integration/test_lifecycle.py @@ -2,10 +2,11 @@ import os import signal import time import pytest +from datetime import datetime, timezone from click.testing import CliRunner from autossh_mgr.cli import cli from autossh_mgr.config import save_tunnels, TunnelConfig, ensure_dirs -from autossh_mgr.process import read_pid_file, is_process_alive +from autossh_mgr.process import read_pid_file, is_process_alive, write_pid_file @pytest.fixture @@ -29,6 +30,22 @@ def set_config_dir(config_dir, monkeypatch): monkeypatch.setenv("AUTOSSH_MGR_CONFIG_DIR", str(config_dir)) +@pytest.fixture(autouse=True) +def cleanup_processes(config_dir): + """Kill any processes recorded in PID files after each test.""" + yield + pids_dir = config_dir / "pids" + if not pids_dir.exists(): + return + for pid_file in pids_dir.glob("*.pid"): + try: + lines = pid_file.read_text().splitlines() + if lines: + os.kill(int(lines[0]), signal.SIGKILL) + except (ValueError, OSError, ProcessLookupError): + pass + + @pytest.fixture def tunnel(config_dir): t = TunnelConfig( @@ -52,10 +69,8 @@ def test_start_writes_pid_file(runner, config_dir, tunnel, fake_autossh): assert result.exit_code == 0, result.output pid_data = read_pid_file(config_dir, "test-tunnel") assert pid_data is not None - pid, started_at = pid_data + pid, _ = pid_data assert is_process_alive(pid) - # cleanup - os.kill(pid, signal.SIGKILL) def test_stop_kills_process(runner, config_dir, tunnel, fake_autossh): @@ -78,14 +93,8 @@ def test_status_shows_running(runner, config_dir, tunnel, fake_autossh): assert result.exit_code == 0 assert "running" in result.output - pid_data = read_pid_file(config_dir, "test-tunnel") - if pid_data: - os.kill(pid_data[0], signal.SIGKILL) - def test_stale_pid_cleaned_on_start(runner, config_dir, tunnel, fake_autossh): - from autossh_mgr.process import write_pid_file - from datetime import datetime, timezone write_pid_file(config_dir, "test-tunnel", 9999999, datetime.now(timezone.utc)) result = runner.invoke(cli, ["start", "test-tunnel"]) @@ -96,8 +105,6 @@ def test_stale_pid_cleaned_on_start(runner, config_dir, tunnel, fake_autossh): assert pid_data is not None assert pid_data[0] != 9999999 - os.kill(pid_data[0], signal.SIGKILL) - def test_restart(runner, config_dir, tunnel, fake_autossh): runner.invoke(cli, ["start", "test-tunnel"]) @@ -109,8 +116,7 @@ def test_restart(runner, config_dir, tunnel, fake_autossh): second_pid = read_pid_file(config_dir, "test-tunnel")[0] assert second_pid != first_pid assert is_process_alive(second_pid) - - os.kill(second_pid, signal.SIGKILL) + assert not is_process_alive(first_pid) def test_idempotent_start(runner, config_dir, tunnel, fake_autossh): @@ -122,8 +128,6 @@ def test_idempotent_start(runner, config_dir, tunnel, fake_autossh): assert "already running" in result.output assert read_pid_file(config_dir, "test-tunnel")[0] == first_pid - os.kill(first_pid, signal.SIGKILL) - def test_idempotent_stop(runner, tunnel): result = runner.invoke(cli, ["stop", "test-tunnel"])