67 lines
2.5 KiB
Python
67 lines
2.5 KiB
Python
#!/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()
|