|
|
|
@ -1,11 +1,11 @@
|
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
# pylint: disable=E1101
|
|
|
|
|
import argparse
|
|
|
|
|
import os
|
|
|
|
|
import importlib
|
|
|
|
|
import unittest
|
|
|
|
|
from collections import defaultdict, Counter
|
|
|
|
|
from typing import List, Optional, Tuple
|
|
|
|
|
from parameterized import parameterized_class
|
|
|
|
|
|
|
|
|
|
from cereal import log, car
|
|
|
|
|
from common.realtime import DT_CTRL
|
|
|
|
@ -16,9 +16,10 @@ from selfdrive.car.gm.values import CAR as GM
|
|
|
|
|
from selfdrive.car.honda.values import CAR as HONDA, HONDA_BOSCH
|
|
|
|
|
from selfdrive.car.hyundai.values import CAR as HYUNDAI
|
|
|
|
|
from selfdrive.car.toyota.values import CAR as TOYOTA
|
|
|
|
|
from selfdrive.car.tests.routes import routes, non_tested_cars
|
|
|
|
|
from selfdrive.car.tests.routes import routes, non_tested_cars, TestRoute
|
|
|
|
|
from selfdrive.test.openpilotci import get_url
|
|
|
|
|
from tools.lib.logreader import LogReader
|
|
|
|
|
from tools.lib.route import Route
|
|
|
|
|
|
|
|
|
|
from panda.tests.safety import libpandasafety_py
|
|
|
|
|
from panda.tests.safety.common import package_can_msg
|
|
|
|
@ -36,7 +37,7 @@ ignore_addr_checks_valid = [
|
|
|
|
|
# build list of test cases
|
|
|
|
|
routes_by_car = defaultdict(set)
|
|
|
|
|
for r in routes:
|
|
|
|
|
routes_by_car[r.car_fingerprint].add(r.route)
|
|
|
|
|
routes_by_car[r.car_model].add(r.route)
|
|
|
|
|
|
|
|
|
|
test_cases: List[Tuple[str, Optional[str]]] = []
|
|
|
|
|
for i, c in enumerate(sorted(all_known_cars())):
|
|
|
|
@ -44,7 +45,6 @@ for i, c in enumerate(sorted(all_known_cars())):
|
|
|
|
|
test_cases.extend((c, r) for r in routes_by_car.get(c, (None, )))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@parameterized_class(('car_model', 'route'), test_cases)
|
|
|
|
|
class TestCarModel(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@ -58,7 +58,10 @@ class TestCarModel(unittest.TestCase):
|
|
|
|
|
disable_radar = False
|
|
|
|
|
for seg in (2, 1, 0):
|
|
|
|
|
try:
|
|
|
|
|
lr = LogReader(get_url(cls.route, seg))
|
|
|
|
|
if cls.ci:
|
|
|
|
|
lr = LogReader(get_url(cls.route, seg))
|
|
|
|
|
else:
|
|
|
|
|
lr = LogReader(Route(cls.route).log_paths()[seg])
|
|
|
|
|
except Exception:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
@ -249,5 +252,33 @@ class TestCarModel(unittest.TestCase):
|
|
|
|
|
failed_checks = {k: v for k, v in checks.items() if v > 0}
|
|
|
|
|
self.assertFalse(len(failed_checks), f"panda safety doesn't agree with openpilot: {failed_checks}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_tests(_routes):
|
|
|
|
|
# TODO: see if there's a cleaner way to do this
|
|
|
|
|
test_cases = unittest.TestSuite()
|
|
|
|
|
for test_route in _routes:
|
|
|
|
|
test = TestCarModel
|
|
|
|
|
for field in test_route._fields:
|
|
|
|
|
setattr(test, field, getattr(test_route, field))
|
|
|
|
|
|
|
|
|
|
# discover tests
|
|
|
|
|
test_cases.addTest(unittest.TestLoader().loadTestsFromTestCase(test))
|
|
|
|
|
return test_cases
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
unittest.main()
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
|
parser.add_argument("--route", help="Specify route to run tests on")
|
|
|
|
|
parser.add_argument("--car_model", help="Specify car model for test route")
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
# Run on user-specified route
|
|
|
|
|
if args.route is not None:
|
|
|
|
|
# TODO: do we want to require specifying car model?
|
|
|
|
|
assert args.car_model is not None, "Car model needed for tests"
|
|
|
|
|
test_route = TestRoute(args.route, args.car_model, ci=False)
|
|
|
|
|
test_cases = load_tests([test_route])
|
|
|
|
|
else:
|
|
|
|
|
test_cases = load_tests(routes)
|
|
|
|
|
|
|
|
|
|
unittest.TextTestRunner().run(test_cases)
|
|
|
|
|