"""Synthetic structural tests only; no OEM image or ARM execution is used.""" import hashlib import importlib.util from pathlib import Path import unittest from unittest.mock import patch ROOT = Path(__file__).resolve().parents[2] PATH = ROOT / "navigation/archived/v038/patch_nav_vehicle_speed_source.py" SPEC = importlib.util.spec_from_file_location("archived_speed_patch", PATH) MODULE = importlib.util.module_from_spec(SPEC) SPEC.loader.exec_module(MODULE) class ArchivedSpeedPatchTests(unittest.TestCase): def fixture(self): settings = dict( SETTER_OFFSET=16, SETTER_CONTINUE=20, CAVE_OFFSET=64, CAVE_SIZE=60, DISPLAY_CALL_SITES=(160, 168, 176, 184, 192), CONVERT_SPEED=256, SAFETY_CALL_SITE=200, ) image = bytearray(320) image[16:20] = MODULE.SETTER_ORIGINAL for site in settings["DISPLAY_CALL_SITES"] + (settings["SAFETY_CALL_SITE"],): image[site:site + 4] = MODULE.encode_thumb_branch(site, 256, link=True) settings["SOURCE_SHA256"] = hashlib.sha256(image).hexdigest() return bytes(image), settings def test_unknown_original_is_rejected(self): with self.assertRaisesRegex(ValueError, "unknown source"): MODULE.patch_image(b"synthetic-not-a-library") def test_thumb_alignment_and_range_are_checked(self): self.assertEqual(MODULE.encode_thumb_branch(0x1000, 0x1004), b"\x00\xf0\x00\xb8") with self.assertRaisesRegex(ValueError, "halfword"): MODULE.encode_thumb_branch(0x1000, 0x1005) with self.assertRaisesRegex(ValueError, "out of range"): MODULE.encode_thumb_branch(0x1000, 0x2001004) def test_only_declared_windows_change(self): original, settings = self.fixture() with patch.multiple(MODULE, **settings): result = MODULE.patch_image(original) allowed = set(range(16, 20)) | set(range(64, 124)) changed = {i for i, (a, b) in enumerate(zip(original, result)) if a != b} self.assertTrue(changed) self.assertLessEqual(changed, allowed) self.assertEqual(len(result), len(original)) for site in settings["DISPLAY_CALL_SITES"] + (settings["SAFETY_CALL_SITE"],): self.assertEqual(result[site:site + 4], original[site:site + 4]) def test_occupied_cave_is_rejected_even_with_matching_hash(self): original, settings = self.fixture() bad = bytearray(original) bad[64] = 1 settings["SOURCE_SHA256"] = hashlib.sha256(bad).hexdigest() with patch.multiple(MODULE, **settings): with self.assertRaisesRegex(ValueError, "code cave"): MODULE.patch_image(bytes(bad)) def test_changed_safety_call_is_rejected(self): original, settings = self.fixture() bad = bytearray(original) bad[200] ^= 1 settings["SOURCE_SHA256"] = hashlib.sha256(bad).hexdigest() with patch.multiple(MODULE, **settings): with self.assertRaisesRegex(ValueError, "overspeed"): MODULE.patch_image(bytes(bad)) if __name__ == "__main__": unittest.main()