Files
MeshCore/test/test_room_web_gzip.py
T
mikecarper 21194b9825 Fix compile and capacity blockers in the full release matrix
Resolve Serial macro and ESP-NOW wrapper compilation errors. Preserve queue, neighbor, advert-history and Room post capacities while using qualified RTC, PSRAM and word-only IRAM storage on constrained ESP32 targets. Reduce Full infrastructure flash through lossless Room web compression, compact crypto and unused exception metadata removal.

Add focused native regressions for storage ownership, exact protocol output, OTA proofs and build policy. Keep physical flash sizes, OTA slots and RAM guard formulas unchanged.
2026-10-24 05:38:23 -07:00

79 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""Verify exact page identity, generation recovery and role-owned resources."""
import gzip
import importlib.util
from pathlib import Path
import shutil
import subprocess
import sys
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts"))
from generate_room_web_html import generate, page_bytes, render, source_page, SOURCE, OUTPUT
from test_replay_reset_integration import extract_braced
class RoomWebGzipTests(unittest.TestCase):
def test_checked_in_page_preserves_every_source_byte(self):
raw = source_page((ROOT / SOURCE).read_text(encoding="ascii"))
packed = page_bytes((ROOT / OUTPUT).read_text(encoding="ascii"))
self.assertEqual(gzip.decompress(packed), raw)
self.assertLess(len(packed), len(raw) // 3)
self.assertFalse(generate(ROOT, check=True))
def test_stale_and_corrupt_assets_fail_check_and_regenerate_idempotently(self):
with tempfile.TemporaryDirectory() as name:
root = Path(name)
(root / SOURCE).parent.mkdir(parents=True)
(root / SOURCE).write_text('static const char ROOM_WEB_HTML[] PROGMEM = R"roomhtml(<title>Room test</title>)roomhtml";\n')
with self.assertRaises(ValueError):
generate(root, check=True)
self.assertTrue(generate(root))
first = (root / OUTPUT).read_bytes()
self.assertFalse(generate(root))
self.assertEqual((root / OUTPUT).read_bytes(), first)
(root / OUTPUT).write_bytes(first.replace(b"0x1f,", b"0x00,", 1))
with self.assertRaises(ValueError):
generate(root, check=True)
self.assertTrue(generate(root))
self.assertEqual((root / OUTPUT).read_bytes(), first)
(root / SOURCE).write_text((root / SOURCE).read_text().replace("Room test", "Room changed"))
with self.assertRaises(ValueError):
generate(root, check=True)
self.assertTrue(generate(root))
self.assertIn(b"Room changed", gzip.decompress(page_bytes((root / OUTPUT).read_text())))
def test_renderer_refuses_a_different_page(self):
with self.assertRaises(ValueError):
render(b"expected", gzip.compress(b"different", mtime=0))
with self.assertRaises(ValueError):
source_page("missing constant")
def test_only_room_role_owns_page_and_default_callback_links_without_it(self):
shared = (ROOT / "src/helpers/esp32/WebConfigServer.cpp").read_text()
self.assertNotIn('#include "RoomWebHtml', shared)
header = (ROOT / "src/helpers/esp32/WebConfigServer.h").read_text()
callback = extract_braced(header, "virtual const uint8_t* roomPageGzip(")
room = (ROOT / "examples/simple_room_server/MyMesh.cpp").read_text()
provider = extract_braced(room, "const uint8_t* MyMesh::roomPageGzip(")
self.assertIn('sizeof(ROOM_WEB_HTML_GZ)', provider)
# Compile the real default callback and prove that a non-Room role
# needs no page header or storage while still answering safely.
compiler = shutil.which("g++")
self.assertIsNotNone(compiler)
with tempfile.TemporaryDirectory() as directory:
source = Path(directory) / "default.cpp"
source.write_text('#include <cstddef>\n#include <cstdint>\n#include <cassert>\nstruct Callback {\n'
+ callback + '\n};\nint main() { Callback c; size_t n=99; assert(c.roomPageGzip(n)==nullptr && n==0); }\n')
binary = source.with_suffix("")
subprocess.run([compiler, "-std=c++11", "-Os", str(source), "-o", str(binary)], check=True)
subprocess.run([str(binary)], check=True)
symbols = subprocess.check_output(["nm", "-C", str(binary)], text=True)
self.assertNotIn("ROOM_WEB_HTML", symbols)
if __name__ == "__main__":
unittest.main()