Files
MeshCore/test/test_wifi_compatibility.py
T

71 lines
3.0 KiB
Python

#!/usr/bin/env python3
"""Execute production ESP32 compatibility settings with NVS and SDK faults."""
from pathlib import Path
import os
import shutil
import subprocess
import sys
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
FIXTURE = ROOT / "test/fixtures/wifi_compatibility"
SANITIZERS = (["-fsanitize=address,undefined", "-fno-sanitize-recover=all",
"-fno-pie", "-no-pie"] if sys.platform.startswith("linux") else [])
ORDINARY = ("defaults", "parse", "protocol_reboot", "mode_reboot", "corrupt",
"invalid", "unloaded", "open_failure", "write_failure", "verify_failure",
"independent", "bg_ap", "bg_ap_race", "bg_lr_start", "owner_conflict",
"driver_failure")
class WiFiCompatibilityTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
compiler = os.environ.get("CXX") or shutil.which("g++") or shutil.which("clang++")
if compiler is None:
raise unittest.SkipTest("a host C++17 compiler is required")
cls.directory = tempfile.TemporaryDirectory(prefix="meshcore-wifi-compat-")
cls.addClassCleanup(cls.directory.cleanup)
cls.binaries = {}
for kind, flags in (
("ordinary", []),
("bridge", ["-DWITH_ESPNOW_BRIDGE=1"]),
("primary", ["-DMESH_PRIMARY_ESPNOW=1"]),
("primary_full", ["-DMESH_PRIMARY_ESPNOW=1", "-DMESH_ESPNOW_RADIO=1"]),
):
binary = Path(cls.directory.name) / (kind + ".exe")
compiled = subprocess.run(
[compiler, "-std=c++17", "-Wall", "-Wextra", "-Werror", *SANITIZERS,
"-DESP32=1", *flags, f"-I{FIXTURE}", f"-I{ROOT / 'src'}",
str(FIXTURE / "test.cpp"), "-o", str(binary)],
capture_output=True, text=True)
if compiled.returncode:
raise AssertionError(compiled.stdout + compiled.stderr)
cls.binaries[kind] = binary
def run_case(self, name, kind="ordinary"):
result = subprocess.run([str(self.binaries[kind]), name], capture_output=True, text=True)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
def test_ordinary_settings(self):
for scenario in ORDINARY:
with self.subTest(scenario=scenario):
self.run_case(scenario)
def test_bridge_build_preserves_normal_and_can_use_bg_when_not_running(self):
for scenario in ORDINARY:
with self.subTest(scenario=scenario):
self.run_case(scenario, "bridge")
def test_primary_espnow_preserves_lr_and_rejects_bg_without_mutation(self):
for kind in ("primary", "primary_full"):
for scenario in ("defaults", "parse", "mode_reboot", "corrupt", "invalid",
"unloaded", "open_failure", "write_failure", "verify_failure",
"primary_conflict"):
with self.subTest(kind=kind, scenario=scenario):
self.run_case(scenario, kind)
if __name__ == "__main__":
unittest.main()