mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-30 18:44:13 +08:00
Align learner protocol and lifecycle fixtures
This commit is contained in:
@@ -72,6 +72,7 @@ def test_shadow_secants_are_scoped_and_final_rollout_has_no_sticky_mode():
|
||||
|
||||
def test_forged_identification_token_rejects_before_controller_execution():
|
||||
value = object.__new__(EventControllerReplay)
|
||||
value.engine = SimpleNamespace() # Explicit empty delegate; no native/controller admission.
|
||||
value._EventControllerReplay__identification_token = object()
|
||||
value.activation_plan = SimpleNamespace(identification_policy=NATIVE_SHADOW_IDENTIFICATION)
|
||||
with pytest.raises(ValueError, match='scope/policy'):
|
||||
|
||||
@@ -5,6 +5,8 @@ from opendbc.car.honda.values import CAR as HONDA
|
||||
from opendbc.car.hyundai.values import CAR as HKG
|
||||
from opendbc.car.toyota.values import CAR as TOYOTA
|
||||
from openpilot.starpilot.flm.learner_factory import from_evidence
|
||||
from openpilot.starpilot.flm.feedback_replay import PROTOCOL as FEEDBACK_PROTOCOL
|
||||
from openpilot.starpilot.flm.source_plant_fit import PROTOCOL as LEGACY_SOURCE_PROTOCOL
|
||||
from openpilot.starpilot.flm.clipping_quality import ZERO_REFERENCE_QUALITY, QUALIFIED_EVENT_CLIPPING_QUALITY
|
||||
from openpilot.starpilot.flm.runtime_adapter_registry import baseline_values
|
||||
from openpilot.starpilot.flm.steerlearnerd import production_adapter_for_evidence
|
||||
@@ -14,15 +16,17 @@ from openpilot.starpilot.flm.tests.test_registered_controls_global import contro
|
||||
|
||||
@pytest.mark.parametrize('platform,mode', ((TOYOTA.TOYOTA_RAV4_TSS2, 'standard'),
|
||||
(HKG.HYUNDAI_IONIQ_6, 'starpilot'), (HONDA.HONDA_CIVIC, None)))
|
||||
def test_actual_registered_producer_explicit_restore_version_and_legacy_default(platform, mode):
|
||||
def test_actual_registered_producer_explicit_restore_version_and_legacy_default(platform, mode, protocol=None, restore_version=8):
|
||||
cp = interfaces[platform].get_non_essential_params(platform)
|
||||
with controls_for(cp, mode, True) as controls:
|
||||
evidence, source, _ = capture(controls)
|
||||
before = controls.CP.as_builder().to_bytes(), baseline_values(controls.LaC)
|
||||
live = production_adapter_for_evidence(controls.CP, evidence, ('event', 'center'), source=source)
|
||||
live = production_adapter_for_evidence(controls.CP, evidence, ('event', 'center'), source=source,
|
||||
source_plant_protocol=protocol)
|
||||
old = from_evidence(controls.CP, evidence, ('event', 'center'), source=source)
|
||||
assert live is not None and live.replay_version == 3 and live.restore_version == 6
|
||||
assert live is not None and live.replay_version == 3 and live.restore_version == restore_version
|
||||
assert live.clipping_quality == ZERO_REFERENCE_QUALITY
|
||||
assert live.source_plant_protocol == (FEEDBACK_PROTOCOL if protocol is None else protocol)
|
||||
for version in (4, 5):
|
||||
legacy = from_evidence(controls.CP, evidence, ('event', 'center'), source=source,
|
||||
event_replay_version=3, event_clipping_quality=QUALIFIED_EVENT_CLIPPING_QUALITY, event_restore_version=version)
|
||||
@@ -30,5 +34,14 @@ def test_actual_registered_producer_explicit_restore_version_and_legacy_default(
|
||||
assert old is not None and old.replay_version == 2 and old.restore_version == 2
|
||||
assert from_evidence(controls.CP, evidence, ('event', 'center'), source=source, event_restore_version=4) is None
|
||||
live.select_objective(('event', 'deadband.high'))
|
||||
assert live.restore_version == 6
|
||||
assert live.restore_version == restore_version
|
||||
assert (controls.CP.as_builder().to_bytes(), baseline_values(controls.LaC)) == before
|
||||
|
||||
|
||||
@pytest.mark.parametrize('platform,mode', ((TOYOTA.TOYOTA_RAV4_TSS2, 'standard'),
|
||||
(HKG.HYUNDAI_IONIQ_6, 'starpilot'), (HONDA.HONDA_CIVIC, None)))
|
||||
def test_actual_registered_producer_explicit_legacy_source_restore6(platform, mode):
|
||||
# Exercise the same real application, refusal and unchanged-controller checks
|
||||
# for the independently selected legacy source protocol as for default8.
|
||||
test_actual_registered_producer_explicit_restore_version_and_legacy_default(
|
||||
platform, mode, protocol=LEGACY_SOURCE_PROTOCOL, restore_version=6)
|
||||
|
||||
@@ -25,15 +25,21 @@ def test_interrupted_neutral_timer_does_not_split_one_large_maneuver():
|
||||
|
||||
|
||||
def test_tracking_attempt_count_uses_same_contiguous_neutral_recovery():
|
||||
objective = SimpleNamespace(group='ff.left', names=('ff_gain_left',), anchor_digest='c' * 64, context_key='d' * 64)
|
||||
objective = SimpleNamespace(group='ff.left', names=('ff_gain_left',), anchor_digest='c' * 64, context_key='d' * 64,
|
||||
parameters=(SimpleNamespace(excitation_floor=.01),))
|
||||
model = SimpleNamespace(heldout_rmse=.001)
|
||||
for neutral, expected in ((11, 0), (51, 1)):
|
||||
engine = trajectory(neutral)
|
||||
samples = tuple({'control_ns': frame.control_ns,
|
||||
samples = tuple({'control_ns': frame.control_ns, 'apply_ns': frame.control_ns + 20_000_000,
|
||||
'control': {'stage_values': (('setpoint', frame.desired_physical_accel),)},
|
||||
'physical': {'lateral_accel': -.2}} for frame in engine.records[::5])
|
||||
# Declared unit basis only: each sampled endpoint has a visible derivative.
|
||||
# This shell does not claim native qualification or current authority.
|
||||
engine.projected = {row['apply_ns']: (0., (1.,)) for row in samples}
|
||||
blocks = ({'block_id': 'whole-physical-turn', 'samples': samples},)
|
||||
episodes = tracking_episodes(engine, blocks, model, objective)
|
||||
assert len(episodes) == expected
|
||||
if episodes:
|
||||
assert episodes[0]['block_ids'] == ('whole-physical-turn',)
|
||||
engine.projected.clear()
|
||||
assert tracking_episodes(engine, blocks, model, objective) == () # No encoded basis, no counted episode.
|
||||
|
||||
@@ -9,6 +9,7 @@ from openpilot.starpilot.flm.event_controller_replay import EventControllerRepla
|
||||
|
||||
def engine():
|
||||
value = object.__new__(EventControllerReplay)
|
||||
value.engine = SimpleNamespace() # Explicit empty delegate for this policy-only shell.
|
||||
value.restore_envelope = None
|
||||
value.objective = SimpleNamespace(parameters=(SimpleNamespace(low=0., high=.25),))
|
||||
value.reference = (0.,)
|
||||
|
||||
@@ -9,7 +9,7 @@ from typing import NoReturn, cast
|
||||
|
||||
import pytest
|
||||
|
||||
from openpilot.starpilot.flm import fit_worker
|
||||
from openpilot.starpilot.flm import fit_worker, native_primitives
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -18,8 +18,13 @@ def worker_io(monkeypatch):
|
||||
incoming, outgoing = io.BytesIO(b'{"test":true}'), io.BytesIO()
|
||||
monkeypatch.setattr(fit_worker, 'sys', SimpleNamespace(platform='darwin',
|
||||
stdin=SimpleNamespace(buffer=incoming), stdout=SimpleNamespace(buffer=outgoing)))
|
||||
# Both worker modules use the same explicitly simulated macOS context.
|
||||
# Linux native-worker resource guards remain real in their own tests.
|
||||
monkeypatch.setattr(native_primitives, 'sys', fit_worker.sys)
|
||||
monkeypatch.setattr(fit_worker.os, 'nice', lambda _: None)
|
||||
monkeypatch.setattr(fit_worker.os, 'sched_setscheduler', lambda *args: None, raising=False)
|
||||
monkeypatch.setattr(fit_worker.os, 'SCHED_OTHER', 0, raising=False)
|
||||
monkeypatch.setattr(fit_worker.os, 'sched_param', lambda priority: SimpleNamespace(sched_priority=priority), raising=False)
|
||||
limits = []
|
||||
monkeypatch.setattr(fit_worker.resource, 'getrlimit', lambda kind: (-1, -1))
|
||||
monkeypatch.setattr(fit_worker.resource, 'setrlimit', lambda *args: limits.append(args))
|
||||
|
||||
@@ -101,15 +101,20 @@ def test_parent_discards_unqualified_successful_child_report(monkeypatch):
|
||||
|
||||
|
||||
def test_daemon_explicitly_constructs_production_response_process():
|
||||
# Current live source tracking owns no numerical plant-bootstrap process.
|
||||
import openpilot.starpilot.flm.steerlearnerd as daemon
|
||||
tree = ast.parse(Path(daemon.__file__).read_text())
|
||||
calls = [node for node in ast.walk(tree) if isinstance(node, ast.Call) and
|
||||
isinstance(node.func, ast.Name) and node.func.id == 'LiveTrackingActor']
|
||||
assert len(calls) == 1
|
||||
keywords = {item.arg: item.value for item in calls[0].keywords}
|
||||
assert isinstance(keywords['bootstrap_process'], ast.Call)
|
||||
assert isinstance(keywords['bootstrap_process'].func, ast.Name)
|
||||
assert keywords['bootstrap_process'].func.id == 'ProductionBootstrapProcess'
|
||||
assert not calls[0].args
|
||||
assert set(keywords) == {'probe_process', 'source_tracking'}
|
||||
assert isinstance(keywords['source_tracking'], ast.Constant)
|
||||
assert keywords['source_tracking'].value is True
|
||||
from openpilot.starpilot.flm.live_tracking_actor import LiveTrackingActor
|
||||
with pytest.raises(ValueError, match='source tracking has no plant bootstrap process'):
|
||||
LiveTrackingActor(bootstrap_process=object(), source_tracking=True)
|
||||
assert isinstance(keywords['probe_process'], ast.Call)
|
||||
assert isinstance(keywords['probe_process'].func, ast.Name)
|
||||
assert keywords['probe_process'].func.id == 'ProbeProcess'
|
||||
@@ -131,10 +136,16 @@ def test_real_pending_child_survives_capture_rollover_but_not_changed_physical_b
|
||||
owner = RetainedResponseRequalifier(old, basis(old), new_drive(old))
|
||||
control, output, _pose = synthetic_pair(owner, 0)
|
||||
binding = owner._binding
|
||||
source = SimpleNamespace(cp_sha256=binding.cp_sha256, source_epoch=binding.source_epoch,
|
||||
reset=binding.reset_generation, calibration_generation=binding.calibration_generation,
|
||||
persistent_source_epoch=binding.persistent_source_epoch)
|
||||
collector = SimpleNamespace(ready=[(control, output)], original_source_capture=SimpleNamespace(epoch=0), live_tracking=None)
|
||||
from openpilot.starpilot.flm.runtime_adapter_registry import SourceState
|
||||
from openpilot.starpilot.flm.torque_emission_replay import EmissionHistory
|
||||
def source_at(now):
|
||||
return SourceState(True, False, binding.reset_generation, binding.source_epoch, now, now+500_000_000,
|
||||
binding.cp_sha256, (), binding.calibration_generation, binding.persistent_source_epoch)
|
||||
source = source_at(99_000_000_000)
|
||||
# Empty original inventory is truthful for this child-lifecycle-only fixture.
|
||||
replay = SimpleNamespace(raw_mode=False, emissions=EmissionHistory(None))
|
||||
collector = SimpleNamespace(ready=[(control, output)], adapter=SimpleNamespace(replay=replay),
|
||||
original_source_capture=SimpleNamespace(epoch=0), live_tracking=None)
|
||||
process = ProductionBootstrapProcess()
|
||||
actor = LiveTrackingActor(bootstrap_process=process)
|
||||
seed = actor.binding_for(collector, source)
|
||||
@@ -150,12 +161,12 @@ def test_real_pending_child_survives_capture_rollover_but_not_changed_physical_b
|
||||
assert actor.tick(collector, source, now_ns=99_000_000_000, current_native=True) is None
|
||||
assert process.child is child and child.poll() is None and not process.reaping
|
||||
collector.original_source_capture.epoch = 1
|
||||
assert actor.tick(collector, source, now_ns=101_000_000_000, current_native=True) is None
|
||||
assert actor.tick(collector, source_at(101_000_000_000), now_ns=101_000_000_000, current_native=True) is None
|
||||
assert actor.seed == seed and process.token == token
|
||||
assert process.child is child and child.poll() is None and not process.reaping
|
||||
assert actor.attempted_epoch == 0 # No duplicate child at capture rotation.
|
||||
collector.ready = [(replace(control, vehicle_model_anchor=(16., 100000., 110000.)), output)]
|
||||
assert actor.tick(collector, source, now_ns=102_000_000_000, current_native=True) is None
|
||||
assert actor.tick(collector, source_at(102_000_000_000), now_ns=102_000_000_000, current_native=True) is None
|
||||
assert process.reaping or process.child is None
|
||||
assert actor.reason == 'actual_response_source_unavailable'
|
||||
finally:
|
||||
|
||||
@@ -114,7 +114,7 @@ def test_physical_tracking_error_uses_force_goal_while_geometry_keeps_original_s
|
||||
rows.append(SimpleNamespace(control_ns=stamp,desired_kinematic_accel=goal,desired_physical_accel=force,
|
||||
inputs=(('vEgo',20.),),healthy=True))
|
||||
if index%5==0:
|
||||
points.append({'control_ns':stamp,'control':{'stage_values':(('setpoint',goal),)},
|
||||
points.append({'control_ns':stamp,'apply_ns':stamp+20_000_000,'control':{'stage_values':(('setpoint',goal),)},
|
||||
'physical':{'lateral_accel':force,'roll_rad':-.2}})
|
||||
engine=SimpleNamespace(records=rows,replay_windows=((first,rows[-1].control_ns),),
|
||||
_frame_context=lambda frame:True,identity='a'*64,baseline_revision='b'*64)
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "43b3191cf68f5e0cd10581d20c3ee38210c130f6e0b847453ed69477ed8edea0", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "cad571a1c0a2273b2af705736b5ed8e30def48befd996b0802ccffd13af667fa", "schema_version": 1}
|
||||
|
||||
Reference in New Issue
Block a user