# SPDX-License-Identifier: MPL-2.0
import gzip
import importlib.util
import json
from pathlib import Path
import stat
import struct
import subprocess
import sys
import tempfile
import unittest
from unittest.mock import patch
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "tools"))
import tundra
spec = importlib.util.spec_from_file_location("collector", tundra.ROOT / "tools/collect-device.py")
collector = importlib.util.module_from_spec(spec)
spec.loader.exec_module(collector)
class PackagingTests(unittest.TestCase):
def test_cpio_roundtrip_and_reproducibility(self):
entries = [("dev", stat.S_IFDIR | 0o755, b"", 0, 0),
("dev/console", stat.S_IFCHR | 0o600, b"", 5, 1),
("init", stat.S_IFREG | 0o755, b"init-payload", 0, 0)]
a = tundra.cpio(entries)
self.assertEqual(a, tundra.cpio(entries))
data = gzip.decompress(a)
cursor = 0
decoded = {}
while True:
self.assertEqual(data[cursor:cursor + 6], b"070701")
fields = [int(data[cursor + 6 + 8 * n:cursor + 14 + 8 * n], 16) for n in range(13)]
cursor += 110
name = data[cursor:cursor + fields[11] - 1].decode()
cursor = (cursor + fields[11] + 3) & ~3
payload = data[cursor:cursor + fields[6]]
cursor = (cursor + fields[6] + 3) & ~3
if name == "TRAILER!!!":
break
decoded[name] = (fields, payload)
self.assertEqual(decoded["init"][1], b"init-payload")
self.assertEqual(decoded["dev/console"][0][9:11], [5, 1])
self.assertEqual(decoded["init"][0][1], stat.S_IFREG | 0o755)
# Independent parser: GNU cpio, never extract a device node onto the host.
p = subprocess.run(["cpio", "-it"], input=data, capture_output=True, check=True)
self.assertIn(b"dev/console", p.stdout)
self.assertIn(b"init", p.stdout)
def test_cpio_rejects_escape(self):
for name in ("/init", "../init", "dev/../../init"):
with self.assertRaises(ValueError):
tundra.cpio([(name, stat.S_IFREG | 0o755, b"", 0, 0)])
def test_manifest_inheritance_and_cycle(self):
with tempfile.TemporaryDirectory() as d:
root = Path(d)
(root / "main.xml").write_text('')
(root / "sub.xml").write_text('')
self.assertEqual(tundra.flatten_manifest(root, "main.xml"),
[{"path": "src/kernel", "url": "https://example.org/kernel", "revision": "tag"}])
(root / "sub.xml").write_text('')
with self.assertRaises(ValueError):
tundra.flatten_manifest(root, "main.xml")
def test_sargo_boot_roundtrip(self):
folder = tundra.ROOT / "out/sargo-stage0"
metadata_file = folder / "image.json"
if not metadata_file.exists():
self.skipTest("Run ./tundra prepare-sargo first")
info = json.loads(metadata_file.read_text())
image = folder / info["file"]
self.assertEqual(tundra.digest(image), info["sha256"])
self.assertFalse(info["flashReady"])
with tempfile.TemporaryDirectory() as d:
subprocess.run([sys.executable, str(tundra.checked_source("aosp-mkbootimg") / "unpack_bootimg.py"),
"--boot_img", str(image), "--out", d], check=True, capture_output=True)
self.assertEqual((Path(d) / "ramdisk").read_bytes(), (folder / "initramfs.cpio.gz").read_bytes())
kernel = tundra.ROOT / "downloads/aosp-sargo-kernel" / info["kernelSource"]["commit"] / "Image.lz4-dtb"
self.assertEqual(tundra.digest(Path(d) / "kernel"), tundra.digest(kernel))
self.assertEqual(struct.unpack_from("