#!/usr/bin/env python3 """Создаёт и проверяет fixture отмены рекурсивного F5.""" from __future__ import annotations import pathlib import sys def payload(size: int) -> bytes: return bytes(((index * 29 + 17) & 0xFF) for index in range(size)) BIG = payload(4 * 1024 * 1024) AFTER = b"may be committed before traversal reaches BIG\r\n" def create(root: pathlib.Path) -> None: tree = root / "CSRC" / "TREE" tree.mkdir(parents=True) (root / "CDST").mkdir() (tree / "BIG.BIN").write_bytes(BIG) (tree / "AFTER.TXT").write_bytes(AFTER) def verify(root: pathlib.Path) -> None: source = root / "CSRC" / "TREE" target = root / "CDST" / "TREE" failures: list[str] = [] if (source / "BIG.BIN").read_bytes() != BIG: failures.append("source BIG.BIN изменён") if (source / "AFTER.TXT").read_bytes() != AFTER: failures.append("source AFTER.TXT изменён") if not target.is_dir(): failures.append("root target-каталог не был создан до cancel") else: big_target = target / "BIG.BIN" if big_target.exists(): failures.append("BIG.BIN committed несмотря на ранний cancel") after_target = target / "AFTER.TXT" if after_target.exists() and after_target.read_bytes() != AFTER: failures.append("частично завершённый AFTER.TXT повреждён") temporary = [path.name for path in target.iterdir() if path.name.upper().endswith(".TMP")] if temporary: failures.append(f"после cancel остались temp: {temporary}") if failures: for failure in failures: print(f"FAIL: {failure}") raise SystemExit(1) print("PASS: tree cancel removed active temp; source intact; no BIG commit.") def main() -> None: if len(sys.argv) != 3 or sys.argv[1] not in {"create", "verify"}: raise SystemExit(f"usage: {sys.argv[0]} create|verify DIR") root = pathlib.Path(sys.argv[2]) if sys.argv[1] == "create": create(root) else: verify(root) if __name__ == "__main__": main()