mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-09-30 19:33:42 +08:00
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:
@@ -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()
|
||||
|
||||
@@ -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,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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user