from __future__ import annotations import importlib.util import os import sys from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] SCRIPT = ROOT / "scripts" / "release_backup_snapshot.py" def load_snapshot_module(): spec = importlib.util.spec_from_file_location("release_backup_snapshot_test", SCRIPT) assert spec is not None and spec.loader is not None module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module) return module def test_snapshot_is_byte_complete_and_reuses_only_verified_backup_bytes(tmp_path: Path) -> None: snapshot = load_snapshot_module() source = tmp_path / "source" source.mkdir() (source / "same.bin").write_bytes(b"unchanged") (source / "changed.bin").write_bytes(b"before") (source / "empty").mkdir() prior = tmp_path / "prior" prior_manifest = tmp_path / "prior.tsv" snapshot.create_snapshot(source, prior, prior_manifest, label="storage") snapshot.verify_snapshot(prior, prior_manifest) (source / "changed.bin").write_bytes(b"after") current = tmp_path / "current" current_manifest = tmp_path / "current.tsv" snapshot.create_snapshot( source, current, current_manifest, label="storage", link_dest_snapshot=prior, link_dest_manifest=prior_manifest, ) snapshot.verify_snapshot(current, current_manifest) assert os.path.samefile(prior / "same.bin", current / "same.bin") assert not os.path.samefile(prior / "changed.bin", current / "changed.bin") assert (current / "changed.bin").read_bytes() == b"after" assert (current / "empty").is_dir() def test_snapshot_rejects_symlinked_content(tmp_path: Path) -> None: snapshot = load_snapshot_module() source = tmp_path / "source" source.mkdir() target = source / "target.bin" target.write_bytes(b"target") try: (source / "link.bin").symlink_to(target) except OSError: pytest.skip("Symlink creation is unavailable on this host") with pytest.raises(RuntimeError, match="refuses symlinked content"): snapshot.create_snapshot(source, tmp_path / "snapshot", tmp_path / "manifest.tsv", label="storage") def test_snapshot_verification_rejects_changed_retained_bytes(tmp_path: Path) -> None: snapshot = load_snapshot_module() source = tmp_path / "source" source.mkdir() (source / "artifact.bin").write_bytes(b"retained") retained = tmp_path / "snapshot" manifest = tmp_path / "manifest.tsv" snapshot.create_snapshot(source, retained, manifest, label="storage") (retained / "artifact.bin").chmod(0o644) (retained / "artifact.bin").write_bytes(b"tampered") with pytest.raises(RuntimeError, match="checksum differs"): snapshot.verify_snapshot(retained, manifest)