#!/usr/bin/env python3 """Создаёт и проверяет HDD-fixture рекурсивного группового F8.""" from __future__ import annotations import pathlib import sys def payload(size: int, seed: int) -> bytes: return bytes(((index * 29 + seed) & 0xFF) for index in range(size)) def create(root: pathlib.Path) -> None: panel = root / "RDEL" adir = panel / "ADIR" bdir = panel / "BDIR" keepdir = panel / "KEEPDIR" (adir / "EMPTY").mkdir(parents=True) bdir.mkdir(parents=True) keepdir.mkdir(parents=True) # Несколько файлов в одном каталоге проверяют, что F_NEXT продолжает # перечисление после удаления только что возвращённой записи. for index, size in enumerate((0, 1, 16, 4097)): (adir / f"A{index}.BIN").write_bytes(payload(size, index + 3)) deep = adir for depth in range(1, 13): deep = deep / f"D{depth:02d}" deep.mkdir() (deep / f"F{depth:02d}.TXT").write_bytes( payload(depth * 7, depth + 19) ) (bdir / "B0.TXT").write_bytes(b"delete second root\r\n") (bdir / "B1.BIN").write_bytes(payload(513, 71)) (panel / "TOP.BIN").write_bytes(payload(33, 91)) (panel / "KEEP.TXT").write_bytes(b"keep top-level payload\r\n") (keepdir / "SAFE.BIN").write_bytes(payload(257, 111)) def verify(root: pathlib.Path) -> None: panel = root / "RDEL" failures: list[str] = [] for name in ("ADIR", "BDIR", "TOP.BIN"): if (panel / name).exists(): failures.append(f"выбранный объект не удалён: {name}") keep_file = panel / "KEEP.TXT" if not keep_file.is_file() or keep_file.read_bytes() != b"keep top-level payload\r\n": failures.append("невыбранный KEEP.TXT отсутствует или изменён") safe = panel / "KEEPDIR" / "SAFE.BIN" if not safe.is_file() or safe.read_bytes() != payload(257, 111): failures.append("невыбранное дерево KEEPDIR изменено") remaining = sorted( path.relative_to(panel).as_posix().upper() for path in panel.rglob("*") ) if remaining != ["KEEP.TXT", "KEEPDIR", "KEEPDIR/SAFE.BIN"]: failures.append(f"неожиданный остаток RDEL: {remaining}") if failures: for failure in failures: print(f"FAIL: {failure}") raise SystemExit(1) print("PASS: selected file and two directory trees deleted; KEEP preserved.") 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()