mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-12 07:23:45 +08:00
Preserve guard interfaces and make runtime types explicit
This commit is contained in:
@@ -374,6 +374,7 @@ class ForceStopTests(unittest.TestCase):
|
||||
|
||||
def test_sign_behind_stopped_lead_stops_at_line_after_lead_leaves(self):
|
||||
self.queue_behind_lead()
|
||||
assert self.owner.queue_line is not None
|
||||
self.assertAlmostEqual(self.owner.queue_line, 9.5)
|
||||
for tick in range(30, 35):
|
||||
plan = self.owner.step(frame(tick, speed_mps=0., horizon_m=12., light=False, standstill=True, lead_present=True,
|
||||
@@ -408,6 +409,7 @@ class ForceStopTests(unittest.TestCase):
|
||||
plan = self.owner.step(frame(60, speed_mps=0., horizon_m=5., light=False, standstill=True, lead_present=True,
|
||||
lead_distance_m=4., lead_speed_mps=0.), self.tune)
|
||||
self.assertFalse(plan.forcing)
|
||||
assert self.owner.queue_line is not None
|
||||
self.assertAlmostEqual(self.owner.queue_line, 8.5)
|
||||
|
||||
def test_driver_gas_while_queued_forgets_the_sign(self):
|
||||
|
||||
@@ -7,7 +7,7 @@ from openpilot.starpilot.models.runtime_bridge.usb import USBProtection
|
||||
|
||||
|
||||
class DomUSBProtection(USBProtection):
|
||||
def protect_call(self, call):
|
||||
def protect_call(self, call, *, fresh_source=False):
|
||||
if isinstance(call.arg.aux, HCQInfo) and call.arg.aux.device == ('QCOM',) and call.body.op is Ops.SINK:
|
||||
return Protection.protect_call(self, call, fresh_source=True)
|
||||
return super().protect_call(call)
|
||||
return super().protect_call(call, fresh_source=fresh_source)
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
"bootstrap.py": "2efd3aaffb98d30e316fb950dac77b16f0866dfeed1c9767b97dad915e4d0c63",
|
||||
"bounded_wait.c": "a9e1a82e50ebefd983b3dbc6f784adc465cbd06848debed11dfff80cc8a832fe",
|
||||
"capture.py": "834cf5d83725729f30aec68a7ba5ca4897701dd4aa34147f0b49d8b0a9b9e81a",
|
||||
"dom_admission.py": "45ca0ad26271b6606af258af040ded846b19b74f693f837dd802fa71b9e9a284",
|
||||
"dom_admission.py": "f02dd5d30a2a38bd9ca03481c2d4fb42982453da052d3551bdd6f05a5ada1a92",
|
||||
"dom_loader.py": "6a51233e641a42a093d8c9412f4bba809133d7e9b9aeb212dcdeeb102c12a49b",
|
||||
"dom_usb.py": "f57983bac65f61873d67fa644e9eedde6eecec9d026130c31d8e55efe2185c0d",
|
||||
"dom_usb.py": "b329c614eeef71698e8acee8acafa727cc7e2635f9a595bfac1b50e668747aaf",
|
||||
"libbounded_wait.so": "24ed559861c8636c1026cad9a244854bb2236b5ee8b91bf21c5efbf688fa4a69",
|
||||
"libusb_guards.so": "66a3dfe48ac17899862ab80160cf6dac2c9b9707234527ba0d808f3b68404114",
|
||||
"ops-mapping.json": "8acf8d759ffd597684fce9e0879b488cf2b32c3f05a5ca355a77ba0026c6bb95",
|
||||
"qcom.py": "da93aa4b1929fbb881056669a78e765d113a2ace2d766e1cf7cce40ddba8ab95",
|
||||
"usb.py": "a2e84aa6d6be4cd7b8db7bf9dae85f67a6008de5c6e93ecb288fefede2b46e23",
|
||||
"usb.py": "3de547d0b92b75333593fca8f985406894e3be2c4e02b34a5fd52205ddecd890",
|
||||
"usb_guards.c": "8b3c207de74f92b74980da35428cff6f4a198ce97f9f8b6e64aded74e0110316"
|
||||
},
|
||||
"native_abi": "linux-aarch64-64bit",
|
||||
|
||||
@@ -17,7 +17,7 @@ _GUARD_HASHES = {
|
||||
'libbounded_wait.so': '24ed559861c8636c1026cad9a244854bb2236b5ee8b91bf21c5efbf688fa4a69',
|
||||
'libusb_guards.so': '66a3dfe48ac17899862ab80160cf6dac2c9b9707234527ba0d808f3b68404114',
|
||||
}
|
||||
_POLICY_SHA256 = '2eec2cf23b56e46e25adea32dd500cd37da53905ad9391dc6b020cb905b65f42'
|
||||
_POLICY_SHA256 = '06b6304d889166a448c4e48bb737933cbdeeedfe49a4c629af11ba06bd30e46b'
|
||||
_selection = None
|
||||
_protection = None
|
||||
_laboratory_request_json = None
|
||||
|
||||
@@ -14,3 +14,65 @@ def test_usb_guard_rejects_explicit_fresh_qcom_source_before_access():
|
||||
exec(compile(ast.Module(body=[method], type_ignores=[]), str(source), 'exec'), namespace)
|
||||
with pytest.raises(ValueError, match='not qualified'):
|
||||
namespace['protect_call'](object(), object(), fresh_source=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('fresh_source', 'qualified'), [(False, True), (True, True), (True, False)])
|
||||
def test_dom_guard_preserves_qualified_qcom_dispatch(fresh_source, qualified):
|
||||
from types import SimpleNamespace
|
||||
|
||||
calls = []
|
||||
class Protection:
|
||||
def protect_call(self, call, *, fresh_source=False):
|
||||
calls.append((call, fresh_source))
|
||||
return call
|
||||
|
||||
class HCQInfo:
|
||||
device = ('QCOM',)
|
||||
|
||||
sink = object()
|
||||
namespace = {}
|
||||
namespace.update(Protection=Protection, HCQInfo=HCQInfo, Ops=SimpleNamespace(SINK=sink))
|
||||
root = Path(__file__).resolve().parents[1] / 'runtime_bridge'
|
||||
for filename, classname in [('usb.py', 'USBProtection'), ('dom_usb.py', 'DomUSBProtection')]:
|
||||
source = root / filename
|
||||
tree = ast.parse(source.read_text())
|
||||
owner = next(node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == classname)
|
||||
exec(compile(ast.Module(body=[owner], type_ignores=[]), str(source), 'exec'), namespace)
|
||||
|
||||
guard_type = namespace['DomUSBProtection']
|
||||
assert isinstance(guard_type, type)
|
||||
guard = guard_type.__new__(guard_type)
|
||||
call = SimpleNamespace(arg=SimpleNamespace(aux=HCQInfo() if qualified else object()), body=SimpleNamespace(op=sink))
|
||||
if qualified:
|
||||
assert guard.protect_call(call, fresh_source=fresh_source) is call
|
||||
assert calls == [(call, True)]
|
||||
else:
|
||||
with pytest.raises(ValueError, match='not qualified'):
|
||||
guard.protect_call(call, fresh_source=True)
|
||||
assert calls == []
|
||||
|
||||
|
||||
def test_runtime_policy_matches_packaged_guard_sources():
|
||||
from openpilot.starpilot.models.runtime_bridge import runtime
|
||||
runtime._verify_policy()
|
||||
|
||||
|
||||
def test_runtime_policy_still_rejects_each_modified_guard(tmp_path, monkeypatch):
|
||||
import json
|
||||
import shutil
|
||||
from openpilot.starpilot.models.runtime_bridge import runtime
|
||||
|
||||
root = Path(runtime.__file__).parent
|
||||
policy = json.loads((root / 'guard-policy.json').read_text())
|
||||
for name in ['guard-policy.json', *policy['files']]:
|
||||
shutil.copyfile(root / name, tmp_path / name)
|
||||
monkeypatch.setattr(runtime, '__file__', str(tmp_path / 'runtime.py'))
|
||||
runtime._verify_policy()
|
||||
for name in ['guard-policy.json', *policy['files']]:
|
||||
path = tmp_path / name
|
||||
original = path.read_bytes()
|
||||
path.write_bytes(original + b'\n')
|
||||
with pytest.raises(RuntimeError, match='changed'):
|
||||
runtime._verify_policy()
|
||||
path.write_bytes(original)
|
||||
runtime._verify_policy()
|
||||
|
||||
@@ -356,7 +356,7 @@ class Runtime:
|
||||
ego_speeds = (car_state.vEgo, car_state.vEgoCluster)
|
||||
ego_valid = car_fresh and all(type(speed) in (int, float) and math.isfinite(speed) and
|
||||
(car_state.standstill or speed >= 0.) for speed in ego_speeds)
|
||||
ego = (sd.SpeedPair(sd.DomainStatus.VALID, *(max(0., speed) for speed in ego_speeds), self.session_id, now_ns)
|
||||
ego = (sd.SpeedPair(sd.DomainStatus.VALID, max(0., ego_speeds[0]), max(0., ego_speeds[1]), self.session_id, now_ns)
|
||||
if ego_valid else sd.SpeedPair(sd.DomainStatus.STALE if sm.logMonoTime.get("carState", 0) else sd.DomainStatus.UNKNOWN))
|
||||
host = comp.HostState(bool(CP.openpilotLongitudinalControl), host_long, bool(selfdrive.enabled and selfdrive_fresh),
|
||||
bool(controls.forceDecel) if controls_fresh else True, selected, selected_cluster)
|
||||
|
||||
@@ -132,6 +132,7 @@ class TestStopObservation(unittest.TestCase):
|
||||
if expected is None:
|
||||
self.assertIsNone(owner.distance_m)
|
||||
else:
|
||||
assert owner.distance_m is not None
|
||||
self.assertAlmostEqual(owner.distance_m, expected, places=2)
|
||||
owner.observe(None, now_ns=BASE + 900_000_000)
|
||||
self.assertIsNone(owner.distance_m)
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "ae58f86d7b25e48aa0d608b5d95a87e0cf59caaa0c223af2d5abe5f56c260be3", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "5708a3cd319cd5c96ad0fa1679a47712342bb2b70ff983b410bc308aad184d47", "schema_version": 1}
|
||||
|
||||
Reference in New Issue
Block a user