Files
StarPilot/openpilot/starpilot/galaxy/tests/test_setting_descriptions.py
T

117 lines
6.7 KiB
Python

"""Purpose coverage for all source-expanded setting/action keys, without defaults."""
from dataclasses import replace
import json
from pathlib import Path
from openpilot.starpilot.galaxy.setting_descriptions import DESCRIPTIONS, INITIALIZATION, description, purpose
from openpilot.starpilot.ui.feature_settings_state import FeatureRow
from openpilot.starpilot.ui.long_profile_feature import CATEGORY_HELP, VALUE_HELP
from openpilot.starpilot.longitudinal.profile_preferences import SCALARS
from openpilot.starpilot.controllers.wheel_actions import KEYS as WHEEL_KEYS
from openpilot.starpilot.conditional_mode.actions import BOOLEAN_FIELDS, NUMBER_FIELDS
def inventory():
return set(json.loads((Path(__file__).parent / 'description-key-inventory.json').read_text()))
def test_all_expanded_description_keys_have_a_purpose_before_timing_or_warning():
keys = inventory()
assert set(DESCRIPTIONS) <= keys
for key in keys:
row = FeatureRow(key, 'Test action', 'On', reason='Saved for the next drive')
text = purpose(row)
assert text, key
first = description(row).split('.')[0].lower()
assert not first.startswith(('saved', 'warning', 'requires', 'applies')), key
assert not any(word in first for word in ('next drive', 'migration', 'does not', 'restart')), key
assert row.reason == 'Saved for the next drive' # Presentation does not mutate the canonical owner.
for key in INITIALIZATION:
assert INITIALIZATION[key] in description(FeatureRow(key, 'Setting', 'On'))
def test_generated_inventory_matches_actual_canonical_field_and_button_sources():
keys = inventory()
for scalars in SCALARS.values():
assert set(scalars) <= keys
assert {'long_repair:' + key for key in scalars} <= keys
assert {'wheel:' + key for key in WHEEL_KEYS} <= keys
for section in ('cem', 'ccm'):
assert {'conditional:' + section + ':' + field for field in
BOOLEAN_FIELDS[section] | NUMBER_FIELDS[section] | {'persist_manual'}} <= keys
for name in ('traffic', 'aggressive', 'standard', 'relaxed'):
for category in CATEGORY_HELP:
assert 'profile:' + name + ':' + category in keys
assert {'profile:' + name + ':' + category + ':' + str(index) for index in range(10)} <= keys
for suffix in VALUE_HELP:
assert all(name + suffix in keys for name in ('Aggressive', 'Standard', 'Relaxed'))
def test_real_warning_kept_after_purpose_and_false_blanket_next_drive_removed():
row = FeatureRow('LongPitch', 'Grade Compensation', 'Invalid', available=False,
reason='Invalid saved value; repair required')
assert description(row).startswith('Compensates acceleration and braking for road grade.')
assert description(row).endswith(row.reason)
assert 'next drive' not in description(replace(row, available=True, reason='Saved for the next drive'))
inactive = FeatureRow('TrafficFollow', 'Following', '1.2', reason='Saved values are inactive while Custom Driving Profiles is Off')
assert inactive.reason in description(inactive)
pending = FeatureRow('AlwaysOnLateral', 'Always On Lateral', 'On', reason='Applies after the next startup')
assert 'pending vehicle configuration' in description(pending)
assert 'pending vehicle configuration' not in description(replace(pending, reason='Keep steering assistance available'))
assert 'below' in purpose(FeatureRow('conditional:cem:speed_mps', 'Speed', '20'))
assert 'at or above' in purpose(FeatureRow('conditional:ccm:speed_mps', 'Speed', '20'))
camera = FeatureRow('SLCPriority1', 'Primary source', 'Vision',
reason='Camera signs are unavailable; choose a connected source')
assert description(camera).startswith(purpose(camera))
assert camera.reason in description(camera)
ownership = FeatureRow('ForceAutoTuneOff', 'Use StarPilot Auto Learn', 'On',
reason='Saved for this vehicle. StarPilot Controller uses its vehicle tune; automatic learning is currently unavailable.')
assert 'StarPilot Controller uses its vehicle tune' in description(ownership)
assert 'Saved for this vehicle' not in description(ownership)
maps = FeatureRow('SLCPriority2', 'Secondary source', 'Maps',
reason='Maps needs a verified provider and an installed offline map package')
assert maps.reason in description(maps)
def test_actual_owner_projections_have_no_uncovered_setting(tmp_path):
from opendbc.car.car_helpers import interfaces
from opendbc.car.gm.values import CAR as GM
from opendbc.car.hyundai.values import CAR as HYUNDAI
from opendbc.car.toyota.values import CAR as TOYOTA
from opendbc.car.ford.values import CAR as FORD
from openpilot.common.params import Params
from openpilot.starpilot.galaxy.settings import PAGES, _projection
from openpilot.starpilot.ui.feature_settings_owner import FeatureSettingsOwner
from openpilot.starpilot.ui.appearance_owner import AppearanceOwner
from openpilot.starpilot.ui.display_owner import DisplayOwner
from openpilot.starpilot.ui.sounds_owner import SoundsOwner
from openpilot.starpilot.ui.pip_owner import PiPOwner
from openpilot.starpilot.ui.vasm_owner import VASMOwner
from openpilot.starpilot.ui.sentry_owner import SentryOwner
from openpilot.starpilot.galaxy.developer_settings import DeveloperSettingsOwner
from openpilot.starpilot.ui.presentation import Profile
params = Params(str(tmp_path))
def check(rows, page):
for row in rows:
if row.key:
assert purpose(row), (page, row.key)
assert _projection(row)['reason'].startswith(purpose(row))
check(DeveloperSettingsOwner(params, lambda: True).snapshot().rows, 'developer')
for candidate in (GM.CHEVROLET_BOLT_EUV, GM.CHEVROLET_VOLT, HYUNDAI.HYUNDAI_IONIQ_6,
TOYOTA.TOYOTA_RAV4_TSS2_2023, FORD.FORD_ESCAPE_MK4):
cp = interfaces[candidate].get_non_essential_params(candidate)
owner = FeatureSettingsOwner(params, lambda group: True, vehicle_fingerprint=lambda cp=cp: cp.carFingerprint,
vehicle_params=lambda cp=cp: cp, show_cruise_intervals=True, galaxy=lambda: True)
for page in PAGES - {'appearance', 'display', 'sounds', 'pip', 'sentry', 'vasm'}:
state = owner.snapshot(page, parked=True, system_long=True, lateral_context=True, metric=False)
check(state.rows, page)
for profile in (Profile.COMPACT, Profile.LARGE):
check(AppearanceOwner(params, lambda: True).snapshot(profile).rows, 'appearance')
check(DisplayOwner(params, lambda: True).snapshot(profile).rows, 'display')
for page, owner in (('sounds', SoundsOwner(params, lambda: True)), ('pip', PiPOwner(params, lambda: True, lambda: False)),
('vasm', VASMOwner(params, lambda: True)), ('sentry', SentryOwner(params, lambda: True))):
check(owner.snapshot().rows, page)