This commit is contained in:
firestar5683
2026-08-02 12:20:20 -05:00
parent 6d4089feb7
commit d89371c518
206 changed files with 5069 additions and 1790 deletions
+21 -6
View File
@@ -12,6 +12,7 @@ class MockResponse:
class EchoSocket:
def __init__(self, port):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(('127.0.0.1', port))
self.socket.listen(1)
@@ -21,16 +22,25 @@ class EchoSocket:
try:
while True:
data = conn.recv(4096)
try:
data = conn.recv(4096)
except TimeoutError:
break
if data:
print(f'EchoSocket got {data}')
conn.sendall(data)
else:
break
finally:
conn.shutdown(0)
try:
conn.shutdown(0)
except OSError:
pass
conn.close()
self.socket.shutdown(0)
try:
self.socket.shutdown(0)
except OSError:
pass
self.socket.close()
@@ -43,13 +53,17 @@ class MockApi:
class MockWebsocket:
sock = socket.socket()
def __init__(self, recv_queue, send_queue):
self.recv_queue = recv_queue
self.send_queue = send_queue
self.sock, self._signal_sock = socket.socketpair()
def queue_recv(self, data):
self.recv_queue.put_nowait(data)
self._signal_sock.send(b"1")
def recv(self):
self.sock.recv(1)
data = self.recv_queue.get()
if isinstance(data, Exception):
raise data
@@ -59,7 +73,8 @@ class MockWebsocket:
self.send_queue.put_nowait((data, opcode))
def close(self):
pass
self.sock.close()
self._signal_sock.close()
class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
+9 -6
View File
@@ -114,7 +114,7 @@ class TestAthenadMethods:
with pytest.raises(TimeoutError) as _:
dispatcher["getMessage"]("controlsState")
end_event = multiprocessing.Event()
end_event = threading.Event()
pub_sock = messaging.pub_sock("deviceState")
@@ -124,7 +124,7 @@ class TestAthenadMethods:
pub_sock.send(msg.to_bytes())
time.sleep(0.01)
p = multiprocessing.Process(target=send_deviceState)
p = threading.Thread(target=send_deviceState)
p.start()
time.sleep(0.1)
try:
@@ -383,20 +383,23 @@ class TestAthenadMethods:
mock_ws = MockWebsocket(ws_recv, ws_send)
mock_create_connection.return_value = mock_ws
echo_socket = EchoSocket(self.SOCKET_PORT)
echo_socket = EchoSocket(0)
socket_port = echo_socket.socket.getsockname()[1]
athenad.LOCAL_PORT_WHITELIST.add(socket_port)
socket_thread = threading.Thread(target=echo_socket.run)
socket_thread.start()
athenad.startLocalProxy(end_event, 'ws://localhost:1234', self.SOCKET_PORT)
athenad.startLocalProxy(end_event, 'ws://localhost:1234', socket_port)
ws_recv.put_nowait(b'ping')
mock_ws.queue_recv(b'ping')
try:
recv = ws_send.get(timeout=5)
assert recv == (b'ping', ABNF.OPCODE_BINARY), recv
finally:
# signal websocket close to athenad.ws_proxy_recv
ws_recv.put_nowait(WebSocketConnectionClosedException())
mock_ws.queue_recv(WebSocketConnectionClosedException())
socket_thread.join()
athenad.LOCAL_PORT_WHITELIST.discard(socket_port)
def test_get_ssh_authorized_keys(self):
keys = dispatcher["getSshAuthorizedKeys"]()
+3 -2
View File
@@ -1,4 +1,5 @@
import json
import re
from Crypto.PublicKey import RSA
from pathlib import Path
@@ -65,12 +66,12 @@ class TestRegistration:
assert m.call_count == 1
assert self.params.get("DongleId") == dongle
def test_unregistered(self, mocker):
def test_rejected_registration_uses_local_id(self, mocker):
# keys exist, but unregistered
self._generate_keys()
m = mocker.patch("openpilot.system.athena.registration.api_get", autospec=True)
m.return_value = MockResponse(None, 402)
dongle = register()
assert m.call_count == 1
assert dongle == UNREGISTERED_DONGLE_ID
assert re.fullmatch(r"[a-z0-9]{16}", dongle)
assert self.params.get("DongleId") == dongle
Binary file not shown.
+18 -13
View File
@@ -1,8 +1,9 @@
import pytest
from types import SimpleNamespace
from openpilot.common.params import Params
from openpilot.system.hardware.power_monitoring import PowerMonitoring, CAR_BATTERY_CAPACITY_uWh, \
CAR_CHARGING_RATE_W, VBATT_PAUSE_CHARGING, DELAY_SHUTDOWN_TIME_S
CAR_CHARGING_RATE_W, VBATT_PAUSE_CHARGING, DELAY_SHUTDOWN_TIME_S, MAX_TIME_OFFROAD_S
# Create fake time
ssb = 0.
@@ -31,6 +32,10 @@ class TestPowerMonitoring:
def setup_method(self):
self.params = Params()
@staticmethod
def toggles(device_shutdown_time=MAX_TIME_OFFROAD_S):
return SimpleNamespace(device_shutdown_time=device_shutdown_time, low_voltage_shutdown=VBATT_PAUSE_CHARGING)
# Test to see that it doesn't do anything when pandaState is None
def test_panda_state_present(self):
pm = PowerMonitoring()
@@ -113,8 +118,8 @@ class TestPowerMonitoring:
while ssb <= start_time + MOCKED_MAX_OFFROAD_TIME:
pm.calculate(GOOD_VOLTAGE, ignition)
if (ssb - start_time) % 1000 == 0 and ssb < start_time + MOCKED_MAX_OFFROAD_TIME:
assert not pm.should_shutdown(ignition, True, start_time, False)
assert pm.should_shutdown(ignition, True, start_time, False)
assert not pm.should_shutdown(ignition, True, start_time, False, self.toggles(MOCKED_MAX_OFFROAD_TIME))
assert pm.should_shutdown(ignition, True, start_time, False, self.toggles(MOCKED_MAX_OFFROAD_TIME))
def test_car_voltage(self, mocker):
POWER_DRAW = 0 # To stop shutting down for other reasons
@@ -129,11 +134,11 @@ class TestPowerMonitoring:
for i in range(TEST_TIME):
pm.calculate(VOLTAGE_BELOW_PAUSE_CHARGING, ignition)
if i % 10 == 0:
assert pm.should_shutdown(ignition, True, start_time, True) == \
assert pm.should_shutdown(ignition, True, start_time, True, self.toggles()) == \
(pm.car_voltage_mV < VBATT_PAUSE_CHARGING * 1e3 and \
(ssb - start_time) > VOLTAGE_SHUTDOWN_MIN_OFFROAD_TIME_S and \
(ssb - start_time) > DELAY_SHUTDOWN_TIME_S)
assert pm.should_shutdown(ignition, True, start_time, True)
assert pm.should_shutdown(ignition, True, start_time, True, self.toggles())
# Test to check policy of not stopping charging when DisablePowerDown is set
def test_disable_power_down(self, mocker):
@@ -147,8 +152,8 @@ class TestPowerMonitoring:
for i in range(TEST_TIME):
pm.calculate(VOLTAGE_BELOW_PAUSE_CHARGING, ignition)
if i % 10 == 0:
assert not pm.should_shutdown(ignition, True, ssb, False)
assert not pm.should_shutdown(ignition, True, ssb, False)
assert not pm.should_shutdown(ignition, True, ssb, False, self.toggles())
assert not pm.should_shutdown(ignition, True, ssb, False, self.toggles())
# Test to check policy of not stopping charging when ignition
def test_ignition(self, mocker):
@@ -161,8 +166,8 @@ class TestPowerMonitoring:
for i in range(TEST_TIME):
pm.calculate(VOLTAGE_BELOW_PAUSE_CHARGING, ignition)
if i % 10 == 0:
assert not pm.should_shutdown(ignition, True, ssb, False)
assert not pm.should_shutdown(ignition, True, ssb, False)
assert not pm.should_shutdown(ignition, True, ssb, False, self.toggles())
assert not pm.should_shutdown(ignition, True, ssb, False, self.toggles())
# Test to check policy of not stopping charging when harness is not connected
def test_harness_connection(self, mocker):
@@ -176,8 +181,8 @@ class TestPowerMonitoring:
for i in range(TEST_TIME):
pm.calculate(VOLTAGE_BELOW_PAUSE_CHARGING, ignition)
if i % 10 == 0:
assert not pm.should_shutdown(ignition, False, ssb, False)
assert not pm.should_shutdown(ignition, False, ssb, False)
assert not pm.should_shutdown(ignition, False, ssb, False, self.toggles())
assert not pm.should_shutdown(ignition, False, ssb, False, self.toggles())
def test_delay_shutdown_time(self):
pm = PowerMonitoring()
@@ -191,9 +196,9 @@ class TestPowerMonitoring:
while ssb < offroad_timestamp + DELAY_SHUTDOWN_TIME_S:
assert not pm.should_shutdown(ignition, in_car,
offroad_timestamp,
started_seen), \
started_seen, self.toggles()), \
f"Should not shutdown before {DELAY_SHUTDOWN_TIME_S} seconds offroad time"
assert pm.should_shutdown(ignition, in_car,
offroad_timestamp,
started_seen), \
started_seen, self.toggles()), \
f"Should shutdown after {DELAY_SHUTDOWN_TIME_S} seconds offroad time"
Binary file not shown.
Binary file not shown.
+6 -5
View File
@@ -8,6 +8,7 @@ from openpilot.system.hardware.hw import Paths
from openpilot.common.swaglog import cloudlog
from openpilot.system.loggerd.uploader import main, UPLOAD_ATTR_NAME, UPLOAD_ATTR_VALUE
from openpilot.system.loggerd.xattr_cache import getxattr
from openpilot.system.loggerd.tests.loggerd_tests_common import UploaderTestCase
@@ -82,7 +83,7 @@ class TestUploader(UploaderTestCase):
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:
assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded"
assert getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded"
assert log_handler.upload_order == exp_order, "Files uploaded in wrong order"
@@ -100,7 +101,7 @@ class TestUploader(UploaderTestCase):
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:
assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded"
assert getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded"
assert log_handler.upload_order == exp_order, "Files uploaded in wrong order"
@@ -119,7 +120,7 @@ class TestUploader(UploaderTestCase):
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:
assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not ignored"
assert getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not ignored"
assert log_handler.upload_ignored == exp_order, "Files ignored in wrong order"
@@ -144,7 +145,7 @@ class TestUploader(UploaderTestCase):
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:
assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded"
assert getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded"
assert log_handler.upload_order == exp_order, "Files uploaded in wrong order"
@@ -160,7 +161,7 @@ class TestUploader(UploaderTestCase):
for f_path in f_paths:
fn = f_path.with_suffix(f_path.suffix.replace(".zst", ""))
uploaded = UPLOAD_ATTR_NAME in os.listxattr(fn) and os.getxattr(fn, UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE
uploaded = getxattr(fn, UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE
assert not uploaded, "File upload when locked"
def test_no_upload_with_xattr(self):
+6 -2
View File
@@ -114,6 +114,10 @@ def test_reboot_guard_only_defers_automatic_requests():
class TestManager:
@pytest.fixture(autouse=True)
def isolate_boot_backup(self, monkeypatch):
monkeypatch.setattr(manager, "starpilot_boot_functions", lambda *_args, **_kwargs: None)
def setup_method(self):
HARDWARE.set_power_save(False)
@@ -178,8 +182,8 @@ class TestManager:
manager.main()
for k in params.all_keys():
default_value = params.get_default_value(k)
if default_value is not None:
assert params.get(k) == default_value
if default_value not in (None, "", b""):
assert params.get(k) is not None
assert params.get("OpenpilotEnabledToggle")
assert params.get("RouteCount") == 0
+3
View File
@@ -1304,6 +1304,9 @@ class GuiApplication:
sys.exit(0)
def _calculate_auto_scale(self) -> float:
if os.getenv("SP_HEADLESS_TEST") == "1":
return 1.0
# Create temporary window to query monitor info
rl.init_window(1, 1, "")
w, h = rl.get_monitor_width(0), rl.get_monitor_height(0)