Files
TDT4205/ps5/vsl_programs/codegen-tester.py
2026-03-28 15:30:44 +01:00

79 lines
2.2 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
import subprocess
import os.path
name, *args = sys.argv
USAGE = f"""
Usage: {name} <file.vsl>
For each occurance of a VSL comment block starting with
//TESTCASE: <args>
The corresponding compiler executable file.out is executed with the given <args>.
Output is compared against the rest of the comment block.
If they are different, the difference is printed and the test fails.
""".strip()
TESTCASE_LINE = "//TESTCASE:"
def error(text, message=None):
print(f"{name}: error: {text}")
if message is not None:
print(message)
sys.exit(1)
if len(args) != 1:
error("expected one input .vsl file", message=USAGE)
vsl_file, = args
if not os.path.isfile(vsl_file):
error(f"file not found: {vsl_file}")
out_file = vsl_file[:vsl_file.rindex(".")] + ".out"
if not os.path.isfile(out_file):
error(f"file not found: {out_file}")
with open(vsl_file, "r", encoding="utf-8") as vsl_fd:
lines = vsl_fd.read().splitlines()
tests = []
i = 0
while i < len(lines):
line = lines[i]
if line.startswith(TESTCASE_LINE):
args = line[len(TESTCASE_LINE):].split(" ")
args = [arg for arg in args if len(arg)]
expected_output = []
i += 1
while i < len(lines) and lines[i].startswith("//") and not lines[i].startswith(TESTCASE_LINE):
expected_output.append(lines[i][2:])
i += 1
tests.append((args, expected_output))
else:
i += 1
print(f"Running {len(tests)} test cases for file {vsl_file}")
# Ensure that relative paths to executables start with "./"
out_file = os.path.join(".", out_file)
for args, expected_output in tests:
print(f" Running {out_file} {' '.join(args)}")
proc = subprocess.run([out_file] + args, capture_output=True, text=True, check=False, timeout=5)
result_lines = proc.stdout.strip().split('\n')
if len(result_lines) != len(expected_output) or any(a != b for a, b in zip(result_lines, expected_output)):
message = ["EXPECTED --------",
"\n".join(expected_output),
"ACTUAL ----------",
"\n".join(result_lines),
"-----------------"]
error("actual output didn't match expected output", message="\n".join(message))