#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-only """Assemble two real bundles in temporary directories and verify every byte.""" import argparse import hashlib import json from pathlib import Path import subprocess import sys import tempfile PROJECT = Path(__file__).absolute().parents[2] def contents(root): return {p.relative_to(root).as_posix(): p.read_bytes() for p in root.rglob("*") if p.is_file()} def validate(files, catalog_data): manifest = json.loads(files["manifest.json"]) catalog = json.loads(catalog_data) assert manifest["catalog_sha256"] == hashlib.sha256(catalog_data).hexdigest() assert manifest["snapshot"] == catalog["snapshot"] assert len(manifest["inputs"]) == len(catalog["inputs"]) expected_entries = {(x["root"], x["path"]): x for x in catalog["inputs"]} expected_files = {"manifest.json"} seen = set() for entry in manifest["inputs"]: key = (entry["root"], entry["path"]) assert key not in seen seen.add(key) original = expected_entries[key] assert {k: entry[k] for k in original} == original path = "inputs/" + entry["root"] + "/" + entry["path"] if entry["range"] is not None: path += ".notice.txt" assert entry["output"] == path expected_files.add(path) data = files[path] assert len(data) == entry["output_size"] assert hashlib.sha256(data).hexdigest() == entry["output_sha256"] assert seen == set(expected_entries) assert len(manifest["generated"]) == 1 assert manifest["generated"][0]["path"] == "README.txt" for entry in manifest["generated"]: expected_files.add(entry["path"]) data = files[entry["path"]] assert len(data) == entry["size"] assert hashlib.sha256(data).hexdigest() == entry["sha256"] assert set(files) == expected_files, "unexpected or missing bundle files" return len(manifest["inputs"]) def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--sdk-root", type=Path, required=True) parser.add_argument("--toolchain-root", type=Path, required=True) args = parser.parse_args() catalog = (PROJECT / "third_party/release-notices/inputs.json").read_bytes() with tempfile.TemporaryDirectory(prefix="actual-release-notices-") as temporary: base = Path(temporary) outputs = [] for name in ("first", "second"): output = base / name subprocess.run([ sys.executable, str(PROJECT / "tools/release_notices.py"), "--sdk-root", str(args.sdk_root), "--toolchain-root", str(args.toolchain_root), "--output", str(output), ], check=True, timeout=60) files = contents(output) count = validate(files, catalog) outputs.append(files) assert outputs[0] == outputs[1], "bundle names/bytes differ" files = outputs[0] print(f"PASS: two actual bundles; {count} inputs; {len(files)} files; " f"{sum(map(len, files.values()))} bytes; all payloads verified and deterministic") print("manifest SHA-256:", hashlib.sha256(files["manifest.json"]).hexdigest()) return 0 if __name__ == "__main__": sys.exit(main())