michael@0: #! /usr/bin/python michael@0: michael@0: """This script takes the file produced by DMD's test mode and checks its michael@0: correctness. michael@0: michael@0: It produces the following output files: $TMP/test-{fixed,filtered,diff}.dmd. michael@0: michael@0: It runs the appropriate fix* script to get nice stack traces. It also michael@0: filters out platform-specific details from the test output file. michael@0: michael@0: Note: you must run this from the same directory that you invoked DMD's test michael@0: mode, otherwise the fix* script will not work properly, because some of the michael@0: paths in the test output are relative. michael@0: michael@0: """ michael@0: michael@0: from __future__ import print_function michael@0: michael@0: import os michael@0: import platform michael@0: import re michael@0: import subprocess michael@0: import sys michael@0: import tempfile michael@0: michael@0: michael@0: def main(): michael@0: michael@0: # Arguments michael@0: michael@0: if (len(sys.argv) != 3): michael@0: print("usage:", sys.argv[0], " ") michael@0: sys.exit(1) michael@0: michael@0: srcdir = sys.argv[1] michael@0: michael@0: # Filenames michael@0: michael@0: tempdir = tempfile.gettempdir() michael@0: in_name = sys.argv[2] michael@0: fixed_name = tempdir + os.sep + "test-fixed.dmd" michael@0: filtered_name = tempdir + os.sep + "test-filtered.dmd" michael@0: diff_name = tempdir + os.sep + "test-diff.dmd" michael@0: expected_name = srcdir + os.sep + \ michael@0: "memory/replace/dmd/test-expected.dmd" michael@0: michael@0: # Fix stack traces michael@0: michael@0: print("fixing output to", fixed_name) michael@0: michael@0: sysname = platform.system() michael@0: if sysname == "Linux": michael@0: fix = srcdir + os.sep + "tools/rb/fix-linux-stack.pl" michael@0: elif sysname == "Darwin": michael@0: fix = srcdir + os.sep + "tools/rb/fix_macosx_stack.py" michael@0: else: michael@0: print("unhandled platform: " + sysname, file=sys.stderr) michael@0: sys.exit(1) michael@0: michael@0: subprocess.call(fix, stdin=open(in_name, "r"), michael@0: stdout=open(fixed_name, "w")) michael@0: michael@0: # Filter output michael@0: michael@0: # In stack trace records we filter out most stack frames. The only thing michael@0: # we leave behind is a "DMD.cpp" entry if we see one or more frames that michael@0: # have DMD.cpp in them. There is simply too much variation to do anything michael@0: # better than that. michael@0: # michael@0: # As for stack frame records, alas, we filter them out entirely because michael@0: # they have even more variation. michael@0: michael@0: print("filtering output to", filtered_name) michael@0: michael@0: with open(fixed_name, "r") as fin, \ michael@0: open(filtered_name, "w") as fout: michael@0: michael@0: test_frame_re = re.compile(r".*(DMD.cpp)") michael@0: michael@0: for line in fin: michael@0: if re.match(r" (Allocated at|Reported( again)? at)", line): michael@0: # It's a stack trace record. michael@0: print(line, end='', file=fout) michael@0: michael@0: # Filter the stack trace -- print a single line if we see one michael@0: # or more frames involving DMD.cpp. michael@0: seen_DMD_frame = False michael@0: for frame in fin: michael@0: if re.match(r" ", frame): michael@0: m = test_frame_re.match(frame) michael@0: if m: michael@0: seen_DMD_frame = True michael@0: else: michael@0: # We're past the stack trace. michael@0: if seen_DMD_frame: michael@0: print(" ... DMD.cpp", file=fout) michael@0: print(frame, end='', file=fout) michael@0: break michael@0: michael@0: elif re.search("in stack frame record", line): michael@0: # Stack frame record. Get the whole thing (we know how many michael@0: # lines it has). michael@0: line2 = fin.next() michael@0: line3 = fin.next() michael@0: line4 = fin.next() michael@0: line5 = fin.next() michael@0: line6 = fin.next() michael@0: michael@0: else: michael@0: # A line that needs no special handling. Copy it through. michael@0: print(line, end='', file=fout) michael@0: michael@0: # Compare with expected output michael@0: michael@0: print("diffing output to", diff_name) michael@0: michael@0: ret = subprocess.call(["diff", "-u", expected_name, filtered_name], michael@0: stdout=open(diff_name, "w")) michael@0: michael@0: if ret == 0: michael@0: print("test PASSED") michael@0: else: michael@0: print("test FAILED (did you remember to run this script and Firefox " michael@0: "in the same directory?)") michael@0: michael@0: michael@0: if __name__ == "__main__": michael@0: main()