ci: nicer output for test_onroad (#33961)

* viz

* viz

* fix

* show more

* fix

* failure

* cleanup
pull/33982/head
Maxime Desroches 6 months ago committed by GitHub
parent 3e88d680a5
commit 700a5651bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 69
      selfdrive/test/test_onroad.py

@ -11,6 +11,7 @@ import numpy as np
import zstandard as zstd import zstandard as zstd
from collections import Counter, defaultdict from collections import Counter, defaultdict
from pathlib import Path from pathlib import Path
from tabulate import tabulate
from cereal import car, log from cereal import car, log
import cereal.messaging as messaging import cereal.messaging as messaging
@ -241,10 +242,9 @@ class TestOnroad:
assert len(veryslow) < 5, f"Too many slow frame draw times: {veryslow}" assert len(veryslow) < 5, f"Too many slow frame draw times: {veryslow}"
def test_cpu_usage(self, subtests): def test_cpu_usage(self, subtests):
result = "\n" print("\n------------------------------------------------")
result += "------------------------------------------------\n" print("------------------ CPU Usage -------------------")
result += "------------------ CPU Usage -------------------\n" print("------------------------------------------------")
result += "------------------------------------------------\n"
plogs_by_proc = defaultdict(list) plogs_by_proc = defaultdict(list)
for pl in self.msgs['procLog']: for pl in self.msgs['procLog']:
@ -252,13 +252,14 @@ class TestOnroad:
if len(x.cmdline) > 0: if len(x.cmdline) > 0:
n = list(x.cmdline)[0] n = list(x.cmdline)[0]
plogs_by_proc[n].append(x) plogs_by_proc[n].append(x)
print(plogs_by_proc.keys())
cpu_ok = True cpu_ok = True
dt = (self.msgs['procLog'][-1].logMonoTime - self.msgs['procLog'][0].logMonoTime) / 1e9 dt = (self.msgs['procLog'][-1].logMonoTime - self.msgs['procLog'][0].logMonoTime) / 1e9
header = ['process', 'usage', 'expected', 'max allowed', 'test result']
rows = []
for proc_name, expected in PROCS.items(): for proc_name, expected in PROCS.items():
err = "" error = ""
usage = 0. usage = 0.
x = plogs_by_proc[proc_name] x = plogs_by_proc[proc_name]
if len(x) > 2: if len(x) > 2:
@ -267,15 +268,15 @@ class TestOnroad:
max_allowed = max(expected * 1.8, expected + 5.0) max_allowed = max(expected * 1.8, expected + 5.0)
if usage > max_allowed: if usage > max_allowed:
err = "USING MORE CPU THAN EXPECTED" error = "❌ USING MORE CPU THAN EXPECTED ❌"
cpu_ok = False
else: else:
err = "NO METRICS FOUND" error = "❌ NO METRICS FOUND ❌"
result += f"{proc_name.ljust(35)} {usage=:5.2f}% {expected=:5.2f}% {max_allowed=:5.2f}% {err}\n"
if len(err) > 0:
cpu_ok = False cpu_ok = False
result += "------------------------------------------------\n"
rows.append([proc_name, usage, expected, max_allowed, error or ""])
print(tabulate(rows, header, tablefmt="simple_grid", stralign="center", numalign="center", floatfmt=".2f"))
# Ensure there's no missing procs # Ensure there's no missing procs
all_procs = {p.name for p in self.msgs['managerState'][0].managerState.processes if p.shouldBeRunning} all_procs = {p.name for p in self.msgs['managerState'][0].managerState.processes if p.shouldBeRunning}
@ -287,11 +288,9 @@ class TestOnroad:
procs_tot = sum([(max(x) if isinstance(x, tuple) else x) for x in PROCS.values()]) procs_tot = sum([(max(x) if isinstance(x, tuple) else x) for x in PROCS.values()])
with subtests.test(name="total CPU"): with subtests.test(name="total CPU"):
assert procs_tot < MAX_TOTAL_CPU, "Total CPU budget exceeded" assert procs_tot < MAX_TOTAL_CPU, "Total CPU budget exceeded"
result += "------------------------------------------------\n" print("------------------------------------------------")
result += f"Total allocated CPU usage is {procs_tot}%, budget is {MAX_TOTAL_CPU}%, {MAX_TOTAL_CPU-procs_tot:.1f}% left\n" print(f"Total allocated CPU usage is {procs_tot}%, budget is {MAX_TOTAL_CPU}%, {MAX_TOTAL_CPU-procs_tot:.1f}% left")
result += "------------------------------------------------\n" print("------------------------------------------------")
print(result)
assert cpu_ok assert cpu_ok
@ -379,10 +378,12 @@ class TestOnroad:
def test_timings(self): def test_timings(self):
passed = True passed = True
result = "\n" print("\n------------------------------------------------")
result += "------------------------------------------------\n" print("----------------- Service Timings --------------")
result += "----------------- Service Timings --------------\n" print("------------------------------------------------")
result += "------------------------------------------------\n"
header = ['service', 'max', 'min', 'mean', 'expected mean', 'rsd', 'max allowed rsd', 'test result']
rows = []
for s, (maxmin, rsd) in TIMINGS.items(): for s, (maxmin, rsd) in TIMINGS.items():
offset = int(SERVICE_LIST[s].frequency * LOG_OFFSET) offset = int(SERVICE_LIST[s].frequency * LOG_OFFSET)
msgs = [m.logMonoTime for m in self.msgs[s][offset:]] msgs = [m.logMonoTime for m in self.msgs[s][offset:]]
@ -392,21 +393,17 @@ class TestOnroad:
ts = np.diff(msgs) / 1e9 ts = np.diff(msgs) / 1e9
dt = 1 / SERVICE_LIST[s].frequency dt = 1 / SERVICE_LIST[s].frequency
try: errors = []
np.testing.assert_allclose(np.mean(ts), dt, rtol=0.03, err_msg=f"{s} - failed mean timing check") if not np.allclose(np.mean(ts), dt, rtol=0.03, atol=0):
np.testing.assert_allclose([np.max(ts), np.min(ts)], dt, rtol=maxmin, err_msg=f"{s} - failed max/min timing check") errors.append("❌ FAILED MEAN TIMING CHECK ❌")
except Exception as e: if not np.allclose([np.max(ts), np.min(ts)], dt, rtol=maxmin, atol=0):
result += str(e) + "\n" errors.append("❌ FAILED MAX/MIN TIMING CHECK ❌")
passed = False if (np.std(ts)/dt) > rsd:
errors.append("❌ FAILED RSD TIMING CHECK ❌")
if np.std(ts) / dt > rsd: passed = not errors
result += f"{s} - failed RSD timing check\n" rows.append([s, *(np.array([np.max(ts), np.min(ts), np.mean(ts), dt])*1e3), np.std(ts)/dt, rsd, "\n".join(errors) or ""])
passed = False
print(tabulate(rows, header, tablefmt="simple_grid", stralign="center", numalign="center", floatfmt=".2f"))
result += f"{s.ljust(40)}: {np.array([np.mean(ts), np.max(ts), np.min(ts)])*1e3}\n"
result += f"{''.ljust(40)} {np.max(np.absolute([np.max(ts)/dt, np.min(ts)/dt]))} {np.std(ts)/dt}\n"
result += "="*67
print(result)
assert passed assert passed
@release_only @release_only

Loading…
Cancel
Save