#!/usr/bin/env python3 """Создание и проверка HDD-набора отрицательных сценариев copy-job.""" from __future__ import annotations import pathlib import sys SIZES = { "BEGIN.BIN": 8192, "LATE.BIN": 4096, "READERR.BIN": 4096, "RONLY.BIN": 4096, "RENAME.BIN": 4096, "RACE.BIN": 4096, } def content(name: str, size: int) -> bytes: seed = sum(name.encode("ascii")) & 0xFF return bytes((seed + index * 29 + (index >> 7)) & 0xFF for index in range(size)) def create(root: pathlib.Path) -> None: source = root / "SOURCE" (root / "TARGET").mkdir(parents=True) source.mkdir() for name, size in SIZES.items(): (source / name).write_bytes(content(name, size)) def verify(root: pathlib.Path) -> None: failures: list[str] = [] source = root / "SOURCE" target = root / "TARGET" result = root / "RESULT.TXT" for name, size in SIZES.items(): path = source / name if not path.is_file() or path.read_bytes() != content(name, size): failures.append(f"повреждён SOURCE/{name}") expected_lines = [ "PASS missing EXE errno 3", "PASS missing source cleanup", "PASS cancel before first read", "PASS last block stops before commit", "PASS cancel at pre-commit", "PASS read error cleanup", "PASS readonly write cleanup", "PASS rename error cleanup", "PASS target race refuses overwrite", "PASS EMM restored", "ALL PASS", ] if not result.is_file(): failures.append("не создан RESULT.TXT") else: text = result.read_bytes().decode("cp866", errors="replace") for line in expected_lines: if line not in text: failures.append(f"нет строки результата: {line}") if not target.is_dir(): failures.append("исчез TARGET") else: unexpected = sorted(path.name for path in target.iterdir() if path.name.upper() != "RACE.BIN") if unexpected: failures.append("лишние файлы TARGET: " + ", ".join(unexpected)) race = target / "RACE.BIN" if not race.is_file() or race.read_bytes() != b"KEEP": failures.append("RACE.BIN перезаписан или отсутствует") temporaries = sorted(path.name for path in target.glob("~SC*.TMP")) if temporaries: failures.append("остались temp: " + ", ".join(temporaries)) if failures: for failure in failures: print(f"FAIL: {failure}") raise SystemExit(1) print("PASS: missing EXE, cancel, read/readonly/rename, race и EMM cleanup.") 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()