From 4f4cb4e7d9e3d825d0d4b2056f24e7ea86aa18cb Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Fri, 23 Oct 2026 22:43:56 -0500 Subject: [PATCH] Align source fixtures and cover composite MAIN freshness --- .../car/toyota/tests/test_prius_inactive.py | 4 +- .../opendbc/car/toyota/tests/test_retrofit.py | 22 ++++---- .../opendbc/car/toyota/tests/test_zss.py | 4 +- .../opendbc/safety/tests/test_toyota_pedal.py | 6 +- .../safety/tests/test_toyota_pedal_parent.py | 56 +++++++++++++++++++ .../aol/tests/test_full_engagement.py | 9 ++- openpilot/starpilot/aol/tests/test_gm.py | 2 +- .../toyota/tests/test_legacy_advert_filter.py | 2 +- .../tests/test_native_wheel_callbacks.py | 2 +- .../flm/tests/test_calibration_lifecycle.py | 4 +- prebuilt.json | 2 +- 11 files changed, 87 insertions(+), 26 deletions(-) diff --git a/opendbc_repo/opendbc/car/toyota/tests/test_prius_inactive.py b/opendbc_repo/opendbc/car/toyota/tests/test_prius_inactive.py index 3fd93a2738..34c0bfddac 100644 --- a/opendbc_repo/opendbc/car/toyota/tests/test_prius_inactive.py +++ b/opendbc_repo/opendbc/car/toyota/tests/test_prius_inactive.py @@ -16,9 +16,9 @@ from openpilot.starpilot.car.toyota.prius_preferences import PriusFilterPreferen def make_ci(identity, params, *, standstill=False): rack = structs.CarParams.CarFw.new_message(ecu=structs.CarParams.Ecu.eps, - fwVersion=b'8965B47070' + bytes(6)) + fwVersion=b'8965B47070' + bytes(6), brand='toyota', address=0x7A1) cp = CarInterface.get_params(identity, {0: {0x2FF: 4}, 1: {}, 2: {}}, [rack], False, False, False) - assert cp.safetyConfigs[0].safetyParam == 4169 + assert cp.safetyConfigs[0].safetyParam == 0xD049 ci = CarInterface(cp) ci.CC.prius_filter_input = PriusFilterPreference(cp, params) state = structs.CarState(canValid=True, canTimeout=False, standstill=standstill, diff --git a/opendbc_repo/opendbc/car/toyota/tests/test_retrofit.py b/opendbc_repo/opendbc/car/toyota/tests/test_retrofit.py index 989cb4536e..60ff37df43 100644 --- a/opendbc_repo/opendbc/car/toyota/tests/test_retrofit.py +++ b/opendbc_repo/opendbc/car/toyota/tests/test_retrofit.py @@ -12,12 +12,12 @@ def params(car, fp=None, alpha=False): class TestRetrofit(unittest.TestCase): def test_prius_smart_dsu_requires_exact_rack_and_source(self): from opendbc.car.structs import CarParams - rack = CarParams.CarFw.new_message(ecu=CarParams.Ecu.eps, fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00') + rack = CarParams.CarFw.new_message(ecu=CarParams.Ecu.eps, fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00', brand='toyota', address=0x7A1) from opendbc.car.toyota.prius_longitudinal import enabled from opendbc.car.toyota.prius_longitudinal import stopping_decel_rate for alpha in (False, True): cp = CarInterface.get_params(CAR.TOYOTA_PRIUS_RETROFIT, {0: {0x2FF: 4}, 1: {}, 2: {}}, [rack], alpha, False, False) - self.assertEqual(cp.safetyConfigs[0].safetyParam, 4169) + self.assertEqual(cp.safetyConfigs[0].safetyParam, 0xD049) self.assertTrue(enabled(cp)) self.assertFalse(cp.dashcamOnly) self.assertTrue(cp.openpilotLongitudinalControl) @@ -29,14 +29,14 @@ class TestRetrofit(unittest.TestCase): automatic = CarInterface.get_params(CAR.TOYOTA_PRIUS, {0: {0x2FF: 4}, 1: {}, 2: {}}, [rack], False, False, False) self.assertTrue(enabled(automatic)) self.assertEqual(automatic.carFingerprint, CAR.TOYOTA_PRIUS) - self.assertEqual(automatic.safetyConfigs[0].safetyParam, 4169) + self.assertEqual(automatic.safetyConfigs[0].safetyParam, 0xD049) self.assertFalse(automatic.flags & ToyotaFlags.TSS2) self.assertAlmostEqual(automatic.steerActuatorDelay, .14) from opendbc.car.toyota.prius_longitudinal import configured, prepare_stock self.assertTrue(prepare_stock(automatic)) self.assertTrue(configured(automatic)) self.assertFalse(enabled(automatic)) - self.assertEqual(automatic.safetyConfigs[0].safetyParam, 4681) + self.assertEqual(automatic.safetyConfigs[0].safetyParam, 0xD249) self.assertFalse(automatic.openpilotLongitudinalControl) self.assertTrue(automatic.pcmCruise) self.assertTrue(prepare_stock(automatic)) @@ -66,7 +66,7 @@ class TestRetrofit(unittest.TestCase): for field, value in (('passive', True), ('notCar', True), ('dashcamOnly', True), ('pcmCruise', False), ('openpilotLongitudinalControl', True), ('secOcRequired', True), ('flags', int(ToyotaFlags.GAS_INTERCEPTOR)), - ('carFingerprint', CAR.TOYOTA_COROLLA), ('alternativeExperience', 160)): + ('carFingerprint', CAR.TOYOTA_COROLLA), ('alternativeExperience', 96)): rejected = cp.as_reader().as_builder() setattr(rejected, field, value) self.assertFalse(qualified(rejected), field) @@ -75,7 +75,7 @@ class TestRetrofit(unittest.TestCase): rejected.safetyConfigs[0].safetyParam = word self.assertFalse(qualified(rejected), word) self.assertFalse(native_accepts_cp(rejected, int(structs.CarParams.SafetyModel.toyota), word), word) - for ae in (0, 1, 33, 128, 160, 256, 288): + for ae in (0, 1, 33, 128, 96, 256, 544): rejected = cp.as_reader().as_builder() rejected.alternativeExperience = ae self.assertFalse(qualified(rejected, marked_only=True), ae) @@ -89,7 +89,7 @@ class TestRetrofit(unittest.TestCase): rejected = cp.as_reader().as_builder() rejected.safetyConfigs[0].safetyModel = structs.CarParams.SafetyModel.noOutput self.assertFalse(qualified(rejected)) - for fp in ({0: {0x2FF: 8}, 1: {}, 2: {}}, {0: {}, 1: {}, 2: {0x343: 8}}): + for fp in ({0: {0x2FF: 7}, 1: {}, 2: {}}, {0: {}, 1: {}, 2: {0x343: 8}}): takeover = params(CAR.TOYOTA_MATRIX_RETROFIT, fp, alpha) self.assertTrue(takeover.dashcamOnly) self.assertFalse(qualified(takeover)) @@ -114,7 +114,7 @@ class TestRetrofit(unittest.TestCase): def test_observed_takeover_requires_paired_port(self): for car in (CAR.TOYOTA_MATRIX_RETROFIT, CAR.TOYOTA_PRIUS_RETROFIT): - for fp in ({0: {0x2FF: 8}, 1: {}, 2: {}}, + for fp in ({0: {0x2FF: 7}, 1: {}, 2: {}}, {0: {}, 1: {}, 2: {0x343: 8}}): cp = params(car, fp, True) self.assertTrue(cp.dashcamOnly) @@ -133,7 +133,7 @@ class TestRetrofit(unittest.TestCase): def test_retrofit_rack_is_distinct_from_standard_prius(self): from opendbc.car.structs import CarParams - fw = CarParams.CarFw.new_message(ecu=CarParams.Ecu.eps, fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00') + fw = CarParams.CarFw.new_message(ecu=CarParams.Ecu.eps, fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00', brand='toyota', address=0x7A1) fp = {0: {}, 1: {}, 2: {}} cp = CarInterface.get_params(CAR.TOYOTA_PRIUS_RETROFIT, fp, [fw], False, False, False) self.assertFalse(cp.dashcamOnly) @@ -170,7 +170,7 @@ class TestRetrofit(unittest.TestCase): from opendbc.car.toyota.values import DBC rack = structs.CarParams.CarFw.new_message(ecu=structs.CarParams.Ecu.eps, - fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00') + fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00', brand='toyota', address=0x7A1) cases = ((CAR.TOYOTA_PRIUS, False, 'ACC_CONTROL', 'DISTANCE', 0), (CAR.TOYOTA_PRIUS_RETROFIT, False, 'ACC_CONTROL', 'DISTANCE', 0), (CAR.TOYOTA_PRIUS, True, 'SDSU', 'FD_BUTTON', 0), @@ -179,7 +179,7 @@ class TestRetrofit(unittest.TestCase): (CAR.TOYOTA_COROLLA_TSS2, False, 'ACC_CONTROL', 'DISTANCE', 2)) for car, filtered, message, signal, bus in cases: with self.subTest(car=car, filtered=filtered): - cp = CarInterface.get_params(car, {0: {0x2FF: 4} if filtered else {}, 1: {}, 2: {}}, + cp = CarInterface.get_params(car, {0: {0x2FF: 8} if filtered else {}, 1: {}, 2: {}}, [rack] if filtered else [], False, False, False) cs = CarState(cp) parsers = cs.get_can_parsers(cp) diff --git a/opendbc_repo/opendbc/car/toyota/tests/test_zss.py b/opendbc_repo/opendbc/car/toyota/tests/test_zss.py index 7f706e6c6f..b3afad1ab2 100644 --- a/opendbc_repo/opendbc/car/toyota/tests/test_zss.py +++ b/opendbc_repo/opendbc/car/toyota/tests/test_zss.py @@ -72,10 +72,10 @@ class TestZssCaller(unittest.TestCase): fwVersion=b'8965B47070' + bytes(6)) cp = CarInterface.get_params(CAR.TOYOTA_PRIUS, {0: {0x23: 8, 0x2FF: 8}, 1: {}, 2: {}}, [rack], False, False, False) self.assertTrue(configured(cp)) - self.assertEqual(cp.safetyConfigs[0].safetyParam, 4169) + self.assertEqual(cp.safetyConfigs[0].safetyParam, 0x8049) sibling = cp.as_reader().as_builder() sibling.flags |= 1 << 17 self.assertFalse(configured(sibling)) self.assertTrue(prepare_stock(cp)) - self.assertEqual(cp.safetyConfigs[0].safetyParam, 4681) + self.assertEqual(cp.safetyConfigs[0].safetyParam, 0x8249) self.assertTrue(cp.flags & ToyotaFlags.ZSS) diff --git a/opendbc_repo/opendbc/safety/tests/test_toyota_pedal.py b/opendbc_repo/opendbc/safety/tests/test_toyota_pedal.py index 645f327aec..dc3f1534c1 100644 --- a/opendbc_repo/opendbc/safety/tests/test_toyota_pedal.py +++ b/opendbc_repo/opendbc/safety/tests/test_toyota_pedal.py @@ -55,7 +55,7 @@ class TestPairedPedal(unittest.TestCase): def test_factory_current_words_and_exact_negatives(self): self.assertTrue(pedal.configured(self.cp)) self.assertEqual(self.cp.safetyConfigs[0].safetyParam, 0x2049) - for fp in ({0: {0x201: 7}, 1: {}, 2: {}}, {0: {}, 1: {0x201: 6}, 2: {}}, {0: {0x201: 6, 0x2FF: 8}, 1: {}, 2: {}}): + for fp in ({0: {0x201: 7}, 1: {}, 2: {}}, {0: {}, 1: {0x201: 6}, 2: {}}, {0: {0x201: 5, 0x2FF: 8}, 1: {}, 2: {}}): cp = CarInterface.get_params(self.candidate, fp, firmware(self.candidate), False, False, False) self.assertFalse(pedal.configured(cp)) self.assertTrue(pedal.prepare_stock(self.cp)) @@ -107,9 +107,9 @@ class TestPairedPedal(unittest.TestCase): self.safety.set_timer(1_300_001) self.assertFalse(self.tx(0.1)) self.assertTrue(self.tx(0)) - for word in (0x2149, 0x2849, 0x3049, 0xA049): + for word in (0x2149, 0x2849, 0x3048, 0xA048): self.init(word) - self.assertFalse(self.tx(0)) + self.assertFalse(self.tx(0), hex(word)) self.assertFalse(self.tx(0.1)) def test_native_command_pair_bounds_checksum_bus_and_neutral(self): diff --git a/opendbc_repo/opendbc/safety/tests/test_toyota_pedal_parent.py b/opendbc_repo/opendbc/safety/tests/test_toyota_pedal_parent.py index 4fbe3954ec..77c22e4880 100644 --- a/opendbc_repo/opendbc/safety/tests/test_toyota_pedal_parent.py +++ b/opendbc_repo/opendbc/safety/tests/test_toyota_pedal_parent.py @@ -44,3 +44,59 @@ def test_parent_catalog_and_warm_switch_are_exact(word, parent): finally: safety.set_alternative_experience(0) safety.set_safety_hooks(structs.CarParams.SafetyModel.noOutput, 0) + + +@pytest.mark.parametrize('word', (0xF149, 0xF349, 0xF04D, 0xF24D)) +@pytest.mark.parametrize('fault', ('main_off', 'main_stale')) +def test_composite_alternate_main_keeps_its_independent_freshness(word, fault): + from opendbc.can import CANPacker + from opendbc.car import Bus + from opendbc.car.toyota import pedal + from opendbc.car.toyota.values import CAR, DBC + + safety = libsafety_py.libsafety + safety.init_tests() + safety.set_alternative_experience(32) + assert safety.set_safety_hooks(structs.CarParams.SafetyModel.toyota, word) == 0 + safety.set_aol_test_heartbeat(True) + identity = CAR.LEXUS_GS_F if word in (0xF149, 0xF349) else CAR.LEXUS_IS + packer = CANPacker(DBC[identity][Bus.pt]) + now = 1_000_000 + counter = 0 + + def tick(*, main=True, omit_main=False): + nonlocal now, counter + now += 10_000 + safety.set_timer(now) + frames = helpers.physical(packer, cruise=True) + frames.append(packer.make_can_msg('PCS_HUD', 0, {})) + frames.append(packer.make_can_msg('PCM_CRUISE_ALT', 0, {'UI_SET_SPEED': 90})) + if not omit_main: + frames.append(packer.make_can_msg('DSU_CRUISE', 0, {'MAIN_ON': main, 'SET_SPEED': 90})) + address, data, bus = packer.make_can_msg('GAS_SENSOR', 0, { + 'INTERCEPTOR_GAS': 0, 'INTERCEPTOR_GAS2': 0, 'COUNTER_PEDAL': counter, 'STATE': 0}) + counter = (counter + 1) & 15 + data = bytearray(data) + data[-1] = pedal.checksum(data) + frames.append((address, bytes(data), bus)) + for address, data, bus in frames: + safety.safety_rx_hook(libsafety_py.make_CANPacket(address, bus, data)) + safety.safety_tick() + safety.aol_set_host_request(3) + + try: + assert safety.current_safety_config.rx_checks_len == 8 + for _ in range(30): + tick() + expected = 1 if word in (0xF349, 0xF24D) else 3 + assert safety.safety_config_valid() + assert safety.aol_get_permission_mask() == expected + for _ in range(40): + tick(main=False, omit_main=fault == 'main_stale') + assert safety.aol_get_permission_mask() == 0 + for _ in range(30): + tick() + assert safety.aol_get_permission_mask() == expected + finally: + safety.set_alternative_experience(0) + safety.set_safety_hooks(structs.CarParams.SafetyModel.noOutput, 0) diff --git a/openpilot/starpilot/aol/tests/test_full_engagement.py b/openpilot/starpilot/aol/tests/test_full_engagement.py index 1d6e455f99..ca3eadc58b 100644 --- a/openpilot/starpilot/aol/tests/test_full_engagement.py +++ b/openpilot/starpilot/aol/tests/test_full_engagement.py @@ -123,18 +123,21 @@ def test_vehicle_fault_rearm_cannot_be_bypassed(factory, field): -def test_gm_resolved_fault_accepts_new_successful_engagement_only(): +def test_gm_resolved_fault_rearms_only_after_healthy_main_observation(): owner, cs = GmAolCardIntent(SETTINGS), state() observe(owner, cs, 1, enabled=False, active=False) owner.update(cs, now_ns=2, fault_active=True) assert owner._main_cycle_required and not owner.allowed_latch owner.update(cs, now_ns=3, fault_active=False) - assert owner._main_cycle_required and not owner.allowed_latch + assert not owner._main_cycle_required and owner.allowed_latch observe(owner, cs, 3, active=False) - assert owner._main_cycle_required and not owner.allowed_latch + assert not owner._main_cycle_required and owner.allowed_latch observe(owner, cs, 4) assert owner.allowed_latch and not owner._main_cycle_required assert not owner.pause_lateral + cs.cruiseState.available = False + owner.update(cs, now_ns=5, fault_active=False) + assert not owner.allowed_latch def test_physical_owners_cannot_be_forged_by_host_engagement(): diff --git a/openpilot/starpilot/aol/tests/test_gm.py b/openpilot/starpilot/aol/tests/test_gm.py index 96b7cc9a92..850b620c53 100644 --- a/openpilot/starpilot/aol/tests/test_gm.py +++ b/openpilot/starpilot/aol/tests/test_gm.py @@ -866,7 +866,7 @@ class TestGmAol(unittest.TestCase): requested = [] for tick in range(18): now = 1_000_000_000 + tick * 10_000_000 - out, sources = feed_car(ci, packer, now, counter=tick % 4, active=False, brake=True, regen=True) + out, sources = feed_car(ci, packer, now, counter=tick % 4, active=False, brake=True, regen=True, eps_status=1) sources = [source for source in sources if source[0] not in (0x1C4, 0xBE, 0xF1)] sources.extend([packer.make_can_msg('AcceleratorPedal2', 0, {'CruiseState': 0}), packer.make_can_msg('ECMAcceleratorPos', 0, {'BrakePedalPos': 12}), diff --git a/openpilot/starpilot/car/toyota/tests/test_legacy_advert_filter.py b/openpilot/starpilot/car/toyota/tests/test_legacy_advert_filter.py index 831b898ba2..a6a1cf979b 100644 --- a/openpilot/starpilot/car/toyota/tests/test_legacy_advert_filter.py +++ b/openpilot/starpilot/car/toyota/tests/test_legacy_advert_filter.py @@ -16,7 +16,7 @@ def test_complete_sdsu_cp_tunes_retained_for_advertisement(candidate, stock): fp[0][0x2FF] = 4 new = CarInterface.get_params(candidate, fp, fw, False, False, False) assert legacy_advert_filter.enabled(new) and advert_filter.enabled(new) - assert not toyota_auto_hold_supported(new) + assert toyota_auto_hold_supported(new) == toyota_auto_hold_supported(old) if stock: assert rav4h_filter.prepare_stock(old) and advert_filter.prepare_stock(new) assert legacy_advert_filter.configured(new) diff --git a/openpilot/starpilot/controllers/tests/test_native_wheel_callbacks.py b/openpilot/starpilot/controllers/tests/test_native_wheel_callbacks.py index 0f4c65500d..4d89b06ee5 100644 --- a/openpilot/starpilot/controllers/tests/test_native_wheel_callbacks.py +++ b/openpilot/starpilot/controllers/tests/test_native_wheel_callbacks.py @@ -137,7 +137,7 @@ def test_toyota_default_gap_callback_saves_personality_once(native_session, monk runtime, session, ui, _, _ = native_session rack = structs.CarParams.CarFw.new_message(ecu=structs.CarParams.Ecu.eps, fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00') - ui.CP = CarInterface.get_params(getattr(CAR, vehicle), {0: {0x2FF: 4} if filtered else {}, 1: {}, 2: {}}, + ui.CP = CarInterface.get_params(getattr(CAR, vehicle), {0: {0x2FF: 8} if filtered else {}, 1: {}, 2: {}}, [rack] if filtered else [], False, False, False) ui.has_longitudinal_control = ui.CP.openpilotLongitudinalControl ui.personality = 1 diff --git a/openpilot/starpilot/flm/tests/test_calibration_lifecycle.py b/openpilot/starpilot/flm/tests/test_calibration_lifecycle.py index 5110fe2a4e..5df58cc45a 100644 --- a/openpilot/starpilot/flm/tests/test_calibration_lifecycle.py +++ b/openpilot/starpilot/flm/tests/test_calibration_lifecycle.py @@ -218,6 +218,7 @@ def test_actual_main_source_reader_reuses_lifecycle_for_cache_and_persistence(): '__getitem__': lambda self, key: cal, 'all_checks': lambda self, keys: True, })() + sm.seen = {'extrinsicsCalibration': True} sm.valid = {'extrinsicsCalibration': True} sm.logMonoTime = {'extrinsicsCalibration': BASE} sm.recv_time = {'extrinsicsCalibration': BASE / 1e9} @@ -250,7 +251,8 @@ def test_actual_main_source_reader_reuses_lifecycle_for_cache_and_persistence(): assert persistence.current_sources('fresh-identity', fresh.source_epoch)[0] == 'fresh-identity' for tick in range(100): gap = BASE + (tick + 1) * 1_000_000_000 - assert not source_reader(gap).enabled + retained = source_reader(gap) + assert retained.enabled and retained.source_epoch == fresh.source_epoch sm.logMonoTime['extrinsicsCalibration'] = gap + 1 sm.recv_time['extrinsicsCalibration'] = (gap + 1) / 1e9 resumed = source_reader(gap + 1) diff --git a/prebuilt.json b/prebuilt.json index f3f9783285..c1aa13e41c 100644 --- a/prebuilt.json +++ b/prebuilt.json @@ -1 +1 @@ -{"protected_inventory_sha256": "91232f8d24f79ff480b1bf29dfc58b1ec124af6001e6793a0326068b19192c18", "schema_version": 1} +{"protected_inventory_sha256": "ffb6b1825429c5d33a8adecb7f88aa090fb9f21d84c94b9cac3e37267e6bd4f4", "schema_version": 1}