import hashlib import json import subprocess import sys import tempfile import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] MANIFEST = json.loads((ROOT / "manifest.json").read_text())["files"] SCRIPT = ROOT / "scripts/apply.py" class ApplyPatchTests(unittest.TestCase): def setUp(self): self.temp = tempfile.TemporaryDirectory() self.site = Path(self.temp.name) for name in MANIFEST: target = self.site / name target.parent.mkdir(parents=True, exist_ok=True) target.write_bytes((ROOT / "upstream" / name).read_bytes()) def tearDown(self): self.temp.cleanup() def command(self, action): return subprocess.run( [sys.executable, str(SCRIPT), action, "--site-packages", str(self.site)], capture_output=True, text=True, ) def test_apply_is_idempotent_and_rollback_restores_originals(self): self.assertEqual(self.command("--check").returncode, 0) for _ in range(2): result = self.command("--apply") self.assertEqual(result.returncode, 0, result.stderr) for name, hashes in MANIFEST.items(): target = self.site / name self.assertEqual(hashlib.sha256(target.read_bytes()).hexdigest(), hashes["patched_sha256"]) backup = target.with_name(target.name + ".ppu-dsv4.orig") self.assertEqual(hashlib.sha256(backup.read_bytes()).hexdigest(), hashes["original_sha256"]) result = self.command("--rollback") self.assertEqual(result.returncode, 0, result.stderr) for name, hashes in MANIFEST.items(): self.assertEqual(hashlib.sha256((self.site / name).read_bytes()).hexdigest(), hashes["original_sha256"]) def test_unknown_base_refuses_before_any_file_is_changed(self): changed = self.site / next(iter(MANIFEST)) changed.write_bytes(b"unexpected version\n") result = self.command("--apply") self.assertNotEqual(result.returncode, 0) self.assertIn("does not match", result.stderr) for name, hashes in list(MANIFEST.items())[1:]: self.assertEqual(hashlib.sha256((self.site / name).read_bytes()).hexdigest(), hashes["original_sha256"]) if __name__ == "__main__": unittest.main()