#!/usr/bin/env python3 """Тест задачи 09: сборка crash.c с ASAN/UBSAN и прогон входов.""" import os import subprocess import sys HERE = os.path.dirname(os.path.abspath(__file__)) SRC = os.path.join(HERE, "crash.c") BIN = os.path.join(HERE, "crash_checked") failures = 0 def check(cond, name, extra=""): global failures if cond: print(f"ok {name}") else: print(f"FAIL {name} {extra}") failures += 1 def main(): r = subprocess.run(["gcc", "-g", "-O1", "-Wall", "-Wextra", "-fsanitize=address,undefined", "-fno-omit-frame-pointer", SRC, "-o", BIN], capture_output=True, text=True, timeout=180) check(r.returncode == 0, "сборка с ASAN/UBSAN прошла", r.stderr[:800]) if r.returncode != 0: print("\nFAILURES: 1") sys.exit(1) cases = [ ([], "len=5"), (["world"], "len=5"), (["a"], "len=1"), ([""], "len=0"), (["x" * 300], "len=300"), ] for args, expect in cases: try: run = subprocess.run([BIN] + args, capture_output=True, text=True, timeout=60, env={**os.environ, "ASAN_OPTIONS": "detect_leaks=1"}) except subprocess.TimeoutExpired: check(False, f"вход {args or '<нет>'}: завершился за 60 c") continue out = run.stdout.strip() err = run.stderr label = f"вход {args[0][:12]!r}" if args else "вход без аргумента" check(run.returncode == 0, f"{label}: код возврата 0 (получен {run.returncode})") check(out == expect, f"{label}: вывод {expect!r} (получено {out!r})") check("AddressSanitizer" not in err and "runtime error" not in err, f"{label}: санитайзеры молчат", err[:400].replace("\n", " | ")) # answer.txt заполнен (проверка на «не оставил заготовку») apath = os.path.join(HERE, "answer.txt") if os.path.exists(apath): txt = open(apath, encoding="utf-8").read() check("..." not in txt and len(txt) > 400, "answer.txt заполнен разбором (ревью отдельно)") else: check(False, "answer.txt: файл с разбором не найден") print(f"\n{'FAILURES: %d' % failures if failures else 'ALL PASS'}") sys.exit(1 if failures else 0) if __name__ == "__main__": main()