redo.py revision 9e643dbb9254ad1e0d82b923f58fc64eeeec5be1
1#!/usr/bin/env python 2 3""" 4A simple utility to redo the failed/errored tests. 5 6You need to specify the session directory in order for this script to locate the 7tests which need to be re-run. 8 9See also dotest.py, the test driver running the test suite. 10 11Type: 12 13./dotest.py -h 14 15for help. 16""" 17 18import os, sys 19import re 20 21# If True, redo with no '-t' option for the test driver. 22no_trace = False 23 24# To be filled with the filterspecs found in the session logs. 25redo_specs = [] 26 27# There is a known bug with respect to comp_specs and arch_specs, in that if we 28# encountered "-C clang" and "-C gcc" when visiting the session files, both 29# compilers will end up in the invocation of the test driver when rerunning. 30# That is: ./dotest -v -C clang^gcc ... -f ...". Ditto for "-A" flags. 31# The "-C compiler" for comp_specs. 32comp_specs = set() 33# The "-A arch" for arch_specs. 34arch_specs = set() 35 36def usage(): 37 print"""\ 38Usage: redo.py [-n] session_dir 39where options: 40-n : when running the tests, do not turn on trace mode, i.e, no '-t' option 41 is passed to the test driver (this will run the tests faster) 42 43and session_dir specifies the session directory which contains previously 44recorded session infos for all the test cases which either failed or errored.""" 45 sys.exit(0) 46 47def where(session_dir, test_dir): 48 """Returns the full path to the session directory; None if non-existent.""" 49 abspath = os.path.abspath(session_dir) 50 if os.path.isdir(abspath): 51 return abspath 52 53 session_dir_path = os.path.join(test_dir, session_dir) 54 if os.path.isdir(session_dir_path): 55 return session_dir_path 56 57 return None 58 59# This is the pattern for the line from the log file to redo a test. 60# We want the filter spec. 61filter_pattern = re.compile("^\./dotest\.py.*-f (.*)$") 62comp_pattern = re.compile(" -C ([^ ]+) ") 63arch_pattern = re.compile(" -A ([^ ]+) ") 64def redo(suffix, dir, names): 65 """Visitor function for os.path.walk(path, visit, arg).""" 66 global redo_specs 67 global comp_specs 68 global arch_specs 69 global filter_pattern 70 global comp_pattern 71 global arch_pattern 72 73 for name in names: 74 if name.endswith(suffix): 75 #print "Find a log file:", name 76 if name.startswith("Error") or name.startswith("Failure"): 77 with open(os.path.join(dir, name), 'r') as log: 78 content = log.read() 79 for line in content.splitlines(): 80 match = filter_pattern.match(line) 81 if match: 82 filterspec = match.group(1) 83 print "adding filterspec:", filterspec 84 redo_specs.append(filterspec) 85 comp = comp_pattern.search(line) 86 if comp: 87 comp_specs.add(comp.group(1)) 88 arch = arch_pattern.search(line) 89 if arch: 90 arch_specs.add(arch.group(1)) 91 else: 92 continue 93 94def main(): 95 """Read the session directory and run the failed test cases one by one.""" 96 global no_trace 97 global redo_specs 98 99 if len(sys.argv) < 2 or len(sys.argv) > 3: 100 usage() 101 102 index = 1 103 while index < len(sys.argv): 104 if sys.argv[index].startswith('-'): 105 # We should continue processing... 106 pass 107 else: 108 # End of option processing. 109 break 110 111 if sys.argv[index] == '-n': 112 no_trace = True 113 index += 1 114 115 session_dir = sys.argv[index] 116 117 test_dir = sys.path[0] 118 if not test_dir.endswith('test'): 119 print "This script expects to reside in lldb's test directory." 120 sys.exit(-1) 121 122 #print "The test directory:", test_dir 123 session_dir_path = where(session_dir, test_dir) 124 125 #print "Session dir path:", session_dir_path 126 os.chdir(test_dir) 127 os.path.walk(session_dir_path, redo, ".log") 128 129 filters = " -f ".join(redo_specs) 130 compilers = (" -C %s" % "^".join(comp_specs)) if comp_specs else None 131 archs = (" -A %s" % "^".join(arch_specs)) if arch_specs else None 132 133 command = "./dotest.py %s %s -v %s -f " % (compilers if compilers else "", 134 archs if archs else "", 135 "" if no_trace else "-t") 136 137 138 print "Running %s" % (command + filters) 139 os.system(command + filters) 140 141if __name__ == '__main__': 142 main() 143