Files
ESP32_Serial_Swiss_Army_Knife/tools/idf_candidate/test_prepare.py
T
Commander1024 797d2681ac Migrate to IDF 5.5.3 candidate
Pin PlatformIO packages and toolchains, rebase protected SDK
overrides, and add WebSocket receive regression coverage. Document
isolated candidate validation, archive provenance, and remaining gates.
2026-09-18 14:23:13 +02:00

99 lines
4.6 KiB
Python

"""Offline fail-closed helper checks; does not download/install/build."""
import hashlib
import io
import pathlib
import tarfile
import tempfile
import unittest
import json
from unittest import mock
import stage_app
import prepare
class Contracts(unittest.TestCase):
def test_hash_and_size(self):
with tempfile.TemporaryDirectory() as directory:
path = pathlib.Path(directory) / "artifact"
path.write_bytes(b"candidate")
item = {"size": 9, "checksum": {"sha256": hashlib.sha256(b"candidate").hexdigest()}}
prepare.verify(path, item)
path.write_bytes(b"Candidate")
with self.assertRaises(ValueError):
prepare.verify(path, item)
path.write_bytes(b"candidate-extra")
with self.assertRaises(ValueError):
prepare.verify(path, item)
def test_network_allowlist(self):
prepare.check_url("https://dl.registry.platformio.org/download/a")
prepare.check_url("https://dl.registry.nm1.platformio.org/download/a")
for url in ("http://dl.registry.platformio.org/a", "https://example.com/a", "https://dl.registry.platformio.org.evil/a"):
with self.assertRaises(ValueError):
prepare.check_url(url)
def test_contract_failure(self):
with self.assertRaises(ValueError):
prepare.require(False)
def test_member_ambiguity(self):
stream = io.BytesIO()
with tarfile.open(fileobj=stream, mode="w") as archive:
for name in ("package.json", "./package.json"):
entry = tarfile.TarInfo(name)
entry.size = 2
archive.addfile(entry, io.BytesIO(b"{}"))
stream.seek(0)
with tarfile.open(fileobj=stream) as archive:
with self.assertRaises(ValueError):
prepare.member(archive, "package.json")
with self.assertRaises(ValueError):
prepare.member(archive, "missing")
class Staging(unittest.TestCase):
def test_fresh_snapshot_and_manifest(self):
with tempfile.TemporaryDirectory() as directory:
root = pathlib.Path(directory)
base = root / ".pio/idf-candidate-5.5.3"
base.mkdir(parents=True)
(base / "app").mkdir()
(base / "app/sentinel").write_text("old")
(root / "platformio.ini").write_text("[platformio]\nplatform = platformio/espressif32@6.13.0\n")
(root / "src").mkdir()
(root / "src/main.c").write_text("modified working tree")
(root / "src/secret").write_text("never copy")
ws = root / "tests/sdk_security_overrides/ws.c"
ws.parent.mkdir(parents=True)
ws.write_text("explicit fixture")
items = [{"package": "platformio/platform/espressif32", "version": "6.13.0", "name": "platform.tar.gz"}]
with mock.patch.object(stage_app.subprocess, "check_output", return_value=b"platformio.ini\0src/main.c\0"):
dest = stage_app.stage("app-validated", root, base, items)
manifest = json.loads((dest / "app-source-manifest.json").read_text())
for name, digest in manifest.items():
self.assertEqual(hashlib.sha256((dest / name).read_bytes()).hexdigest(), digest)
self.assertIn(str(base / "core"), (dest / "platformio.ini").read_text())
self.assertEqual((dest / "src/main.c").read_text(), "modified working tree")
self.assertTrue((dest / "tests/sdk_security_overrides/ws.c").exists())
self.assertFalse((dest / "src/secret").exists())
self.assertEqual((base / "app/sentinel").read_text(), "old")
for name in ("app", "app-validated"):
with self.assertRaises(FileExistsError):
stage_app.stage(name, root, base, items)
for name in ("../escape", "/tmp/escape", "", ".", "..", "app/nested"):
with self.assertRaises(ValueError):
stage_app.stage(name, root, base, items)
(base / "linked").symlink_to(root, target_is_directory=True)
with self.assertRaises(ValueError):
stage_app.stage("linked", root, base, items)
(root / "src/main.c").unlink()
(root / "src/main.c").symlink_to(root / "platformio.ini")
with self.assertRaises(ValueError):
stage_app.stage("unsafe", root, base, items)
self.assertFalse((base / "unsafe").exists())
if __name__ == "__main__":
unittest.main()