mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 05:23:41 +08:00
107 lines
5.8 KiB
Python
107 lines
5.8 KiB
Python
"""Real I6 callers: existing upstream mismatch ownership, no denied LONG output."""
|
|
from contextlib import ExitStack
|
|
|
|
import pytest
|
|
from openpilot.cereal import log
|
|
from openpilot.common.prefix import OpenpilotPrefix
|
|
from openpilot.starpilot.aol.tests import test_ioniq_availability as fixture
|
|
|
|
|
|
def test_native_brake_withdrawal_precedes_card_source_without_losing_lateral():
|
|
case = fixture.IoniqAvailabilityTests(methodName='runTest')
|
|
with ExitStack() as cleanup:
|
|
cleanup.callback(case.doCleanups)
|
|
cleanup.enter_context(OpenpilotPrefix())
|
|
sd, _, drive, card, receive = case._ioniq_availability_callers(full_op=True)
|
|
# PandaStates is a real10Hz service. Prime the ordinary healthy100Hz
|
|
# callers until the next ORIGINAL10Hz publication is due; the installed
|
|
# route likewise had latestPanda FALSE before the mismatch decision.
|
|
for tick in range(2, 10):
|
|
warm_axis, warm_state, warm_command = drive(tick)
|
|
assert warm_state.enabled and warm_axis.lateralActive and warm_axis.longitudinalActive
|
|
assert warm_command.latActive and warm_command.longActive
|
|
axis, state, command = drive(10, native_request_lat=True, allowed=True, native_request_long=True,
|
|
long_allowed=False, panda_controls_allowed=False)
|
|
assert int(sd.sm.logMonoTime['pandaStates']) == 10_100_000_000
|
|
assert all(not panda.controlsAllowed for panda in sd.sm['pandaStates'])
|
|
# Native denial takes effect immediately. Healthy independently granted LAT
|
|
# and its existing intent do not become a fabricated critical source fault.
|
|
assert not axis.longitudinalActive and not command.longActive
|
|
assert axis.lateralActive and command.latActive
|
|
assert state.enabled and not sd.aol_authority_lost
|
|
assert log.OnroadEvent.EventName.controlsMismatch not in sd.events.names
|
|
assert sd.mismatch_counter > 0
|
|
assert receive(10_100_000_000, axis=sd.pm.messages['aolAxisState'], event=sd.pm.messages['onroadEvents'])
|
|
assert card.aol_card_intent.allowed_latch
|
|
axis, state, command = drive(11, brake=True, native_request_lat=True, allowed=True,
|
|
native_request_long=True, long_allowed=False, panda_controls_allowed=False)
|
|
assert not state.enabled and not state.active
|
|
assert axis.lateralActive and command.latActive
|
|
assert not axis.longitudinalActive and not command.longActive
|
|
assert log.OnroadEvent.EventName.controlsMismatch not in sd.events.names
|
|
assert receive(10_110_000_000, state=fixture.car_state(brake=True),
|
|
axis=sd.pm.messages['aolAxisState'], event=sd.pm.messages['onroadEvents'])
|
|
assert card.aol_card_intent.allowed_latch
|
|
|
|
|
|
def test_persistent_native_long_denial_still_hits_original_upstream_mismatch_counter():
|
|
case = fixture.IoniqAvailabilityTests(methodName='runTest')
|
|
with ExitStack() as cleanup:
|
|
cleanup.callback(case.doCleanups)
|
|
cleanup.enter_context(OpenpilotPrefix())
|
|
sd, _, drive, _, _ = case._ioniq_availability_callers(full_op=True)
|
|
for tick in range(2, 10):
|
|
warm_axis, warm_state, warm_command = drive(tick)
|
|
assert warm_state.enabled and warm_axis.lateralActive and warm_axis.longitudinalActive
|
|
assert warm_command.latActive and warm_command.longActive
|
|
for tick in range(10, 214):
|
|
axis, state, command = drive(tick, native_request_lat=True, allowed=True,
|
|
native_request_long=True, long_allowed=False, panda_controls_allowed=False)
|
|
if tick == 10:
|
|
assert int(sd.sm.logMonoTime['pandaStates']) == 10_100_000_000
|
|
assert all(not panda.controlsAllowed for panda in sd.sm['pandaStates'])
|
|
assert not axis.longitudinalActive and not command.longActive
|
|
if log.OnroadEvent.EventName.controlsMismatch in sd.events.names:
|
|
break
|
|
assert axis.lateralActive and command.latActive and state.enabled
|
|
assert sd.mismatch_counter >= 200
|
|
assert log.OnroadEvent.EventName.controlsMismatch in sd.events.names
|
|
assert not state.enabled and not axis.lateralActive and not command.latActive
|
|
|
|
|
|
@pytest.mark.parametrize('fault', ['lat_denied', 'native_invalid', 'rx_fault', 'relay_fault', 'inconsistent_long_receipt'])
|
|
def test_other_native_denials_and_faults_remain_immediate(fault):
|
|
case = fixture.IoniqAvailabilityTests(methodName='runTest')
|
|
with ExitStack() as cleanup:
|
|
cleanup.callback(case.doCleanups)
|
|
cleanup.enter_context(OpenpilotPrefix())
|
|
sd, _, drive, _, _ = case._ioniq_availability_callers(full_op=True)
|
|
options = {'native_request_lat': True, 'allowed': True, 'native_request_long': True,
|
|
'long_allowed': False, 'panda_controls_allowed': False}
|
|
if fault == 'lat_denied':
|
|
options['allowed'] = False
|
|
elif fault == 'native_invalid':
|
|
options['native_valid'] = False
|
|
elif fault == 'rx_fault':
|
|
options['panda_fault'] = True
|
|
elif fault == 'relay_fault':
|
|
options['relay_fault'] = True
|
|
else:
|
|
options['panda_controls_allowed'] = True
|
|
axis, state, command = drive(2, **options)
|
|
assert not axis.longitudinalActive and not command.longActive
|
|
if fault == 'inconsistent_long_receipt':
|
|
# controlsAllowed is an independent Panda observation. A healthy LAT
|
|
# grant with denied LONG is not itself an immediate integrity fault.
|
|
from openpilot.starpilot.aol.runtime import current_native
|
|
native = current_native(sd.sm, sd.CP, now_ns=axis.observedMonoTime,
|
|
axis_session_id=sd.aol_session_id)
|
|
assert native is not None and native.requestedLongitudinal and not native.longitudinalAllowed
|
|
assert native.requestedLateral and native.lateralAllowed
|
|
assert all(p.controlsAllowed for p in native.pandaInventory)
|
|
assert state.enabled and axis.lateralActive and command.latActive
|
|
assert log.OnroadEvent.EventName.controlsMismatch not in sd.events.names
|
|
else:
|
|
assert log.OnroadEvent.EventName.controlsMismatch in sd.events.names
|
|
assert not state.enabled and not axis.lateralActive and not command.latActive
|