Files
wecker/tests/test_single_instance.py
T

72 lines
2.2 KiB
Python

import pytest
import sys
from unittest.mock import MagicMock, patch
# Mock hardware modules before importing wecker (tests run off the Pi).
sys.modules["RPi"] = MagicMock()
sys.modules["RPi.GPIO"] = MagicMock()
sys.modules["pygame"] = MagicMock()
import common # noqa: E402
import wecker # noqa: E402
@pytest.fixture
def mock_pid_file(tmp_path):
"""Provides a temporary PID file path and resets the lock fd."""
pid_file = tmp_path / "wecker.pid"
with patch("wecker.PID_FILE", str(pid_file)):
wecker._pid_lock_fd = None
yield pid_file
if wecker._pid_lock_fd is not None:
try:
wecker._pid_lock_fd.close()
except OSError:
pass
wecker._pid_lock_fd = None
def test_ensure_single_instance_success(mock_pid_file):
"""Test that the script can start if no other instance holds the lock."""
with patch("os.getpid", return_value=1234):
wecker.ensure_single_instance()
assert mock_pid_file.read_text() == "1234"
def test_ensure_single_instance_already_running(mock_pid_file):
"""Test that the script exits if another instance holds the lock."""
with patch("fcntl.flock", side_effect=BlockingIOError), pytest.raises(
SystemExit
) as excinfo:
wecker.ensure_single_instance()
assert excinfo.value.code == 1
def test_ensure_single_instance_overwrites_stale_pid(mock_pid_file):
"""Test that a stale PID file is overwritten once the lock is acquired."""
mock_pid_file.write_text("5678")
with patch("os.getpid", return_value=1234):
wecker.ensure_single_instance()
assert mock_pid_file.read_text() == "1234"
def test_remove_pid_file_success(mock_pid_file):
"""Test that remove_pid_file closes the lock and removes the file."""
with patch("os.getpid", return_value=1234):
wecker.ensure_single_instance()
wecker.remove_pid_file()
assert not mock_pid_file.exists()
def test_pid_file_defined_once_across_modules():
"""DRY principle: PID_FILE must be defined in common.py and imported."""
assert wecker.PID_FILE is common.PID_FILE, (
"wecker.PID_FILE must reference common.PID_FILE, not redefine it"
)
assert common.PID_FILE.endswith("wecker.pid")