Files
MeshCore/test/test_consolidated_profiles.py
T
mikecarper b00d346df7 Unify Heltec V4 OLED, TFT and headless display selection
Detect OLED or the original stock TFT touch assembly in ordinary V4.2/V4.3
images. Add saved live display.type auto/oled/tft/off selection and report
the active selection in board output. Keep sensors on primary I2C, preserve
shared power, and isolate TFT FSPI from radio HSPI through sleep and changes.

Consolidate future picker/build choices only with application capability
proof. Retain exact legacy OTA identities and separate R8 hardware images.
Document controls and physical qualification limits.

Validation: five serialized Full builds with capability/size/RAM checks;
focused host tests, existing R8/T-Deck/OLED regressions, build-profile suite,
and picker/provider tests. V4.3 OLED live changes and off/auto reboot
persistence passed on Mercerwood. Physical TFT qualification remains pending.
2026-10-26 15:19:17 -07:00

419 lines
27 KiB
Python

"""No-build contracts for evidence-bound firmware choice consolidation."""
from copy import deepcopy
import json
import os
from pathlib import Path
import shlex
import subprocess
import sys
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts"))
import consolidated_profiles as consolidated
SOURCE = "a" * 40
CASES = (
dict(target="heltec_v4_sensor", legacy="heltec_v4_tft_sensor",
board="heltec_v4", platform="ESP32_PLATFORM", key="unifiedV4Display",
capability="display.heltec_v4.unified",
marker="meshcore.capability.display.heltec_v4.unified.v1",
flags=["-DHELTEC_V4_DISPLAY_UNIFIED=1", "-DDISPLAY_CLASS=HeltecV4Display"]),
dict(target="PicoW_companion_radio", legacy="PicoW_companion_radio_wifi",
board="rpipicow", platform="RP2040_PLATFORM", key="combinedCompanion",
capability="companion.picow.combined",
marker="meshcore.capability.companion.picow.combined.v1",
flags=["-DPICOW_COMBINED_COMPANION=1", "-DENABLE_USB_INTERFACE=1",
"-DENABLE_WIFI_INTERFACE=1", "-DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH=1"]),
dict(target="heltec_v4_repeater", legacy="heltec_v4_expansionkit_repeater",
board="heltec_v4", platform="ESP32_PLATFORM", key="oledExpansionCompatible",
capability="hardware.heltec_v4.oled_kit",
marker="meshcore.capability.hardware.heltec_v4.oled_kit.v1",
flags=["-DHELTEC_V4_OLED_KIT_COMPAT=1", "-DHELTEC_LORA_V4_OLED=1",
"-DDISPLAY_CLASS=SSD1306Display", "-DENV_PIN_SDA=4", "-DENV_PIN_SCL=3"]),
dict(target="heltec_v4_r8_tft_room_server",
legacy="heltec_v4_r8_tft_portrait_room_server_observer_mqtt",
board="heltec_v4_r8", platform="ESP32_PLATFORM", key="displayRotation",
capability="display.rotation.runtime",
marker="meshcore.capability.display.rotation.heltec_r8.v1",
flags=["-DHELTEC_TFT_RUNTIME_ROTATION=1", "-DHELTEC_V4_R8_TFT=1",
"-DDISPLAY_CLASS=ST7789LCDDisplay"]),
dict(target="heltec_v4_tft_companion_radio_full_femon",
legacy="heltec_v4_expansionkit_tft_companion_radio_full_femon",
board="heltec_v4", platform="ESP32_PLATFORM", key="tftExpansionCompatible",
capability="hardware.heltec_v4.tft_kit",
marker="meshcore.capability.hardware.heltec_v4.tft_kit.v1",
flags=["-DHELTEC_V4_TFT_KIT_COMPAT=1", "-DHELTEC_LORA_V4_TFT=1",
"-DDISPLAY_CLASS=ST7789LCDDisplay"]),
)
ACCESSORY_CASES = (
dict(base="muzi_base_uno", legacy="muzi_base_uno_superIO", board="muzi_base",
marker="muzi_superio", roles=("ble", "full"), flag="MUZI_BASE_ACCESSORY_AUTODETECT",
flags=["-DMUZI_BASE=1", "-DMUZI_BASE_ACCESSORY_AUTODETECT=1", "-DDISPLAY_CLASS=SH1107Display",
"-DRADIO_CLASS=CustomSX1262", "-DUSE_SX1262=1"]),
dict(base="muzi_base_duo", legacy="muzi_base_duo_superIO", board="muzi_base",
marker="muzi_superio", roles=("ble", "full"), flag="MUZI_BASE_ACCESSORY_AUTODETECT",
flags=["-DMUZI_BASE=1", "-DMUZI_BASE_ACCESSORY_AUTODETECT=1", "-DDISPLAY_CLASS=SH1107Display",
"-DRADIO_CLASS=CustomLR1121", "-DUSE_LR1121=1"]),
dict(base="LilyGo_T-Echo-Lite", legacy="LilyGo_T-Echo-Lite_non_shell", board="t-echo",
marker="techo_lite", roles=("usb", "ble", "full"), flag="TECHO_LITE_DISPLAY_AUTODETECT",
flags=["-DLILYGO_TECHO_LITE=1", "-DTECHO_LITE_DISPLAY_AUTODETECT=1",
"-DDISPLAY_CLASS=GxEPDDisplay", "-DEINK_DISPLAY_MODEL=GxEPD2_122_T61"]),
)
def environment(case):
return dict(board=case["board"], build_flags=list(case["flags"]))
def manifest(case, target=None, proof=True):
return dict(target=target or case["target"], verified=True,
platform=case["platform"], source_commit=SOURCE,
build_profile="full", capabilities=[case["capability"]] if proof else [],
verification=[dict(capability=case["capability"], present=True,
source="packaged application", evidence=case["marker"])] if proof else [])
def record(case, target=None, proof=True):
row = manifest(case, target, proof)
return dict(manifest=row, files=[row["target"] + ".bin"])
class ConsolidatedProfileTests(unittest.TestCase):
def test_r8_rotation_proof_covers_all_four_supported_roles(self):
case = next(case for case in CASES if case["key"] == "displayRotation")
for role in ("repeater", "room_server", "sensor", "companion_radio_full"):
target = "heltec_v4_r8_tft_" + role
with self.subTest(target=target):
self.assertEqual(consolidated.runtime_metadata(manifest(case, target), environment(case), SOURCE),
dict(displayRotation=True, displayRotationSource=SOURCE))
for role in ("kiss_modem", "partition_expander", "other", "companion_radio_wifi"):
with self.subTest(role=role), self.assertRaises(ValueError):
consolidated.runtime_metadata(manifest(case, "heltec_v4_r8_tft_" + role), environment(case), SOURCE)
def test_original_v4_tft_full_kit_alias_keeps_identical_wiring_and_battery_guard(self):
from test_upstream_observer_recipes import Recipes
from test_t114_autodisplay_recipes import defines
recipes = Recipes()
canonical = "env:heltec_v4_tft_companion_radio_full_femon"
legacy = "env:heltec_v4_expansionkit_tft_companion_radio_full_femon"
flags = defines(recipes.value(canonical, "build_flags"))
self.assertEqual(flags, defines(recipes.value(legacy, "build_flags")))
for key, value in dict(HELTEC_V4_TFT_KIT_COMPAT="1", HELTEC_V4_DISPLAY_UNIFIED="1", DISPLAY_CLASS="HeltecV4Display",
AUTO_SHUTDOWN_MILLIVOLTS="3400", MESHCORE_REQUIRES_COMPANION_RADIO_FULL="1",
PIN_BOARD_SDA="4", PIN_BOARD_SCL="3", PIN_TFT_RST="18", PIN_TFT_LEDA_CTL="21",
PIN_TFT_CS="15", PIN_TFT_DC="16", PIN_TFT_SCL="17", PIN_TFT_SDA="33").items():
self.assertEqual(flags.get(key), value, key)
for option in ("board", "board_build.partitions", "board_build.flash_mode", "build_src_filter", "lib_deps"):
self.assertEqual(recipes.value(canonical, option), recipes.value(legacy, option), option)
def test_exact_current_configuration_and_packaged_marker_emit_source_bound_metadata(self):
for case in CASES:
with self.subTest(target=case["target"]):
self.assertEqual(consolidated.runtime_metadata(manifest(case), environment(case), SOURCE),
{case["key"]: True, case["key"] + "Source": SOURCE})
self.assertEqual(consolidated.runtime_metadata(manifest(case, proof=False),
environment(case), SOURCE), {},
"Current recipes must not relabel a historical application")
def test_metadata_rejects_unverified_or_wrong_application_evidence(self):
for case in CASES:
base = manifest(case)
invalid_rows = (
{"verified": False}, {"platform": "OTHER_PLATFORM"},
{"target": "other_board_repeater"}, {"verification": []},
{"verification": [{**base["verification"][0], "present": False}]},
{"verification": [{**base["verification"][0], "present": 1}]},
{"verification": [{**base["verification"][0], "source": "linked image"}]},
{"verification": [{**base["verification"][0], "evidence": "a familiar driver name"}]},
{"verification": [{**base["verification"][0], "capability": "other.capability"}]},
)
for changed in invalid_rows:
with self.subTest(target=case["target"], changed=changed), self.assertRaises(ValueError):
consolidated.runtime_metadata({**base, **changed}, environment(case), SOURCE)
def test_metadata_requires_full_matching_release_source(self):
for case in CASES:
for source in (None, "a" * 8, "g" * 40, "A" * 40, "b" * 40):
with self.subTest(target=case["target"], source=source), self.assertRaises(ValueError):
consolidated.runtime_metadata({**manifest(case), "source_commit": source},
environment(case), SOURCE)
for release_source in (None, "a" * 8, "b" * 40):
with self.subTest(target=case["target"], release_source=release_source), self.assertRaises(ValueError):
consolidated.runtime_metadata(manifest(case), environment(case), release_source)
def test_metadata_rejects_unknown_board_and_later_define_or_undefine_overrides(self):
for case in CASES:
with self.subTest(target=case["target"], board="unknown"), self.assertRaises(ValueError):
consolidated.runtime_metadata(manifest(case), {**environment(case), "board": "unknown"}, SOURCE)
for flag in case["flags"]:
key = flag[2:].split("=", 1)[0]
for override in ("-U" + key, "-D" + key + "=0"):
changed = {**environment(case), "build_flags": case["flags"] + [override]}
with self.subTest(target=case["target"], override=override), self.assertRaises(ValueError):
consolidated.runtime_metadata(manifest(case), changed, SOURCE)
def test_replacements_are_limited_to_known_exact_legacy_targets(self):
for case in CASES:
self.assertIn((case["target"], case["key"]), consolidated.replacements(case["legacy"]))
self.assertNotIn((case["target"], case["key"]), consolidated.replacements(case["target"]))
self.assertEqual(consolidated.replacements(case["legacy"] + "_custom"), [])
for target in ("other_PicoW_companion_radio_usb", "heltec_v4_r8_expansionkit_sensor",
"heltec_v4_r8_tft_portrait_sensor_observer_mqtt", "other_without_display_repeater"):
with self.subTest(target=target):
self.assertEqual(consolidated.replacements(target), [])
def test_configuration_replacement_requires_both_known_matching_boards(self):
for case in CASES:
canonical = "env:" + case["target"]
legacy = "env:" + case["legacy"]
envs = {canonical: environment(case), legacy: environment(case)}
self.assertEqual(consolidated.configuration_replacement(case["legacy"], envs), case["target"])
for changed in ({legacy: environment(case)}, {canonical: environment(case)},
{canonical: environment(case), legacy: {**environment(case), "board": "other"}},
{canonical: {**environment(case), "board": "unknown"},
legacy: {**environment(case), "board": "unknown"}}):
with self.subTest(target=case["target"], envs=changed):
self.assertIsNone(consolidated.configuration_replacement(case["legacy"], changed))
def test_configuration_replacement_preserves_candidate_flag_overrides(self):
for case in CASES:
for flag in case["flags"]:
key = flag[2:].split("=", 1)[0]
for override in ("-U" + key, "-D" + key + "=0"):
envs = {"env:" + case["legacy"]: environment(case),
"env:" + case["target"]: {**environment(case),
"build_flags": case["flags"] + [override]}}
with self.subTest(target=case["target"], override=override):
self.assertIsNone(consolidated.configuration_replacement(case["legacy"], envs))
def test_omission_requires_matching_profile_policy_and_real_packaged_successor(self):
for case in CASES:
legacy = record(case, case["legacy"], proof=False)
canonical = record(case)
legacy["manifest"]["capabilities"].append("sensor.profile.full")
canonical["manifest"]["capabilities"].append("sensor.profile.full")
before = deepcopy([legacy, canonical])
for inputs in ([legacy, canonical], [canonical, legacy]):
with self.subTest(target=case["target"], order=[r["manifest"]["target"] for r in inputs]):
self.assertEqual(consolidated.omit_redundant_records(inputs), [canonical])
self.assertEqual([legacy, canonical], before)
self.assertEqual(consolidated.omit_redundant_records([legacy]), [legacy])
for changed in (dict(build_profile="reduced"), dict(verified=False), dict(verification=[]),
dict(platform="OTHER_PLATFORM"), dict(target=case["target"] + "_custom"),
dict(capabilities=[case["capability"], "sensor.profile.reduced"]),
dict(verification=[{**canonical["manifest"]["verification"][0], "source": "linked image"}]),
dict(verification=[{**canonical["manifest"]["verification"][0], "evidence": "other marker"}])):
candidate = {**canonical, "manifest": {**canonical["manifest"], **changed}}
with self.subTest(target=case["target"], changed=changed):
self.assertEqual(consolidated.omit_redundant_records([legacy, candidate]), [legacy, candidate])
def test_historical_manifests_are_never_relabelled_by_current_recipe_defaults(self):
for case in CASES:
legacy, current_name_old_image = record(case, case["legacy"], False), record(case, proof=False)
inputs = [legacy, current_name_old_image]
before = deepcopy(inputs)
self.assertEqual(consolidated.omit_redundant_records(inputs), inputs)
self.assertEqual(inputs, before)
def test_rc32_headless_choice_requires_exact_canonical_autodetection_marker(self):
target, legacy_target = "heltec_rc32_repeater", "heltec_rc32_without_display_repeater"
canonical = dict(manifest=dict(target=target, platform="ESP32_PLATFORM", verified=True,
build_profile="full", capabilities=["display.autodetect"], verification=[dict(
capability="display.autodetect", present=True, source="packaged application",
evidence="meshcore.capability.display.autodetect.rc32.v1")]), files=[target + ".bin"])
legacy = dict(manifest=dict(target=legacy_target, platform="ESP32_PLATFORM", verified=True,
build_profile="full", capabilities=[], verification=[]), files=[legacy_target + ".bin"])
before = deepcopy([legacy, canonical])
self.assertEqual(consolidated.omit_redundant_records([legacy, canonical]), [canonical])
self.assertEqual([legacy, canonical], before)
for changed in (dict(verified=False), dict(platform="NRF52_PLATFORM"), dict(capabilities=[]),
dict(verification=[]), dict(build_profile="reduced"),
dict(capabilities=["display.autodetect", "sensor.profile.reduced"]),
dict(verification=[{**canonical["manifest"]["verification"][0], "source": "linked image"}]),
dict(verification=[{**canonical["manifest"]["verification"][0], "present": False}]),
dict(verification=[{**canonical["manifest"]["verification"][0],
"evidence": "meshcore.capability.display.autodetect.heltec_r8.v1"}])):
candidate = {**canonical, "manifest": {**canonical["manifest"], **changed}}
with self.subTest(changed=changed):
self.assertEqual(consolidated.omit_redundant_records([legacy, candidate]), [legacy, candidate])
self.assertEqual(consolidated.omit_redundant_records([legacy]), [legacy])
def test_rc32_configuration_successor_requires_resolved_auto_display_recipe(self):
target, legacy = "heltec_rc32_companion_radio_full", "heltec_rc32_without_display_companion_radio_full"
flags = ["-DRC32_DISPLAY_AUTODETECT=1", "-DHELTEC_RC32=1", "-DDISPLAY_CLASS=NV3001BDisplay"]
env = dict(board="heltec-rc32", build_flags=flags)
envs = {"env:" + target: env, "env:" + legacy: env}
self.assertEqual(consolidated.configuration_replacement(legacy, envs), target)
for override in ("-URC32_DISPLAY_AUTODETECT", "-DRC32_DISPLAY_AUTODETECT=0",
"-UHELTEC_RC32", "-DHELTEC_RC32=0", "-DDISPLAY_CLASS=NullDisplayDriver"):
changed = {**envs, "env:" + target: {**env, "build_flags": flags + [override]}}
with self.subTest(override=override):
self.assertIsNone(consolidated.configuration_replacement(legacy, changed))
changed = {key: {**value, "board": "unknown"} for key, value in envs.items()}
self.assertIsNone(consolidated.configuration_replacement(legacy, changed))
@unittest.skipIf(os.name == "nt", "Bash release contracts run on Linux/WSL")
def test_bulk_shell_wiring_omits_aliases_preserves_direct_identity_and_demands_application_marker(self):
config = []
setup, checks = [], []
for case in CASES:
for target in (case["target"], case["legacy"]):
config.append(["env:" + target, [["board", case["board"]], ["build_flags", case["flags"]]]])
setup.append("SUPPORTED_PIO_ENVS+=(" + shlex.quote(target) + ")")
for mapping, value in (("PIO_ENV_PLATFORM_BY_NAME", case["platform"]),
("PIO_ENV_BOARD_BY_NAME", case["board"]),
("PIO_ENV_BUILD_BASE_BY_NAME", target)):
setup.append(mapping + "[" + shlex.quote(target) + "]=" + shlex.quote(value))
checks.append("check_choice " + " ".join(shlex.quote(value) for value in (
case["legacy"], case["target"], case["platform"],
case["capability"] + "=" + case["marker"])))
program = r'''
set -euo pipefail
source build.sh
pio() { echo 'PlatformIO must not run in this test' >&2; return 99; }
@SETUP@
ALL_PIO_ENVS=("${SUPPORTED_PIO_ENVS[@]}")
PIO_CONFIG_JSON=@CONFIG@
BUILD_PROFILE_FOR_TARGET=full
check_choice() {
local legacy=$1 canonical=$2 platform=$3 expected=$4
[ "$(get_consolidated_hardware_replacement "$legacy")" = "$canonical" ]
is_redundant_bulk_build_target "$legacy"
is_known_pio_env "$legacy"
[ "$(get_pio_build_env "$legacy")" = "$legacy" ]
! get_consolidated_hardware_replacement "$canonical"
BUILD_APPLICATION_EXPECTATIONS=() BUILD_EXPECTATIONS=() BUILD_CAPABILITIES=() BUILD_REDUCTIONS=()
declare_build_capability_contract "$canonical" "$platform"
[[ " ${BUILD_APPLICATION_EXPECTATIONS[*]} " == *" $expected "* ]]
}
@CHECKS@
PIO_CONFIG_JSON=@OVERRIDDEN@
@OVERRIDE_CHECKS@
'''
overridden = deepcopy(config)
for case in CASES:
row = next(row for row in overridden if row[0] == "env:" + case["target"])
row[1][1][1].append("-U" + case["flags"][0][2:].split("=", 1)[0])
program = program.replace("@SETUP@", "\n".join(setup))
program = program.replace("@CHECKS@", "\n".join(checks))
program = program.replace("@CONFIG@", shlex.quote(json.dumps(config)))
program = program.replace("@OVERRIDDEN@", shlex.quote(json.dumps(overridden)))
program = program.replace("@OVERRIDE_CHECKS@", "\n".join(
"! get_consolidated_hardware_replacement " + shlex.quote(case["legacy"]) for case in CASES))
result = subprocess.run(["bash", "-c", program], cwd=ROOT, capture_output=True, text=True, timeout=30)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
def test_actual_controls_generator_requires_packaged_proof_from_its_exact_config(self):
import generate_picker_controls as controls
family = "v1.18.0.1.preview1-aaaaaaaa"
with tempfile.TemporaryDirectory(prefix="consolidated-controls-") as folder:
stage = Path(folder)
(stage / "companion").mkdir()
(stage / "release-plan.json").write_text(json.dumps(dict(
source=SOURCE, groups=[dict(key="companion", tag=family)])))
path = stage / "companion/TARGET-MANIFEST.json"
for case in CASES:
row = manifest(case)
row.update(platformio_env=case["target"], files=[case["target"] + "-" + family + ".bin"])
path.write_text(json.dumps([row]))
config = [["env:" + case["target"], [["board", case["board"]], ["build_flags", case["flags"]]]]]
profile = controls.generate(stage, config)["profiles"][case["target"]]
self.assertIs(profile[case["key"]], True)
self.assertEqual(profile[case["key"] + "Source"], SOURCE)
changed = deepcopy(config)
changed[0][1][1][1].append("-U" + case["flags"][0][2:].split("=", 1)[0])
with self.subTest(target=case["target"], reason="overridden recipe"), self.assertRaises(ValueError):
controls.generate(stage, changed)
row["verification"] = []
path.write_text(json.dumps([row]))
with self.subTest(target=case["target"], reason="missing packaged evidence"), self.assertRaises(ValueError):
controls.generate(stage, config)
row["capabilities"] = []
path.write_text(json.dumps([row]))
historical = controls.generate(stage, config)["profiles"][case["target"]]
self.assertNotIn(case["key"], historical)
self.assertNotIn(case["key"] + "Source", historical)
def test_generated_accessory_full_targets_require_exact_radio_board_and_optional_display_recipe(self):
for case in ACCESSORY_CASES:
canonical = case["base"] + "_companion_radio_full"
for base_role in ("usb", "ble"):
canonical_base = case["base"] + "_companion_radio_" + base_role
legacy_base = case["legacy"] + "_companion_radio_" + base_role
env = dict(board=case["board"], build_flags=case["flags"])
envs = {"env:" + canonical_base: env, "env:" + legacy_base: env}
for role in case["roles"]:
target = case["legacy"] + "_companion_radio_" + role
# A BLE request needs its real BLE source; generated Full
# can resolve either attached-transport source recipe.
role_envs = {**envs, "env:" + target: env} if role != "full" else envs
with self.subTest(target=target, canonical_base=canonical_base):
self.assertEqual(consolidated.configuration_replacement(target, role_envs), canonical)
for changed in (
{**env, "board": "unknown"},
{**env, "build_flags": case["flags"] + ["-U" + case["flag"]]},
{**env, "build_flags": case["flags"] + ["-D" + case["flag"] + "=0"]},
{**env, "build_flags": case["flags"] + ["-DDISPLAY_CLASS=NullDisplayDriver"]}):
invalid = {**role_envs, "env:" + canonical_base: changed}
with self.subTest(target=target, changed=changed):
self.assertIsNone(consolidated.configuration_replacement(target, invalid))
if case["base"].startswith("muzi_base_"):
other = next(row for row in ACCESSORY_CASES if row["board"] == "muzi_base"
and row["base"] != case["base"])
wrong_radio = {**envs, "env:" + canonical_base: dict(board=case["board"], build_flags=other["flags"])}
with self.subTest(target=canonical, wrong_radio=other["base"]):
self.assertIsNone(consolidated.configuration_replacement(
case["legacy"] + "_companion_radio_full", wrong_radio))
other_name = other["base"] + "_companion_radio_" + base_role
different_hardware = {"env:" + other_name: env, "env:" + legacy_base: env}
self.assertIsNone(consolidated.configuration_replacement(
case["legacy"] + "_companion_radio_full", different_hardware))
def test_accessory_full_omission_requires_packaged_display_and_both_linked_transports(self):
for case in ACCESSORY_CASES:
canonical_target = case["base"] + "_companion_radio_full"
display = dict(capability="display.autodetect", present=True, source="packaged application",
evidence="meshcore.capability.display.autodetect." + case["marker"] + ".v1")
transport = [dict(capability=key, present=True, source="linked image", evidence=symbol)
for key, symbol in (("companion.usb", "+++MESHCORE-TERM-START"),
("companion.bluetooth", "Companion: starting Bluetooth"))]
canonical = dict(manifest=dict(target=canonical_target, platform="NRF52_PLATFORM", verified=True,
build_profile="full", capabilities=["display.autodetect", "companion.usb", "companion.bluetooth"],
verification=[display, *transport]), files=[canonical_target + ".uf2"])
for role in case["roles"]:
target = case["legacy"] + "_companion_radio_" + role
legacy = dict(manifest=dict(target=target, platform="NRF52_PLATFORM", verified=True,
build_profile="full" if role == "full" else "standard", capabilities=[], verification=[]),
files=[target + ".uf2"])
before = deepcopy([legacy, canonical])
with self.subTest(target=target):
self.assertEqual(consolidated.omit_redundant_records([legacy, canonical]), [canonical])
self.assertEqual([legacy, canonical], before)
self.assertEqual(consolidated.omit_redundant_records([legacy]), [legacy])
invalid = [dict(verified=False), dict(platform="ESP32_PLATFORM"), dict(verification=[]),
dict(capabilities=["companion.usb", "companion.bluetooth"]),
dict(verification=[{**display, "source": "linked image"}, *transport]),
dict(verification=[{**display, "evidence": "meshcore.capability.display.autodetect.rc32.v1"}, *transport])]
for key in ("companion.usb", "companion.bluetooth"):
invalid.append(dict(capabilities=[cap for cap in canonical["manifest"]["capabilities"] if cap != key]))
for change in (dict(present=False), dict(source="packaged application"), dict(evidence="")):
invalid.append(dict(verification=[{**row, **change} if row["capability"] == key else row
for row in canonical["manifest"]["verification"]]))
if role == "full":
invalid.append(dict(build_profile="standard"))
if case["base"].startswith("muzi_base_"):
other = "muzi_base_duo" if case["base"] == "muzi_base_uno" else "muzi_base_uno"
invalid.append(dict(target=other + "_companion_radio_full"))
for changed in invalid:
candidate = {**canonical, "manifest": {**canonical["manifest"], **changed}}
with self.subTest(target=target, changed=changed):
self.assertEqual(consolidated.omit_redundant_records([legacy, candidate]), [legacy, candidate])
if __name__ == "__main__":
unittest.main()