test(gm): feed actual steering transmit receipts in healthy fixtures

Keep existing assertions and runtime behavior unchanged. Model healthy transport by returning only actually emitted steering commands; retain missing, stale, wrong-bus and rejected receipt coverage.
This commit is contained in:
Dom
2026-10-31 09:25:04 -05:00
parent 5197fe4568
commit 6a972ae87e
5 changed files with 38 additions and 5 deletions
@@ -214,7 +214,15 @@ def test_actual_card_retires_rejected_cold_wait_before_next_request():
card = TestGmAol.card(cp, saved)
cleanup.callback(card.vehicle_startup.close)
card.ci_initialized = True
card.publish_sendcan = lambda *args, **kwargs: None
steering_receipts = []
def publish_sendcan(frames, valid=True):
# This idle transport fixture confirms only the commands actually sent.
if valid:
steering_receipts.extend((address, bytes(data), 128)
for address, data, bus in frames if address == 0x180 and bus == 0)
card.publish_sendcan = publish_sendcan
published = {}
card.pm.send = lambda name, message: published.__setitem__(name, message.as_reader())
for tick in range(20):
@@ -245,6 +253,8 @@ def test_actual_card_retires_rejected_cold_wait_before_next_request():
control = messaging.new_message('carControl', valid=True, logMonoTime=now)
card.sm.update_msgs(now/1e9, [m.as_reader() for m in messages]+[control.as_reader()])
rows = parse(card, now, counter=tick % 4, packets_only=True)
rows = steering_receipts + rows
steering_receipts.clear()
batch = messaging.log_from_bytes(module.can_list_to_can_capnp(rows)).as_builder()
batch.logMonoTime = now
with patch.object(module, 'REPLAY', False), \
@@ -84,6 +84,7 @@ def joined_case(cleanup, bridge, *, c9=False, pedal='none', engage=False, cp=Non
bridge.reset_host()
packer = CANPacker(DBC[card.CP.carFingerprint][Bus.pt])
receipt_queue = deque()
steering_receipts = []
sd.steering_companion = SteeringCompanion(sock=object())
original_receive = messaging.recv_one_or_none
original_update = sd.sm.update_msgs
@@ -235,10 +236,11 @@ def joined_case(cleanup, bridge, *, c9=False, pedal='none', engage=False, cp=Non
mock.patch.object(card_module.time, 'clock_gettime_ns', return_value=now), \
mock.patch.object(card_module.messaging, 'new_message', side_effect=card_message), \
mock.patch.object(card_module.messaging, 'drain_sock_raw', return_value=[b'physical-can']), \
mock.patch.object(card_module, 'can_capnp_to_list', return_value=[(now, rows)]), \
mock.patch.object(card_module, 'can_capnp_to_list', return_value=[(now - 1, list(steering_receipts)), (now, rows)]), \
mock.patch.object(card_module, 'REPLAY', False), mock.patch.object(card.sm, 'update'), \
mock.patch.object(card.RI, 'update', return_value=None):
cs, rd = card.state_update()
steering_receipts.clear()
if publish:
card.state_publish(cs, rd)
current['last_cs'] = cs
@@ -280,6 +282,8 @@ def joined_case(cleanup, bridge, *, c9=False, pedal='none', engage=False, cp=Non
assert not accepted
else:
assert accepted, (hex(frame.address), frame.src)
if frame.address == 0x180:
steering_receipts.append((frame.address, bytes(frame.dat), 128))
native_due = BASE
for tick in range(26):
@@ -410,7 +414,15 @@ def test_gm_initial_main_waits_on_original_soft_occurrence(index, braking, varia
cleanup.callback(card.vehicle_startup.close)
packer = CANPacker(DBC[card.CP.carFingerprint][Bus.pt])
card.ci_initialized = True
card.publish_sendcan = lambda *args, **kwargs: None
steering_receipts = []
def publish_sendcan(frames, valid=True):
# This idle transport fixture confirms only the commands actually sent.
if valid:
steering_receipts.extend((address, bytes(data), 128)
for address, data, bus in frames if address == 0x180 and bus == 0)
card.publish_sendcan = publish_sendcan
def packets(now, tick, main=True):
rows = parsed_packets(card.CP, packer, now, tick, 8., main)
@@ -494,6 +506,8 @@ def test_gm_initial_main_waits_on_original_soft_occurrence(index, braking, varia
card.sm.update_msgs(now / 1e9, [incoming.messages[k] for k in ('aolSafetyWire', 'pandaStates')] +
[axis.as_reader(), events.as_reader(), control.as_reader()])
rows = packets(now, tick, main=not (mutate and variation == 'main_off'))
rows = steering_receipts + rows
steering_receipts.clear()
batch = messaging.log_from_bytes(module.can_list_to_can_capnp(rows)).as_builder()
batch.logMonoTime = now
with patch.object(module, 'REPLAY', False), \
@@ -59,8 +59,12 @@ def test_initializing_gm_output_is_inactive_and_profile_complete(cp):
sent = []
last_ns = 0
last_counter = 0
steering_receipts = []
for tick in range(600):
now = 12_380_000_000 + tick * 10_000_000
if controller.bolt_steering_ack_counter:
controller.observe_steering_receipts([(now - 5_000_000, steering_receipts)])
steering_receipts = []
cs.loopback_lka_steering_cmd_updated = bool(last_ns)
cs.loopback_lka_steering_cmd_ts_nanos = last_ns
cs.loopback_lka_steering_cmd_counter = last_counter
@@ -74,6 +78,7 @@ def test_initializing_gm_output_is_inactive_and_profile_complete(cp):
last_ns = now
last_counter = (data[0] >> 4) & 3
sent.append(now)
steering_receipts.append((address, bytes(data), 128))
else:
assert controller.startup_acc_keepalive
brake_bus = (2 if controller.ordinary_sdgm_long or controller.volt_sdgm_long or
@@ -53,6 +53,7 @@ class TestBoltCcControlsLow(unittest.TestCase):
active_frames = gas_frames = cancelled_frames = 0
drive_pedal_frames = low_pedal_frames = stock_withdrawals = 0
last_feeds = {}
steering_receipts = []
internal_frames = 0
internal_status_frames = 0
from opendbc.safety.tests.test_gm_bolt_pedal import TestGmBoltPedalSafety
@@ -100,7 +101,8 @@ class TestBoltCcControlsLow(unittest.TestCase):
internal_frames += 1
internal_status_frames += int(address == 0x3D1)
libsafety_py.libsafety.safety_tick()
cs = ci.update([(now, frames)])
cs = ci.update([(now - 5_000_000, steering_receipts), (now, frames)])
steering_receipts = []
self.assertTrue(cs.canValid)
expected_gear = (structs.CarState.GearShifter.drive if (stock_acc and tick < 180) or 180 <= tick < 220
else structs.CarState.GearShifter.low)
@@ -178,6 +180,8 @@ class TestBoltCcControlsLow(unittest.TestCase):
last_feeds[frame[0]] = frame[1]
else:
self.assertTrue(allowed, (tick, hex(frame[0])))
if frame[0] == 0x180:
steering_receipts.append((frame[0], bytes(frame[1]), 128))
if stock_acc and (60 <= tick < 100 or 220 <= tick < 240):
pedals = [frame for frame in commands if frame[0] == 0x200]
for frame in pedals:
+1 -1
View File
@@ -1 +1 @@
{"protected_inventory_sha256": "ca816095734ed05a1df904518ae8fba5c046d54795aeb5d2d5994ad81cdbf2c5", "schema_version": 1}
{"protected_inventory_sha256": "5db79cb8c42032788e5f19f02eb3eae22e79b7e7a2b8f47022f3225107b36161", "schema_version": 1}