src/voxip_kiosk -> src/daynivo_kiosk, with every import, the launchers, install.sh, the Makefile and the manager's gunicorn app path. An upgrade replaces /usr/lib/voxip-kiosk/python as a whole, so the old package disappears; tested by upgrading an installation of the previous commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
86 lines
2.5 KiB
Python
86 lines
2.5 KiB
Python
import pytest
|
|
|
|
from daynivo_kiosk import services
|
|
from daynivo_kiosk.cdp import CDPError
|
|
from daynivo_kiosk.config import save_config
|
|
from daynivo_kiosk.healthcheck import CDP_FAILURES_BEFORE_RESTART, DISPLAY_RETRY_AFTER, HealthCheck
|
|
|
|
|
|
class World:
|
|
def __init__(self):
|
|
self.units = {u: {"ActiveState": "active"} for u in (services.X_UNIT, services.BROWSER_UNIT, services.AGENT_UNIT, services.MANAGER_UNIT)}
|
|
self.actions = []
|
|
self.now = 10_000.0
|
|
self.cdp_ok = True
|
|
|
|
def unit_status(self, unit):
|
|
return self.units[unit]
|
|
|
|
def systemctl(self, *args):
|
|
self.actions.append(args)
|
|
|
|
def version(self):
|
|
if not self.cdp_ok:
|
|
raise CDPError("timeout")
|
|
return {}
|
|
|
|
|
|
@pytest.fixture
|
|
def world(paths):
|
|
w = World()
|
|
hc = HealthCheck(paths, unit_status=w.unit_status, systemctl=w.systemctl, cdp=w, throttled=lambda: None,
|
|
disk=lambda p: {"percent": 40}, now=lambda: w.now)
|
|
return w, hc
|
|
|
|
|
|
def test_all_healthy_no_actions(world):
|
|
w, hc = world
|
|
report = hc.run()
|
|
assert report["actions"] == [] and w.actions == []
|
|
|
|
|
|
def test_failed_browser_waits_for_cooldown(world):
|
|
w, hc = world
|
|
w.units[services.BROWSER_UNIT] = {"ActiveState": "failed", "Result": "start-limit-hit"}
|
|
hc.run()
|
|
assert w.actions == []
|
|
w.now += DISPLAY_RETRY_AFTER
|
|
hc.run()
|
|
assert ("reset-failed", services.BROWSER_UNIT) in w.actions
|
|
assert ("start", "--no-block", services.BROWSER_UNIT) in w.actions
|
|
|
|
|
|
def test_failed_manager_restarts_immediately(world):
|
|
w, hc = world
|
|
w.units[services.MANAGER_UNIT] = {"ActiveState": "failed"}
|
|
hc.run()
|
|
assert ("start", "--no-block", services.MANAGER_UNIT) in w.actions
|
|
|
|
|
|
def test_browser_restart_disabled_is_respected(world, paths):
|
|
w, hc = world
|
|
save_config(paths.config_file, {"browser_restart": False})
|
|
w.units[services.BROWSER_UNIT] = {"ActiveState": "inactive"}
|
|
hc.run()
|
|
assert w.actions == []
|
|
|
|
|
|
def test_unresponsive_devtools_restarts_browser(world):
|
|
w, hc = world
|
|
hc.run() # browser seen active
|
|
w.now += 100
|
|
w.cdp_ok = False
|
|
for _ in range(CDP_FAILURES_BEFORE_RESTART - 1):
|
|
hc.run()
|
|
assert w.actions == []
|
|
hc.run()
|
|
assert ("restart", "--no-block", services.BROWSER_UNIT) in w.actions
|
|
|
|
|
|
def test_maintenance_mode_blocks_actions(world, paths):
|
|
w, hc = world
|
|
(paths.health_run_dir / "maintenance").touch()
|
|
w.units[services.AGENT_UNIT] = {"ActiveState": "inactive"}
|
|
report = hc.run()
|
|
assert report["maintenance"] is True and w.actions == []
|