Skip to content

Commit

Permalink
move some car tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sshane committed Aug 16, 2024
1 parent 562d109 commit 9b57fb2
Show file tree
Hide file tree
Showing 4 changed files with 470 additions and 0 deletions.
56 changes: 56 additions & 0 deletions opendbc/car/test_can_fingerprint.py
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
74 changes: 74 additions & 0 deletions opendbc/car/test_docs.py
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}"
Loading

0 comments on commit 9b57fb2

Please sign in to comment.