mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 05:23:41 +08:00
80fbb4f6db
Register vehicle controls, planner modes, UI actions and Galaxy services after their providers exist. Wire the shared runtime entrypoints and cover their combined behavior. Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> Co-authored-by: Daniel Koepping <elkoled@gmail.com> Co-authored-by: Danny <dannyirwin31@yahoo.com> Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com> Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com> Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com> Co-authored-by: Kacper Rączy <gfw.kra@gmail.com> Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu> Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com> Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Co-authored-by: stef <19478336+stefpi@users.noreply.github.com> Co-authored-by: whoisdomi <dcantu83@gmail.com> Co-authored-by: Intelli <contact@intelli.software> Co-authored-by: haraschax <6804392+haraschax@users.noreply.github.com> Co-authored-by: prabhaavp <prabhaav@msu.edu>
172 lines
9.2 KiB
Python
172 lines
9.2 KiB
Python
import unittest
|
|
import tempfile
|
|
import json
|
|
from pathlib import Path
|
|
from openpilot.starpilot.lateral.tests.test_inferred_torque_overrides import SavedParams
|
|
from openpilot.starpilot.settings_retirement import retire_settings, PROFILE_FLAGS
|
|
from openpilot.starpilot.longitudinal.profile_document import default_personality_profiles, profile_document, migrate_profile_document
|
|
from openpilot.starpilot.ui.appearance_preferences import RETIRED_DISPLAY_KEYS
|
|
from openpilot.starpilot.ui.onroad_customization import PARAM_KEY as LAYOUT_KEY, default_document, read_customization
|
|
|
|
|
|
class TestSettingsRetirement(unittest.TestCase):
|
|
def setUp(self):
|
|
self.directory = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.directory.cleanup)
|
|
self.params = SavedParams(self.directory.name)
|
|
def test_inactive_cruise_features_do_not_become_enabled(self):
|
|
self.params.put_bool('QOLLongitudinal', False)
|
|
self.params.put_bool('ForceStops', True)
|
|
self.params.put_bool('ReverseCruise', True)
|
|
self.params.put('CustomCruise', 7.0)
|
|
retire_settings(self.params)
|
|
self.assertEqual(self.params.get('ForceStops'), b'0')
|
|
self.assertEqual(self.params.get('ReverseCruise'), b'0')
|
|
self.assertEqual(self.params.get('CustomCruise'), b'1.0')
|
|
self.assertIsNone(self.params.get('QOLLongitudinal'))
|
|
self.params.put_bool('ForceStops', True)
|
|
retire_settings(self.params)
|
|
self.assertEqual(self.params.get('ForceStops'), b'1')
|
|
def test_active_cruise_values_and_steering_values_survive(self):
|
|
self.params.put_bool('QOLLongitudinal', True)
|
|
self.params.put_bool('ForceStops', True)
|
|
self.params.put('CustomCruise', 7.0)
|
|
self.params.put('SteerLatAccel', 3.2)
|
|
self.params.put_bool('AdvancedLateralTune', False)
|
|
retire_settings(self.params)
|
|
self.assertEqual(self.params.get('ForceStops'), b'1')
|
|
self.assertEqual(self.params.get('CustomCruise'), b'7.0')
|
|
self.assertEqual(self.params.get('SteerLatAccel'), b'3.2')
|
|
self.assertIsNone(self.params.get('AdvancedLateralTune'))
|
|
def test_inactive_legacy_curve_does_not_activate(self):
|
|
profiles = default_personality_profiles(False)
|
|
profiles['standard']['following'] = {'preset': 'custom', 'curve': [2.0]*10}
|
|
profiles['standard']['acceleration'] = {'preset': 'sport', 'curve': [], 'legacyActivation': True}
|
|
profiles['relaxed']['following'] = {'preset': 'custom', 'curve': [2.5]*10}
|
|
document = profile_document(profiles, enabled=True)
|
|
self.params.put('LongitudinalPersonalityProfiles', document)
|
|
self.params.put_bool('StandardPersonalityProfile', False)
|
|
self.params.put_bool('RelaxedPersonalityProfile', True)
|
|
retire_settings(self.params)
|
|
result = migrate_profile_document(self.params.get('LongitudinalPersonalityProfiles'))
|
|
assert result is not None
|
|
assert result is not None
|
|
self.assertEqual(result['profiles']['standard']['following']['preset'], 'dom_default')
|
|
self.assertEqual(result['profiles']['standard']['acceleration']['preset'], 'selected_profile')
|
|
self.assertEqual(result['profiles']['relaxed']['following']['curve'], [2.5]*10)
|
|
self.assertTrue(all(self.params.get(key) is None for key in PROFILE_FLAGS))
|
|
before = self.params.get('LongitudinalPersonalityProfiles')
|
|
retire_settings(self.params)
|
|
self.assertEqual(self.params.get('LongitudinalPersonalityProfiles'), before)
|
|
def test_invalid_documents_retained_and_unconfigured_allowed(self):
|
|
self.params.put_bool('StandardPersonalityProfile', False)
|
|
self.params.put('LongitudinalPersonalityProfiles', 'bad')
|
|
self.assertTrue(retire_settings(self.params))
|
|
self.assertEqual(self.params.get('LongitudinalPersonalityProfiles'), b'bad')
|
|
self.assertIsNone(self.params.get('StandardPersonalityProfile'))
|
|
self.params.put('LongitudinalPersonalityProfiles', {})
|
|
retire_settings(self.params)
|
|
self.assertIsNone(self.params.get('StandardPersonalityProfile'))
|
|
def test_unsafe_switch_and_invalid_evidence_are_bounded_and_preserved(self):
|
|
self.params.put('RetiredSettingsEvidence', 'not-json')
|
|
self.params.put('QOLLongitudinal', 'x' * 100000)
|
|
self.params.put_bool('ForceStops', True)
|
|
issues = retire_settings(self.params)
|
|
self.assertTrue(any('existing evidence retained' in issue for issue in issues))
|
|
self.assertEqual(self.params.get('RetiredSettingsEvidence'), b'not-json')
|
|
self.assertEqual(self.params.get('ForceStops'), b'0')
|
|
self.assertIsNone(self.params.get('QOLLongitudinal'))
|
|
|
|
def test_absent_parent_is_off_only_on_first_reconciliation(self):
|
|
self.params.put_bool('ForceStops', True)
|
|
self.params.put_bool('ReverseCruise', True)
|
|
profiles = default_personality_profiles(False)
|
|
profiles['standard']['following'] = {'preset': 'custom', 'curve': [2.0]*10}
|
|
self.params.put('LongitudinalPersonalityProfiles', profile_document(profiles, enabled=True))
|
|
retire_settings(self.params)
|
|
self.assertEqual(self.params.get('ForceStops'), b'0')
|
|
self.assertEqual(self.params.get('ReverseCruise'), b'0')
|
|
result = migrate_profile_document(self.params.get('LongitudinalPersonalityProfiles'))
|
|
assert result is not None
|
|
self.assertEqual(result['profiles']['standard']['following']['preset'], 'dom_default')
|
|
self.params.put_bool('ForceStops', True)
|
|
self.params.put_bool('ReverseCruise', True)
|
|
self.params.put('LongitudinalPersonalityProfiles', profile_document(profiles, enabled=True))
|
|
retire_settings(self.params)
|
|
self.assertEqual(self.params.get('ForceStops'), b'1')
|
|
self.assertEqual(self.params.get('ReverseCruise'), b'1')
|
|
result = migrate_profile_document(self.params.get('LongitudinalPersonalityProfiles'))
|
|
assert result is not None
|
|
self.assertEqual(result['profiles']['standard']['following']['curve'], [2.0]*10)
|
|
|
|
def test_fresh_namespace_completes_and_preserves_later_choice(self):
|
|
retire_settings(self.params)
|
|
state = json.loads(self.params.get('SettingsRetirementState'))
|
|
self.assertEqual(set(state['completed']), {'cruise', 'profiles', 'display'})
|
|
self.params.put_bool('ForceStops', True)
|
|
retire_settings(self.params)
|
|
self.assertEqual(self.params.get('ForceStops'), b'1')
|
|
|
|
|
|
def write(self, key, raw):
|
|
Path(self.params.get_param_path(key)).write_bytes(raw)
|
|
|
|
def test_display_switches_fold_into_layout_once(self):
|
|
for key, raw in (("HideSpeed", b"1"), ("HideMaxSpeed", b"1"), ("HideSteeringWheel", b"1"), ("HideDMIcon", b"1"),
|
|
("EnableTorqueBarWidget", b"0"), ("StoppedTimer", b"1"), ("RainbowPath", b"1")):
|
|
self.write(key, raw)
|
|
custom = default_document()
|
|
custom["roadColors"]["compact"]["pathMode"] = "color"
|
|
self.params.put(LAYOUT_KEY, custom)
|
|
retire_settings(self.params)
|
|
document = read_customization(self.params)
|
|
large, compact = document["layouts"]["large"], document["layouts"]["compact"]
|
|
self.assertEqual([large[key]["enabled"] for key in ("current_speed", "steering_wheel", "driver_monitor", "torque_bar")],
|
|
[False, False, False, False])
|
|
# The small UI never honored the speed and wheel switches.
|
|
self.assertEqual([compact[key]["enabled"] for key in ("steering_wheel", "driver_monitor", "torque_bar", "stopped_timer")],
|
|
[True, False, False, True])
|
|
self.assertIs(document["showMaxSpeed"], False)
|
|
self.assertEqual((document["roadColors"]["large"]["pathMode"], document["roadColors"]["compact"]["pathMode"]), ("rainbow", "color"))
|
|
for key in RETIRED_DISPLAY_KEYS:
|
|
self.assertIsNone(self.params.get(key))
|
|
# Completed: a later layout edit survives even if a default switch file reappears.
|
|
document["layouts"]["large"]["current_speed"]["enabled"] = True
|
|
self.params.put(LAYOUT_KEY, document)
|
|
self.write("HideSpeed", b"1")
|
|
retire_settings(self.params)
|
|
self.assertTrue(read_customization(self.params)["layouts"]["large"]["current_speed"]["enabled"])
|
|
|
|
def test_default_and_corrupt_switches_leave_layout_bytes_alone(self):
|
|
self.write("HideSpeed", b"0")
|
|
self.write("EnableTorqueBarWidget", b"bad")
|
|
retire_settings(self.params)
|
|
self.assertIsNone(self.params.get(LAYOUT_KEY))
|
|
self.assertIsNone(self.params.get("EnableTorqueBarWidget"))
|
|
|
|
def test_invalid_layout_is_kept_and_unreadable_layout_retries(self):
|
|
self.write(LAYOUT_KEY, b'{"version": 99}')
|
|
self.write("HideSpeed", b"1")
|
|
issues = retire_settings(self.params)
|
|
self.assertEqual(self.params.get(LAYOUT_KEY), b'{"version": 99}')
|
|
self.assertEqual(self.params.get("HideSpeed"), b"1")
|
|
self.assertNotIn("display", json.loads(self.params.get("SettingsRetirementState"))["completed"])
|
|
self.assertIn("Invalid onroad layout kept; display switches were not carried over", issues)
|
|
self.params.put(LAYOUT_KEY, default_document())
|
|
retire_settings(self.params)
|
|
self.assertFalse(read_customization(self.params)["layouts"]["large"]["current_speed"]["enabled"])
|
|
self.assertIsNone(self.params.get("HideSpeed"))
|
|
|
|
other = tempfile.TemporaryDirectory()
|
|
self.addCleanup(other.cleanup)
|
|
self.params = SavedParams(other.name)
|
|
Path(self.params.get_param_path(LAYOUT_KEY)).mkdir()
|
|
self.write("HideSpeed", b"1")
|
|
retire_settings(self.params)
|
|
self.assertNotIn("display", json.loads(self.params.get("SettingsRetirementState"))["completed"])
|
|
self.assertEqual(self.params.get("HideSpeed"), b"1")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|