-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
470 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from parameterized import parameterized | ||
|
||
from openpilot.selfdrive.car.can_definitions import CanData | ||
from openpilot.selfdrive.car.car_helpers import FRAME_FINGERPRINT, can_fingerprint | ||
from openpilot.selfdrive.car.fingerprints import _FINGERPRINTS as FINGERPRINTS | ||
|
||
|
||
class TestCanFingerprint: | ||
@parameterized.expand(list(FINGERPRINTS.items())) | ||
def test_can_fingerprint(self, car_model, fingerprints): | ||
"""Tests online fingerprinting function on offline fingerprints""" | ||
|
||
for fingerprint in fingerprints: # can have multiple fingerprints for each platform | ||
can = [CanData(address=address, dat=b'\x00' * length, src=src) | ||
for address, length in fingerprint.items() for src in (0, 1)] | ||
|
||
fingerprint_iter = iter([can]) | ||
car_fingerprint, finger = can_fingerprint(lambda **kwargs: [next(fingerprint_iter, [])]) # noqa: B023 | ||
|
||
assert car_fingerprint == car_model | ||
assert finger[0] == fingerprint | ||
assert finger[1] == fingerprint | ||
assert finger[2] == {} | ||
|
||
def test_timing(self, subtests): | ||
# just pick any CAN fingerprinting car | ||
car_model = "CHEVROLET_BOLT_EUV" | ||
fingerprint = FINGERPRINTS[car_model][0] | ||
|
||
cases = [] | ||
|
||
# case 1 - one match, make sure we keep going for 100 frames | ||
can = [CanData(address=address, dat=b'\x00' * length, src=src) | ||
for address, length in fingerprint.items() for src in (0, 1)] | ||
cases.append((FRAME_FINGERPRINT, car_model, can)) | ||
|
||
# case 2 - no matches, make sure we keep going for 100 frames | ||
can = [CanData(address=1, dat=b'\x00' * 1, src=src) for src in (0, 1)] # uncommon address | ||
cases.append((FRAME_FINGERPRINT, None, can)) | ||
|
||
# case 3 - multiple matches, make sure we keep going for 200 frames to try to eliminate some | ||
can = [CanData(address=2016, dat=b'\x00' * 8, src=src) for src in (0, 1)] # common address | ||
cases.append((FRAME_FINGERPRINT * 2, None, can)) | ||
|
||
for expected_frames, car_model, can in cases: | ||
with subtests.test(expected_frames=expected_frames, car_model=car_model): | ||
frames = 0 | ||
|
||
def can_recv(**kwargs): | ||
nonlocal frames | ||
frames += 1 | ||
return [can] # noqa: B023 | ||
|
||
car_fingerprint, _ = can_fingerprint(can_recv) | ||
assert car_fingerprint == car_model | ||
assert frames == expected_frames + 2 # TODO: fix extra frames |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
from collections import defaultdict | ||
import pytest | ||
import re | ||
|
||
from openpilot.selfdrive.car.car_helpers import interfaces | ||
from openpilot.selfdrive.car.docs import get_all_car_docs | ||
from openpilot.selfdrive.car.docs_definitions import Cable, Column, PartType, Star | ||
from openpilot.selfdrive.car.honda.values import CAR as HONDA | ||
from openpilot.selfdrive.car.values import PLATFORMS | ||
|
||
|
||
class TestCarDocs: | ||
@classmethod | ||
def setup_class(cls): | ||
cls.all_cars = get_all_car_docs() | ||
|
||
def test_duplicate_years(self, subtests): | ||
make_model_years = defaultdict(list) | ||
for car in self.all_cars: | ||
with subtests.test(car_docs_name=car.name): | ||
make_model = (car.make, car.model) | ||
for year in car.year_list: | ||
assert year not in make_model_years[make_model], f"{car.name}: Duplicate model year" | ||
make_model_years[make_model].append(year) | ||
|
||
def test_missing_car_docs(self, subtests): | ||
all_car_docs_platforms = [name for name, config in PLATFORMS.items()] | ||
for platform in sorted(interfaces.keys()): | ||
with subtests.test(platform=platform): | ||
assert platform in all_car_docs_platforms, f"Platform: {platform} doesn't have a CarDocs entry" | ||
|
||
def test_naming_conventions(self, subtests): | ||
# Asserts market-standard car naming conventions by brand | ||
for car in self.all_cars: | ||
with subtests.test(car=car.name): | ||
tokens = car.model.lower().split(" ") | ||
if car.car_name == "hyundai": | ||
assert "phev" not in tokens, "Use `Plug-in Hybrid`" | ||
assert "hev" not in tokens, "Use `Hybrid`" | ||
if "plug-in hybrid" in car.model.lower(): | ||
assert "Plug-in Hybrid" in car.model, "Use correct capitalization" | ||
if car.make != "Kia": | ||
assert "ev" not in tokens, "Use `Electric`" | ||
elif car.car_name == "toyota": | ||
if "rav4" in tokens: | ||
assert "RAV4" in car.model, "Use correct capitalization" | ||
|
||
def test_torque_star(self, subtests): | ||
# Asserts brand-specific assumptions around steering torque star | ||
for car in self.all_cars: | ||
with subtests.test(car=car.name): | ||
# honda sanity check, it's the definition of a no torque star | ||
if car.car_fingerprint in (HONDA.HONDA_ACCORD, HONDA.HONDA_CIVIC, HONDA.HONDA_CRV, HONDA.HONDA_ODYSSEY, HONDA.HONDA_PILOT): | ||
assert car.row[Column.STEERING_TORQUE] == Star.EMPTY, f"{car.name} has full torque star" | ||
elif car.car_name in ("toyota", "hyundai"): | ||
assert car.row[Column.STEERING_TORQUE] != Star.EMPTY, f"{car.name} has no torque star" | ||
|
||
def test_year_format(self, subtests): | ||
for car in self.all_cars: | ||
with subtests.test(car=car.name): | ||
assert re.search(r"\d{4}-\d{4}", car.name) is None, f"Format years correctly: {car.name}" | ||
|
||
def test_harnesses(self, subtests): | ||
for car in self.all_cars: | ||
with subtests.test(car=car.name): | ||
if car.name == "comma body": | ||
pytest.skip() | ||
|
||
car_part_type = [p.part_type for p in car.car_parts.all_parts()] | ||
car_parts = list(car.car_parts.all_parts()) | ||
assert len(car_parts) > 0, f"Need to specify car parts: {car.name}" | ||
assert car_part_type.count(PartType.connector) == 1, f"Need to specify one harness connector: {car.name}" | ||
assert car_part_type.count(PartType.mount) == 1, f"Need to specify one mount: {car.name}" | ||
assert Cable.right_angle_obd_c_cable_1_5ft in car_parts, f"Need to specify a right angle OBD-C cable (1.5ft): {car.name}" |
Oops, something went wrong.