Files
StarPilot/openpilot/starpilot/ui/tests/test_conditional_reason_semantics.py
T
firestar5683 a82935f326 User interfaces and Android Auto
Integrate onroad views, configurable widgets, local settings, steering-profile contracts, Bluetooth and Android Auto with their device and runtime services.

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: Daniel Koepping <elkoled@gmail.com>
Co-authored-by: Danny <dannyirwin31@yahoo.com>
Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com>
Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com>
Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com>
Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu>
Co-authored-by: Shane Smiskol <shane@smiskol.com>
Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>
Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com>
Co-authored-by: stef <19478336+stefpi@users.noreply.github.com>
Co-authored-by: whoisdomi <dcantu83@gmail.com>

Co-authored-by: Intelli <contact@intelli.software>
Co-authored-by: pharmacomaniac <blittle65@gmail.com>

Co-authored-by: prabhaavp <prabhaav@msu.edu>
2026-10-14 20:02:39 -05:00

72 lines
3.7 KiB
Python

"""Keep readiness receipts intact while missing road data stays visually neutral."""
from typing import Any
from unittest.mock import Mock
from dataclasses import replace
import unittest
from openpilot.cereal import log, messaging
from openpilot.starpilot.conditional_mode.host import HostProposal
from openpilot.starpilot.conditional_mode.projection import ProjectedScene
from openpilot.starpilot.conditional_mode.policy import Authority, Decision, ModeChoice, Reason
from openpilot.starpilot.conditional_mode.runtime_settings import SettingsSnapshot, DocumentState, SafeModeState
from openpilot.starpilot.conditional_mode.status import StatusPublisher
from openpilot.starpilot.ui.conditional_status import ConditionalPerceptionProjector
from openpilot.starpilot.ui.onroad_conditional import status, stop_active
from openpilot.starpilot.ui.onroad_state import OnroadState, SpeedLimitObservation
def changed_arguments(arguments: dict[str, Any], changes: dict[str, Any]) -> dict[str, Any]:
return arguments | changes
def check_fresh_validated_receipt_preserves_unavailable_reason(choice, policy_reason):
now = 100_000_000_000
drive_id = now - 1_000_000_000
authority = Authority(True, True, False, False, False, True)
decision = Decision(True, False, True, True, policy_reason, 0)
settings = SettingsSnapshot('test', 1, now, now, DocumentState.ABSENT, SafeModeState.ABSENT_FALSE, None, None, None)
# Controlled wire reasons isolate presentation; this is not policy/control admission.
proposal = HostProposal(choice, Mock(spec=ProjectedScene, authority=authority), decision, None, 'inactive_axis', settings.revision)
event = messaging.new_message('slcState')
event.valid = True
event.logMonoTime = now
StatusPublisher().attach(event, proposal, settings, now_ns=now, drive_id=drive_id,
model_ns=now, car_state_ns=now)
args: dict[str, Any] = {'now_ns': now + 20_000_000, 'event_ns': now, 'drive_id': drive_id, 'choice': choice,
'lateral_active': True, 'selfdrive_enabled': False, 'car_valid': True, 'system_long': True}
with log.Event.from_bytes(event.to_bytes()) as received:
projector = ConditionalPerceptionProjector()
value = projector.project(received.slcState, **args)
assert value is not None and value.reason == policy_reason.value
assert not value.effective_experimental
assert not received.slcState.conditionalMode.hasOverride
ui = OnroadState(False, True, 0.0, 0.0, SpeedLimitObservation(), conditional_perception=value)
display = status(ui)
assert display is None
assert not stop_active(ui)
for changed in ({'now_ns': now + 200_000_001}, {'drive_id': drive_id + 1}, {'car_valid': False},
{'system_long': False}, {'lateral_active': False}, {'choice': ModeChoice.STOCK}):
rejected = ConditionalPerceptionProjector().project(received.slcState, **changed_arguments(args, changed))
assert rejected is None
ui = replace(ui, conditional_perception=rejected)
assert status(ui) is None and not stop_active(ui)
class TestConditionalReasonSemantics(unittest.TestCase):
def test_cem_missing_scene_is_neutral(self):
check_fresh_validated_receipt_preserves_unavailable_reason(ModeChoice.CEM, Reason.SCENE_UNAVAILABLE)
def test_cem_unavailable_is_neutral(self):
check_fresh_validated_receipt_preserves_unavailable_reason(ModeChoice.CEM, Reason.UNAVAILABLE)
def test_ccm_missing_scene_is_neutral(self):
check_fresh_validated_receipt_preserves_unavailable_reason(ModeChoice.CCM, Reason.SCENE_UNAVAILABLE)
def test_ccm_unavailable_is_neutral(self):
check_fresh_validated_receipt_preserves_unavailable_reason(ModeChoice.CCM, Reason.UNAVAILABLE)
if __name__ == '__main__':
unittest.main()