Files
MeshCore/test/test_rak_combined_build_config.py
T

105 lines
5.4 KiB
Python

#!/usr/bin/env python3
"""Keep experimental RAK configs matched and separate from release recipes."""
import configparser
import hashlib
import importlib.util
import json
import os
from pathlib import Path
import re
import shlex
import subprocess
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "scripts/generate_rak4631_combined_test.py"
SPEC = importlib.util.spec_from_file_location("rak_combined_config", SCRIPT)
generator = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(generator)
def ini(path):
result = configparser.ConfigParser(interpolation=None)
result.read(path)
return result
class RakCombinedBuildConfigTest(unittest.TestCase):
def test_matching_profiles_preserve_identity_and_never_run_platformio(self):
original = (ROOT / "platformio.ini").read_bytes()
variant = (ROOT / "variants/rak4631/platformio.ini").read_bytes()
base_flags = shlex.split(ini(ROOT / "platformio.ini")["nrf52_base"]["build_flags"])
base_optimizers = [flag for flag in base_flags
if re.fullmatch(r"-O(?:[0-3sgz]|fast)", flag)]
self.assertTrue(base_optimizers)
self.assertEqual(base_optimizers[-1], "-Oz")
with tempfile.TemporaryDirectory(prefix="meshcore-rak-config-") as temp:
directory = Path(temp)
marker = directory / "unexpected-platformio"
fake_pio = directory / "pio"
fake_pio.write_text("#!/bin/sh\ntouch " + shlex.quote(str(marker)) + "\nexit 91\n")
fake_pio.chmod(0o755)
output = directory / "generated configs"
result = subprocess.run(["python3", str(SCRIPT), "--output", str(output)],
cwd=ROOT, text=True, capture_output=True,
env={**os.environ, "PATH": str(directory) + os.pathsep + os.environ["PATH"]})
self.assertEqual(result.returncode, 0, result.stderr)
self.assertFalse(marker.exists(), "config generation invoked PlatformIO")
receipt = json.loads((output / "profile-flags.json").read_text())
self.assertEqual(receipt["loop_stack_bytes"], 8192)
self.assertEqual(receipt["full_rule_capacity"], 63)
self.assertEqual(receipt["mota_target_id"], "0x05f5ffae")
self.assertEqual(len(result.stdout.splitlines()), 4)
for item in receipt["configs"]:
name = item["profile"]
config_path = Path(item["config"])
config = ini(config_path)
overlay_path = output / ("overlay-" + name + ".ini")
overlay = ini(overlay_path)["env:" + receipt["target"]]
flags = overlay["build_flags"]
self.assertIn("-DMOTA_TARGET_ID=0x05f5ffae", flags)
self.assertIn("-D MAX_NEIGHBOURS=50", flags)
self.assertNotIn("FLOOD_PACKET_FILTER_SLOTS", flags)
self.assertIn("-Ofast", overlay["build_unflags"])
self.assertEqual([flag for flag in shlex.split(flags)
if re.fullmatch(r"-O(?:[0-3sgz]|fast)", flag)], [],
"trial overlays must inherit canonical -Oz without overriding it")
self.assertIn("-DLORA_FREQ=910.525", flags)
self.assertIn(str(overlay_path), config["platformio"]["extra_configs"])
self.assertEqual(hashlib.sha256(config_path.read_bytes()).hexdigest(), item["config_sha256"])
combined = name.startswith("combined")
self.assertEqual("-DRAK4631_COMBINED_ETHERNET=1" in flags, combined)
self.assertEqual("-DETHERNET_ENABLED=1" in flags, combined)
self.assertEqual("lib_deps" in overlay, combined)
if combined:
self.assertIn(generator.ETHERNET_LIBRARY, overlay["lib_deps"])
reduced = name.endswith("reduced")
self.assertEqual("-UENV_INCLUDE_BME680_BSEC" in flags, reduced)
if reduced:
self.assertIn("-DENV_INCLUDE_INA219=1", flags)
self.assertIn("${rak4631.build_flags}", flags)
self.assertNotIn("-UENV_INCLUDE_GPS", flags)
self.assertNotIn("ENV_INCLUDE_GPS", overlay["build_unflags"])
# GPS comes from the inherited full sensor base; the
# reduction never removes or overrides that driver.
self.assertIn("-D ENV_INCLUDE_GPS=1", ini(ROOT / "platformio.ini")["sensor_base"]["build_flags"])
self.assertEqual((ROOT / "platformio.ini").read_bytes(), original)
self.assertEqual((ROOT / "variants/rak4631/platformio.ini").read_bytes(), variant)
def test_rejects_release_output_and_invalid_version_before_writing(self):
with self.assertRaisesRegex(ValueError, "outside the repository"):
generator.generate(ROOT / "out" / "unexpected-trial", "v1.17.1.9-test")
with tempfile.TemporaryDirectory() as temp:
output = Path(temp) / "configs"
for version in ("", "v1\n-DOTHER=1", 'v1"bad', "v1;bad", "v1$(bad)"):
with self.subTest(version=version), self.assertRaisesRegex(ValueError, "firmware version"):
generator.generate(output, version)
self.assertFalse(output.exists())
if __name__ == "__main__":
unittest.main()