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

unittest -> pytest #2049

Draft
wants to merge 49 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
836dfbc
fix test_body
bongbui321 Sep 26, 2024
2d57e32
fix test_chrysler
bongbui321 Sep 26, 2024
b019cad
fix test_defaults
bongbui321 Sep 26, 2024
b359317
fix test_elm327
bongbui321 Sep 26, 2024
7be1fb5
fix test_ford
bongbui321 Sep 26, 2024
1e3bb0b
fix test_gm
bongbui321 Sep 26, 2024
00bce0b
fix test_honda
bongbui321 Sep 26, 2024
e14caad
fix test_hyundai_canfd
bongbui321 Sep 26, 2024
369bacd
fix test_hyundai
bongbui321 Sep 26, 2024
15588d1
fix test_mazda
bongbui321 Sep 26, 2024
e92296a
fix test_nissan
bongbui321 Sep 26, 2024
291c1c0
fix test_subaru
bongbui321 Sep 26, 2024
b23e169
fix test_tesla
bongbui321 Sep 26, 2024
f765988
fix test_toyota
bongbui321 Sep 26, 2024
c67a7cc
fix test_volkswagen_mqb
bongbui321 Sep 26, 2024
75bd683
fix test_volkwagen_pq
bongbui321 Sep 26, 2024
80d84cc
fix hyundai_common
bongbui321 Sep 26, 2024
3ffd1e6
fix common.py
bongbui321 Sep 26, 2024
40b9082
PandaSafetyTestBase
bongbui321 Sep 26, 2024
e571716
try fix
bongbui321 Sep 26, 2024
01627bd
pytest.skip()
bongbui321 Sep 26, 2024
e13c98d
minor fixes
bongbui321 Sep 26, 2024
25f62ec
super() setUp() and setUpClass()
bongbui321 Sep 26, 2024
5545704
fix pytest.skip()
bongbui321 Sep 26, 2024
ba4c66b
test
bongbui321 Sep 26, 2024
af9442e
fix long asserts
bongbui321 Sep 26, 2024
a060694
fix weird long asserts and typo
bongbui321 Sep 26, 2024
c9ef7a4
subtests
bongbui321 Sep 26, 2024
e95117d
self._frange_round
bongbui321 Sep 26, 2024
6ace055
cleanup frange
bongbui321 Sep 27, 2024
59b007f
start usbprotocol
bongbui321 Sep 27, 2024
9c7cb3d
fix test_comms
bongbui321 Sep 27, 2024
a374fb0
fix test_pandalib
bongbui321 Sep 27, 2024
4c133c4
subtest usbprotocol
bongbui321 Sep 27, 2024
7f2098f
fix reset_tx test
bongbui321 Sep 27, 2024
7a38a9a
cleanup
bongbui321 Sep 27, 2024
beb9963
no executable
bongbui321 Sep 27, 2024
ed27deb
no unittest
bongbui321 Sep 27, 2024
a0fd079
Revert "no unittest"
bongbui321 Sep 27, 2024
b31f5bf
Revert "no executable"
bongbui321 Sep 27, 2024
bcf1c5c
Revert "cleanup"
bongbui321 Sep 27, 2024
5b96ffd
fix that
bongbui321 Sep 27, 2024
f2bd951
use pytest-order
bongbui321 Sep 28, 2024
29b28c7
no executable usbprotocol
bongbui321 Sep 28, 2024
514322f
update pyproject
bongbui321 Sep 28, 2024
09667af
Merge branch 'master' of https://github.com/commaai/panda into unitte…
bongbui321 Sep 28, 2024
89d8396
no executable for tests/safety
bongbui321 Sep 28, 2024
479c201
fix mutation.sh
bongbui321 Sep 28, 2024
f78f42e
fix that
bongbui321 Oct 1, 2024
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
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ flake8-implicit-str-concat.allow-multiline=false

[tool.ruff.lint.flake8-tidy-imports.banned-api]
"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!"
"unittest".msg = "Use pytest"

[tool.pytest.ini_options]
addopts = "-n auto --ignore-glob='*.sh'"
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ def find_version(*file_paths):
"pytest-xdist",
"pytest-timeout",
"pytest-randomly",
"pytest-subtests",
"pytest-order",
"parameterized",
"pre-commit",
"numpy",
Expand Down
308 changes: 154 additions & 154 deletions tests/safety/common.py

Large diffs are not rendered by default.

40 changes: 19 additions & 21 deletions tests/safety/hyundai_common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import unittest

import pytest
import panda.tests.safety.common as common
from panda.tests.libpanda import libpanda_py
from panda.tests.safety.common import make_msg
Expand Down Expand Up @@ -28,16 +27,16 @@ def test_button_sends(self):
- CANCEL allowed while cruise is enabled
"""
self.safety.set_controls_allowed(0)
self.assertFalse(self._tx(self._button_msg(Buttons.RESUME, bus=self.BUTTONS_TX_BUS)))
self.assertFalse(self._tx(self._button_msg(Buttons.SET, bus=self.BUTTONS_TX_BUS)))
assert not self._tx(self._button_msg(Buttons.RESUME, bus=self.BUTTONS_TX_BUS))
assert not self._tx(self._button_msg(Buttons.SET, bus=self.BUTTONS_TX_BUS))

self.safety.set_controls_allowed(1)
self.assertTrue(self._tx(self._button_msg(Buttons.RESUME, bus=self.BUTTONS_TX_BUS)))
self.assertFalse(self._tx(self._button_msg(Buttons.SET, bus=self.BUTTONS_TX_BUS)))
assert self._tx(self._button_msg(Buttons.RESUME, bus=self.BUTTONS_TX_BUS))
assert not self._tx(self._button_msg(Buttons.SET, bus=self.BUTTONS_TX_BUS))

for enabled in (True, False):
self._rx(self._pcm_status_msg(enabled))
self.assertEqual(enabled, self._tx(self._button_msg(Buttons.CANCEL, bus=self.BUTTONS_TX_BUS)))
assert enabled == self._tx(self._button_msg(Buttons.CANCEL, bus=self.BUTTONS_TX_BUS))

def test_enable_control_allowed_from_cruise(self):
"""
Expand All @@ -53,11 +52,11 @@ def test_enable_control_allowed_from_cruise(self):
self._rx(self._button_msg(Buttons.NONE))

self._rx(self._pcm_status_msg(False))
self.assertFalse(self.safety.get_controls_allowed())
assert not self.safety.get_controls_allowed()
self._rx(self._button_msg(btn, main_button=main_button))
self._rx(self._pcm_status_msg(True))
controls_allowed = btn in ENABLE_BUTTONS or main_button
self.assertEqual(controls_allowed, self.safety.get_controls_allowed())
assert controls_allowed == self.safety.get_controls_allowed()

def test_sampling_cruise_buttons(self):
"""
Expand All @@ -66,10 +65,10 @@ def test_sampling_cruise_buttons(self):
self._rx(self._button_msg(Buttons.SET))
for i in range(2 * PREV_BUTTON_SAMPLES):
self._rx(self._pcm_status_msg(False))
self.assertFalse(self.safety.get_controls_allowed())
assert not self.safety.get_controls_allowed()
self._rx(self._pcm_status_msg(True))
controls_allowed = i < PREV_BUTTON_SAMPLES
self.assertEqual(controls_allowed, self.safety.get_controls_allowed())
assert controls_allowed == self.safety.get_controls_allowed()
self._rx(self._button_msg(Buttons.NONE))


Expand All @@ -80,10 +79,10 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest):
DISABLED_ECU_ACTUATION_MSG: tuple[int, int]

@classmethod
def setUpClass(cls):
def setup_class(cls):
if cls.__name__ == "HyundaiLongitudinalBase":
cls.safety = None
raise unittest.SkipTest
raise pytest.skip()

# override these tests from PandaCarSafetyTest, hyundai longitudinal uses button enable
def test_disable_control_allowed_from_cruise(self):
Expand Down Expand Up @@ -117,20 +116,20 @@ def test_set_resume_buttons(self):
self.safety.set_controls_allowed(0)
for _ in range(10):
self._rx(self._button_msg(btn_prev))
self.assertFalse(self.safety.get_controls_allowed())
assert not self.safety.get_controls_allowed()

# should enter controls allowed on falling edge and not transitioning to cancel
should_enable = btn_cur != btn_prev and \
btn_cur != Buttons.CANCEL and \
btn_prev in (Buttons.RESUME, Buttons.SET)

self._rx(self._button_msg(btn_cur))
self.assertEqual(should_enable, self.safety.get_controls_allowed())
assert should_enable == self.safety.get_controls_allowed()

def test_cancel_button(self):
self.safety.set_controls_allowed(1)
self._rx(self._button_msg(Buttons.CANCEL))
self.assertFalse(self.safety.get_controls_allowed())
assert not self.safety.get_controls_allowed()

def test_tester_present_allowed(self):
"""
Expand All @@ -140,18 +139,17 @@ def test_tester_present_allowed(self):

addr, bus = self.DISABLED_ECU_UDS_MSG
tester_present = libpanda_py.make_CANPacket(addr, bus, b"\x02\x3E\x80\x00\x00\x00\x00\x00")
self.assertTrue(self._tx(tester_present))
assert self._tx(tester_present)

not_tester_present = libpanda_py.make_CANPacket(addr, bus, b"\x03\xAA\xAA\x00\x00\x00\x00\x00")
self.assertFalse(self._tx(not_tester_present))
assert not self._tx(not_tester_present)

def test_disabled_ecu_alive(self):
"""
If the ECU knockout failed, make sure the relay malfunction is shown
"""

addr, bus = self.DISABLED_ECU_ACTUATION_MSG
self.assertFalse(self.safety.get_relay_malfunction())
assert not self.safety.get_relay_malfunction()
self._rx(make_msg(bus, addr, 8))
self.assertTrue(self.safety.get_relay_malfunction())

assert self.safety.get_relay_malfunction()
2 changes: 1 addition & 1 deletion tests/safety/mutation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ for safety_model in ${SAFETY_MODELS[@]}; do
echo ""
echo ""
echo -e "Testing mutations on : $safety_model"
mull-runner-17 --ld-search-path /lib/x86_64-linux-gnu/ ../libpanda/libpanda.so -test-program=./$safety_model
mull-runner-17 --ld-search-path /lib/x86_64-linux-gnu/ ../libpanda/libpanda.so -test-program=python3 $safety_model
done
41 changes: 17 additions & 24 deletions tests/safety/test_body.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#!/usr/bin/env python3
import unittest

import panda.tests.safety.common as common

from panda import Panda
Expand All @@ -12,7 +9,7 @@ class TestBody(common.PandaSafetyTest):
TX_MSGS = [[0x250, 0], [0x251, 0], [0x350, 0], [0x351, 0],
[0x1, 0], [0x1, 1], [0x1, 2], [0x1, 3]]

def setUp(self):
def setup_method(self):
self.packer = CANPackerPanda("comma_body")
self.safety = libpanda_py.libpanda
self.safety.set_safety_hooks(Panda.SAFETY_BODY, 0)
Expand All @@ -35,36 +32,32 @@ def _max_motor_rpm_cmd_msg(self, max_rpm_l, max_rpm_r):
return self.packer.make_can_msg_panda("MAX_MOTOR_RPM_CMD", 0, values)

def test_rx_hook(self):
self.assertFalse(self.safety.get_controls_allowed())
self.assertFalse(self.safety.get_vehicle_moving())
assert not self.safety.get_controls_allowed()
assert not self.safety.get_vehicle_moving()

# controls allowed when we get MOTORS_DATA message
self.assertTrue(self._rx(self._torque_cmd_msg(0, 0)))
self.assertTrue(self.safety.get_vehicle_moving()) # always moving
self.assertFalse(self.safety.get_controls_allowed())
assert self._rx(self._torque_cmd_msg(0, 0))
assert self.safety.get_vehicle_moving()# always moving
assert not self.safety.get_controls_allowed()

self.assertTrue(self._rx(self._motors_data_msg(0, 0)))
self.assertTrue(self.safety.get_vehicle_moving()) # always moving
self.assertTrue(self.safety.get_controls_allowed())
assert self._rx(self._motors_data_msg(0, 0))
assert self.safety.get_vehicle_moving()# always moving
assert self.safety.get_controls_allowed()

def test_tx_hook(self):
self.assertFalse(self._tx(self._torque_cmd_msg(0, 0)))
self.assertFalse(self._tx(self._knee_torque_cmd_msg(0, 0)))
assert not self._tx(self._torque_cmd_msg(0, 0))
assert not self._tx(self._knee_torque_cmd_msg(0, 0))
self.safety.set_controls_allowed(True)
self.assertTrue(self._tx(self._torque_cmd_msg(0, 0)))
self.assertTrue(self._tx(self._knee_torque_cmd_msg(0, 0)))
assert self._tx(self._torque_cmd_msg(0, 0))
assert self._tx(self._knee_torque_cmd_msg(0, 0))

def test_can_flasher(self):
# CAN flasher always allowed
self.safety.set_controls_allowed(False)
self.assertTrue(self._tx(common.make_msg(0, 0x1, 8)))
assert self._tx(common.make_msg(0, 0x1, 8))

# 0xdeadfaceU enters CAN flashing mode for base & knee
for addr in (0x250, 0x350):
self.assertTrue(self._tx(common.make_msg(0, addr, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0\x0a')))
self.assertFalse(self._tx(common.make_msg(0, addr, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0'))) # not correct data/len
self.assertFalse(self._tx(common.make_msg(0, addr + 1, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0\x0a'))) # wrong address


if __name__ == "__main__":
unittest.main()
assert self._tx(common.make_msg(0, addr, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0\x0a'))
assert not self._tx(common.make_msg(0, addr, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0'))# not correct data/len
assert not self._tx(common.make_msg(0, addr + 1, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0\x0a'))# wrong address
20 changes: 7 additions & 13 deletions tests/safety/test_chrysler.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3
import unittest
from panda import Panda
from panda.tests.libpanda import libpanda_py
import panda.tests.safety.common as common
Expand All @@ -24,7 +22,7 @@ class TestChryslerSafety(common.PandaCarSafetyTest, common.MotorTorqueSteeringSa

DAS_BUS = 0

def setUp(self):
def setup_method(self):
self.packer = CANPackerPanda("chrysler_pacifica_2017_hybrid_generated")
self.safety = libpanda_py.libpanda
self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, 0)
Expand Down Expand Up @@ -63,14 +61,14 @@ def test_buttons(self):
self.safety.set_controls_allowed(controls_allowed)

# resume only while controls allowed
self.assertEqual(controls_allowed, self._tx(self._button_msg(resume=True)))
assert controls_allowed == self._tx(self._button_msg(resume=True))

# can always cancel
self.assertTrue(self._tx(self._button_msg(cancel=True)))
assert self._tx(self._button_msg(cancel=True))

# only one button at a time
self.assertFalse(self._tx(self._button_msg(cancel=True, resume=True)))
self.assertFalse(self._tx(self._button_msg(cancel=False, resume=False)))
assert not self._tx(self._button_msg(cancel=True, resume=True))
assert not self._tx(self._button_msg(cancel=False, resume=False))


class TestChryslerRamDTSafety(TestChryslerSafety):
Expand All @@ -86,7 +84,7 @@ class TestChryslerRamDTSafety(TestChryslerSafety):

LKAS_ACTIVE_VALUE = 2

def setUp(self):
def setup_method(self):
self.packer = CANPackerPanda("chrysler_ram_dt_generated")
self.safety = libpanda_py.libpanda
self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, Panda.FLAG_CHRYSLER_RAM_DT)
Expand All @@ -110,7 +108,7 @@ class TestChryslerRamHDSafety(TestChryslerSafety):

LKAS_ACTIVE_VALUE = 2

def setUp(self):
def setup_method(self):
self.packer = CANPackerPanda("chrysler_ram_hd_generated")
self.safety = libpanda_py.libpanda
self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, Panda.FLAG_CHRYSLER_RAM_HD)
Expand All @@ -119,7 +117,3 @@ def setUp(self):
def _speed_msg(self, speed):
values = {"Vehicle_Speed": speed}
return self.packer.make_can_msg_panda("ESP_8", 0, values)


if __name__ == "__main__":
unittest.main()
21 changes: 7 additions & 14 deletions tests/safety/test_defaults.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#!/usr/bin/env python3
import unittest

import panda.tests.safety.common as common

from panda import Panda
Expand All @@ -12,13 +9,13 @@ def test_rx_hook(self):
# default rx hook allows all msgs
for bus in range(4):
for addr in self.SCANNED_ADDRS:
self.assertTrue(self._rx(common.make_msg(bus, addr, 8)), f"failed RX {addr=}")
assert self._rx(common.make_msg(bus, addr, 8)), f"failed RX {addr=}"


class TestNoOutput(TestDefaultRxHookBase):
TX_MSGS = []

def setUp(self):
def setup_method(self):
self.safety = libpanda_py.libpanda
self.safety.set_safety_hooks(Panda.SAFETY_NOOUTPUT, 0)
self.safety.init_tests()
Expand All @@ -27,7 +24,7 @@ def setUp(self):
class TestSilent(TestNoOutput):
"""SILENT uses same hooks as NOOUTPUT"""

def setUp(self):
def setup_method(self):
self.safety = libpanda_py.libpanda
self.safety.set_safety_hooks(Panda.SAFETY_SILENT, 0)
self.safety.init_tests()
Expand All @@ -38,7 +35,7 @@ class TestAllOutput(TestDefaultRxHookBase):
TX_MSGS = [[addr, bus] for addr in common.PandaSafetyTest.SCANNED_ADDRS
for bus in range(4)]

def setUp(self):
def setup_method(self):
self.safety = libpanda_py.libpanda
self.safety.set_safety_hooks(Panda.SAFETY_ALLOUTPUT, 0)
self.safety.init_tests()
Expand All @@ -48,11 +45,11 @@ def test_spam_can_buses(self):
for bus in range(4):
for addr in self.SCANNED_ADDRS:
should_tx = [addr, bus] in self.TX_MSGS
self.assertEqual(should_tx, self._tx(common.make_msg(bus, addr, 8)), f"allowed TX {addr=} {bus=}")
assert should_tx == self._tx(common.make_msg(bus, addr, 8)), f"allowed TX {addr=} {bus=}"

def test_default_controls_not_allowed(self):
# controls always allowed
self.assertTrue(self.safety.get_controls_allowed())
assert self.safety.get_controls_allowed()

def test_tx_hook_on_wrong_safety_mode(self):
# No point, since we allow all messages
Expand All @@ -63,11 +60,7 @@ class TestAllOutputPassthrough(TestAllOutput):
FWD_BLACKLISTED_ADDRS = {}
FWD_BUS_LOOKUP = {0: 2, 2: 0}

def setUp(self):
def setup_method(self):
self.safety = libpanda_py.libpanda
self.safety.set_safety_hooks(Panda.SAFETY_ALLOUTPUT, 1)
self.safety.init_tests()


if __name__ == "__main__":
unittest.main()
15 changes: 4 additions & 11 deletions tests/safety/test_elm327.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#!/usr/bin/env python3
import unittest

import panda.tests.safety.common as common

from panda import DLC_TO_LEN, Panda
Expand All @@ -16,7 +13,7 @@ class TestElm327(TestDefaultRxHookBase):
*[0x18DB33F1], # 29-bit UDS functional address
] for bus in range(4)]

def setUp(self):
def setup_method(self):
self.safety = libpanda_py.libpanda
self.safety.set_safety_hooks(Panda.SAFETY_ELM327, 0)
self.safety.init_tests()
Expand All @@ -26,23 +23,19 @@ def test_tx_hook(self):
for bus in range(4):
for addr in self.SCANNED_ADDRS:
should_tx = [addr, bus] in self.TX_MSGS
self.assertEqual(should_tx, self._tx(common.make_msg(bus, addr, 8)))
assert should_tx == self._tx(common.make_msg(bus, addr, 8))

# ELM only allows 8 byte UDS/KWP messages under ISO 15765-4
for msg_len in DLC_TO_LEN:
should_tx = msg_len == 8
self.assertEqual(should_tx, self._tx(common.make_msg(0, 0x700, msg_len)))
assert should_tx == self._tx(common.make_msg(0, 0x700, msg_len))

# TODO: perform this check for all addresses
# 4 to 15 are reserved ISO-TP frame types (https://en.wikipedia.org/wiki/ISO_15765-2)
for byte in range(0xff):
should_tx = (byte >> 4) <= 3
self.assertEqual(should_tx, self._tx(common.make_msg(0, GM_CAMERA_DIAG_ADDR, dat=bytes([byte] * 8))))
assert should_tx == self._tx(common.make_msg(0, GM_CAMERA_DIAG_ADDR, dat=bytes([byte] * 8)))

def test_tx_hook_on_wrong_safety_mode(self):
# No point, since we allow many diagnostic addresses
pass


if __name__ == "__main__":
unittest.main()
Loading
Loading