mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 13:33:42 +08:00
106 lines
5.8 KiB
Python
106 lines
5.8 KiB
Python
"""Subset controller prefix only: no native-result/token/admission transfer."""
|
|
from dataclasses import replace
|
|
import pickle
|
|
from types import MappingProxyType
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
|
|
from openpilot.starpilot.flm.canonical_surface_adapter import GROUPS
|
|
from openpilot.starpilot.flm.controller_replay import _run
|
|
from openpilot.starpilot.flm.event_controller_replay import EventControllerReplay
|
|
from openpilot.starpilot.flm.event_objective import EffectObjective
|
|
from openpilot.starpilot.flm.tests.test_event_controller_prefix import fixture, observed
|
|
|
|
|
|
def full_and_subset(domain='torque', nonzero=True, epsilon=.01):
|
|
original = fixture(domain, nonzero=nonzero)
|
|
envelope = original.records[0].effect_trace.envelope.for_trial(GROUPS['ff.left'])
|
|
objective = EffectObjective('ff.left', envelope.trial_names, envelope.trial_anchor, envelope.context_key)
|
|
full = EventControllerReplay(original.engine, objective, envelope.replay_anchor(), activation_plan=original.activation_plan)
|
|
full.rebuild_causal_features(epsilon=epsilon)
|
|
small = envelope.for_trial(('ff_gain_left',))
|
|
selected = EffectObjective('ff.left', small.trial_names, small.trial_anchor, small.context_key)
|
|
subset = EventControllerReplay(original.engine, selected, small.replay_anchor(), activation_plan=original.activation_plan)
|
|
return full, subset
|
|
|
|
|
|
@pytest.mark.parametrize('domain', ('torque', 'starpilot', 'pid'))
|
|
@pytest.mark.parametrize('nonzero', (False, True))
|
|
@pytest.mark.parametrize('shadow,delta', ((False, .000000001), (True, .01), (True, -.01)))
|
|
def test_actual_full_to_subset_prefix_matches_independent_tail_state_logs_maps_and_native(domain, nonzero, shadow, delta):
|
|
full, subset = full_and_subset(domain, nonzero=nonzero)
|
|
source = full._EventControllerReplay__controller_prefix
|
|
assert source is not None and len(source[1]) == 30
|
|
independent = EventControllerReplay(subset.engine, subset.objective, subset.original_anchor, activation_plan=subset.activation_plan)
|
|
assert subset.reuse_subset_causal_features(full) is True
|
|
rebound = subset._EventControllerReplay__controller_prefix
|
|
assert rebound is not None and rebound[0] == subset._causal_input_key(.01)
|
|
assert rebound[0] != source[0] and rebound[1:] == source[1:]
|
|
assert all(type(part) is MappingProxyType and part is not old for part, old in zip(rebound[1:], source[1:], strict=True))
|
|
assert subset._EventControllerReplay__strict_rollouts is None
|
|
assert subset._EventControllerReplay__identification_token is not full._EventControllerReplay__identification_token
|
|
with pytest.raises(TypeError):
|
|
rebound[1][0] = 1.
|
|
coordinates = (subset.reference[0] + delta,)
|
|
expected, before, native_before = observed(independent, coordinates, shadow=shadow)
|
|
actual, after, native_after = observed(subset, coordinates, shadow=shadow)
|
|
assert pickle.dumps(actual, protocol=5) == pickle.dumps(expected, protocol=5)
|
|
assert len(before) == 60 and len(after) == 30 and after == before[30:]
|
|
assert native_after == native_before
|
|
|
|
|
|
@pytest.mark.parametrize('defect', ('missing', 'stale', 'mutable', 'bad_raw_type', 'bad_snapshot', 'nondefault_epsilon'))
|
|
def test_missing_stale_unknown_prefix_does_not_change_valid_fd_transfer(defect):
|
|
epsilon = .02 if defect == 'nondefault_epsilon' else .01
|
|
full, subset = full_and_subset(epsilon=epsilon)
|
|
source = full._EventControllerReplay__controller_prefix
|
|
if defect == 'missing':
|
|
full._EventControllerReplay__controller_prefix = None
|
|
elif defect == 'stale':
|
|
full._EventControllerReplay__controller_prefix = (b'not-current', *source[1:])
|
|
elif defect == 'mutable':
|
|
full._EventControllerReplay__controller_prefix = (source[0], dict(source[1]), *source[2:])
|
|
elif defect == 'bad_raw_type':
|
|
raw = dict(source[1])
|
|
raw[next(iter(raw))] = 0 # Must not alias raw Float64 output.
|
|
full._EventControllerReplay__controller_prefix = (source[0], MappingProxyType(raw), *source[2:])
|
|
elif defect == 'bad_snapshot':
|
|
snapshots = dict(source[3])
|
|
snapshots[next(iter(snapshots))] = object()
|
|
full._EventControllerReplay__controller_prefix = (*source[:3], MappingProxyType(snapshots))
|
|
assert subset.reuse_subset_causal_features(full, epsilon=epsilon) is True
|
|
assert subset._EventControllerReplay__controller_prefix is None
|
|
assert subset.projected and subset._EventControllerReplay__strict_rollouts is None
|
|
with mock.patch('openpilot.starpilot.flm.event_controller_replay._run', wraps=_run) as run:
|
|
subset._rollout((subset.reference[0] + .000000001,),
|
|
_identification_token=subset._EventControllerReplay__identification_token)
|
|
assert run.call_count == 60
|
|
|
|
|
|
@pytest.mark.parametrize('change', ('prior', 'foreign_engine', 'plan', 'late_fault', 'native'))
|
|
def test_existing_fd_guard_failure_never_transfers_controller_certificate(change):
|
|
full, subset = full_and_subset()
|
|
if change == 'prior':
|
|
subset.prior_full['ff_gain_right'] = .002
|
|
elif change == 'foreign_engine':
|
|
other, _ = full_and_subset()
|
|
subset.engine = other.engine
|
|
elif change == 'plan':
|
|
subset.activation_plan = replace(subset.activation_plan, physical_context='c' * 64)
|
|
elif change == 'late_fault':
|
|
full.records[-1] = replace(full.records[-1], healthy=False)
|
|
else:
|
|
stamp, event = next(iter(full.emissions.events.items()))
|
|
full.emissions.events[stamp] = replace(event, witness=event.witness._replace(final_raw=event.witness.final_raw + 1))
|
|
assert subset.reuse_subset_causal_features(full) is False
|
|
assert subset._EventControllerReplay__controller_prefix is None
|
|
assert subset._EventControllerReplay__strict_rollouts is None
|
|
|
|
|
|
def test_source_shadow_token_cannot_become_destination_permission():
|
|
full, subset = full_and_subset()
|
|
assert subset.reuse_subset_causal_features(full)
|
|
with pytest.raises(ValueError, match='identification scope'):
|
|
subset._rollout((.01,), _identification_token=full._EventControllerReplay__identification_token)
|