forked from IQ.Lvbs/IQ.Pilot
IQ.Pilot Prebuilt Release @ ab07000
This commit is contained in:
129
iqdbc_repo/iqdbc/car/volkswagen/tests/test_volkswagen.py
Normal file
129
iqdbc_repo/iqdbc/car/volkswagen/tests/test_volkswagen.py
Normal file
@@ -0,0 +1,129 @@
|
||||
import random
|
||||
import re
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from iqdbc.car import structs
|
||||
from iqdbc.car.volkswagen.carstate import CarState
|
||||
from iqdbc.car.structs import CarParams
|
||||
from iqdbc.car.volkswagen.values import CAR, FW_QUERY_CONFIG, WMI
|
||||
from iqdbc.car.volkswagen.fingerprints import FW_VERSIONS
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
CHASSIS_CODE_PATTERN = re.compile('[A-Z0-9]{2}')
|
||||
# TODO: determine the unknown groups
|
||||
SPARE_PART_FW_PATTERN = re.compile(b'\xf1\x87(?P<gateway>[0-9][0-9A-Z]{2})(?P<unknown>[0-9][0-9A-Z][0-9])(?P<unknown2>[0-9A-Z]{2}[0-9])([A-Z0-9]| )')
|
||||
|
||||
|
||||
class TestVolkswagenPlatformConfigs:
|
||||
def test_spare_part_fw_pattern(self, subtests):
|
||||
# Relied on for determining if a FW is likely VW
|
||||
for platform, ecus in FW_VERSIONS.items():
|
||||
with subtests.test(platform=platform.value):
|
||||
for fws in ecus.values():
|
||||
for fw in fws:
|
||||
assert SPARE_PART_FW_PATTERN.match(fw) is not None, f"Bad FW: {fw}"
|
||||
|
||||
def test_chassis_codes(self, subtests):
|
||||
for platform in CAR:
|
||||
with subtests.test(platform=platform.value):
|
||||
assert len(platform.config.wmis) > 0, "WMIs not set"
|
||||
assert len(platform.config.chassis_codes) > 0, "Chassis codes not set"
|
||||
assert all(CHASSIS_CODE_PATTERN.match(cc) for cc in
|
||||
platform.config.chassis_codes), "Bad chassis codes"
|
||||
|
||||
# No two platforms should share chassis codes
|
||||
for comp in CAR:
|
||||
if platform == comp:
|
||||
continue
|
||||
|
||||
shared_chassis_codes = platform.config.chassis_codes & comp.config.chassis_codes
|
||||
if len(shared_chassis_codes) == 0:
|
||||
continue
|
||||
|
||||
# A shared chassis code is unambiguous when the VIN WMI separates the candidates.
|
||||
if platform.config.wmis.isdisjoint(comp.config.wmis):
|
||||
continue
|
||||
|
||||
platform_model_years = getattr(platform.config, "model_years", set())
|
||||
comp_model_years = getattr(comp.config, "model_years", set())
|
||||
if platform_model_years and comp_model_years and platform_model_years.isdisjoint(comp_model_years):
|
||||
continue
|
||||
|
||||
assert set() == shared_chassis_codes, f"Shared chassis codes: {comp}"
|
||||
|
||||
def test_custom_fuzzy_fingerprinting(self, subtests):
|
||||
all_radar_fw = list({fw for ecus in FW_VERSIONS.values() for fw in ecus.get((Ecu.fwdRadar, 0x757, None), [])})
|
||||
|
||||
for platform in CAR:
|
||||
with subtests.test(platform=platform.name):
|
||||
# Fuzzy matching keys off the radar ECU (CHECK_FUZZY_ECUS), so a platform that
|
||||
# declares no radar ECU can never be VIN-matched and should never be expected to match.
|
||||
platform_has_radar = (Ecu.fwdRadar, 0x757, None) in FW_VERSIONS.get(platform, {})
|
||||
for wmi in WMI:
|
||||
for chassis_code in platform.config.chassis_codes | {"00"}:
|
||||
platform_model_years = getattr(platform.config, "model_years", set())
|
||||
model_years = platform_model_years if platform_model_years else {"0"}
|
||||
for model_year in model_years | {"0"}:
|
||||
vin = ["0"] * 17
|
||||
vin[0:3] = wmi
|
||||
vin[6:8] = chassis_code
|
||||
vin[9] = model_year
|
||||
vin = "".join(vin)
|
||||
|
||||
# Check a few FW cases - expected, unexpected
|
||||
for radar_fw in random.sample(all_radar_fw, 5) + [b'\xf1\x875Q0907572G \xf1\x890571', b'\xf1\x877H9907572AA\xf1\x890396']:
|
||||
model_year_match = len(platform_model_years) == 0 or model_year in platform_model_years
|
||||
should_match = ((wmi in platform.config.wmis and chassis_code in platform.config.chassis_codes and model_year_match) and
|
||||
radar_fw in all_radar_fw and platform_has_radar)
|
||||
|
||||
live_fws = {(0x757, None): [radar_fw]}
|
||||
matches = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(live_fws, vin, FW_VERSIONS)
|
||||
|
||||
expected_matches = {platform} if should_match else set()
|
||||
assert expected_matches == matches, "Bad match"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("button_type", (
|
||||
structs.CarState.ButtonEvent.Type.setCruise,
|
||||
structs.CarState.ButtonEvent.Type.resumeCruise,
|
||||
))
|
||||
def test_button_enable_is_blocked_while_cruise_fault_lateral_mode_is_still_faulted(button_type):
|
||||
state = object.__new__(CarState)
|
||||
state.CP = SimpleNamespace(pcmCruise=False)
|
||||
state.cruise_fault_lateral_active = True
|
||||
state.cruise_faulted = True
|
||||
|
||||
button_events = [structs.CarState.ButtonEvent(pressed=False, type=button_type)]
|
||||
|
||||
assert not state.update_button_enable(button_events)
|
||||
|
||||
|
||||
def test_button_enable_recovers_once_cruise_fault_clears():
|
||||
state = object.__new__(CarState)
|
||||
state.CP = SimpleNamespace(pcmCruise=False)
|
||||
state.cruise_fault_lateral_active = True
|
||||
state.cruise_faulted = False
|
||||
|
||||
button_events = [structs.CarState.ButtonEvent(
|
||||
pressed=False,
|
||||
type=structs.CarState.ButtonEvent.Type.setCruise,
|
||||
)]
|
||||
|
||||
assert state.update_button_enable(button_events)
|
||||
|
||||
|
||||
def test_pq_hca_ready_does_not_complete_eps_initialization():
|
||||
state = object.__new__(CarState)
|
||||
state.eps_init_complete = False
|
||||
|
||||
state.frame = 0
|
||||
assert state.update_hca_state("READY", ready_confirms_init=False) == (True, False)
|
||||
|
||||
state.frame = 317
|
||||
assert state.update_hca_state("FAULT", ready_confirms_init=False) == (True, False)
|
||||
|
||||
state.frame = 1001
|
||||
assert state.update_hca_state("FAULT", ready_confirms_init=False) == (False, True)
|
||||
Reference in New Issue
Block a user