move_detect/tests/test_health.py
유창욱 752afc3f00 feat(edge): heartbeat telemetry + monotonic timers + queue/camera robustness
- Split clocks: detector timers/cooldowns run on a MONOTONIC clock (immune to an
  NTP step on an RTC-less Pi); wall time is used only for the HMAC X-Timestamp
  and Event.occurred_at. Fixes false IMMOBILITY / dropped tracks after a clock jump.
- Heartbeat is time-based (30s, predictable regardless of load) and now carries
  temp/throttle/queue_pending/config_version telemetry.
- A dead (no-frame) camera counts as erroring instead of a healthy frame, so a
  silent monitoring outage no longer looks green.
- Offline queue: isolate one undecodable row instead of wedging every event behind
  it; classify 401 (stale clock) as transient, never a poison-drop.
- New edge/health.py: vcgencmd temp/throttle parsing, None off-Pi (no fake 0).
2026-07-25 19:20:23 +09:00

41 lines
1.5 KiB
Python

from edge.health import parse_temp, parse_throttle, read_health
def test_parse_temp_reads_vcgencmd_output():
assert parse_temp("temp=54.3'C\n") == 54.3
def test_parse_temp_returns_none_on_garbage():
assert parse_temp("") is None
assert parse_temp("no equals sign") is None
def test_parse_throttle_true_when_a_currently_active_bit_is_set():
assert parse_throttle("throttled=0x4") is True # bit2: currently throttled
assert parse_throttle("throttled=0x1") is True # bit0: under-voltage now
def test_parse_throttle_false_for_zero_and_for_past_only_latches():
assert parse_throttle("throttled=0x0") is False
# 0x50000 = bits 16,18 (under-voltage/throttle HAPPENED since boot) but nothing active now.
assert parse_throttle("throttled=0x50000") is False
def test_parse_throttle_none_on_garbage():
assert parse_throttle("throttled=notahexnum") is None
def test_read_health_returns_nones_off_pi_without_touching_subprocess():
# No vcgencmd on the build machine / server: read_health must return Nones (never a fake 0)
# and must NOT invoke the runner at all.
calls = []
out = read_health(run=lambda cmd: calls.append(cmd) or "", which=lambda name: None)
assert out == {"temp": None, "throttle": None}
assert calls == []
def test_read_health_parses_injected_vcgencmd_on_pi():
def fake_run(cmd):
return "temp=61.7'C\n" if "measure_temp" in cmd else "throttled=0x0\n"
out = read_health(run=fake_run, which=lambda name: "/usr/bin/vcgencmd")
assert out == {"temp": 61.7, "throttle": False}