Unittest to pytest (#32366)

* add pytest-asyncio

* switch common

* switch selfdrive

* switch system

* switch tools

* small fixes

* fix setUp and valgrind pytest

* switch to setup

* fix random

* switch mock

* switch test_lateral_limits

* revert test_ui

* fix poetry.lock

* add unittest to banned-api

* add inline ignores to remaining unittest imports

* revert test_models

* revert check_can_parser_performance

* one more skip

---------

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
This commit is contained in:
cl0cks4fe
2024-05-17 11:01:44 -07:00
committed by GitHub
parent f5bca9c08c
commit dd9d5d4528
84 changed files with 1215 additions and 1548 deletions
+3 -7
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python3
import time
import unittest
import numpy as np
from openpilot.selfdrive.test.helpers import with_processes, phone_only
@@ -9,9 +8,9 @@ from openpilot.system.camerad.snapshot.snapshot import get_snapshots
TEST_TIME = 45
REPEAT = 5
class TestCamerad(unittest.TestCase):
class TestCamerad:
@classmethod
def setUpClass(cls):
def setup_class(cls):
pass
def _numpy_rgb2gray(self, im):
@@ -49,7 +48,4 @@ class TestCamerad(unittest.TestCase):
passed += int(res)
time.sleep(2)
self.assertGreaterEqual(passed, REPEAT)
if __name__ == "__main__":
unittest.main()
assert passed >= REPEAT
@@ -1,14 +1,13 @@
#!/usr/bin/env python3
import json
import os
import unittest
import requests
TEST_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)))
MANIFEST = os.path.join(TEST_DIR, "../agnos.json")
class TestAgnosUpdater(unittest.TestCase):
class TestAgnosUpdater:
def test_manifest(self):
with open(MANIFEST) as f:
@@ -17,10 +16,6 @@ class TestAgnosUpdater(unittest.TestCase):
for img in m:
r = requests.head(img['url'], timeout=10)
r.raise_for_status()
self.assertEqual(r.headers['Content-Type'], "application/x-xz")
assert r.headers['Content-Type'] == "application/x-xz"
if not img['sparse']:
assert img['hash'] == img['hash_raw']
if __name__ == "__main__":
unittest.main()
+7 -11
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import pytest
import time
import random
import unittest
import subprocess
from panda import Panda
@@ -10,14 +10,14 @@ from openpilot.system.hardware.tici.hardware import Tici
from openpilot.system.hardware.tici.amplifier import Amplifier
class TestAmplifier(unittest.TestCase):
class TestAmplifier:
@classmethod
def setUpClass(cls):
def setup_class(cls):
if not TICI:
raise unittest.SkipTest
pytest.skip()
def setUp(self):
def setup_method(self):
# clear dmesg
subprocess.check_call("sudo dmesg -C", shell=True)
@@ -25,7 +25,7 @@ class TestAmplifier(unittest.TestCase):
Panda.wait_for_panda(None, 30)
self.panda = Panda()
def tearDown(self):
def teardown_method(self):
HARDWARE.reset_internal_panda()
def _check_for_i2c_errors(self, expected):
@@ -68,8 +68,4 @@ class TestAmplifier(unittest.TestCase):
if self._check_for_i2c_errors(True):
break
else:
self.fail("didn't hit any i2c errors")
if __name__ == "__main__":
unittest.main()
pytest.fail("didn't hit any i2c errors")
+1 -6
View File
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
import pytest
import time
import unittest
import numpy as np
from openpilot.system.hardware.tici.hardware import Tici
@@ -10,7 +9,7 @@ HARDWARE = Tici()
@pytest.mark.tici
class TestHardware(unittest.TestCase):
class TestHardware:
def test_power_save_time(self):
ts = []
@@ -22,7 +21,3 @@ class TestHardware(unittest.TestCase):
assert 0.1 < np.mean(ts) < 0.25
assert max(ts) < 0.3
if __name__ == "__main__":
unittest.main()
+7 -12
View File
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
from collections import defaultdict, deque
import pytest
import unittest
import time
import numpy as np
from dataclasses import dataclass
@@ -40,15 +39,15 @@ PROCS = [
@pytest.mark.tici
class TestPowerDraw(unittest.TestCase):
class TestPowerDraw:
def setUp(self):
def setup_method(self):
write_car_param()
# wait a bit for power save to disable
time.sleep(5)
def tearDown(self):
def teardown_method(self):
manager_cleanup()
def get_expected_messages(self, proc):
@@ -97,7 +96,7 @@ class TestPowerDraw(unittest.TestCase):
return now, msg_counts, time.monotonic() - start_time - SAMPLE_TIME
@mock_messages(['liveLocationKalman'])
def test_camera_procs(self):
def test_camera_procs(self, subtests):
baseline = get_power()
prev = baseline
@@ -122,12 +121,8 @@ class TestPowerDraw(unittest.TestCase):
expected = proc.power
msgs_received = sum(msg_counts[msg] for msg in proc.msgs)
tab.append([proc.name, round(expected, 2), round(cur, 2), self.get_expected_messages(proc), msgs_received, round(warmup_time[proc.name], 2)])
with self.subTest(proc=proc.name):
self.assertTrue(self.valid_msg_count(proc, msg_counts), f"expected {self.get_expected_messages(proc)} msgs, got {msgs_received} msgs")
self.assertTrue(self.valid_power_draw(proc, cur), f"expected {expected:.2f}W, got {cur:.2f}W")
with subtests.test(proc=proc.name):
assert self.valid_msg_count(proc, msg_counts), f"expected {self.get_expected_messages(proc)} msgs, got {msgs_received} msgs"
assert self.valid_power_draw(proc, cur), f"expected {expected:.2f}W, got {cur:.2f}W"
print(tabulate(tab))
print(f"Baseline {baseline:.2f}W\n")
if __name__ == "__main__":
unittest.main()
+2 -3
View File
@@ -1,6 +1,5 @@
import os
import random
import unittest
from pathlib import Path
@@ -54,7 +53,7 @@ class MockApiIgnore():
def get_token(self):
return "fake-token"
class UploaderTestCase(unittest.TestCase):
class UploaderTestCase:
f_type = "UNKNOWN"
root: Path
@@ -66,7 +65,7 @@ class UploaderTestCase(unittest.TestCase):
def set_ignore(self):
uploader.Api = MockApiIgnore
def setUp(self):
def setup_method(self):
uploader.Api = MockApi
uploader.fake_upload = True
uploader.force_wifi = True
+5 -10
View File
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
import time
import threading
import unittest
from collections import namedtuple
from pathlib import Path
from collections.abc import Sequence
@@ -17,9 +16,9 @@ class TestDeleter(UploaderTestCase):
def fake_statvfs(self, d):
return self.fake_stats
def setUp(self):
def setup_method(self):
self.f_type = "fcamera.hevc"
super().setUp()
super().setup_method()
self.fake_stats = Stats(f_bavail=0, f_blocks=10, f_frsize=4096)
deleter.os.statvfs = self.fake_statvfs
@@ -64,7 +63,7 @@ class TestDeleter(UploaderTestCase):
finally:
self.join_thread()
self.assertEqual(deleted_order, f_paths, "Files not deleted in expected order")
assert deleted_order == f_paths, "Files not deleted in expected order"
def test_delete_order(self):
self.assertDeleteOrder([
@@ -105,7 +104,7 @@ class TestDeleter(UploaderTestCase):
time.sleep(0.01)
self.join_thread()
self.assertTrue(f_path.exists(), "File deleted with available space")
assert f_path.exists(), "File deleted with available space"
def test_no_delete_with_lock_file(self):
f_path = self.make_file_with_data(self.seg_dir, self.f_type, lock=True)
@@ -116,8 +115,4 @@ class TestDeleter(UploaderTestCase):
time.sleep(0.01)
self.join_thread()
self.assertTrue(f_path.exists(), "File deleted when locked")
if __name__ == "__main__":
unittest.main()
assert f_path.exists(), "File deleted when locked"
+17 -22
View File
@@ -6,7 +6,6 @@ import random
import shutil
import subprocess
import time
import unittest
from pathlib import Path
from parameterized import parameterized
@@ -33,14 +32,14 @@ FILE_SIZE_TOLERANCE = 0.5
@pytest.mark.tici # TODO: all of loggerd should work on PC
class TestEncoder(unittest.TestCase):
class TestEncoder:
def setUp(self):
def setup_method(self):
self._clear_logs()
os.environ["LOGGERD_TEST"] = "1"
os.environ["LOGGERD_SEGMENT_LENGTH"] = str(SEGMENT_LENGTH)
def tearDown(self):
def teardown_method(self):
self._clear_logs()
def _clear_logs(self):
@@ -85,7 +84,7 @@ class TestEncoder(unittest.TestCase):
file_path = f"{route_prefix_path}--{i}/{camera}"
# check file exists
self.assertTrue(os.path.exists(file_path), f"segment #{i}: '{file_path}' missing")
assert os.path.exists(file_path), f"segment #{i}: '{file_path}' missing"
# TODO: this ffprobe call is really slow
# check frame count
@@ -98,13 +97,13 @@ class TestEncoder(unittest.TestCase):
frame_count = int(probe.split('\n')[0].strip())
counts.append(frame_count)
self.assertEqual(frame_count, expected_frames,
f"segment #{i}: {camera} failed frame count check: expected {expected_frames}, got {frame_count}")
assert frame_count == expected_frames, \
f"segment #{i}: {camera} failed frame count check: expected {expected_frames}, got {frame_count}"
# sanity check file size
file_size = os.path.getsize(file_path)
self.assertTrue(math.isclose(file_size, size, rel_tol=FILE_SIZE_TOLERANCE),
f"{file_path} size {file_size} isn't close to target size {size}")
assert math.isclose(file_size, size, rel_tol=FILE_SIZE_TOLERANCE), \
f"{file_path} size {file_size} isn't close to target size {size}"
# Check encodeIdx
if encode_idx_name is not None:
@@ -118,24 +117,24 @@ class TestEncoder(unittest.TestCase):
frame_idxs = [m.frameId for m in encode_msgs]
# Check frame count
self.assertEqual(frame_count, len(segment_idxs))
self.assertEqual(frame_count, len(encode_idxs))
assert frame_count == len(segment_idxs)
assert frame_count == len(encode_idxs)
# Check for duplicates or skips
self.assertEqual(0, segment_idxs[0])
self.assertEqual(len(set(segment_idxs)), len(segment_idxs))
assert 0 == segment_idxs[0]
assert len(set(segment_idxs)) == len(segment_idxs)
self.assertTrue(all(valid))
assert all(valid)
self.assertEqual(expected_frames * i, encode_idxs[0])
assert expected_frames * i == encode_idxs[0]
first_frames.append(frame_idxs[0])
self.assertEqual(len(set(encode_idxs)), len(encode_idxs))
assert len(set(encode_idxs)) == len(encode_idxs)
self.assertEqual(1, len(set(first_frames)))
assert 1 == len(set(first_frames))
if TICI:
expected_frames = fps * SEGMENT_LENGTH
self.assertEqual(min(counts), expected_frames)
assert min(counts) == expected_frames
shutil.rmtree(f"{route_prefix_path}--{i}")
try:
@@ -150,7 +149,3 @@ class TestEncoder(unittest.TestCase):
managed_processes['encoderd'].stop()
managed_processes['camerad'].stop()
managed_processes['sensord'].stop()
if __name__ == "__main__":
unittest.main()
+25 -30
View File
@@ -2,7 +2,6 @@
import os
import time
import threading
import unittest
import logging
import json
from pathlib import Path
@@ -38,8 +37,8 @@ cloudlog.addHandler(log_handler)
class TestUploader(UploaderTestCase):
def setUp(self):
super().setUp()
def setup_method(self):
super().setup_method()
log_handler.reset()
def start_thread(self):
@@ -80,13 +79,13 @@ class TestUploader(UploaderTestCase):
exp_order = self.gen_order([self.seg_num], [])
self.assertTrue(len(log_handler.upload_ignored) == 0, "Some files were ignored")
self.assertFalse(len(log_handler.upload_order) < len(exp_order), "Some files failed to upload")
self.assertFalse(len(log_handler.upload_order) > len(exp_order), "Some files were uploaded twice")
assert len(log_handler.upload_ignored) == 0, "Some files were ignored"
assert not len(log_handler.upload_order) < len(exp_order), "Some files failed to upload"
assert not len(log_handler.upload_order) > len(exp_order), "Some files were uploaded twice"
for f_path in exp_order:
self.assertEqual(os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME), UPLOAD_ATTR_VALUE, "All files not uploaded")
assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded"
self.assertTrue(log_handler.upload_order == exp_order, "Files uploaded in wrong order")
assert log_handler.upload_order == exp_order, "Files uploaded in wrong order"
def test_upload_with_wrong_xattr(self):
self.gen_files(lock=False, xattr=b'0')
@@ -98,13 +97,13 @@ class TestUploader(UploaderTestCase):
exp_order = self.gen_order([self.seg_num], [])
self.assertTrue(len(log_handler.upload_ignored) == 0, "Some files were ignored")
self.assertFalse(len(log_handler.upload_order) < len(exp_order), "Some files failed to upload")
self.assertFalse(len(log_handler.upload_order) > len(exp_order), "Some files were uploaded twice")
assert len(log_handler.upload_ignored) == 0, "Some files were ignored"
assert not len(log_handler.upload_order) < len(exp_order), "Some files failed to upload"
assert not len(log_handler.upload_order) > len(exp_order), "Some files were uploaded twice"
for f_path in exp_order:
self.assertEqual(os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME), UPLOAD_ATTR_VALUE, "All files not uploaded")
assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded"
self.assertTrue(log_handler.upload_order == exp_order, "Files uploaded in wrong order")
assert log_handler.upload_order == exp_order, "Files uploaded in wrong order"
def test_upload_ignored(self):
self.set_ignore()
@@ -117,13 +116,13 @@ class TestUploader(UploaderTestCase):
exp_order = self.gen_order([self.seg_num], [])
self.assertTrue(len(log_handler.upload_order) == 0, "Some files were not ignored")
self.assertFalse(len(log_handler.upload_ignored) < len(exp_order), "Some files failed to ignore")
self.assertFalse(len(log_handler.upload_ignored) > len(exp_order), "Some files were ignored twice")
assert len(log_handler.upload_order) == 0, "Some files were not ignored"
assert not len(log_handler.upload_ignored) < len(exp_order), "Some files failed to ignore"
assert not len(log_handler.upload_ignored) > len(exp_order), "Some files were ignored twice"
for f_path in exp_order:
self.assertEqual(os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME), UPLOAD_ATTR_VALUE, "All files not ignored")
assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not ignored"
self.assertTrue(log_handler.upload_ignored == exp_order, "Files ignored in wrong order")
assert log_handler.upload_ignored == exp_order, "Files ignored in wrong order"
def test_upload_files_in_create_order(self):
seg1_nums = [0, 1, 2, 10, 20]
@@ -142,13 +141,13 @@ class TestUploader(UploaderTestCase):
time.sleep(5)
self.join_thread()
self.assertTrue(len(log_handler.upload_ignored) == 0, "Some files were ignored")
self.assertFalse(len(log_handler.upload_order) < len(exp_order), "Some files failed to upload")
self.assertFalse(len(log_handler.upload_order) > len(exp_order), "Some files were uploaded twice")
assert len(log_handler.upload_ignored) == 0, "Some files were ignored"
assert not len(log_handler.upload_order) < len(exp_order), "Some files failed to upload"
assert not len(log_handler.upload_order) > len(exp_order), "Some files were uploaded twice"
for f_path in exp_order:
self.assertEqual(os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME), UPLOAD_ATTR_VALUE, "All files not uploaded")
assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded"
self.assertTrue(log_handler.upload_order == exp_order, "Files uploaded in wrong order")
assert log_handler.upload_order == exp_order, "Files uploaded in wrong order"
def test_no_upload_with_lock_file(self):
self.start_thread()
@@ -163,7 +162,7 @@ class TestUploader(UploaderTestCase):
for f_path in f_paths:
fn = f_path.with_suffix(f_path.suffix.replace(".bz2", ""))
uploaded = UPLOAD_ATTR_NAME in os.listxattr(fn) and os.getxattr(fn, UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE
self.assertFalse(uploaded, "File upload when locked")
assert not uploaded, "File upload when locked"
def test_no_upload_with_xattr(self):
self.gen_files(lock=False, xattr=UPLOAD_ATTR_VALUE)
@@ -173,7 +172,7 @@ class TestUploader(UploaderTestCase):
time.sleep(5)
self.join_thread()
self.assertEqual(len(log_handler.upload_order), 0, "File uploaded again")
assert len(log_handler.upload_order) == 0, "File uploaded again"
def test_clear_locks_on_startup(self):
f_paths = self.gen_files(lock=True, boot=False)
@@ -183,8 +182,4 @@ class TestUploader(UploaderTestCase):
for f_path in f_paths:
lock_path = f_path.with_suffix(f_path.suffix + ".lock")
self.assertFalse(lock_path.is_file(), "File lock not cleared on startup")
if __name__ == "__main__":
unittest.main()
assert not lock_path.is_file(), "File lock not cleared on startup"
+10 -14
View File
@@ -4,7 +4,6 @@ import pytest
import json
import time
import datetime
import unittest
import subprocess
import cereal.messaging as messaging
@@ -15,24 +14,24 @@ GOOD_SIGNAL = bool(int(os.getenv("GOOD_SIGNAL", '0')))
@pytest.mark.tici
class TestRawgpsd(unittest.TestCase):
class TestRawgpsd:
@classmethod
def setUpClass(cls):
def setup_class(cls):
os.system("sudo systemctl start systemd-resolved")
os.system("sudo systemctl restart ModemManager lte")
wait_for_modem()
@classmethod
def tearDownClass(cls):
def teardown_class(cls):
managed_processes['qcomgpsd'].stop()
os.system("sudo systemctl restart systemd-resolved")
os.system("sudo systemctl restart ModemManager lte")
def setUp(self):
def setup_method(self):
at_cmd("AT+QGPSDEL=0")
self.sm = messaging.SubMaster(['qcomGnss', 'gpsLocation', 'gnssMeasurements'])
def tearDown(self):
def teardown_method(self):
managed_processes['qcomgpsd'].stop()
os.system("sudo systemctl restart systemd-resolved")
@@ -57,18 +56,18 @@ class TestRawgpsd(unittest.TestCase):
os.system("sudo systemctl restart ModemManager")
assert self._wait_for_output(30)
def test_startup_time(self):
def test_startup_time(self, subtests):
for internet in (True, False):
if not internet:
os.system("sudo systemctl stop systemd-resolved")
with self.subTest(internet=internet):
with subtests.test(internet=internet):
managed_processes['qcomgpsd'].start()
assert self._wait_for_output(7)
managed_processes['qcomgpsd'].stop()
def test_turns_off_gnss(self):
def test_turns_off_gnss(self, subtests):
for s in (0.1, 1, 5):
with self.subTest(runtime=s):
with subtests.test(runtime=s):
managed_processes['qcomgpsd'].start()
time.sleep(s)
managed_processes['qcomgpsd'].stop()
@@ -87,7 +86,7 @@ class TestRawgpsd(unittest.TestCase):
if should_be_loaded:
assert valid_duration == "10080" # should be max time
injected_time = datetime.datetime.strptime(injected_time_str.replace("\"", ""), "%Y/%m/%d,%H:%M:%S")
self.assertLess(abs((datetime.datetime.utcnow() - injected_time).total_seconds()), 60*60*12)
assert abs((datetime.datetime.utcnow() - injected_time).total_seconds()) < 60*60*12
else:
valid_duration, injected_time_str = out.split(",", 1)
injected_time_str = injected_time_str.replace('\"', '').replace('\'', '')
@@ -119,6 +118,3 @@ class TestRawgpsd(unittest.TestCase):
time.sleep(15)
managed_processes['qcomgpsd'].stop()
self.check_assistance(True)
if __name__ == "__main__":
unittest.main(failfast=True)
+9 -13
View File
@@ -2,7 +2,6 @@
import os
import pytest
import time
import unittest
import numpy as np
from collections import namedtuple, defaultdict
@@ -99,9 +98,9 @@ def read_sensor_events(duration_sec):
return {k: v for k, v in events.items() if len(v) > 0}
@pytest.mark.tici
class TestSensord(unittest.TestCase):
class TestSensord:
@classmethod
def setUpClass(cls):
def setup_class(cls):
# enable LSM self test
os.environ["LSM_SELF_TEST"] = "1"
@@ -119,10 +118,10 @@ class TestSensord(unittest.TestCase):
managed_processes["sensord"].stop()
@classmethod
def tearDownClass(cls):
def teardown_class(cls):
managed_processes["sensord"].stop()
def tearDown(self):
def teardown_method(self):
managed_processes["sensord"].stop()
def test_sensors_present(self):
@@ -133,9 +132,9 @@ class TestSensord(unittest.TestCase):
m = getattr(measurement, measurement.which())
seen.add((str(m.source), m.which()))
self.assertIn(seen, SENSOR_CONFIGURATIONS)
assert seen in SENSOR_CONFIGURATIONS
def test_lsm6ds3_timing(self):
def test_lsm6ds3_timing(self, subtests):
# verify measurements are sampled and published at 104Hz
sensor_t = {
@@ -152,7 +151,7 @@ class TestSensord(unittest.TestCase):
sensor_t[m.sensor].append(m.timestamp)
for s, vals in sensor_t.items():
with self.subTest(sensor=s):
with subtests.test(sensor=s):
assert len(vals) > 0
tdiffs = np.diff(vals) / 1e6 # millis
@@ -166,9 +165,9 @@ class TestSensord(unittest.TestCase):
stddev = np.std(tdiffs)
assert stddev < 2.0, f"Standard-dev to big {stddev}"
def test_sensor_frequency(self):
def test_sensor_frequency(self, subtests):
for s, msgs in self.events.items():
with self.subTest(sensor=s):
with subtests.test(sensor=s):
freq = len(msgs) / self.sample_secs
ef = SERVICE_LIST[s].frequency
assert ef*0.85 <= freq <= ef*1.15
@@ -246,6 +245,3 @@ class TestSensord(unittest.TestCase):
state_two = get_irq_count(self.sensord_irq)
assert state_one == state_two, "Interrupts received after sensord stop!"
if __name__ == "__main__":
unittest.main()
+3 -7
View File
@@ -2,7 +2,6 @@
import glob
import os
import time
import unittest
import cereal.messaging as messaging
from openpilot.selfdrive.manager.process_config import managed_processes
@@ -10,8 +9,8 @@ from openpilot.system.hardware.hw import Paths
from openpilot.common.swaglog import cloudlog, ipchandler
class TestLogmessaged(unittest.TestCase):
def setUp(self):
class TestLogmessaged:
def setup_method(self):
# clear the IPC buffer in case some other tests used cloudlog and filled it
ipchandler.close()
ipchandler.connect()
@@ -25,7 +24,7 @@ class TestLogmessaged(unittest.TestCase):
messaging.drain_sock(self.sock)
messaging.drain_sock(self.error_sock)
def tearDown(self):
def teardown_method(self):
del self.sock
del self.error_sock
managed_processes['logmessaged'].stop(block=True)
@@ -55,6 +54,3 @@ class TestLogmessaged(unittest.TestCase):
logsize = sum([os.path.getsize(f) for f in self._get_log_files()])
assert (n*len(msg)) < logsize < (n*(len(msg)+1024))
if __name__ == "__main__":
unittest.main()
+2 -7
View File
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
import pytest
import time
import unittest
import cereal.messaging as messaging
from cereal.services import SERVICE_LIST
@@ -13,9 +12,9 @@ from openpilot.system.hardware.tici.pins import GPIO
# TODO: test TTFF when we have good A-GNSS
@pytest.mark.tici
class TestPigeond(unittest.TestCase):
class TestPigeond:
def tearDown(self):
def teardown_method(self):
managed_processes['pigeond'].stop()
@with_processes(['pigeond'])
@@ -54,7 +53,3 @@ class TestPigeond(unittest.TestCase):
assert gpio_read(GPIO.UBLOX_RST_N) == 0
assert gpio_read(GPIO.GNSS_PWR_EN) == 0
if __name__ == "__main__":
unittest.main()
+41 -45
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import pytest
import os
import pathlib
import unittest
import tempfile
import subprocess
@@ -14,9 +14,9 @@ from openpilot.system.updated.casync import tar
LOOPBACK = os.environ.get('LOOPBACK', None)
class TestCasync(unittest.TestCase):
class TestCasync:
@classmethod
def setUpClass(cls):
def setup_class(cls):
cls.tmpdir = tempfile.TemporaryDirectory()
# Build example contents
@@ -43,7 +43,7 @@ class TestCasync(unittest.TestCase):
# Ensure we have chunk reuse
assert len(hashes) > len(set(hashes))
def setUp(self):
def setup_method(self):
# Clear target_lo
if LOOPBACK is not None:
self.target_lo = LOOPBACK
@@ -53,7 +53,7 @@ class TestCasync(unittest.TestCase):
self.target_fn = os.path.join(self.tmpdir.name, next(tempfile._get_candidate_names()))
self.seed_fn = os.path.join(self.tmpdir.name, next(tempfile._get_candidate_names()))
def tearDown(self):
def teardown_method(self):
for fn in [self.target_fn, self.seed_fn]:
try:
os.unlink(fn)
@@ -67,9 +67,9 @@ class TestCasync(unittest.TestCase):
stats = casync.extract(target, sources, self.target_fn)
with open(self.target_fn, 'rb') as target_f:
self.assertEqual(target_f.read(), self.contents)
assert target_f.read() == self.contents
self.assertEqual(stats['remote'], len(self.contents))
assert stats['remote'] == len(self.contents)
def test_seed(self):
target = casync.parse_caibx(self.manifest_fn)
@@ -83,10 +83,10 @@ class TestCasync(unittest.TestCase):
stats = casync.extract(target, sources, self.target_fn)
with open(self.target_fn, 'rb') as target_f:
self.assertEqual(target_f.read(), self.contents)
assert target_f.read() == self.contents
self.assertGreater(stats['seed'], 0)
self.assertLess(stats['remote'], len(self.contents))
assert stats['seed'] > 0
assert stats['remote'] < len(self.contents)
def test_already_done(self):
"""Test that an already flashed target doesn't download any chunks"""
@@ -101,9 +101,9 @@ class TestCasync(unittest.TestCase):
stats = casync.extract(target, sources, self.target_fn)
with open(self.target_fn, 'rb') as f:
self.assertEqual(f.read(), self.contents)
assert f.read() == self.contents
self.assertEqual(stats['target'], len(self.contents))
assert stats['target'] == len(self.contents)
def test_chunk_reuse(self):
"""Test that chunks that are reused are only downloaded once"""
@@ -119,11 +119,11 @@ class TestCasync(unittest.TestCase):
stats = casync.extract(target, sources, self.target_fn)
with open(self.target_fn, 'rb') as f:
self.assertEqual(f.read(), self.contents)
assert f.read() == self.contents
self.assertLess(stats['remote'], len(self.contents))
assert stats['remote'] < len(self.contents)
@unittest.skipUnless(LOOPBACK, "requires loopback device")
@pytest.mark.skipif(not LOOPBACK, reason="requires loopback device")
def test_lo_simple_extract(self):
target = casync.parse_caibx(self.manifest_fn)
sources = [('remote', casync.RemoteChunkReader(self.store_fn), casync.build_chunk_dict(target))]
@@ -131,11 +131,11 @@ class TestCasync(unittest.TestCase):
stats = casync.extract(target, sources, self.target_lo)
with open(self.target_lo, 'rb') as target_f:
self.assertEqual(target_f.read(len(self.contents)), self.contents)
assert target_f.read(len(self.contents)) == self.contents
self.assertEqual(stats['remote'], len(self.contents))
assert stats['remote'] == len(self.contents)
@unittest.skipUnless(LOOPBACK, "requires loopback device")
@pytest.mark.skipif(not LOOPBACK, reason="requires loopback device")
def test_lo_chunk_reuse(self):
"""Test that chunks that are reused are only downloaded once"""
target = casync.parse_caibx(self.manifest_fn)
@@ -146,12 +146,12 @@ class TestCasync(unittest.TestCase):
stats = casync.extract(target, sources, self.target_lo)
with open(self.target_lo, 'rb') as f:
self.assertEqual(f.read(len(self.contents)), self.contents)
assert f.read(len(self.contents)) == self.contents
self.assertLess(stats['remote'], len(self.contents))
assert stats['remote'] < len(self.contents)
class TestCasyncDirectory(unittest.TestCase):
class TestCasyncDirectory:
"""Tests extracting a directory stored as a casync tar archive"""
NUM_FILES = 16
@@ -174,7 +174,7 @@ class TestCasyncDirectory(unittest.TestCase):
os.symlink(f"file_{i}.txt", os.path.join(directory, f"link_{i}.txt"))
@classmethod
def setUpClass(cls):
def setup_class(cls):
cls.tmpdir = tempfile.TemporaryDirectory()
# Create casync files
@@ -190,16 +190,16 @@ class TestCasyncDirectory(unittest.TestCase):
subprocess.check_output(["casync", "make", "--compression=xz", "--store", cls.store_fn, cls.manifest_fn, cls.orig_fn])
@classmethod
def tearDownClass(cls):
def teardown_class(cls):
cls.tmpdir.cleanup()
cls.directory_to_extract.cleanup()
def setUp(self):
def setup_method(self):
self.cache_dir = tempfile.TemporaryDirectory()
self.working_dir = tempfile.TemporaryDirectory()
self.out_dir = tempfile.TemporaryDirectory()
def tearDown(self):
def teardown_method(self):
self.cache_dir.cleanup()
self.working_dir.cleanup()
self.out_dir.cleanup()
@@ -216,32 +216,32 @@ class TestCasyncDirectory(unittest.TestCase):
stats = casync.extract_directory(target, sources, pathlib.Path(self.out_dir.name), tmp_filename)
with open(os.path.join(self.out_dir.name, "file_0.txt"), "rb") as f:
self.assertEqual(f.read(), self.contents)
assert f.read() == self.contents
with open(os.path.join(self.out_dir.name, "link_0.txt"), "rb") as f:
self.assertEqual(f.read(), self.contents)
self.assertEqual(os.readlink(os.path.join(self.out_dir.name, "link_0.txt")), "file_0.txt")
assert f.read() == self.contents
assert os.readlink(os.path.join(self.out_dir.name, "link_0.txt")) == "file_0.txt"
return stats
def test_no_cache(self):
self.setup_cache(self.cache_dir.name, [])
stats = self.run_test()
self.assertGreater(stats['remote'], 0)
self.assertEqual(stats['cache'], 0)
assert stats['remote'] > 0
assert stats['cache'] == 0
def test_full_cache(self):
self.setup_cache(self.cache_dir.name, range(self.NUM_FILES))
stats = self.run_test()
self.assertEqual(stats['remote'], 0)
self.assertGreater(stats['cache'], 0)
assert stats['remote'] == 0
assert stats['cache'] > 0
def test_one_file_cache(self):
self.setup_cache(self.cache_dir.name, range(1))
stats = self.run_test()
self.assertGreater(stats['remote'], 0)
self.assertGreater(stats['cache'], 0)
self.assertLess(stats['cache'], stats['remote'])
assert stats['remote'] > 0
assert stats['cache'] > 0
assert stats['cache'] < stats['remote']
def test_one_file_incorrect_cache(self):
self.setup_cache(self.cache_dir.name, range(self.NUM_FILES))
@@ -249,19 +249,15 @@ class TestCasyncDirectory(unittest.TestCase):
f.write(b"1234")
stats = self.run_test()
self.assertGreater(stats['remote'], 0)
self.assertGreater(stats['cache'], 0)
self.assertGreater(stats['cache'], stats['remote'])
assert stats['remote'] > 0
assert stats['cache'] > 0
assert stats['cache'] > stats['remote']
def test_one_file_missing_cache(self):
self.setup_cache(self.cache_dir.name, range(self.NUM_FILES))
os.unlink(os.path.join(self.cache_dir.name, "file_12.txt"))
stats = self.run_test()
self.assertGreater(stats['remote'], 0)
self.assertGreater(stats['cache'], 0)
self.assertGreater(stats['cache'], stats['remote'])
if __name__ == "__main__":
unittest.main()
assert stats['remote'] > 0
assert stats['cache'] > 0
assert stats['cache'] > stats['remote']
+34 -40
View File
@@ -1,7 +1,5 @@
#!/usr/bin/env python3
import asyncio
import unittest
from unittest.mock import Mock, MagicMock, patch
import json
# for aiortc and its dependencies
import warnings
@@ -20,15 +18,15 @@ from openpilot.system.webrtc.device.audio import AudioInputStreamTrack
from openpilot.common.realtime import DT_DMON
class TestStreamSession(unittest.TestCase):
def setUp(self):
class TestStreamSession:
def setup_method(self):
self.loop = asyncio.new_event_loop()
def tearDown(self):
def teardown_method(self):
self.loop.stop()
self.loop.close()
def test_outgoing_proxy(self):
def test_outgoing_proxy(self, mocker):
test_msg = log.Event.new_message()
test_msg.logMonoTime = 123
test_msg.valid = True
@@ -36,27 +34,27 @@ class TestStreamSession(unittest.TestCase):
expected_dict = {"type": "customReservedRawData0", "logMonoTime": 123, "valid": True, "data": "test"}
expected_json = json.dumps(expected_dict).encode()
channel = Mock(spec=RTCDataChannel)
channel = mocker.Mock(spec=RTCDataChannel)
mocked_submaster = messaging.SubMaster(["customReservedRawData0"])
def mocked_update(t):
mocked_submaster.update_msgs(0, [test_msg])
with patch.object(messaging.SubMaster, "update", side_effect=mocked_update):
proxy = CerealOutgoingMessageProxy(mocked_submaster)
proxy.add_channel(channel)
mocker.patch.object(messaging.SubMaster, "update", side_effect=mocked_update)
proxy = CerealOutgoingMessageProxy(mocked_submaster)
proxy.add_channel(channel)
proxy.update()
proxy.update()
channel.send.assert_called_once_with(expected_json)
channel.send.assert_called_once_with(expected_json)
def test_incoming_proxy(self):
def test_incoming_proxy(self, mocker):
tested_msgs = [
{"type": "customReservedRawData0", "data": "test"}, # primitive
{"type": "can", "data": [{"address": 0, "busTime": 0, "dat": "", "src": 0}]}, # list
{"type": "testJoystick", "data": {"axes": [0, 0], "buttons": [False]}}, # dict
]
mocked_pubmaster = MagicMock(spec=messaging.PubMaster)
mocked_pubmaster = mocker.MagicMock(spec=messaging.PubMaster)
proxy = CerealIncomingMessageProxy(mocked_pubmaster)
@@ -65,44 +63,40 @@ class TestStreamSession(unittest.TestCase):
mocked_pubmaster.send.assert_called_once()
mt, md = mocked_pubmaster.send.call_args.args
self.assertEqual(mt, msg["type"])
self.assertIsInstance(md, capnp._DynamicStructBuilder)
self.assertTrue(hasattr(md, msg["type"]))
assert mt == msg["type"]
assert isinstance(md, capnp._DynamicStructBuilder)
assert hasattr(md, msg["type"])
mocked_pubmaster.reset_mock()
def test_livestream_track(self):
def test_livestream_track(self, mocker):
fake_msg = messaging.new_message("livestreamDriverEncodeData")
config = {"receive.return_value": fake_msg.to_bytes()}
with patch("cereal.messaging.SubSocket", spec=True, **config):
track = LiveStreamVideoStreamTrack("driver")
mocker.patch("cereal.messaging.SubSocket", spec=True, **config)
track = LiveStreamVideoStreamTrack("driver")
self.assertTrue(track.id.startswith("driver"))
self.assertEqual(track.codec_preference(), "H264")
assert track.id.startswith("driver")
assert track.codec_preference() == "H264"
for i in range(5):
packet = self.loop.run_until_complete(track.recv())
self.assertEqual(packet.time_base, VIDEO_TIME_BASE)
self.assertEqual(packet.pts, int(i * DT_DMON * VIDEO_CLOCK_RATE))
self.assertEqual(packet.size, 0)
for i in range(5):
packet = self.loop.run_until_complete(track.recv())
assert packet.time_base == VIDEO_TIME_BASE
assert packet.pts == int(i * DT_DMON * VIDEO_CLOCK_RATE)
assert packet.size == 0
def test_input_audio_track(self):
def test_input_audio_track(self, mocker):
packet_time, rate = 0.02, 16000
sample_count = int(packet_time * rate)
mocked_stream = MagicMock(spec=pyaudio.Stream)
mocked_stream = mocker.MagicMock(spec=pyaudio.Stream)
mocked_stream.read.return_value = b"\x00" * 2 * sample_count
config = {"open.side_effect": lambda *args, **kwargs: mocked_stream}
with patch("pyaudio.PyAudio", spec=True, **config):
track = AudioInputStreamTrack(audio_format=pyaudio.paInt16, packet_time=packet_time, rate=rate)
mocker.patch("pyaudio.PyAudio", spec=True, **config)
track = AudioInputStreamTrack(audio_format=pyaudio.paInt16, packet_time=packet_time, rate=rate)
for i in range(5):
frame = self.loop.run_until_complete(track.recv())
self.assertEqual(frame.rate, rate)
self.assertEqual(frame.samples, sample_count)
self.assertEqual(frame.pts, i * sample_count)
if __name__ == "__main__":
unittest.main()
for i in range(5):
frame = self.loop.run_until_complete(track.recv())
assert frame.rate == rate
assert frame.samples == sample_count
assert frame.pts == i * sample_count
+11 -15
View File
@@ -1,8 +1,7 @@
#!/usr/bin/env python
import pytest
import asyncio
import json
import unittest
from unittest.mock import MagicMock, AsyncMock
# for aiortc and its dependencies
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
@@ -20,19 +19,20 @@ from parameterized import parameterized_class
(["testJoystick"], []),
([], []),
])
class TestWebrtcdProc(unittest.IsolatedAsyncioTestCase):
@pytest.mark.asyncio
class TestWebrtcdProc():
async def assertCompletesWithTimeout(self, awaitable, timeout=1):
try:
async with asyncio.timeout(timeout):
await awaitable
except TimeoutError:
self.fail("Timeout while waiting for awaitable to complete")
pytest.fail("Timeout while waiting for awaitable to complete")
async def test_webrtcd(self):
mock_request = MagicMock()
async def test_webrtcd(self, mocker):
mock_request = mocker.MagicMock()
async def connect(offer):
body = {'sdp': offer.sdp, 'cameras': offer.video, 'bridge_services_in': self.in_services, 'bridge_services_out': self.out_services}
mock_request.json.side_effect = AsyncMock(return_value=body)
mock_request.json.side_effect = mocker.AsyncMock(return_value=body)
response = await get_stream(mock_request)
response_json = json.loads(response.text)
return aiortc.RTCSessionDescription(**response_json)
@@ -48,9 +48,9 @@ class TestWebrtcdProc(unittest.IsolatedAsyncioTestCase):
await self.assertCompletesWithTimeout(stream.start())
await self.assertCompletesWithTimeout(stream.wait_for_connection())
self.assertTrue(stream.has_incoming_video_track("road"))
self.assertTrue(stream.has_incoming_audio_track())
self.assertEqual(stream.has_messaging_channel(), len(self.in_services) > 0 or len(self.out_services) > 0)
assert stream.has_incoming_video_track("road")
assert stream.has_incoming_audio_track()
assert stream.has_messaging_channel() == (len(self.in_services) > 0 or len(self.out_services) > 0)
video_track, audio_track = stream.get_incoming_video_track("road"), stream.get_incoming_audio_track()
await self.assertCompletesWithTimeout(video_track.recv())
@@ -59,10 +59,6 @@ class TestWebrtcdProc(unittest.IsolatedAsyncioTestCase):
await self.assertCompletesWithTimeout(stream.stop())
# cleanup, very implementation specific, test may break if it changes
self.assertTrue(mock_request.app["streams"].__setitem__.called, "Implementation changed, please update this test")
assert mock_request.app["streams"].__setitem__.called, "Implementation changed, please update this test"
_, session = mock_request.app["streams"].__setitem__.call_args.args
await self.assertCompletesWithTimeout(session.post_run_cleanup())
if __name__ == "__main__":
unittest.main()