Files
firestar5683 a44635ea6b mofongo
2026-08-01 18:32:41 -05:00

97 lines
3.6 KiB
Python

from openpilot.selfdrive.ui import stall_monitor
def test_stall_report_is_sent_to_bugsink(monkeypatch, tmp_path):
report = {}
def capture_message(message, **kwargs):
report["message"] = message
report.update(kwargs)
monkeypatch.setattr(stall_monitor, "_capture_message", capture_message)
monitor = stall_monitor.UIStallMonitor("raylib_ui")
monitor._dump_dir = tmp_path
dump = "full thread dump"
dump_path = monitor._write_dump(dump)
monitor._report_stall(dump, dump_path, "gui_app.present_end", 5.001, 4.999)
assert report["message"] == "raylib UI main loop stalled"
assert report["tags"] == {"ui_stall_name": "raylib_ui", "ui_stall_phase": "gui_app.present_end"}
assert report["extras"]["stalled_for_s"] == 5.001
assert report["extras"]["phase_for_s"] == 4.999
assert "test_stall_report_is_sent_to_bugsink" in report["extras"]["main_thread_stack"]
assert report["extras"]["thread_dump"] == dump
assert report["attachment_path"] == dump_path
def test_phase_hitches_are_aggregated(monkeypatch):
now = [100.0]
monkeypatch.setattr(stall_monitor.time, "monotonic", lambda: now[0])
monkeypatch.setattr(stall_monitor.cloudlog, "warning", lambda *_args, **_kwargs: None)
monitor = stall_monitor.UIStallMonitor("raylib_ui")
monitor._hitch_report_interval_s = 1.0
monitor._hitch_report_min_count = 2
monitor.set_context({"ui_mode": "small", "started": True})
monitor.progress("gui_app.before_widget_render")
now[0] += 0.4
monitor.progress("gui_app.after_widget_render")
now[0] += 0.3
monitor.progress("gui_app.before_end_drawing")
now[0] += 0.4
report = monitor._take_hitch_report(now[0])
assert report is not None
assert report["total_hitches"] == 2
assert report["phase_counts"] == {
"gui_app.before_widget_render": 1,
"gui_app.after_widget_render": 1,
}
assert report["phase_max_ms"]["gui_app.before_widget_render"] == 400.0
assert report["ui_context"] == {"ui_mode": "small", "started": True}
def test_hitch_report_is_rate_limited_and_sent_to_bugsink(monkeypatch):
reports = []
monkeypatch.setattr(stall_monitor, "_capture_message", lambda message, **kwargs: reports.append((message, kwargs)))
monitor = stall_monitor.UIStallMonitor("raylib_ui")
monitor._hitch_counts.update({"gui_app.before_end_drawing": 3})
monitor._hitch_max_s["gui_app.before_end_drawing"] = 0.75
monitor._hitch_report_interval_s = 10.0
monitor._hitch_report_min_count = 3
monitor._last_hitch_report = 5.0
monitor._hitch_window_started = 5.0
monitor.set_context({"ui_mode": "small", "started": False})
assert monitor._take_hitch_report(14.9) is None
report = monitor._take_hitch_report(15.0)
assert report is not None
monitor._report_hitches(report)
message, kwargs = reports[0]
assert message == "raylib UI frame hitches"
assert kwargs["level"] == "warning"
assert kwargs["tags"] == {
"ui_stall_name": "raylib_ui",
"ui_hitch_worst_phase": "gui_app.before_end_drawing",
"ui_mode": "small",
"ui_onroad": "false",
}
assert kwargs["extras"]["total_hitches"] == 3
assert monitor._take_hitch_report(30.0) is None
def test_stall_report_uses_captured_stack_preview(monkeypatch, tmp_path):
report = {}
monkeypatch.setattr(stall_monitor, "_capture_message", lambda _message, **kwargs: report.update(kwargs))
monitor = stall_monitor.UIStallMonitor("raylib_ui")
dump_path = monitor._write_dump("thread dump")
monitor._report_stall("thread dump", dump_path, "gui_app.before_end_drawing", 5.0, 5.0,
preview="main_thread_stack:\ncaptured before recovery")
assert report["extras"]["main_thread_stack"] == "main_thread_stack:\ncaptured before recovery"