Files
StarPilot/openpilot/system/tests/test_logmessaged.py
T
2026-11-02 09:24:41 -06:00

85 lines
2.8 KiB
Python

import glob
import os
import time
import uuid
from openpilot.common.test import OpenpilotTestCase
import openpilot.cereal.messaging as messaging
from openpilot.system.manager.process_config import managed_processes
from openpilot.common.hardware.hw import Paths
from openpilot.common.swaglog import SWAGLOG_MAX_SIZE, cloudlog
TIMEOUT = 10.
class TestLogmessaged(OpenpilotTestCase):
def setup_method(self):
managed_processes['logmessaged'].start()
while not os.path.exists(Paths.swaglog_ipc()):
time.sleep(0.01)
self.sock = messaging.sub_sock("logMessage", timeout=100, conflate=False)
self.error_sock = messaging.sub_sock("logMessage", timeout=100, conflate=False)
# ensure sockets are connected: probe until each socket has received one.
# debug logs are published but not written to the log files.
# logmessaged handles logs in order, so after the final drain no probes are in flight
pending = {self.sock, self.error_sock}
deadline = time.monotonic() + TIMEOUT
while pending:
assert time.monotonic() < deadline, "timed out connecting to logmessaged"
cloudlog.debug("probe")
time.sleep(0.01)
pending = {s for s in pending if not messaging.drain_sock(s)}
messaging.drain_sock(self.sock)
messaging.drain_sock(self.error_sock)
def teardown_method(self):
del self.sock
del self.error_sock
managed_processes['logmessaged'].stop(block=True)
def _get_log_files(self):
return list(glob.glob(os.path.join(Paths.swaglog_root(), "swaglog.*")))
def _recv_one(self):
deadline = time.monotonic() + TIMEOUT
while (m := messaging.recv_one(self.sock)) is None:
assert time.monotonic() < deadline, "timed out waiting for logMessage"
return m
def _drain(self):
# logmessaged handles logs in order, so everything logged before the sentinel is received before it
sentinel = f"sentinel {uuid.uuid4()}"
cloudlog.debug(sentinel)
msgs = []
while sentinel not in (m := self._recv_one()).logMessage:
msgs.append(m)
return msgs
def test_simple_log(self):
msgs = [f"abc {i}" for i in range(10)]
for m in msgs:
cloudlog.error(m)
m = self._drain()
assert len(m) == len(msgs)
assert len(self._get_log_files()) >= 1
def test_big_log(self):
n = 10
msg = "a"*300*1024
for _ in range(n):
cloudlog.info(msg)
# wait for each one, the non-blocking sender drops logs that don't fit in the socket buffer
assert msg in self._recv_one().logMessage
assert len(self._drain()) == 0
logsize = sum([os.path.getsize(f) for f in self._get_log_files()])
assert (n*len(msg)) < logsize < (n*(len(msg)+1024))
def test_too_big_log(self):
cloudlog.info("a"*SWAGLOG_MAX_SIZE)
cloudlog.info("small")
msgs = self._drain()
assert len(msgs) == 1