"""Optional-screen defaults and exact packaged detection evidence.""" from copy import deepcopy import json from pathlib import Path import subprocess import sys import tempfile import unittest ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / "scripts")) import optional_display_profiles as displays import generate_picker_controls as generator from test_upstream_observer_recipes import Recipes from test_t114_autodisplay_recipes import defines SOURCE = "a" * 40 TARGETS = ("heltec_rc32_repeater", "Heltec_Wireless_Tracker_repeater", "heltec_tracker_v1_1_repeater_observer_mqtt", "heltec_v4_r8_tft_repeater") def manifest(spec, target): return dict(target=target, platform="ESP32_PLATFORM", verified=True, source_commit=SOURCE, capabilities=[displays.CAPABILITY], verification=[dict(capability=displays.CAPABILITY, present=True, source="packaged application", evidence=displays.marker(spec))]) class OptionalDisplayProfilesTest(unittest.TestCase): def test_nrf52_accessories_require_the_exact_radio_panel_and_packaged_marker(self): recipes = Recipes() for target in ("muzi_base_duo_companion_radio_ble", "muzi_base_uno_companion_radio_ble", "LilyGo_T-Echo-Lite_companion_radio_ble"): flags = defines(recipes.value("env:" + target, "build_flags")) board = recipes.value("env:" + target, "board") spec = displays.spec_for_defines(flags, board) self.assertIsNotNone(spec) row = {**manifest(spec, target), "platform": "NRF52_PLATFORM"} result = displays.runtime_metadata(row, flags, SOURCE, board) self.assertEqual(result, dict(displayAuto=True, displayController=spec["controller"], displaySource=SOURCE)) for change in ({spec["flag"]: "0"}, {spec["guard"]: "0"}, {"DISPLAY_CLASS": "NullDisplayDriver"}, {key: "unrelated" for key in spec.get("defines", {})}): with self.subTest(target=target, change=change), self.assertRaises(ValueError): displays.runtime_metadata(row, {**flags, **change}, SOURCE, board) for change in ({"platform": "ESP32_PLATFORM"}, {"verification": []}, {"target": target.replace("duo", "uno") if "duo" in target else "other_companion_radio_ble"}): with self.subTest(target=target, change=change), self.assertRaises(ValueError): displays.runtime_metadata({**row, **change}, flags, SOURCE, board) self.assertEqual(displays.runtime_metadata({**row, "capabilities": []}, flags, SOURCE, board), {}) def test_lite_explicit_compatibility_roles_keep_their_own_display_proof(self): recipes = Recipes() for role in ("repeater", "room_server"): target = "LilyGo_T-Echo-Lite_" + role + "_lora_ota" flags = defines(recipes.value("env:" + target, "build_flags")) board = recipes.value("env:" + target, "board") spec = displays.spec_for_defines(flags, board) legacy = target + "_no_external_sensors" row = {**manifest(spec, legacy), "platform": "NRF52_PLATFORM"} self.assertTrue(displays.runtime_metadata(row, flags, SOURCE, board)["displayAuto"]) def test_all_tracker_full_repeaters_keep_the_measured_safe_neighbor_capacity(self): script = r''' set -euo pipefail source "$1/build_legacy.sh" ESP32_FULL_BUILD=1 for target in Heltec_Wireless_Tracker_repeater_observer_mqtt heltec_tracker_v1_1_repeater_observer_mqtt heltec_tracker_v2_repeater_observer_mqtt; do PLATFORMIO_BUILD_FLAGS="" PLATFORMIO_BUILD_UNFLAGS="" BUILD_REDUCTIONS=() apply_repeater_neighbor_capacity "$target" [[ "$PLATFORMIO_BUILD_FLAGS" == *"-DMAX_NEIGHBOURS=50"* ]] [[ " ${BUILD_REDUCTIONS[*]} " == *"mesh.neighbors limited to 50"* ]] done ESP32_FULL_BUILD=0 ! requires_dram_limited_neighbors Heltec_Wireless_Tracker_repeater_observer_mqtt ''' result = subprocess.run(["bash", "-c", script, "optional-screen-capacity", str(ROOT)], cwd=ROOT, capture_output=True, text=True, check=False) self.assertEqual(result.returncode, 0, result.stdout + result.stderr) def test_optional_hardware_defaults_and_integral_screens_are_separate(self): recipes = Recipes() for spec, target in zip(displays.SPECS, TARGETS): with self.subTest(target=target): flags = defines(recipes.value("env:" + target, "build_flags")) self.assertEqual(displays.spec_for_defines(flags, recipes.value("env:" + target, "board")), spec) if spec["marker"] == "heltec_r8": self.assertEqual(flags["SDCARD_CS"], "3") for target in ("Heltec_T190_repeater_", "LilyGo_T-Echo_Card_repeater", "Heltec_t096_repeater", "Heltec_t1_repeater", "heltec_tracker_v2_repeater", "ThinkNode_M9_repeater_", "heltec_v4_repeater", "heltec_v4_tft_repeater", "heltec_rc32_without_display_repeater", "heltec_rc32_kiss_modem"): with self.subTest(target=target): flags = defines(recipes.value("env:" + target, "build_flags")) self.assertIsNone(displays.spec_for_defines(flags)) def test_exact_flags_application_marker_controller_and_source_are_required(self): recipes = Recipes() for spec, target in zip(displays.SPECS, TARGETS): flags = defines(recipes.value("env:" + target, "build_flags")) row = manifest(spec, target) with self.subTest(target=target): self.assertEqual(displays.runtime_metadata(row, flags, board=spec["board"]), dict(displayAuto=True, displayController=spec["controller"], displaySource=SOURCE)) old = {**row, "capabilities": []} self.assertEqual(displays.runtime_metadata(old, flags), {}) for changed in ({spec["flag"]: "0"}, {spec["guard"]: "0"}, {"DISPLAY_CLASS": "NullDisplayDriver"}): with self.assertRaises(ValueError): displays.runtime_metadata(row, {**flags, **changed}, board=spec["board"]) for changed in ({"verified": False}, {"platform": "NRF52_PLATFORM"}, {"source_commit": SOURCE[:8]}, {"verification": []}, {"target": "unrelated_repeater"}): with self.assertRaises(ValueError): displays.runtime_metadata({**row, **changed}, flags, board=spec["board"]) for key, value in (("present", False), ("source", "linked image"), ("evidence", "unrelated")): bad = deepcopy(row) bad["verification"][0][key] = value with self.assertRaises(ValueError): displays.runtime_metadata(bad, flags, board=spec["board"]) for board in (None, "different_board"): with self.assertRaises(ValueError): displays.runtime_metadata(row, flags, board=board) with self.assertRaisesRegex(ValueError, "source must match"): displays.runtime_metadata(row, flags, "b" * 40, board=spec["board"]) def test_builder_uses_ordered_flags_and_exact_board_without_starting_platformio(self): spec = displays.SPECS[0] flags = ["-D HELTEC_RC32", "-DDISPLAY_CLASS=NV3001BDisplay", "-D RC32_DISPLAY_AUTODETECT=1"] for board, extra, expected in ((spec["board"], [], 0), (spec["board"], ["-U RC32_DISPLAY_AUTODETECT"], 1), (spec["board"], ["-D RC32_DISPLAY_AUTODETECT=0"], 1), ("other_board", [], 1)): config = [["env:sample", [["board", board], ["build_flags", flags + extra]]]] result = subprocess.run([sys.executable, str(ROOT / "scripts/optional_display_profiles.py"), "sample"], input=json.dumps(config), text=True, capture_output=True, check=False) self.assertEqual(result.returncode, expected, result.stderr) if not expected: self.assertEqual(result.stdout.strip(), displays.marker(spec)) def test_real_generator_binds_each_optional_board_to_uploadable_files(self): recipes = Recipes() for spec, target in zip(displays.SPECS, TARGETS): with self.subTest(target=target), tempfile.TemporaryDirectory() as folder: stage = Path(folder) (stage / "companion").mkdir() family = "v1.18.0.1-dev-aaaaaaaa" (stage / "release-plan.json").write_text(json.dumps(dict(source=SOURCE, groups=[dict(key="companion", tag=family)]))) row = manifest(spec, target) row.update(platformio_env="sample", files=[target + "-" + family + suffix for suffix in (".bin", "-merged.bin")]) (stage / "companion/TARGET-MANIFEST.json").write_text(json.dumps([row])) flags = defines(recipes.value("env:" + target, "build_flags")) result = generator.generate(stage, [["env:sample", [["board", spec["board"]], ["build_flags", ["-D" + k + "=" + v for k, v in flags.items()]]]]]) self.assertEqual(result["profiles"][target]["displaySource"], SOURCE) self.assertEqual(result["profiles"][target]["displayController"], spec["controller"]) self.assertTrue(result["profiles"][target]["displayAuto"]) def test_elf_marker_alone_cannot_qualify_the_downloaded_esp32_application(self): spec = displays.SPECS[0] with tempfile.TemporaryDirectory() as folder: root = Path(folder) elf, app, output = root / "firmware.elf", root / "firmware.bin", root / "capabilities.json" elf.write_bytes(displays.marker(spec).encode()) command = [sys.executable, "-B", str(ROOT / "scripts/check_firmware_capabilities.py"), "--image", str(elf), "--firmware-bin", str(app), "--output", str(output), "--target", TARGETS[0], "--platform", "ESP32_PLATFORM", "--build-profile", "full", "--expect-application", displays.CAPABILITY + "=" + displays.marker(spec)] app.write_bytes(b"old display firmware without detection") result = subprocess.run(command, capture_output=True, text=True, check=False) self.assertEqual(result.returncode, 1, result.stdout + result.stderr) self.assertFalse(json.loads(output.read_text())["verified"]) app.write_bytes(b"prefix\0" + displays.marker(spec).encode() + b"\0suffix") result = subprocess.run(command, capture_output=True, text=True, check=False) self.assertEqual(result.returncode, 0, result.stdout + result.stderr) self.assertTrue(json.loads(output.read_text())["verified"]) if __name__ == "__main__": unittest.main()