1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/memory/replace/dmd/check_test_output.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,128 @@ 1.4 +#! /usr/bin/python 1.5 + 1.6 +"""This script takes the file produced by DMD's test mode and checks its 1.7 +correctness. 1.8 + 1.9 +It produces the following output files: $TMP/test-{fixed,filtered,diff}.dmd. 1.10 + 1.11 +It runs the appropriate fix* script to get nice stack traces. It also 1.12 +filters out platform-specific details from the test output file. 1.13 + 1.14 +Note: you must run this from the same directory that you invoked DMD's test 1.15 +mode, otherwise the fix* script will not work properly, because some of the 1.16 +paths in the test output are relative. 1.17 + 1.18 +""" 1.19 + 1.20 +from __future__ import print_function 1.21 + 1.22 +import os 1.23 +import platform 1.24 +import re 1.25 +import subprocess 1.26 +import sys 1.27 +import tempfile 1.28 + 1.29 + 1.30 +def main(): 1.31 + 1.32 + # Arguments 1.33 + 1.34 + if (len(sys.argv) != 3): 1.35 + print("usage:", sys.argv[0], "<topsrcdir> <test.dmd>") 1.36 + sys.exit(1) 1.37 + 1.38 + srcdir = sys.argv[1] 1.39 + 1.40 + # Filenames 1.41 + 1.42 + tempdir = tempfile.gettempdir() 1.43 + in_name = sys.argv[2] 1.44 + fixed_name = tempdir + os.sep + "test-fixed.dmd" 1.45 + filtered_name = tempdir + os.sep + "test-filtered.dmd" 1.46 + diff_name = tempdir + os.sep + "test-diff.dmd" 1.47 + expected_name = srcdir + os.sep + \ 1.48 + "memory/replace/dmd/test-expected.dmd" 1.49 + 1.50 + # Fix stack traces 1.51 + 1.52 + print("fixing output to", fixed_name) 1.53 + 1.54 + sysname = platform.system() 1.55 + if sysname == "Linux": 1.56 + fix = srcdir + os.sep + "tools/rb/fix-linux-stack.pl" 1.57 + elif sysname == "Darwin": 1.58 + fix = srcdir + os.sep + "tools/rb/fix_macosx_stack.py" 1.59 + else: 1.60 + print("unhandled platform: " + sysname, file=sys.stderr) 1.61 + sys.exit(1) 1.62 + 1.63 + subprocess.call(fix, stdin=open(in_name, "r"), 1.64 + stdout=open(fixed_name, "w")) 1.65 + 1.66 + # Filter output 1.67 + 1.68 + # In stack trace records we filter out most stack frames. The only thing 1.69 + # we leave behind is a "DMD.cpp" entry if we see one or more frames that 1.70 + # have DMD.cpp in them. There is simply too much variation to do anything 1.71 + # better than that. 1.72 + # 1.73 + # As for stack frame records, alas, we filter them out entirely because 1.74 + # they have even more variation. 1.75 + 1.76 + print("filtering output to", filtered_name) 1.77 + 1.78 + with open(fixed_name, "r") as fin, \ 1.79 + open(filtered_name, "w") as fout: 1.80 + 1.81 + test_frame_re = re.compile(r".*(DMD.cpp)") 1.82 + 1.83 + for line in fin: 1.84 + if re.match(r" (Allocated at|Reported( again)? at)", line): 1.85 + # It's a stack trace record. 1.86 + print(line, end='', file=fout) 1.87 + 1.88 + # Filter the stack trace -- print a single line if we see one 1.89 + # or more frames involving DMD.cpp. 1.90 + seen_DMD_frame = False 1.91 + for frame in fin: 1.92 + if re.match(r" ", frame): 1.93 + m = test_frame_re.match(frame) 1.94 + if m: 1.95 + seen_DMD_frame = True 1.96 + else: 1.97 + # We're past the stack trace. 1.98 + if seen_DMD_frame: 1.99 + print(" ... DMD.cpp", file=fout) 1.100 + print(frame, end='', file=fout) 1.101 + break 1.102 + 1.103 + elif re.search("in stack frame record", line): 1.104 + # Stack frame record. Get the whole thing (we know how many 1.105 + # lines it has). 1.106 + line2 = fin.next() 1.107 + line3 = fin.next() 1.108 + line4 = fin.next() 1.109 + line5 = fin.next() 1.110 + line6 = fin.next() 1.111 + 1.112 + else: 1.113 + # A line that needs no special handling. Copy it through. 1.114 + print(line, end='', file=fout) 1.115 + 1.116 + # Compare with expected output 1.117 + 1.118 + print("diffing output to", diff_name) 1.119 + 1.120 + ret = subprocess.call(["diff", "-u", expected_name, filtered_name], 1.121 + stdout=open(diff_name, "w")) 1.122 + 1.123 + if ret == 0: 1.124 + print("test PASSED") 1.125 + else: 1.126 + print("test FAILED (did you remember to run this script and Firefox " 1.127 + "in the same directory?)") 1.128 + 1.129 + 1.130 +if __name__ == "__main__": 1.131 + main()