Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_models: fuzz test panda and CarState #30443

Merged
merged 117 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
ab87a86
pre-hypothesis
sshane Nov 4, 2023
2266386
some hypothesis junk
sshane Nov 4, 2023
78a10de
this kinda works but is really slow due to counter check
sshane Nov 4, 2023
3b52f1f
choose addrs from fingerprint
sshane Nov 4, 2023
dfe8d06
stash
sshane Nov 6, 2023
25e4bc7
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Nov 8, 2023
a81f85c
honda nidec brake pressed mismatches fixed
sshane Nov 9, 2023
25d0fd0
bump panda
sshane Nov 9, 2023
430d43b
stash
sshane Nov 9, 2023
aa3cfd5
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Nov 11, 2023
5faf816
tesla: use DI_torque2 (panda msg)
sshane Nov 11, 2023
4eae58a
run
sshane Nov 11, 2023
eba6e59
run
sshane Nov 11, 2023
012e7b9
ah this honda mismatch too
sshane Nov 11, 2023
0d6c50f
no more multi can msgs
sshane Nov 11, 2023
640a6e3
clean up, remove old file
sshane Nov 11, 2023
86ffcd7
add todo
sshane Nov 11, 2023
f8fd185
prob can remove urandom
sshane Nov 11, 2023
91f06c5
stash, huge examples
sshane Nov 11, 2023
e0534f7
fix pq standstill mismatch
sshane Nov 11, 2023
6c235d1
yuge
sshane Nov 11, 2023
c7eeb77
yup there's a leak somewhere
sshane Nov 11, 2023
caa1f19
try to find leak
sshane Nov 13, 2023
d2c598a
skip dashcam (pq and tesla)
sshane Nov 14, 2023
7d0317b
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Nov 14, 2023
0525041
PR comments
sshane Nov 14, 2023
0f77532
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Nov 17, 2023
720d8a7
bump
sshane Nov 17, 2023
41a33a1
draft stash
sshane Nov 17, 2023
e0ab1f5
fix alt brake hondas
sshane Nov 17, 2023
13dd5c9
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Nov 18, 2023
c5b1e2c
bump
sshane Nov 18, 2023
f1bd4e9
bump
sshane Nov 18, 2023
9564eb1
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Nov 22, 2023
e7cd55f
bump
sshane Nov 22, 2023
9aaffda
some clean up
sshane Nov 22, 2023
ab61360
minor clean up
sshane Nov 22, 2023
f58b8c8
more clean up
sshane Nov 22, 2023
8742aef
stash
sshane Nov 22, 2023
b11b32a
fix honda bug
sshane Nov 22, 2023
226089d
more
sshane Nov 22, 2023
32b8705
100 examples
sshane Nov 22, 2023
0ccf8c2
revert tesla
sshane Nov 22, 2023
27c053e
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Nov 28, 2023
04c7b81
no memory leak any more?
sshane Nov 28, 2023
6a64684
bring back tests with skips
sshane Nov 28, 2023
55de2c1
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Dec 9, 2023
26238ba
parameterize max_examples
sshane Dec 9, 2023
cbdcc05
skip interceptor
sshane Dec 9, 2023
fcd8b2b
is jenkins on my branch?
sshane Dec 9, 2023
be1d55e
ooh that's fast
sshane Dec 9, 2023
f549702
50 is not bad for GH CI
sshane Dec 9, 2023
0968d2a
300 might be better with rest of test_models
sshane Dec 9, 2023
79d24b5
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Dec 13, 2023
16b6035
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Dec 13, 2023
55cc0d7
no more detection
sshane Dec 13, 2023
525655e
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Dec 13, 2023
f66a69c
bump
sshane Dec 13, 2023
f613b7e
need CS_prev to catch bugs where openpilot changes and panda doesn't …
sshane Dec 14, 2023
1b4aa92
need to simplify all this
sshane Dec 14, 2023
43521a0
need a warm up first, since some signals are 1 by default (toyota's g…
sshane Dec 14, 2023
5bd42fe
changes
sshane Dec 14, 2023
c81081f
set honda safety param
sshane Dec 14, 2023
5e7d872
set toyota safety param
sshane Dec 14, 2023
52b2296
bump panda
sshane Dec 14, 2023
aa47dc5
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Dec 15, 2023
efaa89a
clean up honda
sshane Dec 15, 2023
00e0b42
rm interceptor
sshane Dec 15, 2023
1533013
thought interleaving addrs might help, but we can fine tune later
sshane Dec 15, 2023
af384e0
Revert "thought interleaving addrs might help, but we can fine tune l…
sshane Dec 15, 2023
824c7ab
get size from dict
sshane Dec 15, 2023
69304cd
what
sshane Dec 15, 2023
61e3d21
add nocapture marker
sshane Dec 15, 2023
c764a2e
clean up
sshane Dec 15, 2023
f552952
try to raise logging level
sshane Dec 16, 2023
26ef068
need to run last as pytest_runtest_call, since it starts capturing
sshane Dec 16, 2023
ce289bb
get capman conditionally
sshane Dec 16, 2023
9e268e2
mark
sshane Dec 16, 2023
19187a9
type fingerprint
sshane Dec 16, 2023
5d91c60
should use gen_empty_fingerprint
sshane Dec 16, 2023
6bfb3e6
no longer needed
sshane Dec 16, 2023
6403f40
draft
sshane Dec 16, 2023
e859838
no longer need gc
sshane Dec 16, 2023
886815d
clean that up
sshane Dec 16, 2023
6d0238f
test everything!
sshane Dec 16, 2023
e835380
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Dec 16, 2023
b916cf2
more clean up
sshane Dec 16, 2023
1fb5d42
more
sshane Dec 16, 2023
43a55b5
no point
sshane Dec 16, 2023
5677d78
fix that
sshane Dec 16, 2023
ce18468
fix errors
sshane Dec 16, 2023
1c1db22
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Dec 16, 2023
43ac48a
bump
sshane Dec 16, 2023
f4a3d58
nice even 300 examples for 300 segs
sshane Dec 16, 2023
6ed0b91
final bump :fingers_crossed:
sshane Dec 16, 2023
65df53b
better import order
sshane Dec 16, 2023
71be169
remove debugging prints
sshane Dec 16, 2023
7fc77b0
warm up kinda works
sshane Dec 16, 2023
237be49
Revert "warm up kinda works"
sshane Dec 16, 2023
0ff37cc
random seed
sshane Dec 16, 2023
610a6cf
Merge remote-tracking branch 'upstream/master' into fuzzy-panda-carstate
sshane Dec 19, 2023
66455ae
revert
sshane Dec 19, 2023
1d04a6e
strat
sshane Dec 19, 2023
bd9db78
add expl comment
sshane Dec 19, 2023
901f912
cmt
sshane Dec 19, 2023
e82a0e5
check controls allowed
sshane Dec 19, 2023
4a31837
Revert "check controls allowed"
sshane Dec 19, 2023
e78d686
not unittests
sshane Dec 19, 2023
0b87e59
run tests!
sshane Dec 19, 2023
0328d95
run tests 2!
sshane Dec 19, 2023
eb316cf
run tests 3!
sshane Dec 19, 2023
ba5a54e
seed unused
sshane Dec 19, 2023
7fb9752
revert
sshane Dec 19, 2023
379c3f2
add shrink phase, and remove health check suppression
sshane Dec 19, 2023
ba20a99
hello
sshane Dec 19, 2023
1e362b6
oncemore
sshane Dec 19, 2023
c6f687c
Update selfdrive/car/tests/test_models.py
sshane Dec 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ node {
'car tests': {
pcStage("car tests") {
sh label: "build", script: "selfdrive/manager/build.py"
sh label: "run car tests", script: "cd selfdrive/car/tests && MAX_EXAMPLES=100 INTERNAL_SEG_CNT=250 FILEREADER_CACHE=1 \
sh label: "run car tests", script: "cd selfdrive/car/tests && MAX_EXAMPLES=300 INTERNAL_SEG_CNT=300 FILEREADER_CACHE=1 \
INTERNAL_SEG_LIST=selfdrive/car/tests/test_models_segs.txt pytest test_models.py test_car_interfaces.py"
}
},
Expand Down
18 changes: 15 additions & 3 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ def pytest_sessionstart(session):
session.config.option.randomly_reorganize = False


@pytest.hookimpl(hookwrapper=True, trylast=True)
def pytest_runtest_call(item):
# ensure we run as a hook after capturemanager's
if item.get_closest_marker("nocapture") is not None:
capmanager = item.config.pluginmanager.getplugin("capturemanager")
with capmanager.global_and_fixture_disabled():
yield
else:
yield


@pytest.fixture(scope="function", autouse=True)
def openpilot_function_fixture():
starting_env = dict(os.environ)
Expand Down Expand Up @@ -58,7 +69,8 @@ def pytest_collection_modifyitems(config, items):

@pytest.hookimpl(trylast=True)
def pytest_configure(config):
config_line = (
"xdist_group_class_property: group tests by a property of the class that contains them"
)
config_line = "xdist_group_class_property: group tests by a property of the class that contains them"
config.addinivalue_line("markers", config_line)

config_line = "nocapture: don't capture test output"
config.addinivalue_line("markers", config_line)
79 changes: 75 additions & 4 deletions selfdrive/car/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import random
import unittest
from collections import defaultdict, Counter
import hypothesis.strategies as st
from hypothesis import Phase, given, settings
from typing import List, Optional, Tuple
from parameterized import parameterized_class

from cereal import log, car
from cereal import messaging, log, car
from openpilot.common.basedir import BASEDIR
from openpilot.common.params import Params
from openpilot.common.realtime import DT_CTRL
Expand All @@ -33,6 +35,7 @@
JOB_ID = int(os.environ.get("JOB_ID", "0"))
INTERNAL_SEG_LIST = os.environ.get("INTERNAL_SEG_LIST", "")
INTERNAL_SEG_CNT = int(os.environ.get("INTERNAL_SEG_CNT", "0"))
MAX_EXAMPLES = int(os.environ.get("MAX_EXAMPLES", "50"))


def get_test_cases() -> List[Tuple[str, Optional[CarTestRoute]]]:
Expand Down Expand Up @@ -67,6 +70,7 @@ class TestCarModelBase(unittest.TestCase):
ci: bool = True

can_msgs: List[capnp.lib.capnp._DynamicStructReader]
fingerprint: dict[int, dict[int, int]]
elm_frame: Optional[int]
car_safety_mode_frame: Optional[int]

Expand Down Expand Up @@ -105,15 +109,15 @@ def setUpClass(cls):
can_msgs = []
cls.elm_frame = None
cls.car_safety_mode_frame = None
fingerprint = gen_empty_fingerprint()
cls.fingerprint = gen_empty_fingerprint()
experimental_long = False
for msg in lr:
if msg.which() == "can":
can_msgs.append(msg)
if len(can_msgs) <= FRAME_FINGERPRINT:
for m in msg.can:
if m.src < 64:
fingerprint[m.src][m.address] = len(m.dat)
cls.fingerprint[m.src][m.address] = len(m.dat)

elif msg.which() == "carParams":
car_fw = msg.carParams.carFw
Expand Down Expand Up @@ -149,7 +153,7 @@ def setUpClass(cls):
cls.can_msgs = sorted(can_msgs, key=lambda msg: msg.logMonoTime)

cls.CarInterface, cls.CarController, cls.CarState = interfaces[cls.car_model]
cls.CP = cls.CarInterface.get_params(cls.car_model, fingerprint, car_fw, experimental_long, docs=False)
cls.CP = cls.CarInterface.get_params(cls.car_model, cls.fingerprint, car_fw, experimental_long, docs=False)
assert cls.CP
assert cls.CP.carFingerprint == cls.car_model

Expand Down Expand Up @@ -297,6 +301,73 @@ def test_car_controller(car_control):
CC = car.CarControl.new_message(cruiseControl={'resume': True})
test_car_controller(CC)

# Skip stdout/stderr capture with pytest, causes elevated memory usage
@pytest.mark.nocapture
@settings(max_examples=MAX_EXAMPLES, deadline=None,
phases=(Phase.reuse, Phase.generate, Phase.shrink))
@given(data=st.data())
def test_panda_safety_carstate_fuzzy(self, data):
"""
For each example, pick a random CAN message on the bus and fuzz its data,
checking for panda state mismatches.
"""

if self.CP.dashcamOnly:
self.skipTest("no need to check panda safety for dashcamOnly")

valid_addrs = [(addr, bus, size) for bus, addrs in self.fingerprint.items() for addr, size in addrs.items()]
address, bus, size = data.draw(st.sampled_from(valid_addrs))

msg_strategy = st.binary(min_size=size, max_size=size)
msgs = data.draw(st.lists(msg_strategy, min_size=20))

CC = car.CarControl.new_message()

for dat in msgs:
# due to panda updating state selectively, only edges are expected to match
# TODO: warm up CarState with real CAN messages to check edge of both sources
# (eg. toyota's gasPressed is the inverse of a signal being set)
prev_panda_gas = self.safety.get_gas_pressed_prev()
prev_panda_brake = self.safety.get_brake_pressed_prev()
prev_panda_regen_braking = self.safety.get_regen_braking_prev()
prev_panda_vehicle_moving = self.safety.get_vehicle_moving()
prev_panda_cruise_engaged = self.safety.get_cruise_engaged_prev()
prev_panda_acc_main_on = self.safety.get_acc_main_on()
Comment on lines +330 to +335
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we re-use the warm up code in test_panda_safety_carstate (or that whole function), but so far I haven't found a nice way to generate examples inside the function. Will do some more looking after this is merged


to_send = libpanda_py.make_CANPacket(address, bus, dat)
self.safety.safety_rx_hook(to_send)

can = messaging.new_message('can', 1)
can.can = [log.CanData(address=address, dat=dat, src=bus)]

CS = self.CI.update(CC, (can.to_bytes(),))

if self.safety.get_gas_pressed_prev() != prev_panda_gas:
self.assertEqual(CS.gasPressed, self.safety.get_gas_pressed_prev())

if self.safety.get_brake_pressed_prev() != prev_panda_brake:
# TODO: remove this exception once this mismatch is resolved
brake_pressed = CS.brakePressed
if CS.brakePressed and not self.safety.get_brake_pressed_prev():
if self.CP.carFingerprint in (HONDA.PILOT, HONDA.RIDGELINE) and CS.brake > 0.05:
brake_pressed = False

self.assertEqual(brake_pressed, self.safety.get_brake_pressed_prev())

if self.safety.get_regen_braking_prev() != prev_panda_regen_braking:
self.assertEqual(CS.regenBraking, self.safety.get_regen_braking_prev())

if self.safety.get_vehicle_moving() != prev_panda_vehicle_moving:
self.assertEqual(not CS.standstill, self.safety.get_vehicle_moving())

if not (self.CP.carName == "honda" and self.CP.carFingerprint not in HONDA_BOSCH):
if self.safety.get_cruise_engaged_prev() != prev_panda_cruise_engaged:
self.assertEqual(CS.cruiseState.enabled, self.safety.get_cruise_engaged_prev())

if self.CP.carName == "honda":
if self.safety.get_acc_main_on() != prev_panda_acc_main_on:
self.assertEqual(CS.cruiseState.available, self.safety.get_acc_main_on())

def test_panda_safety_carstate(self):
"""
Assert that panda safety matches openpilot's carState
Expand Down
Loading