On-device onroad CI test (#19792)
* start onroad test
* cpu usage test works
* nice print
* run in jenkins
* pretty reliable
* bump loggerd cpu usgae
Co-authored-by: Comma Device <device@comma.ai>
old-commit-hash: 5a9769020d
commatwo_master
parent
ebce6a6f56
commit
9e1f524965
4 changed files with 113 additions and 110 deletions
@ -1,108 +0,0 @@ |
||||
#!/usr/bin/env python3 |
||||
import os |
||||
import time |
||||
import sys |
||||
import subprocess |
||||
|
||||
import cereal.messaging as messaging |
||||
from common.basedir import BASEDIR |
||||
from selfdrive.test.helpers import set_params_enabled |
||||
|
||||
def cputime_total(ct): |
||||
return ct.cpuUser + ct.cpuSystem + ct.cpuChildrenUser + ct.cpuChildrenSystem |
||||
|
||||
|
||||
def print_cpu_usage(first_proc, last_proc): |
||||
procs = [ |
||||
("selfdrive.controls.controlsd", 47.0), |
||||
("./loggerd", 42.0), |
||||
("selfdrive.locationd.locationd", 35.0), |
||||
("selfdrive.locationd.paramsd", 12.0), |
||||
("selfdrive.controls.plannerd", 20.0), |
||||
("./_modeld", 7.12), |
||||
("./camerad", 7.07), |
||||
("./_sensord", 6.17), |
||||
("./_ui", 5.82), |
||||
("selfdrive.controls.radard", 5.67), |
||||
("./boardd", 3.63), |
||||
("./_dmonitoringmodeld", 2.67), |
||||
("selfdrive.logmessaged", 1.7), |
||||
("selfdrive.thermald.thermald", 2.41), |
||||
("selfdrive.locationd.calibrationd", 2.0), |
||||
("selfdrive.monitoring.dmonitoringd", 1.90), |
||||
("./proclogd", 1.54), |
||||
("./_gpsd", 0.09), |
||||
("./clocksd", 0.02), |
||||
("./ubloxd", 0.02), |
||||
("selfdrive.tombstoned", 0), |
||||
("./logcatd", 0), |
||||
] |
||||
|
||||
r = True |
||||
dt = (last_proc.logMonoTime - first_proc.logMonoTime) / 1e9 |
||||
result = "------------------------------------------------\n" |
||||
for proc_name, normal_cpu_usage in procs: |
||||
try: |
||||
first = [p for p in first_proc.procLog.procs if proc_name in p.cmdline][0] |
||||
last = [p for p in last_proc.procLog.procs if proc_name in p.cmdline][0] |
||||
cpu_time = cputime_total(last) - cputime_total(first) |
||||
cpu_usage = cpu_time / dt * 100. |
||||
if cpu_usage > max(normal_cpu_usage * 1.1, normal_cpu_usage + 5.0): |
||||
result += f"Warning {proc_name} using more CPU than normal\n" |
||||
r = False |
||||
elif cpu_usage < min(normal_cpu_usage * 0.65, max(normal_cpu_usage - 1.0, 0.0)): |
||||
result += f"Warning {proc_name} using less CPU than normal\n" |
||||
r = False |
||||
result += f"{proc_name.ljust(35)} {cpu_usage:.2f}%\n" |
||||
except IndexError: |
||||
result += f"{proc_name.ljust(35)} NO METRICS FOUND\n" |
||||
r = False |
||||
result += "------------------------------------------------\n" |
||||
print(result) |
||||
return r |
||||
|
||||
def test_cpu_usage(): |
||||
cpu_ok = False |
||||
|
||||
# start manager |
||||
os.environ['SKIP_FW_QUERY'] = "1" |
||||
os.environ['FINGERPRINT'] = "TOYOTA COROLLA TSS2 2019" |
||||
manager_path = os.path.join(BASEDIR, "selfdrive/manager.py") |
||||
manager_proc = subprocess.Popen(["python", manager_path]) |
||||
try: |
||||
proc_sock = messaging.sub_sock('procLog', conflate=True, timeout=2000) |
||||
cs_sock = messaging.sub_sock('controlsState') |
||||
|
||||
# wait until everything's started |
||||
msg = None |
||||
start_time = time.monotonic() |
||||
while msg is None and time.monotonic() - start_time < 240: |
||||
msg = messaging.recv_sock(cs_sock) |
||||
|
||||
# take first sample |
||||
time.sleep(15) |
||||
first_proc = messaging.recv_sock(proc_sock, wait=True) |
||||
if first_proc is None: |
||||
raise Exception("\n\nTEST FAILED: progLog recv timed out\n\n") |
||||
|
||||
# run for a minute and get last sample |
||||
time.sleep(60) |
||||
last_proc = messaging.recv_sock(proc_sock, wait=True) |
||||
cpu_ok = print_cpu_usage(first_proc, last_proc) |
||||
finally: |
||||
manager_proc.terminate() |
||||
ret = manager_proc.wait(20) |
||||
if ret is None: |
||||
manager_proc.kill() |
||||
return cpu_ok |
||||
|
||||
if __name__ == "__main__": |
||||
set_params_enabled() |
||||
|
||||
passed = False |
||||
try: |
||||
passed = test_cpu_usage() |
||||
except Exception as e: |
||||
print("\n\n\n", "TEST FAILED:", str(e), "\n\n\n") |
||||
finally: |
||||
sys.exit(int(not passed)) |
@ -0,0 +1,112 @@ |
||||
#!/usr/bin/env python3 |
||||
import os |
||||
import time |
||||
import subprocess |
||||
import unittest |
||||
from pathlib import Path |
||||
|
||||
import cereal.messaging as messaging |
||||
from common.basedir import BASEDIR |
||||
from common.timeout import Timeout |
||||
from selfdrive.loggerd.config import ROOT |
||||
from selfdrive.test.helpers import set_params_enabled |
||||
from tools.lib.logreader import LogReader |
||||
|
||||
PROCS = [ |
||||
("selfdrive.controls.controlsd", 47.0), |
||||
("./loggerd", 45.0), |
||||
("selfdrive.locationd.locationd", 35.0), |
||||
("selfdrive.controls.plannerd", 20.0), |
||||
("selfdrive.locationd.paramsd", 12.0), |
||||
("./_modeld", 7.12), |
||||
("./camerad", 7.07), |
||||
("./_sensord", 6.17), |
||||
("./_ui", 5.82), |
||||
("selfdrive.controls.radard", 5.67), |
||||
("./boardd", 3.63), |
||||
("./_dmonitoringmodeld", 2.67), |
||||
("selfdrive.logmessaged", 1.7), |
||||
("selfdrive.thermald.thermald", 2.41), |
||||
("selfdrive.locationd.calibrationd", 2.0), |
||||
("selfdrive.monitoring.dmonitoringd", 1.90), |
||||
("./proclogd", 1.54), |
||||
("./_gpsd", 0.09), |
||||
("./clocksd", 0.02), |
||||
("./ubloxd", 0.02), |
||||
("selfdrive.tombstoned", 0), |
||||
("./logcatd", 0), |
||||
] |
||||
|
||||
# ***** test helpers ***** |
||||
|
||||
def cputime_total(ct): |
||||
return ct.cpuUser + ct.cpuSystem + ct.cpuChildrenUser + ct.cpuChildrenSystem |
||||
|
||||
def check_cpu_usage(first_proc, last_proc): |
||||
result = "------------------------------------------------\n" |
||||
result += "------------------ CPU Usage -------------------\n" |
||||
result += "------------------------------------------------\n" |
||||
|
||||
r = True |
||||
dt = (last_proc.logMonoTime - first_proc.logMonoTime) / 1e9 |
||||
for proc_name, normal_cpu_usage in PROCS: |
||||
first, last = None, None |
||||
try: |
||||
first = [p for p in first_proc.procLog.procs if proc_name in p.cmdline][0] |
||||
last = [p for p in last_proc.procLog.procs if proc_name in p.cmdline][0] |
||||
cpu_time = cputime_total(last) - cputime_total(first) |
||||
cpu_usage = cpu_time / dt * 100. |
||||
if cpu_usage > max(normal_cpu_usage * 1.1, normal_cpu_usage + 5.0): |
||||
result += f"Warning {proc_name} using more CPU than normal\n" |
||||
r = False |
||||
elif cpu_usage < min(normal_cpu_usage * 0.65, max(normal_cpu_usage - 1.0, 0.0)): |
||||
result += f"Warning {proc_name} using less CPU than normal\n" |
||||
r = False |
||||
result += f"{proc_name.ljust(35)} {cpu_usage:.2f}%\n" |
||||
except IndexError: |
||||
result += f"{proc_name.ljust(35)} NO METRICS FOUND {first=} {last=}\n" |
||||
r = False |
||||
result += "------------------------------------------------\n" |
||||
print(result) |
||||
return r |
||||
|
||||
|
||||
class TestOnroad(unittest.TestCase): |
||||
|
||||
@classmethod |
||||
def setUpClass(cls): |
||||
os.environ['SKIP_FW_QUERY'] = "1" |
||||
os.environ['FINGERPRINT'] = "TOYOTA COROLLA TSS2 2019" |
||||
set_params_enabled() |
||||
|
||||
initial_segments = set(Path(ROOT).iterdir()) |
||||
|
||||
# start manager and run openpilot for a minute |
||||
try: |
||||
manager_path = os.path.join(BASEDIR, "selfdrive/manager.py") |
||||
proc = subprocess.Popen(["python", manager_path]) |
||||
|
||||
sm = messaging.SubMaster(['carState']) |
||||
with Timeout(60, "controls didn't start"): |
||||
while not sm.updated['carState']: |
||||
sm.update(1000) |
||||
|
||||
time.sleep(60) |
||||
finally: |
||||
proc.terminate() |
||||
if proc.wait(20) is None: |
||||
proc.kill() |
||||
|
||||
new_segments = set(Path(ROOT).iterdir()) - initial_segments |
||||
|
||||
segments = [p for p in new_segments if len(list(p.iterdir())) > 1] |
||||
cls.segment = [s for s in segments if str(s).endswith("--0")][0] |
||||
cls.lr = list(LogReader(os.path.join(str(cls.segment), "rlog.bz2"))) |
||||
|
||||
def test_cpu_usage(self): |
||||
proclogs = [m for m in self.lr if m.which() == 'procLog'] |
||||
cpu_ok = check_cpu_usage(proclogs[5], proclogs[-3]) |
||||
self.assertTrue(cpu_ok) |
||||
|
||||
if __name__ == "__main__": |
||||
unittest.main() |
Loading…
Reference in new issue