Files
StarPilot/openpilot/starpilot/sentry_mode/tests/test_status.py
T
firestar5683 e52e1a6a86 Sentry
Implement Sentry scanning, notification state and worker cancellation through explicit policies and preferences.
2026-10-14 19:56:17 -05:00

70 lines
3.4 KiB
Python

import os
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
from openpilot.starpilot.sentry_mode.policy import Decision
from openpilot.starpilot.sentry_mode.preferences import Preferences, SavedPreferences, encode
from openpilot.starpilot.sentry_mode.status import RuntimeStatus, TTL_NS
class RuntimeStatusTest(unittest.TestCase):
def setUp(self):
self.directory = tempfile.TemporaryDirectory()
self.addCleanup(self.directory.cleanup)
self.now = 10_000_000_000
self.boot_now = self.now + 50_000_000_000
self.identity = "current-boot"
self.status = RuntimeStatus(Path(self.directory.name).resolve(), clock=lambda: self.now,
boot=lambda: self.identity, boot_clock=lambda: self.boot_now)
preferences = Preferences(True)
self.saved = SavedPreferences(encode(preferences), True, True, preferences)
self.environment = patch.dict(os.environ, STARPILOT_SENTRY_DEVELOPMENT="1")
self.environment.start()
self.addCleanup(self.environment.stop)
def test_saved_enable_is_not_armed_and_fresh_countdown_is_observed(self):
self.assertEqual(self.status.runtime_snapshot(self.saved)[0], "Waiting for monitor")
self.status.publish(Decision("arming", seconds_remaining=82), self.saved.raw, "idle")
self.assertEqual(self.status.runtime_snapshot(self.saved)[0], "Arming · 82s")
self.status.publish(Decision("armed"), self.saved.raw, "stored")
self.assertEqual(self.status.runtime_snapshot(self.saved)[0], "Monitoring motion")
self.status.publish(Decision("disabled_ignition"), self.saved.raw, "stored")
self.assertEqual(self.status.runtime_snapshot(self.saved)[0], "Not armed")
def test_expired_future_reboot_resume_or_changed_settings_never_show_armed(self):
for failure in ("expired", "future", "reboot", "resume", "settings"):
with self.subTest(failure=failure):
self.now = 10_000_000_000
self.boot_now = self.now + 50_000_000_000
self.identity = "current-boot"
preferences = Preferences(True)
self.saved = SavedPreferences(encode(preferences), True, True, preferences)
self.status.last_published = None
self.status.publish(Decision("armed"), self.saved.raw, "idle")
if failure == "expired":
self.now += TTL_NS + 1
elif failure == "future":
self.now -= 1
elif failure == "reboot":
self.identity = "another-boot"
elif failure == "resume":
self.boot_now += 300_000_000
else:
assert self.saved.raw is not None
self.saved = SavedPreferences(self.saved.raw + b" ", True, True, self.saved.preferences)
self.assertEqual(self.status.runtime_snapshot(self.saved)[0], "Waiting for monitor")
def test_legacy_development_flag_does_not_gate_real_monitor_and_unsafe_status_is_rejected(self):
self.status.publish(Decision("armed"), self.saved.raw, "idle")
with patch.dict(os.environ, STARPILOT_SENTRY_DEVELOPMENT="0"):
self.assertEqual(self.status.runtime_snapshot(self.saved)[0], "Monitoring motion")
destination = Path(self.directory.name) / "status.json"
original = destination.read_bytes()
destination.unlink()
target = Path(self.directory.name) / "other"
target.write_bytes(original)
destination.symlink_to(target)
self.assertEqual(self.status.runtime_snapshot(self.saved)[0], "Waiting for monitor")