"""TC-07: kill-switch + env-driven config (no hardcoded thresholds). ``WATCHDOG_ENABLED=false`` -> the daemon is inert (idle, no ticks). Thresholds / intervals / timeouts come from env, not constants. """ from watchdog.config import Config def test_killswitch_off_is_inert(monkeypatch): from watchdog import __main__ as entry cfg = Config.from_env({"WATCHDOG_ENABLED": "false", "WATCHDOG_INTERVAL_S": "0"}) assert cfg.enabled is False built = {"n": 0} class _Dog: def tick(self): built["n"] += 1 # If run() ever constructed a Watchdog / ticked while disabled, this would fire. monkeypatch.setattr(entry, "Watchdog", lambda c: _Dog()) monkeypatch.setattr(entry.time, "sleep", lambda *_: None) entry.run(cfg=cfg, max_ticks=3) assert built["n"] == 0 # inert: never ticked def test_thresholds_read_from_env(): cfg = Config.from_env( { "WATCHDOG_INTERVAL_S": "7", "WATCHDOG_MEM_PCT": "77", "WATCHDOG_QUEUE_DEPTH": "9", "WATCHDOG_AGENT_HUNG_MIN": "5", "WATCHDOG_STAGE_STUCK_MIN": "11", "WATCHDOG_ORCH_DOWN_TICKS": "4", "WATCHDOG_COOLDOWN_S": "60", "WATCHDOG_HTTP_TIMEOUT_S": "2", "WATCHDOG_CONTAINERS": "orchestrator,plane-app", "WATCHDOG_DEPS": "gitea=http://g/healthz,plane=http://p/", } ) assert cfg.interval_s == 7.0 assert cfg.mem_pct == 77.0 assert cfg.queue_depth == 9 assert cfg.agent_hung_s == 5 * 60.0 assert cfg.stage_stuck_s == 11 * 60.0 assert cfg.orch_down_ticks == 4 assert cfg.cooldown_s == 60.0 assert cfg.http_timeout_s == 2.0 assert cfg.containers == ["orchestrator", "plane-app"] assert cfg.deps == {"gitea": "http://g/healthz", "plane": "http://p/"} def test_defaults_when_env_absent(): cfg = Config.from_env({}) assert cfg.enabled is True assert cfg.interval_s == 30.0 assert cfg.metrics_url.endswith(":8500/metrics") assert cfg.disk_crit_enabled is False assert cfg.containers == ["orchestrator"] assert cfg.deps == {} def test_malformed_env_degrades_to_default(): # A garbage numeric value must not crash config; it degrades to the default. cfg = Config.from_env({"WATCHDOG_INTERVAL_S": "abc", "WATCHDOG_MEM_PCT": ""}) assert cfg.interval_s == 30.0 assert cfg.mem_pct == 90.0 # -- ORCH-111: proc_blocking config (kill-switch default-off + safe threshold) -- def test_proc_blocking_defaults_off_and_safe(): cfg = Config.from_env({}) assert cfg.proc_enabled is False # opt-in (needs `pid: host`) assert cfg.proc_patterns == ["pytest"] assert cfg.proc_cooldown_s == 1800.0 # Cross-invariant (adr-0041 D2): the default age threshold MUST exceed the max # legitimate test-run budget max(merge_retest_timeout_s=600, coverage=900). assert cfg.proc_age_s > 900.0 def test_proc_blocking_thresholds_read_from_env(): cfg = Config.from_env( { "WATCHDOG_PROC_ENABLED": "true", "WATCHDOG_PROC_AGE_MIN": "45", "WATCHDOG_PROC_PATTERNS": "pytest,coverage run", "WATCHDOG_PROC_COOLDOWN_S": "900", } ) assert cfg.proc_enabled is True assert cfg.proc_age_s == 45 * 60.0 assert cfg.proc_patterns == ["pytest", "coverage run"] assert cfg.proc_cooldown_s == 900.0 def test_proc_blocking_malformed_env_degrades(): cfg = Config.from_env({"WATCHDOG_PROC_AGE_MIN": "nope", "WATCHDOG_PROC_ENABLED": ""}) assert cfg.proc_age_min == 60.0 assert cfg.proc_enabled is False