forked from IQ.Lvbs/IQ.Pilot
IQ.Pilot Prebuilt Release @ ab07000
This commit is contained in:
91
iqpilot/tests/test_auto_units.py
Normal file
91
iqpilot/tests/test_auto_units.py
Normal file
@@ -0,0 +1,91 @@
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.iqpilot.common.auto_units import CONFIRMATIONS, AutoUnits
|
||||
|
||||
SEATTLE = (47.6062, -122.3321)
|
||||
BERLIN = (52.5200, 13.4050)
|
||||
LONDON = (51.5074, -0.1278)
|
||||
|
||||
|
||||
class StubAutoUnits(AutoUnits):
|
||||
def __init__(self, params):
|
||||
super().__init__(params)
|
||||
self.position = (0.0, 0.0, False)
|
||||
|
||||
def _position(self):
|
||||
return self.position
|
||||
|
||||
|
||||
def settle(auto_units, position, count=CONFIRMATIONS, start=0.0):
|
||||
auto_units.position = position
|
||||
for i in range(count):
|
||||
auto_units.update(now=start + i * 100.0)
|
||||
return start + count * 100.0
|
||||
|
||||
|
||||
class TestAutoUnits:
|
||||
def setup_method(self):
|
||||
self.params = Params()
|
||||
self.params.put_bool("IQAutoUnits", True)
|
||||
self.params.remove("IQAutoUnitsRegion")
|
||||
self.params.put_bool("IsMetric", False)
|
||||
self.auto_units = StubAutoUnits(self.params)
|
||||
|
||||
def test_no_fix_does_nothing(self):
|
||||
settle(self.auto_units, (0.0, 0.0, False))
|
||||
assert self.params.get("IQAutoUnitsRegion") is None
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
def test_disabled_does_nothing(self):
|
||||
self.params.put_bool("IQAutoUnits", False)
|
||||
settle(self.auto_units, (*BERLIN, True))
|
||||
assert self.params.get("IQAutoUnitsRegion") is None
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
def test_metric_region_switches_to_metric(self):
|
||||
settle(self.auto_units, (*BERLIN, True))
|
||||
assert self.params.get("IQAutoUnitsRegion") == "METRIC"
|
||||
assert self.params.get_bool("IsMetric")
|
||||
|
||||
def test_mph_region_stays_imperial(self):
|
||||
settle(self.auto_units, (*SEATTLE, True))
|
||||
assert self.params.get("IQAutoUnitsRegion") == "US"
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
def test_uk_stays_imperial(self):
|
||||
self.params.put_bool("IsMetric", True)
|
||||
settle(self.auto_units, (*LONDON, True))
|
||||
assert self.params.get("IQAutoUnitsRegion") == "GB"
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
def test_border_crossing_switches_units(self):
|
||||
now = settle(self.auto_units, (*SEATTLE, True))
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
settle(self.auto_units, (*BERLIN, True), start=now)
|
||||
assert self.params.get("IQAutoUnitsRegion") == "METRIC"
|
||||
assert self.params.get_bool("IsMetric")
|
||||
|
||||
def test_manual_override_is_kept_within_a_region(self):
|
||||
now = settle(self.auto_units, (*SEATTLE, True))
|
||||
self.params.put_bool("IsMetric", True)
|
||||
|
||||
settle(self.auto_units, (*SEATTLE, True), start=now)
|
||||
assert self.params.get_bool("IsMetric")
|
||||
|
||||
def test_unconfirmed_region_is_not_applied(self):
|
||||
settle(self.auto_units, (*BERLIN, True), count=CONFIRMATIONS - 1)
|
||||
assert self.params.get("IQAutoUnitsRegion") is None
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
def test_flapping_region_resets_confirmations(self):
|
||||
now = 0.0
|
||||
for position in (BERLIN, SEATTLE, BERLIN, SEATTLE):
|
||||
now = settle(self.auto_units, (*position, True), count=1, start=now)
|
||||
assert self.params.get("IQAutoUnitsRegion") is None
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
def test_rate_limited(self):
|
||||
self.auto_units.position = (*BERLIN, True)
|
||||
for _ in range(CONFIRMATIONS * 4):
|
||||
self.auto_units.update(now=1.0)
|
||||
assert self.params.get("IQAutoUnitsRegion") is None
|
||||
165
iqpilot/tests/test_geo_regions.py
Normal file
165
iqpilot/tests/test_geo_regions.py
Normal file
@@ -0,0 +1,165 @@
|
||||
import pytest
|
||||
|
||||
from openpilot.iqpilot.common.geo_regions import METRIC_REGION, UNKNOWN_REGION, region_for_position, region_is_metric
|
||||
|
||||
US_POINTS = [
|
||||
(47.6062, -122.3321, "Seattle"),
|
||||
(42.3314, -83.0458, "Detroit"),
|
||||
(42.8864, -78.8784, "Buffalo"),
|
||||
(25.7617, -80.1918, "Miami"),
|
||||
(29.7604, -95.3698, "Houston"),
|
||||
(32.7157, -117.1611, "San Diego"),
|
||||
(34.0522, -118.2437, "Los Angeles"),
|
||||
(61.2181, -149.9003, "Anchorage"),
|
||||
(58.3019, -134.4197, "Juneau"),
|
||||
(64.8378, -147.7164, "Fairbanks"),
|
||||
(21.3069, -157.8583, "Honolulu"),
|
||||
(18.4655, -66.1057, "San Juan"),
|
||||
(13.4757, 144.7489, "Guam"),
|
||||
(44.9778, -93.2650, "Minneapolis"),
|
||||
(40.7128, -74.0060, "New York"),
|
||||
(41.8781, -87.6298, "Chicago"),
|
||||
(31.7900, -106.4300, "El Paso"),
|
||||
(26.2034, -98.2300, "McAllen"),
|
||||
(44.8016, -68.7712, "Bangor"),
|
||||
(48.7519, -122.4787, "Bellingham"),
|
||||
(46.8772, -96.7898, "Fargo"),
|
||||
(48.6023, -93.4093, "International Falls"),
|
||||
(46.4953, -84.3453, "Sault Ste. Marie MI"),
|
||||
(47.1211, -88.5694, "Houghton"),
|
||||
(41.6528, -83.5379, "Toledo"),
|
||||
(42.1370, -83.1930, "Trenton MI"),
|
||||
(39.7392, -104.9903, "Denver"),
|
||||
(33.4484, -112.0740, "Phoenix"),
|
||||
(30.3322, -81.6557, "Jacksonville"),
|
||||
(42.3601, -71.0589, "Boston"),
|
||||
(38.9072, -77.0369, "Washington DC"),
|
||||
]
|
||||
|
||||
GB_POINTS = [
|
||||
(51.5074, -0.1278, "London"),
|
||||
(54.5973, -5.9301, "Belfast"),
|
||||
(55.8642, -4.2518, "Glasgow"),
|
||||
(51.4816, -3.1791, "Cardiff"),
|
||||
(51.4545, -2.5879, "Bristol"),
|
||||
(53.4084, -2.9916, "Liverpool"),
|
||||
(53.4808, -2.2426, "Manchester"),
|
||||
(55.9533, -3.1883, "Edinburgh"),
|
||||
(52.4862, -1.8904, "Birmingham"),
|
||||
(53.8008, -1.5491, "Leeds"),
|
||||
(57.4778, -4.2247, "Inverness"),
|
||||
(57.1497, -2.0943, "Aberdeen"),
|
||||
(56.4620, -2.9707, "Dundee"),
|
||||
(58.6373, -3.0689, "John o' Groats"),
|
||||
(54.1509, -4.4814, "Douglas"),
|
||||
(49.1858, -2.1064, "St Helier"),
|
||||
(55.0000, -7.3200, "Derry"),
|
||||
(54.3438, -7.6315, "Enniskillen"),
|
||||
(54.1751, -6.3402, "Newry"),
|
||||
(54.4783, -8.0906, "Belleek"),
|
||||
(54.5973, -7.3095, "Omagh"),
|
||||
(55.2053, -6.6570, "Portrush"),
|
||||
(58.2090, -6.3890, "Stornoway"),
|
||||
(58.9809, -2.9605, "Kirkwall"),
|
||||
(60.1546, -1.1494, "Lerwick"),
|
||||
(50.7184, -3.5339, "Exeter"),
|
||||
(50.3755, -4.1427, "Plymouth"),
|
||||
(52.6309, 1.2974, "Norwich"),
|
||||
(54.9783, -1.6178, "Newcastle"),
|
||||
(51.8642, -2.2382, "Gloucester"),
|
||||
(52.4140, -4.0810, "Aberystwyth"),
|
||||
(51.6214, -3.9436, "Swansea"),
|
||||
(50.6938, -1.3040, "Newport IoW"),
|
||||
]
|
||||
|
||||
LR_POINTS = [
|
||||
(6.3005, -10.7969, "Monrovia"),
|
||||
(4.3750, -7.7169, "Harper"),
|
||||
(6.9956, -9.4722, "Gbarnga"),
|
||||
(6.0667, -8.1333, "Zwedru"),
|
||||
(8.4219, -9.7478, "Voinjama"),
|
||||
(5.8808, -10.0467, "Buchanan"),
|
||||
(5.0100, -9.0400, "Greenville"),
|
||||
(7.3500, -8.7200, "Ganta"),
|
||||
]
|
||||
|
||||
METRIC_POINTS = [
|
||||
(49.2827, -123.1207, "Vancouver"),
|
||||
(48.4284, -123.3656, "Victoria"),
|
||||
(43.6532, -79.3832, "Toronto"),
|
||||
(42.3149, -83.0364, "Windsor"),
|
||||
(46.5136, -84.3358, "Sault Ste. Marie ON"),
|
||||
(42.9745, -82.4066, "Sarnia"),
|
||||
(43.2557, -79.8711, "Hamilton"),
|
||||
(42.9849, -81.2453, "London ON"),
|
||||
(45.5019, -73.5674, "Montreal"),
|
||||
(45.4765, -75.7013, "Gatineau"),
|
||||
(46.8139, -71.2080, "Quebec City"),
|
||||
(46.0878, -64.7782, "Moncton"),
|
||||
(44.6488, -63.5752, "Halifax"),
|
||||
(49.8951, -97.1384, "Winnipeg"),
|
||||
(51.0447, -114.0719, "Calgary"),
|
||||
(53.5461, -113.4938, "Edmonton"),
|
||||
(52.1332, -106.6700, "Saskatoon"),
|
||||
(50.6745, -120.3273, "Kamloops"),
|
||||
(32.5149, -117.0382, "Tijuana"),
|
||||
(31.7000, -106.4700, "Ciudad Juarez"),
|
||||
(25.6866, -100.3161, "Monterrey"),
|
||||
(27.5060, -99.5075, "Nuevo Laredo"),
|
||||
(19.4326, -99.1332, "Mexico City"),
|
||||
(53.3498, -6.2603, "Dublin"),
|
||||
(51.8985, -8.4756, "Cork"),
|
||||
(53.2707, -9.0568, "Galway"),
|
||||
(54.9503, -7.7345, "Letterkenny"),
|
||||
(54.0000, -6.4000, "Dundalk"),
|
||||
(54.2489, -6.9683, "Monaghan"),
|
||||
(54.2766, -8.4761, "Sligo"),
|
||||
(54.6538, -8.1096, "Donegal"),
|
||||
(52.5200, 13.4050, "Berlin"),
|
||||
(52.2297, 21.0122, "Warsaw"),
|
||||
(48.8566, 2.3522, "Paris"),
|
||||
(60.1699, 24.9384, "Helsinki"),
|
||||
(50.4501, 30.5234, "Kyiv"),
|
||||
(-33.8688, 151.2093, "Sydney"),
|
||||
(35.6762, 139.6503, "Tokyo"),
|
||||
(8.4844, -13.2299, "Freetown"),
|
||||
(7.8767, -11.1875, "Kenema"),
|
||||
(8.2783, -10.5733, "Kailahun"),
|
||||
(9.6412, -13.5784, "Conakry"),
|
||||
(7.7562, -8.8179, "Nzerekore"),
|
||||
(7.4125, -7.5539, "Man"),
|
||||
(5.3600, -4.0083, "Abidjan"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("lat, lon, name", US_POINTS)
|
||||
def test_us_positions(lat, lon, name):
|
||||
assert region_for_position(lat, lon) == "US", name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("lat, lon, name", GB_POINTS)
|
||||
def test_gb_positions(lat, lon, name):
|
||||
assert region_for_position(lat, lon) == "GB", name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("lat, lon, name", LR_POINTS)
|
||||
def test_lr_positions(lat, lon, name):
|
||||
assert region_for_position(lat, lon) == "LR", name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("lat, lon, name", METRIC_POINTS)
|
||||
def test_metric_positions(lat, lon, name):
|
||||
assert region_for_position(lat, lon) == METRIC_REGION, name
|
||||
|
||||
|
||||
@pytest.mark.parametrize("lat, lon", [(0.0, 0.0), (0.0, 0.00001), (91.0, 10.0), (10.0, 181.0)])
|
||||
def test_invalid_positions(lat, lon):
|
||||
assert region_for_position(lat, lon) == UNKNOWN_REGION
|
||||
|
||||
|
||||
def test_region_is_metric():
|
||||
assert not region_is_metric("US")
|
||||
assert not region_is_metric("GB")
|
||||
assert not region_is_metric("LR")
|
||||
assert region_is_metric(METRIC_REGION)
|
||||
assert not region_is_metric(UNKNOWN_REGION)
|
||||
206
iqpilot/tests/test_proprietary_loader.py
Normal file
206
iqpilot/tests/test_proprietary_loader.py
Normal file
@@ -0,0 +1,206 @@
|
||||
"""
|
||||
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
|
||||
"""
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from openpilot.iqpilot import _proprietary_loader as loader
|
||||
|
||||
|
||||
def _write(path: Path, content: str = "") -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(content)
|
||||
|
||||
|
||||
def _write_bytes(path: Path, content: bytes) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_bytes(content)
|
||||
|
||||
|
||||
def test_module_root_for_name_prefers_matching_bundle(tmp_path, monkeypatch):
|
||||
repo_root = tmp_path / "repo"
|
||||
model_root = repo_root / "artifacts" / "iqpilot_model_selector_private" / "python"
|
||||
hepha_root = repo_root / "artifacts" / "iqpilot_hephaestusd_private" / "python"
|
||||
|
||||
_write(model_root / "iqpilot_private" / "__init__.py")
|
||||
_write(model_root / "iqpilot_private" / "models" / "__init__.py")
|
||||
_write(model_root / "iqpilot_private" / "models" / "manager.py", "VALUE = 'models'\n")
|
||||
|
||||
_write(hepha_root / "iqpilot_private" / "__init__.py")
|
||||
_write(hepha_root / "iqpilot_private" / "konn3kt" / "__init__.py")
|
||||
_write(hepha_root / "iqpilot_private" / "konn3kt" / "hephaestus" / "__init__.py")
|
||||
_write(hepha_root / "iqpilot_private" / "konn3kt" / "hephaestus" / "hephaestusd.py", "VALUE = 'hepha'\n")
|
||||
|
||||
monkeypatch.setattr(loader, "__file__", str(repo_root / "iqpilot" / "_proprietary_loader.py"))
|
||||
|
||||
resolved = loader._module_root_for_name("iqpilot_private.konn3kt.hephaestus.hephaestusd")
|
||||
assert resolved == hepha_root
|
||||
|
||||
|
||||
def test_load_private_module_uses_matching_bundle(tmp_path, monkeypatch):
|
||||
repo_root = tmp_path / "repo"
|
||||
model_root = repo_root / "artifacts" / "iqpilot_model_selector_private" / "python"
|
||||
hepha_root = repo_root / "artifacts" / "iqpilot_hephaestusd_private" / "python"
|
||||
|
||||
_write(model_root / "iqpilot_private" / "__init__.py")
|
||||
_write(model_root / "iqpilot_private" / "models" / "__init__.py")
|
||||
_write(model_root / "iqpilot_private" / "models" / "manager.py", "VALUE = 'models'\n")
|
||||
|
||||
_write(hepha_root / "iqpilot_private" / "__init__.py")
|
||||
_write(hepha_root / "iqpilot_private" / "konn3kt" / "__init__.py")
|
||||
_write(hepha_root / "iqpilot_private" / "konn3kt" / "hephaestus" / "__init__.py")
|
||||
_write(hepha_root / "iqpilot_private" / "konn3kt" / "hephaestus" / "hephaestusd.py", "VALUE = 'hepha'\n")
|
||||
|
||||
monkeypatch.setattr(loader, "__file__", str(repo_root / "iqpilot" / "_proprietary_loader.py"))
|
||||
monkeypatch.setenv("IQPILOT_PROPRIETARY_ROOT", "")
|
||||
|
||||
old_sys_path = list(sys.path)
|
||||
for key in [k for k in sys.modules if k.startswith("iqpilot_private") or k == "test_public_module"]:
|
||||
sys.modules.pop(key, None)
|
||||
|
||||
try:
|
||||
sys.modules["test_public_module"] = type(sys)("test_public_module")
|
||||
private_module = loader.load_private_module("test_public_module", "iqpilot_private.konn3kt.hephaestus.hephaestusd")
|
||||
assert private_module.VALUE == "hepha"
|
||||
assert sys.modules["test_public_module"].VALUE == "hepha"
|
||||
finally:
|
||||
sys.path[:] = old_sys_path
|
||||
for key in [k for k in sys.modules if k.startswith("iqpilot_private") or k == "test_public_module"]:
|
||||
sys.modules.pop(key, None)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sig_keypair():
|
||||
pytest.importorskip("cryptography")
|
||||
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
||||
|
||||
private_key = Ed25519PrivateKey.generate()
|
||||
public_key = private_key.public_key()
|
||||
return (
|
||||
private_key.private_bytes_raw(),
|
||||
public_key.public_bytes_raw(),
|
||||
)
|
||||
|
||||
|
||||
def _sign_file(private_key_bytes: bytes, file_path: Path) -> bytes:
|
||||
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
||||
|
||||
private_key = Ed25519PrivateKey.from_private_bytes(private_key_bytes)
|
||||
digest = hashlib.sha256(file_path.read_bytes()).digest()
|
||||
return private_key.sign(digest)
|
||||
|
||||
|
||||
def test_signature_valid_passes(tmp_path, monkeypatch, sig_keypair):
|
||||
priv, pub = sig_keypair
|
||||
monkeypatch.setattr(loader, "_IQPILOT_PUBLIC_KEY", pub)
|
||||
monkeypatch.setattr(loader, "_verified_roots", set())
|
||||
monkeypatch.setenv("IQPILOT_SKIP_SIGNATURE_VERIFY", "")
|
||||
|
||||
bundle_root = tmp_path / "bundle"
|
||||
python_root = bundle_root / "python"
|
||||
python_root.mkdir(parents=True)
|
||||
(python_root / "iqpilot_private").mkdir()
|
||||
|
||||
so_path = python_root / "dummy.so"
|
||||
_write_bytes(so_path, b"VALID SO CONTENT")
|
||||
|
||||
sig = _sign_file(priv, so_path)
|
||||
manifest = {
|
||||
"python/dummy.so": {"sha256": hashlib.sha256(so_path.read_bytes()).hexdigest(), "size": so_path.stat().st_size, "mode": 0o644},
|
||||
"signatures": {"python/dummy.so": base64.b64encode(sig).decode("ascii")},
|
||||
}
|
||||
(bundle_root / "manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
|
||||
|
||||
loader._verify_bundle_signatures(python_root)
|
||||
|
||||
|
||||
def test_signature_tampered_raises(tmp_path, monkeypatch, sig_keypair):
|
||||
priv, pub = sig_keypair
|
||||
monkeypatch.setattr(loader, "_IQPILOT_PUBLIC_KEY", pub)
|
||||
monkeypatch.setattr(loader, "_verified_roots", set())
|
||||
monkeypatch.setenv("IQPILOT_SKIP_SIGNATURE_VERIFY", "")
|
||||
|
||||
bundle_root = tmp_path / "bundle"
|
||||
python_root = bundle_root / "python"
|
||||
python_root.mkdir(parents=True)
|
||||
(python_root / "iqpilot_private").mkdir()
|
||||
|
||||
so_path = python_root / "dummy.so"
|
||||
_write_bytes(so_path, b"VALID SO CONTENT")
|
||||
|
||||
sig = _sign_file(priv, so_path)
|
||||
|
||||
so_path.write_bytes(b"TAMPERED CONTENT")
|
||||
|
||||
manifest = {
|
||||
"python/dummy.so": {"sha256": hashlib.sha256(b"VALID SO CONTENT").hexdigest(), "size": 16, "mode": 0o644},
|
||||
"signatures": {"python/dummy.so": base64.b64encode(sig).decode("ascii")},
|
||||
}
|
||||
(bundle_root / "manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
|
||||
|
||||
with pytest.raises(loader.ProprietaryModuleIntegrityError):
|
||||
loader._verify_bundle_signatures(python_root)
|
||||
|
||||
|
||||
def test_signature_skip_env_warns(tmp_path, monkeypatch, sig_keypair):
|
||||
priv, pub = sig_keypair
|
||||
monkeypatch.setattr(loader, "_IQPILOT_PUBLIC_KEY", pub)
|
||||
monkeypatch.setattr(loader, "_verified_roots", set())
|
||||
monkeypatch.setenv("IQPILOT_SKIP_SIGNATURE_VERIFY", "1")
|
||||
|
||||
bundle_root = tmp_path / "bundle"
|
||||
python_root = bundle_root / "python"
|
||||
python_root.mkdir(parents=True)
|
||||
(python_root / "iqpilot_private").mkdir()
|
||||
|
||||
so_path = python_root / "dummy.so"
|
||||
_write_bytes(so_path, b"ANY CONTENT")
|
||||
|
||||
sig = _sign_file(priv, so_path)
|
||||
manifest = {
|
||||
"python/dummy.so": {"sha256": hashlib.sha256(so_path.read_bytes()).hexdigest(), "size": so_path.stat().st_size, "mode": 0o644},
|
||||
"signatures": {"python/dummy.so": base64.b64encode(sig).decode("ascii")},
|
||||
}
|
||||
(bundle_root / "manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
|
||||
|
||||
import warnings
|
||||
|
||||
with pytest.warns(RuntimeWarning, match="Skipping signature verification"):
|
||||
loader._verify_bundle_signatures(python_root)
|
||||
|
||||
|
||||
def test_signature_no_manifest_backward_compat(tmp_path, monkeypatch):
|
||||
"""Bundles built before signing support should load without error."""
|
||||
monkeypatch.setattr(loader, "_verified_roots", set())
|
||||
monkeypatch.setenv("IQPILOT_SKIP_SIGNATURE_VERIFY", "")
|
||||
|
||||
bundle_root = tmp_path / "bundle"
|
||||
python_root = bundle_root / "python"
|
||||
python_root.mkdir(parents=True)
|
||||
(python_root / "iqpilot_private").mkdir()
|
||||
|
||||
loader._verify_bundle_signatures(python_root)
|
||||
|
||||
|
||||
def test_signature_manifest_without_signatures_backward_compat(tmp_path, monkeypatch):
|
||||
"""Manifests without a 'signatures' key should load without error."""
|
||||
monkeypatch.setattr(loader, "_verified_roots", set())
|
||||
monkeypatch.setenv("IQPILOT_SKIP_SIGNATURE_VERIFY", "")
|
||||
|
||||
bundle_root = tmp_path / "bundle"
|
||||
python_root = bundle_root / "python"
|
||||
python_root.mkdir(parents=True)
|
||||
(python_root / "iqpilot_private").mkdir()
|
||||
|
||||
manifest = {
|
||||
"python/dummy.py": {"sha256": "abc", "size": 3, "mode": 0o644},
|
||||
}
|
||||
(bundle_root / "manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
|
||||
|
||||
loader._verify_bundle_signatures(python_root)
|
||||
Reference in New Issue
Block a user