Files
RustRaptor/tools/test_runtime_archives.py

83 lines
4.0 KiB
Python

"""Small archive fixtures; no game build or production data copy required."""
import hashlib
from pathlib import Path
import tempfile
import unittest
import zipfile
from assemble_runtime import iter_archive_files
class RuntimeArchiveTests(unittest.TestCase):
def test_manifest_derived_payload_survives_cache_filter_and_relocation(self):
with tempfile.TemporaryDirectory() as directory:
package = Path(directory) / "package"
payload = "data/hd/jobs/reviewed-family/derived/200a2-derived.png"
required = ["data/INDEX", "data/hd/hd.json", payload]
fixtures = {
"data/INDEX": b"catalog",
"data/hd/hd.json": b"manifest",
payload: b"accepted derived PNG bytes",
"data/hd/jobs/reviewed-family/derived/rejected-preview.png": b"not admitted",
"derived/preview.png": b"private cache",
"target/build-cache": b"build",
".reference/private": b"private",
"mods/demo/art/source/parent.png": b"authoring reference",
"mods/demo/art/runtime.png": b"mod runtime",
"bin/raptor-rust": b"Linux only",
"bin/raptor-rust.exe": b"Windows",
}
for name, data in fixtures.items():
path = package / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(data)
archive = Path(directory) / "windows.zip"
skipped = {"target", "dist", ".reference", "derived", "lib"}
selected = list(iter_archive_files(
package, archive, skipped, excluded_files=(Path("bin/raptor-rust"),),
required_files=required))
names = {path.relative_to(package).as_posix() for path in selected}
self.assertTrue(set(required) <= names)
self.assertEqual(names - set(required), {"mods/demo/art/runtime.png", "bin/raptor-rust.exe"})
with zipfile.ZipFile(archive, "w") as output:
for path in selected:
output.write(path, "RustRaptor/" + path.relative_to(package).as_posix())
relocated = Path(directory) / "Portable Windows Ω folder"
with zipfile.ZipFile(archive) as packed:
packed.extractall(relocated)
for name in required:
original = package / name
copied = relocated / "RustRaptor" / name
self.assertEqual(hashlib.sha256(copied.read_bytes()).digest(),
hashlib.sha256(original.read_bytes()).digest())
def test_missing_manifest_payload_fails_before_yielding_files(self):
with tempfile.TemporaryDirectory() as directory:
package = Path(directory)
with self.assertRaises(FileNotFoundError):
next(iter_archive_files(package, package / "out.zip", {"derived"},
required_files=["data/hd/missing.png"]))
def test_explicit_exclusion_cannot_silently_drop_manifest_payload(self):
with tempfile.TemporaryDirectory() as directory:
package = Path(directory)
path = package / "data/required"
path.parent.mkdir()
path.write_bytes(b"required")
with self.assertRaisesRegex(ValueError, "missing required files"):
list(iter_archive_files(package, package / "out.zip", set(),
excluded_files=(Path("data/required"),),
required_files=["data/required"]))
def test_manifest_path_cannot_escape_package(self):
with tempfile.TemporaryDirectory() as directory:
package = Path(directory)
for name in ("../outside", str(package / "absolute")):
with self.subTest(name=name), self.assertRaises(ValueError):
list(iter_archive_files(package, package / "out.zip", set(),
required_files=[name]))
if __name__ == "__main__":
unittest.main()