Merge remote-tracking branch 'upstream/master' into disp-personality

pull/31760/head
Shane Smiskol 1 year ago
commit 6af6057ba7
  1. 12
      .vscode/settings.json
  2. 2
      pyproject.toml
  3. 5
      selfdrive/car/__init__.py
  4. 2
      selfdrive/car/card.py
  5. 5
      selfdrive/car/chrysler/values.py
  6. 6
      selfdrive/car/ford/values.py
  7. 6
      selfdrive/car/honda/values.py
  8. 6
      selfdrive/car/hyundai/values.py
  9. 5
      selfdrive/car/mazda/values.py
  10. 5
      selfdrive/car/nissan/interface.py
  11. 6
      selfdrive/car/subaru/values.py
  12. 3
      selfdrive/car/tests/routes.py
  13. 25
      selfdrive/car/tests/test_models.py
  14. 6
      selfdrive/car/toyota/values.py
  15. 6
      selfdrive/car/volkswagen/values.py
  16. 37
      selfdrive/test/helpers.py
  17. 60
      selfdrive/updated/tests/test_updated.py
  18. 6
      tools/car_porting/test_car_model.py

@ -12,5 +12,15 @@
"**/.git": true, "**/.git": true,
"**/.venv": true, "**/.venv": true,
"**/__pycache__": true "**/__pycache__": true
} },
"python.analysis.exclude": [
"**/.git",
"**/.venv",
"**/__pycache__",
// exclude directories should be using the symlinked version
"common/**",
"selfdrive/**",
"system/**",
"tools/**",
]
} }

@ -177,6 +177,8 @@ lint.ignore = ["E741", "E402", "C408", "ISC003", "B027", "B024"]
line-length = 160 line-length = 160
target-version="py311" target-version="py311"
exclude = [ exclude = [
"body",
"cereal",
"panda", "panda",
"opendbc", "opendbc",
"rednose_repo", "rednose_repo",

@ -318,3 +318,8 @@ class Platforms(str, ReprEnum):
for flag, platforms in platforms_with_flag.items(): for flag, platforms in platforms_with_flag.items():
print(f"{flag:32s}: {', '.join(p.name for p in platforms)}") print(f"{flag:32s}: {', '.join(p.name for p in platforms)}")
class PlatformFlags(IntFlag):
def __init__(self, value: int):
assert value < 2**32, "undefined behaviour with >32 bit flags"

@ -70,7 +70,7 @@ class CarD:
if prev_cp is not None: if prev_cp is not None:
self.params.put("CarParamsPrevRoute", prev_cp) self.params.put("CarParamsPrevRoute", prev_cp)
# Write CarParams for radard # Write CarParams for controls and radard
cp_bytes = self.CP.to_bytes() cp_bytes = self.CP.to_bytes()
self.params.put("CarParams", cp_bytes) self.params.put("CarParams", cp_bytes)
self.params.put_nonblocking("CarParamsCache", cp_bytes) self.params.put_nonblocking("CarParamsCache", cp_bytes)

@ -1,16 +1,15 @@
from enum import IntFlag
from dataclasses import dataclass, field from dataclasses import dataclass, field
from cereal import car from cereal import car
from panda.python import uds from panda.python import uds
from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, Platforms, dbc_dict from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, PlatformFlags, Platforms, dbc_dict
from openpilot.selfdrive.car.docs_definitions import CarHarness, CarInfo, CarParts from openpilot.selfdrive.car.docs_definitions import CarHarness, CarInfo, CarParts
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16 from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16
Ecu = car.CarParams.Ecu Ecu = car.CarParams.Ecu
class ChryslerFlags(IntFlag): class ChryslerFlags(PlatformFlags):
# Detected flags # Detected flags
HIGHER_MIN_STEERING_SPEED = 1 HIGHER_MIN_STEERING_SPEED = 1

@ -1,9 +1,9 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag from enum import Enum
import panda.python.uds as uds import panda.python.uds as uds
from cereal import car from cereal import car
from openpilot.selfdrive.car import AngleRateLimit, CarSpecs, dbc_dict, DbcDict, PlatformConfig, Platforms from openpilot.selfdrive.car import AngleRateLimit, CarSpecs, PlatformFlags, dbc_dict, DbcDict, PlatformConfig, Platforms
from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column, \ from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column, \
Device Device
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16 from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16
@ -39,7 +39,7 @@ class CarControllerParams:
pass pass
class FordFlags(IntFlag): class FordFlags(PlatformFlags):
# Static flags # Static flags
CANFD = 1 CANFD = 1

@ -1,10 +1,10 @@
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum, IntFlag from enum import Enum
from cereal import car from cereal import car
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
from panda.python import uds from panda.python import uds
from openpilot.selfdrive.car import CarSpecs, PlatformConfig, Platforms, dbc_dict from openpilot.selfdrive.car import CarSpecs, PlatformConfig, PlatformFlags, Platforms, dbc_dict
from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16 from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16
@ -45,7 +45,7 @@ class CarControllerParams:
self.STEER_LOOKUP_V = [v * -1 for v in CP.lateralParams.torqueV][1:][::-1] + list(CP.lateralParams.torqueV) self.STEER_LOOKUP_V = [v * -1 for v in CP.lateralParams.torqueV][1:][::-1] + list(CP.lateralParams.torqueV)
class HondaFlags(IntFlag): class HondaFlags(PlatformFlags):
# Detected flags # Detected flags
# Bosch models with alternate set of LKAS_HUD messages # Bosch models with alternate set of LKAS_HUD messages
BOSCH_EXT_HUD = 1 BOSCH_EXT_HUD = 1

@ -1,11 +1,11 @@
import re import re
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag from enum import Enum
from cereal import car from cereal import car
from panda.python import uds from panda.python import uds
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, Platforms, dbc_dict from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, PlatformFlags, Platforms, dbc_dict
from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16 from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16
@ -51,7 +51,7 @@ class CarControllerParams:
self.STEER_MAX = 384 self.STEER_MAX = 384
class HyundaiFlags(IntFlag): class HyundaiFlags(PlatformFlags):
# Dynamic Flags # Dynamic Flags
CANFD_HDA2 = 1 CANFD_HDA2 = 1
CANFD_ALT_BUTTONS = 2 CANFD_ALT_BUTTONS = 2

@ -1,9 +1,8 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import IntFlag
from cereal import car from cereal import car
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, Platforms, dbc_dict from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, PlatformFlags, Platforms, dbc_dict
from openpilot.selfdrive.car.docs_definitions import CarHarness, CarInfo, CarParts from openpilot.selfdrive.car.docs_definitions import CarHarness, CarInfo, CarParts
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries
@ -37,7 +36,7 @@ class MazdaCarSpecs(CarSpecs):
tireStiffnessFactor: float = 0.7 # not optimized yet tireStiffnessFactor: float = 0.7 # not optimized yet
class MazdaFlags(IntFlag): class MazdaFlags(PlatformFlags):
# Static flags # Static flags
# Gen 1 hardware: same CAN messages and same camera # Gen 1 hardware: same CAN messages and same camera
GEN1 = 1 GEN1 = 1

@ -30,11 +30,6 @@ class CarInterface(CarInterfaceBase):
def _update(self, c): def _update(self, c):
ret = self.CS.update(self.cp, self.cp_adas, self.cp_cam) ret = self.CS.update(self.cp, self.cp_adas, self.cp_cam)
buttonEvents = []
be = car.CarState.ButtonEvent.new_message()
be.type = car.CarState.ButtonEvent.Type.accelCruise
buttonEvents.append(be)
events = self.create_common_events(ret, extra_gears=[car.CarState.GearShifter.brake]) events = self.create_common_events(ret, extra_gears=[car.CarState.GearShifter.brake])
if self.CS.lkas_enabled: if self.CS.lkas_enabled:

@ -1,9 +1,9 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag from enum import Enum
from cereal import car from cereal import car
from panda.python import uds from panda.python import uds
from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, Platforms, dbc_dict from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, Platforms, PlatformFlags, dbc_dict
from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Tool, Column from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Tool, Column
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16 from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16
@ -52,7 +52,7 @@ class CarControllerParams:
BRAKE_LOOKUP_V = [BRAKE_MAX, BRAKE_MIN] BRAKE_LOOKUP_V = [BRAKE_MAX, BRAKE_MIN]
class SubaruFlags(IntFlag): class SubaruFlags(PlatformFlags):
# Detected flags # Detected flags
SEND_INFOTAINMENT = 1 SEND_INFOTAINMENT = 1
DISABLE_EYESIGHT = 2 DISABLE_EYESIGHT = 2

@ -10,6 +10,7 @@ from openpilot.selfdrive.car.nissan.values import CAR as NISSAN
from openpilot.selfdrive.car.mazda.values import CAR as MAZDA from openpilot.selfdrive.car.mazda.values import CAR as MAZDA
from openpilot.selfdrive.car.subaru.values import CAR as SUBARU from openpilot.selfdrive.car.subaru.values import CAR as SUBARU
from openpilot.selfdrive.car.toyota.values import CAR as TOYOTA from openpilot.selfdrive.car.toyota.values import CAR as TOYOTA
from openpilot.selfdrive.car.values import Platform
from openpilot.selfdrive.car.volkswagen.values import CAR as VOLKSWAGEN from openpilot.selfdrive.car.volkswagen.values import CAR as VOLKSWAGEN
from openpilot.selfdrive.car.tesla.values import CAR as TESLA from openpilot.selfdrive.car.tesla.values import CAR as TESLA
from openpilot.selfdrive.car.body.values import CAR as COMMA from openpilot.selfdrive.car.body.values import CAR as COMMA
@ -29,7 +30,7 @@ non_tested_cars = [
class CarTestRoute(NamedTuple): class CarTestRoute(NamedTuple):
route: str route: str
car_model: str | None car_model: Platform | None
segment: int | None = None segment: int | None = None

@ -19,6 +19,7 @@ from openpilot.selfdrive.car.fingerprints import all_known_cars
from openpilot.selfdrive.car.car_helpers import FRAME_FINGERPRINT, interfaces from openpilot.selfdrive.car.car_helpers import FRAME_FINGERPRINT, interfaces
from openpilot.selfdrive.car.honda.values import CAR as HONDA, HondaFlags from openpilot.selfdrive.car.honda.values import CAR as HONDA, HondaFlags
from openpilot.selfdrive.car.tests.routes import non_tested_cars, routes, CarTestRoute from openpilot.selfdrive.car.tests.routes import non_tested_cars, routes, CarTestRoute
from openpilot.selfdrive.car.values import PLATFORMS, Platform
from openpilot.selfdrive.controls.controlsd import Controls from openpilot.selfdrive.controls.controlsd import Controls
from openpilot.selfdrive.test.helpers import read_segment_list from openpilot.selfdrive.test.helpers import read_segment_list
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
@ -64,7 +65,7 @@ def get_test_cases() -> list[tuple[str, CarTestRoute | None]]:
@pytest.mark.slow @pytest.mark.slow
@pytest.mark.shared_download_cache @pytest.mark.shared_download_cache
class TestCarModelBase(unittest.TestCase): class TestCarModelBase(unittest.TestCase):
car_model: str | None = None platform: Platform | None = None
test_route: CarTestRoute | None = None test_route: CarTestRoute | None = None
test_route_on_bucket: bool = True # whether the route is on the preserved CI bucket test_route_on_bucket: bool = True # whether the route is on the preserved CI bucket
@ -93,8 +94,8 @@ class TestCarModelBase(unittest.TestCase):
car_fw = msg.carParams.carFw car_fw = msg.carParams.carFw
if msg.carParams.openpilotLongitudinalControl: if msg.carParams.openpilotLongitudinalControl:
experimental_long = True experimental_long = True
if cls.car_model is None and not cls.ci: if cls.platform is None and not cls.ci:
cls.car_model = msg.carParams.carFingerprint cls.platform = PLATFORMS.get(msg.carParams.carFingerprint)
# Log which can frame the panda safety mode left ELM327, for CAN validity checks # Log which can frame the panda safety mode left ELM327, for CAN validity checks
elif msg.which() == 'pandaStates': elif msg.which() == 'pandaStates':
@ -155,15 +156,11 @@ class TestCarModelBase(unittest.TestCase):
if cls.__name__ == 'TestCarModel' or cls.__name__.endswith('Base'): if cls.__name__ == 'TestCarModel' or cls.__name__.endswith('Base'):
raise unittest.SkipTest raise unittest.SkipTest
if 'FILTER' in os.environ:
if not cls.car_model.startswith(tuple(os.environ.get('FILTER').split(','))):
raise unittest.SkipTest
if cls.test_route is None: if cls.test_route is None:
if cls.car_model in non_tested_cars: if cls.platform in non_tested_cars:
print(f"Skipping tests for {cls.car_model}: missing route") print(f"Skipping tests for {cls.platform}: missing route")
raise unittest.SkipTest raise unittest.SkipTest
raise Exception(f"missing test route for {cls.car_model}") raise Exception(f"missing test route for {cls.platform}")
car_fw, can_msgs, experimental_long = cls.get_testing_data() car_fw, can_msgs, experimental_long = cls.get_testing_data()
@ -172,10 +169,10 @@ class TestCarModelBase(unittest.TestCase):
cls.can_msgs = sorted(can_msgs, key=lambda msg: msg.logMonoTime) cls.can_msgs = sorted(can_msgs, key=lambda msg: msg.logMonoTime)
cls.CarInterface, cls.CarController, cls.CarState = interfaces[cls.car_model] cls.CarInterface, cls.CarController, cls.CarState = interfaces[cls.platform]
cls.CP = cls.CarInterface.get_params(cls.car_model, cls.fingerprint, car_fw, experimental_long, docs=False) cls.CP = cls.CarInterface.get_params(cls.platform, cls.fingerprint, car_fw, experimental_long, docs=False)
assert cls.CP assert cls.CP
assert cls.CP.carFingerprint == cls.car_model assert cls.CP.carFingerprint == cls.platform
os.environ["COMMA_CACHE"] = DEFAULT_DOWNLOAD_CACHE_ROOT os.environ["COMMA_CACHE"] = DEFAULT_DOWNLOAD_CACHE_ROOT
@ -478,7 +475,7 @@ class TestCarModelBase(unittest.TestCase):
"This is fine to fail for WIP car ports, just let us know and we can upload your routes to the CI bucket.") "This is fine to fail for WIP car ports, just let us know and we can upload your routes to the CI bucket.")
@parameterized_class(('car_model', 'test_route'), get_test_cases()) @parameterized_class(('platform', 'test_route'), get_test_cases())
@pytest.mark.xdist_group_class_property('test_route') @pytest.mark.xdist_group_class_property('test_route')
class TestCarModel(TestCarModelBase): class TestCarModel(TestCarModelBase):
pass pass

@ -1,11 +1,11 @@
import re import re
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag from enum import Enum
from cereal import car from cereal import car
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car import CarSpecs, PlatformConfig, Platforms from openpilot.selfdrive.car import CarSpecs, PlatformConfig, PlatformFlags, Platforms
from openpilot.selfdrive.car import AngleRateLimit, dbc_dict from openpilot.selfdrive.car import AngleRateLimit, dbc_dict
from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarInfo, Column, CarParts, CarHarness from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarInfo, Column, CarParts, CarHarness
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries
@ -41,7 +41,7 @@ class CarControllerParams:
self.STEER_DELTA_DOWN = 25 # always lower than 45 otherwise the Rav4 faults (Prius seems ok with 50) self.STEER_DELTA_DOWN = 25 # always lower than 45 otherwise the Rav4 faults (Prius seems ok with 50)
class ToyotaFlags(IntFlag): class ToyotaFlags(PlatformFlags):
# Detected flags # Detected flags
HYBRID = 1 HYBRID = 1
SMART_DSU = 2 SMART_DSU = 2

@ -1,12 +1,12 @@
from collections import namedtuple from collections import namedtuple
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag from enum import Enum
from cereal import car from cereal import car
from panda.python import uds from panda.python import uds
from opendbc.can.can_define import CANDefine from opendbc.can.can_define import CANDefine
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car import dbc_dict, CarSpecs, DbcDict, PlatformConfig, Platforms from openpilot.selfdrive.car import PlatformFlags, dbc_dict, CarSpecs, DbcDict, PlatformConfig, Platforms
from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column, \ from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column, \
Device Device
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16 from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16
@ -109,7 +109,7 @@ class CANBUS:
cam = 2 cam = 2
class VolkswagenFlags(IntFlag): class VolkswagenFlags(PlatformFlags):
# Detected flags # Detected flags
STOCK_HCA_PRESENT = 1 STOCK_HCA_PRESENT = 1

@ -88,23 +88,28 @@ def read_segment_list(segment_list_path):
return [(platform[2:], segment) for platform, segment in zip(seg_list[::2], seg_list[1::2], strict=True)] return [(platform[2:], segment) for platform, segment in zip(seg_list[::2], seg_list[1::2], strict=True)]
@contextlib.contextmanager
def http_server_context(handler, setup=None):
host = '127.0.0.1'
server = http.server.HTTPServer((host, 0), handler)
port = server.server_port
t = threading.Thread(target=server.serve_forever)
t.start()
if setup is not None:
setup(host, port)
try:
yield (host, port)
finally:
server.shutdown()
server.server_close()
t.join()
def with_http_server(func, handler=http.server.BaseHTTPRequestHandler, setup=None): def with_http_server(func, handler=http.server.BaseHTTPRequestHandler, setup=None):
@wraps(func) @wraps(func)
def inner(*args, **kwargs): def inner(*args, **kwargs):
host = '127.0.0.1' with http_server_context(handler, setup) as (host, port):
server = http.server.HTTPServer((host, 0), handler) return func(*args, f"http://{host}:{port}", **kwargs)
port = server.server_port
t = threading.Thread(target=server.serve_forever)
t.start()
if setup is not None:
setup(host, port)
try:
return func(*args, f'http://{host}:{port}', **kwargs)
finally:
server.shutdown()
server.server_close()
t.join()
return inner return inner

@ -21,7 +21,7 @@ def run(args, **kwargs):
return subprocess.run(args, **kwargs, check=True) return subprocess.run(args, **kwargs, check=True)
def update_release(directory, name, version, release_notes): def update_release(directory, name, version, agnos_version, release_notes):
with open(directory / "RELEASES.md", "w") as f: with open(directory / "RELEASES.md", "w") as f:
f.write(release_notes) f.write(release_notes)
@ -30,6 +30,9 @@ def update_release(directory, name, version, release_notes):
with open(directory / "common" / "version.h", "w") as f: with open(directory / "common" / "version.h", "w") as f:
f.write(f'#define COMMA_VERSION "{version}"') f.write(f'#define COMMA_VERSION "{version}"')
with open(directory / "launch_env.sh", "w") as f:
f.write(f'export AGNOS_VERSION="{agnos_version}"')
run(["git", "add", "."], cwd=directory) run(["git", "add", "."], cwd=directory)
run(["git", "commit", "-m", f"openpilot release {version}"], cwd=directory) run(["git", "commit", "-m", f"openpilot release {version}"], cwd=directory)
@ -60,8 +63,8 @@ class TestUpdateD(unittest.TestCase):
os.environ["UPDATER_LOCK_FILE"] = str(self.mock_update_path / "safe_staging_overlay.lock") os.environ["UPDATER_LOCK_FILE"] = str(self.mock_update_path / "safe_staging_overlay.lock")
self.MOCK_RELEASES = { self.MOCK_RELEASES = {
"release3": ("0.1.2", "0.1.2 release notes"), "release3": ("0.1.2", "1.2", "0.1.2 release notes"),
"master": ("0.1.3", "0.1.3 release notes"), "master": ("0.1.3", "1.2", "0.1.3 release notes"),
} }
def set_target_branch(self, branch): def set_target_branch(self, branch):
@ -97,7 +100,7 @@ class TestUpdateD(unittest.TestCase):
self.assertEqual(self.params.get_bool("UpdaterFetchAvailable"), fetch_available) self.assertEqual(self.params.get_bool("UpdaterFetchAvailable"), fetch_available)
self.assertEqual(self.params.get_bool("UpdateAvailable"), update_available) self.assertEqual(self.params.get_bool("UpdateAvailable"), update_available)
def _test_update_params(self, branch, version, release_notes): def _test_update_params(self, branch, version, agnos_version, release_notes):
self.assertTrue(self.params.get("UpdaterNewDescription", encoding="utf-8").startswith(f"{version} / {branch}")) self.assertTrue(self.params.get("UpdaterNewDescription", encoding="utf-8").startswith(f"{version} / {branch}"))
self.assertEqual(self.params.get("UpdaterNewReleaseNotes", encoding="utf-8"), f"<p>{release_notes}</p>\n") self.assertEqual(self.params.get("UpdaterNewReleaseNotes", encoding="utf-8"), f"<p>{release_notes}</p>\n")
@ -116,6 +119,22 @@ class TestUpdateD(unittest.TestCase):
time.sleep(1) time.sleep(1)
def test_no_update(self):
# Start on release3, ensure we don't fetch any updates
self.setup_remote_release("release3")
self.setup_basedir_release("release3")
with processes_context(["updated"]) as [updated]:
self._test_params("release3", False, False)
time.sleep(1)
self._test_params("release3", False, False)
self.send_check_for_updates_signal(updated)
self.wait_for_idle()
self._test_params("release3", False, False)
def test_new_release(self): def test_new_release(self):
# Start on release3, simulate a release3 commit, ensure we fetch that update properly # Start on release3, simulate a release3 commit, ensure we fetch that update properly
self.setup_remote_release("release3") self.setup_remote_release("release3")
@ -126,7 +145,7 @@ class TestUpdateD(unittest.TestCase):
time.sleep(1) time.sleep(1)
self._test_params("release3", False, False) self._test_params("release3", False, False)
self.MOCK_RELEASES["release3"] = ("0.1.3", "0.1.3 release notes") self.MOCK_RELEASES["release3"] = ("0.1.3", "1.2", "0.1.3 release notes")
self.update_remote_release("release3") self.update_remote_release("release3")
self.send_check_for_updates_signal(updated) self.send_check_for_updates_signal(updated)
@ -167,6 +186,37 @@ class TestUpdateD(unittest.TestCase):
self._test_params("master", False, True) self._test_params("master", False, True)
self._test_update_params("master", *self.MOCK_RELEASES["master"]) self._test_update_params("master", *self.MOCK_RELEASES["master"])
def test_agnos_update(self):
# Start on release3, push an update with an agnos change
self.setup_remote_release("release3")
self.setup_basedir_release("release3")
with mock.patch("openpilot.system.hardware.AGNOS", "True"), \
mock.patch("openpilot.system.hardware.tici.hardware.Tici.get_os_version", "1.2"), \
mock.patch("openpilot.system.hardware.tici.agnos.get_target_slot_number"), \
mock.patch("openpilot.system.hardware.tici.agnos.flash_agnos_update"), \
processes_context(["updated"]) as [updated]:
self._test_params("release3", False, False)
time.sleep(1)
self._test_params("release3", False, False)
self.MOCK_RELEASES["release3"] = ("0.1.3", "1.3", "0.1.3 release notes")
self.update_remote_release("release3")
self.send_check_for_updates_signal(updated)
self.wait_for_idle()
self._test_params("release3", True, False)
self.send_download_signal(updated)
self.wait_for_idle()
self._test_params("release3", False, True)
self._test_update_params("release3", *self.MOCK_RELEASES["release3"])
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

@ -5,6 +5,7 @@ import unittest
from openpilot.selfdrive.car.tests.routes import CarTestRoute from openpilot.selfdrive.car.tests.routes import CarTestRoute
from openpilot.selfdrive.car.tests.test_models import TestCarModel from openpilot.selfdrive.car.tests.test_models import TestCarModel
from openpilot.selfdrive.car.values import PLATFORMS
from openpilot.tools.lib.route import SegmentName from openpilot.tools.lib.route import SegmentName
@ -31,7 +32,10 @@ if __name__ == "__main__":
route_or_segment_name = SegmentName(args.route_or_segment_name.strip(), allow_route_name=True) route_or_segment_name = SegmentName(args.route_or_segment_name.strip(), allow_route_name=True)
segment_num = route_or_segment_name.segment_num if route_or_segment_name.segment_num != -1 else None segment_num = route_or_segment_name.segment_num if route_or_segment_name.segment_num != -1 else None
test_route = CarTestRoute(route_or_segment_name.route_name.canonical_name, args.car, segment=segment_num)
platform = PLATFORMS.get(args.car)
test_route = CarTestRoute(route_or_segment_name.route_name.canonical_name, platform, segment=segment_num)
test_suite = create_test_models_suite([test_route], ci=args.ci) test_suite = create_test_models_suite([test_route], ci=args.ci)
unittest.TextTestRunner().run(test_suite) unittest.TextTestRunner().run(test_suite)

Loading…
Cancel
Save