Files
StarPilot/openpilot/starpilot/ui/tests/test_startup.py
T
firestarsdog e982987197 Arabesque
2026-10-16 08:40:20 -04:00

103 lines
5.4 KiB
Python

"""The UI choice is final before Raylib creates a window."""
import unittest
from unittest.mock import patch
from openpilot.starpilot.ui import startup
from openpilot.starpilot.ui.presentation import Profile
class TestStartup(unittest.TestCase):
def test_both_profiles_select_custom_with_exact_assets(self):
for profile in (Profile.LARGE, Profile.COMPACT):
with self.subTest(profile=profile), patch.object(startup, "validate_fonts") as fonts, \
patch.object(startup, "validate_artwork") as artwork:
choice = startup.select_ui(profile, {"STARPILOT_UI_FONT_DIR": "/reviewed"})
self.assertTrue(choice.custom)
fonts.assert_called_once_with(profile, "/reviewed")
artwork.assert_called_once_with()
def test_bundled_fonts_select_custom_and_explicit_bad_bundle_fails(self):
for profile in (Profile.LARGE, Profile.COMPACT):
with self.subTest(profile=profile), patch.object(startup, "validate_artwork") as artwork:
choice = startup.select_ui(profile, {})
self.assertTrue(choice.custom)
artwork.assert_called_once_with()
with patch.object(startup, "validate_artwork") as artwork:
choice = startup.select_ui(profile, {"STARPILOT_UI_FONT_DIR": "/missing-fonts"})
self.assertFalse(choice.custom)
artwork.assert_not_called()
with patch.object(startup, "validate_fonts"), patch.object(startup, "validate_artwork", side_effect=ValueError("bad hash")):
self.assertIn("bad hash", startup.select_ui(profile, {"STARPILOT_UI_FONT_DIR": "/bad"}).reason)
def test_force_fails_and_upstream_override_skips_preflight(self):
with self.assertRaisesRegex(RuntimeError, "Forced StarPilot UI"):
startup.select_ui(Profile.LARGE, {"STARPILOT_UI_DEV": "1", "STARPILOT_UI_FONT_DIR": "/missing-fonts"})
with patch.object(startup, "validate_fonts") as fonts, patch.object(startup, "validate_artwork") as artwork:
choice = startup.select_ui(Profile.COMPACT, {"STARPILOT_UI": "upstream", "STARPILOT_UI_DEV": "1"})
self.assertFalse(choice.custom)
fonts.assert_not_called()
artwork.assert_not_called()
def test_main_selects_before_window(self):
from openpilot.selfdrive.ui import ui
events: list[str] = []
def selection(profile, environment):
events.append(f"select:{profile}")
return startup.UiSelection(False, "fixture")
def window(_):
events.append("window")
with patch.object(ui, "select_ui", side_effect=selection), patch.object(ui.gui_app, "init_window", side_effect=window), \
patch.object(ui.gui_app, "render", return_value=iter(())), patch.object(ui, "MainLayout") as layout, \
patch.object(ui, "MiciMainLayout", return_value=object()), patch.object(ui.messaging, "PubMaster"), \
patch.object(ui, "config_realtime_process"), patch.object(ui, "BIG_UI", True):
ui.main()
self.assertEqual(events, ["select:large", "window"])
layout.return_value.close.assert_called_once_with()
with patch.object(ui, "select_ui", side_effect=RuntimeError("bad reviewed font")), \
patch.object(ui.gui_app, "init_window") as initialize, patch.object(ui, "config_realtime_process"):
with self.assertRaisesRegex(RuntimeError, "bad reviewed font"):
ui.main()
initialize.assert_not_called()
def test_display_scheduling_preserves_camera_precedence_and_other_devices(self):
from openpilot.selfdrive.ui import ui
for device, hardware in (("mici", True), ("tici", True), ("tizi", True), ("pc", False)):
with self.subTest(device=device), \
patch.object(ui, "COMMA_HARDWARE", hardware), patch.object(ui.HARDWARE, "get_device_type", return_value=device), \
patch.object(ui, "select_ui", return_value=startup.UiSelection(False, "fixture")), \
patch.object(ui.gui_app, "init_window"), \
patch.object(ui.gui_app, "render", return_value=iter(((False, 0., 0.), (True, .01, .005), (True, .01, .005)))), \
patch.object(ui, "MainLayout"), patch.object(ui, "MiciMainLayout", return_value=object()), \
patch.object(ui.messaging, "PubMaster"), patch.object(ui, "config_realtime_process") as realtime, \
patch.object(ui, "drop_realtime") as normal, patch.object(ui.os, "setpriority") as nice, \
patch.object(ui.os, "sched_getscheduler", return_value=0, create=True), \
patch.object(ui.os, "SCHED_OTHER", 0, create=True), patch.object(ui.os, "getpriority", return_value=0), \
patch.object(ui.os, "sched_getaffinity", return_value={0}, create=True), \
patch.object(ui, "set_core_affinity") as affinity:
ui.main()
realtime.assert_called_once_with(0, ui.Priority.UI)
if hardware:
normal.assert_called_once_with()
nice.assert_called_once_with(ui.os.PRIO_PROCESS, 0, 0)
else:
normal.assert_not_called()
nice.assert_not_called()
self.assertEqual(affinity.call_count, 2 if hardware else 0)
if hardware:
self.assertTrue(all(call.args == ([6],) for call in affinity.call_args_list))
def test_slc_publisher_gate_is_independent_of_ui_selection(self):
self.assertTrue(startup.slc_action_transport_enabled({"STARPILOT_UI_DEV": "1"}))
self.assertTrue(startup.slc_action_transport_enabled({"SLC_REPLAY_RUNTIME": "1"}))
self.assertTrue(startup.slc_action_transport_enabled({"STARPILOT_UI": "upstream", "SLC_REPLAY_RUNTIME": "1"}))
if __name__ == "__main__":
unittest.main()