Files
StarPilot/openpilot/starpilot/tests/test_ford_command_pause.py
2026-10-20 21:21:56 -05:00

88 lines
3.1 KiB
Python

"""A 30ms output lease expiry must not erase a still-fresh stock-Ford arm."""
from dataclasses import replace
import pytest
from openpilot.starpilot.tests.test_ford_reverse_intent import NOW, PRODUCER, baseline, sample, change, native_change
from openpilot.starpilot.car.ford.command_pause import retain_command_pause_intent
def pause():
cp, cs, feedback = baseline()
sm, native = sample(cp, NOW, NOW + 40_000_000, 1, requested=False, allowed=False)
return cp, cs, feedback, sm, native
def test_output_expiry_retains_only_original_intent_then_recovers_with_real_native_grant():
cp, cs, feedback, sm, native = pause()
before = dict(vars(feedback))
for delta in (40_000_000, 60_000_000, 150_000_000):
assert retain_command_pause_intent(feedback, sm, cp, cs, sm['aolAxisState'], NOW + delta, latched=True, producer=PRODUCER)
assert not feedback.observe(sm, cp, cs, NOW + delta, latched=True, intent_producer_session=PRODUCER)
assert vars(feedback) == before
assert not retain_command_pause_intent(feedback, sm, cp, cs, sm['aolAxisState'], NOW + 200_000_001, latched=True, producer=PRODUCER)
fresh, _ = sample(cp, NOW + 160_000_000, NOW + 160_000_000, 2)
assert not feedback.observe(fresh, cp, cs, NOW + 160_000_000, latched=True, intent_producer_session=PRODUCER)
assert feedback.lateral_source_ns == NOW + 160_000_000 and not feedback.failed
@pytest.mark.parametrize(
'fault',
[
'unlatched',
'can',
'main',
'brake',
'gas',
'eps',
'long',
'producer',
'epoch',
'session',
'event',
'native-rx',
'native-heartbeat',
'interrupt8',
'inventory',
'requested',
],
)
def test_command_pause_cannot_hide_health_identity_longitudinal_or_driver_veto(fault):
cp, cs, feedback, sm, native = pause()
latched, producer = True, PRODUCER
if fault == 'unlatched':
latched = False
elif fault == 'can':
cs.canValid = False
elif fault == 'main':
cs.cruiseState.available = False
elif fault == 'brake':
cs.brakePressed = True
elif fault == 'gas':
cs.gasPressed = True
elif fault == 'eps':
cs.steerFaultPermanent = True
elif fault == 'long':
cp.openpilotLongitudinalControl = True
elif fault == 'producer':
producer = 'other-card'
elif fault == 'epoch':
change(sm, 'aolAxisState', lambda a: setattr(a, 'intentIntegrityEpoch', 2))
elif fault == 'session':
change(sm, 'aolAxisState', lambda a: setattr(a, 'sessionId', 'other-axis'))
elif fault == 'event':
change(sm, 'onroadEvents', lambda e: setattr(e[0], 'immediateDisable', True))
elif fault == 'requested':
native_change(sm, native, requestedLateral=True)
elif fault == 'inventory':
native_change(sm, native, pandaSerial='other-panda')
else:
slot = replace(
native.pandaInventory[0],
**{'native-rx': {'safetyRxChecksInvalid': True}, 'native-heartbeat': {'heartbeatLost': True}, 'interrupt8': {'faults': 8}}[fault],
)
native_change(sm, native, pandaInventory=(slot,))
before = dict(vars(feedback))
assert not retain_command_pause_intent(feedback, sm, cp, cs, sm['aolAxisState'], NOW + 40_000_000, latched=latched, producer=producer)
assert vars(feedback) == before