jarvis / tests /test_runtime_watchdog.py
Jonathan Haas
refactor: extract observability snapshot and watchdog runtime loops
7de1e04
Raw
History Blame Contribute Delete
1.76 kB
from __future__ import annotations
import asyncio
import threading
from types import SimpleNamespace
from unittest.mock import MagicMock
import pytest
from jarvis.presence import State
from jarvis.runtime_watchdog import watchdog_loop
@pytest.mark.asyncio
async def test_watchdog_loop_resets_stuck_state_and_records_event() -> None:
observability = SimpleNamespace(record_event=MagicMock())
runtime = SimpleNamespace(
config=SimpleNamespace(
watchdog_listening_timeout_sec=0.05,
watchdog_thinking_timeout_sec=0.05,
watchdog_speaking_timeout_sec=0.05,
),
presence=SimpleNamespace(signals=SimpleNamespace(state=State.THINKING)),
_runtime_invariant_checked_monotonic=0.0,
_check_runtime_invariants=MagicMock(),
_barge_in=threading.Event(),
_flush_output=MagicMock(),
_clear_tts_queue=MagicMock(),
_telemetry={"fallback_responses": 0.0},
_observability=observability,
)
task = asyncio.create_task(
watchdog_loop(
runtime,
state_idle=State.IDLE,
state_listening=State.LISTENING,
state_thinking=State.THINKING,
state_speaking=State.SPEAKING,
poll_sec=0.01,
logger=SimpleNamespace(warning=MagicMock()),
)
)
await asyncio.sleep(0.09)
task.cancel()
with pytest.raises(asyncio.CancelledError):
await task
assert runtime.presence.signals.state == State.IDLE
assert runtime._flush_output.called
assert runtime._clear_tts_queue.called
assert runtime._telemetry["fallback_responses"] >= 1.0
observability.record_event.assert_called()
runtime._check_runtime_invariants.assert_called()