from __future__ import annotations import subprocess import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) from patchwork import Obfuscator EXAMPLES = ROOT / 'examples' EXAMPLE_NAMES = ['hello', 'fizzbuzz', 'classes', 'stress', 'modern', 'future_annotations', 'literals'] SEEDS = [1, 7, 42, 1234, 999999] def run(path: Path) -> str: res = subprocess.run([sys.executable, str(path)], capture_output=True, text=True, timeout=20) if res.returncode != 0: raise RuntimeError(f'{path} exited {res.returncode}\nstderr:\n{res.stderr}') return res.stdout def check_one(name: str, seed: int) -> None: src_path = EXAMPLES / f'{name}.py' expected = run(src_path) obf_src = Obfuscator(seed=seed).obfuscate(src_path.read_text(encoding='utf-8')) obf_path = EXAMPLES / f'{name}_test_{seed}.py' obf_path.write_text(obf_src, encoding='utf-8') try: actual = run(obf_path) finally: obf_path.unlink(missing_ok=True) if actual != expected: raise AssertionError(f'{name} seed={seed}: output mismatch\n--- expected ---\n{expected}--- actual ---\n{actual}') def main() -> int: fails = 0 for name in EXAMPLE_NAMES: for seed in SEEDS: try: check_one(name, seed) print(f'ok: {name:10s} seed={seed}') except Exception as e: fails += 1 print(f'FAIL: {name:10s} seed={seed}: {e}') src = (EXAMPLES / 'hello.py').read_text(encoding='utf-8') a = Obfuscator(seed=1).obfuscate(src) b = Obfuscator(seed=2).obfuscate(src) c = Obfuscator(seed=1).obfuscate(src) if a == b: print('FAIL: polymorphism (seed=1 vs seed=2 produced identical output)') fails += 1 else: print('ok: polymorphism (seeds 1 vs 2 differ)') if a != c: print('FAIL: reproducibility (same seed gave different output)') fails += 1 else: print('ok: reproducibility (seed=1 stable)') literals_src = (EXAMPLES / 'literals.py').read_text(encoding='utf-8') literals_obf = Obfuscator(seed=2026).obfuscate(literals_src) if 'PATCHWORK_LITERAL_MARKER_9f8b6b7d' in literals_obf or 'PATCHWORK_BYTES_MARKER' in literals_obf: print('FAIL: literal markers were present in obfuscated output') fails += 1 else: print('ok: literal markers absent from obfuscated output') future_src = (EXAMPLES / 'future_annotations.py').read_text(encoding='utf-8') for kwargs in ({'encrypt_strings': False}, {'opaque_predicates': False, 'junk_branches': False}): try: obf = Obfuscator(seed=77, **kwargs).obfuscate(future_src) obf_path = EXAMPLES / f'future_annotations_options_{len(kwargs)}.py' obf_path.write_text(obf, encoding='utf-8') try: if run(obf_path) != run(EXAMPLES / 'future_annotations.py'): raise AssertionError('output mismatch') finally: obf_path.unlink(missing_ok=True) print(f'ok: future annotations options {kwargs}') except Exception as e: fails += 1 print(f'FAIL: future annotations options {kwargs}: {e}') print(f'\n{fails} failures' if fails else '\nall good') return 1 if fails else 0 if __name__ == '__main__': raise SystemExit(main())