blob: 2cbdd4e00b87dc7f4870e0ffef8828e605ae8164 [file] [log] [blame]
Johnny Chenc5fa0052011-07-29 22:54:56 +00001#!/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
Johnny Chen4fda4672012-01-24 01:53:02 +000018import os, sys, datetime
Johnny Chenc5fa0052011-07-29 22:54:56 +000019import 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 = []
Johnny Chen9e643db2011-08-16 20:56:10 +000026
Johnny Chencf0bc6d2012-05-07 22:59:00 +000027# The filename components to match for. Only files with the contained component names
28# will be considered for re-run. Examples: ['X86_64', 'clang'].
29filename_components = []
30
Johnny Chen9e643db2011-08-16 20:56:10 +000031# There is a known bug with respect to comp_specs and arch_specs, in that if we
32# encountered "-C clang" and "-C gcc" when visiting the session files, both
33# compilers will end up in the invocation of the test driver when rerunning.
34# That is: ./dotest -v -C clang^gcc ... -f ...". Ditto for "-A" flags.
Johnny Chene90a10e2011-08-16 20:57:05 +000035
Johnny Chen9e643db2011-08-16 20:56:10 +000036# The "-C compiler" for comp_specs.
Johnny Chen13fb6572011-08-16 20:02:59 +000037comp_specs = set()
Johnny Chen9e643db2011-08-16 20:56:10 +000038# The "-A arch" for arch_specs.
Johnny Chen13fb6572011-08-16 20:02:59 +000039arch_specs = set()
Johnny Chenc5fa0052011-07-29 22:54:56 +000040
41def usage():
42 print"""\
Johnny Chencf0bc6d2012-05-07 22:59:00 +000043Usage: redo.py [-F filename_component] [-n] [session_dir]
Johnny Chenc5fa0052011-07-29 22:54:56 +000044where options:
Johnny Chencf0bc6d2012-05-07 22:59:00 +000045-F : only consider the test for re-run if the session filename conatins the filename component
46 for example: -F x86_64
Johnny Chenc5fa0052011-07-29 22:54:56 +000047-n : when running the tests, do not turn on trace mode, i.e, no '-t' option
48 is passed to the test driver (this will run the tests faster)
49
50and session_dir specifies the session directory which contains previously
Johnny Chen4fda4672012-01-24 01:53:02 +000051recorded session infos for all the test cases which either failed or errored.
52
53If sessin_dir is left unspecified, this script uses the heuristic to find the
54possible session directories with names starting with %Y-%m-%d- (for example,
552012-01-23-) and employs the one with the latest timestamp."""
Johnny Chenc5fa0052011-07-29 22:54:56 +000056 sys.exit(0)
57
58def where(session_dir, test_dir):
59 """Returns the full path to the session directory; None if non-existent."""
60 abspath = os.path.abspath(session_dir)
61 if os.path.isdir(abspath):
62 return abspath
63
64 session_dir_path = os.path.join(test_dir, session_dir)
65 if os.path.isdir(session_dir_path):
66 return session_dir_path
67
68 return None
69
70# This is the pattern for the line from the log file to redo a test.
71# We want the filter spec.
Johnny Chen13fb6572011-08-16 20:02:59 +000072filter_pattern = re.compile("^\./dotest\.py.*-f (.*)$")
73comp_pattern = re.compile(" -C ([^ ]+) ")
74arch_pattern = re.compile(" -A ([^ ]+) ")
Johnny Chenc5fa0052011-07-29 22:54:56 +000075def redo(suffix, dir, names):
76 """Visitor function for os.path.walk(path, visit, arg)."""
77 global redo_specs
Johnny Chen13fb6572011-08-16 20:02:59 +000078 global comp_specs
79 global arch_specs
80 global filter_pattern
81 global comp_pattern
82 global arch_pattern
Johnny Chencf0bc6d2012-05-07 22:59:00 +000083 global filename_components
Johnny Chenc5fa0052011-07-29 22:54:56 +000084
85 for name in names:
86 if name.endswith(suffix):
87 #print "Find a log file:", name
88 if name.startswith("Error") or name.startswith("Failure"):
Johnny Chencf0bc6d2012-05-07 22:59:00 +000089 if filename_components:
90 if not all([comp in name for comp in filename_components]):
91 continue
Johnny Chenc5fa0052011-07-29 22:54:56 +000092 with open(os.path.join(dir, name), 'r') as log:
93 content = log.read()
94 for line in content.splitlines():
Johnny Chen13fb6572011-08-16 20:02:59 +000095 match = filter_pattern.match(line)
Johnny Chenc5fa0052011-07-29 22:54:56 +000096 if match:
97 filterspec = match.group(1)
98 print "adding filterspec:", filterspec
99 redo_specs.append(filterspec)
Johnny Chen13fb6572011-08-16 20:02:59 +0000100 comp = comp_pattern.search(line)
101 if comp:
102 comp_specs.add(comp.group(1))
103 arch = arch_pattern.search(line)
104 if arch:
105 arch_specs.add(arch.group(1))
Johnny Chenc5fa0052011-07-29 22:54:56 +0000106 else:
107 continue
108
109def main():
110 """Read the session directory and run the failed test cases one by one."""
111 global no_trace
112 global redo_specs
Johnny Chencf0bc6d2012-05-07 22:59:00 +0000113 global filename_components
Johnny Chenc5fa0052011-07-29 22:54:56 +0000114
Johnny Chen4fda4672012-01-24 01:53:02 +0000115 test_dir = sys.path[0]
Johnny Chen47dcd1e2012-05-16 19:43:14 +0000116 if not test_dir:
117 test_dir = os.getcwd()
Johnny Chen4fda4672012-01-24 01:53:02 +0000118 if not test_dir.endswith('test'):
119 print "This script expects to reside in lldb's test directory."
120 sys.exit(-1)
121
Johnny Chenc5fa0052011-07-29 22:54:56 +0000122 index = 1
123 while index < len(sys.argv):
Johnny Chen11595f52012-08-23 23:45:26 +0000124 if sys.argv[index].startswith('-h') or sys.argv[index].startswith('--help'):
Johnny Chen02dfe4a2011-11-30 19:46:37 +0000125 usage()
126
Johnny Chenc5fa0052011-07-29 22:54:56 +0000127 if sys.argv[index].startswith('-'):
128 # We should continue processing...
129 pass
130 else:
131 # End of option processing.
132 break
133
Johnny Chen6884bdd2012-05-09 21:00:03 +0000134 if sys.argv[index] == '-F':
Johnny Chencf0bc6d2012-05-07 22:59:00 +0000135 # Increment by 1 to fetch the filename component spec.
136 index += 1
137 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
138 usage()
139 filename_components.append(sys.argv[index])
Johnny Chencf0bc6d2012-05-07 22:59:00 +0000140 elif sys.argv[index] == '-n':
Johnny Chenc5fa0052011-07-29 22:54:56 +0000141 no_trace = True
Filipe Cabecinhas1b8de0a2012-05-09 19:02:19 +0000142
143 index += 1
Johnny Chenc5fa0052011-07-29 22:54:56 +0000144
Johnny Chen4fda4672012-01-24 01:53:02 +0000145 if index < len(sys.argv):
146 # Get the specified session directory.
147 session_dir = sys.argv[index]
148 else:
149 # Use heuristic to find the latest session directory.
150 name = datetime.datetime.now().strftime("%Y-%m-%d-")
151 dirs = [d for d in os.listdir(os.getcwd()) if d.startswith(name)]
Filipe Cabecinhas1b8de0a2012-05-09 19:02:19 +0000152 if len(dirs) == 0:
153 print "No default session directory found, please specify it explicitly."
154 usage()
Johnny Chen4fda4672012-01-24 01:53:02 +0000155 session_dir = max(dirs, key=os.path.getmtime)
156 if not session_dir or not os.path.exists(session_dir):
157 print "No default session directory found, please specify it explicitly."
158 usage()
Johnny Chenc5fa0052011-07-29 22:54:56 +0000159
160 #print "The test directory:", test_dir
161 session_dir_path = where(session_dir, test_dir)
162
Johnny Chen4fda4672012-01-24 01:53:02 +0000163 print "Using session dir path:", session_dir_path
Johnny Chenc5fa0052011-07-29 22:54:56 +0000164 os.chdir(test_dir)
165 os.path.walk(session_dir_path, redo, ".log")
166
Johnny Chen4fda4672012-01-24 01:53:02 +0000167 if not redo_specs:
Johnny Chen8aa684d2012-05-16 18:32:05 +0000168 print "No failures/errors recorded within the session directory, please specify a different session directory.\n"
Johnny Chen4fda4672012-01-24 01:53:02 +0000169 usage()
170
Johnny Chenc5fa0052011-07-29 22:54:56 +0000171 filters = " -f ".join(redo_specs)
Greg Clayton8b409152012-10-09 16:54:55 +0000172 compilers = ''
173 for comp in comp_specs:
174 compilers += " -C %s" % (comp)
175 archs = ''
176 for arch in arch_specs:
177 archs += "--arch %s " % (arch)
Johnny Chen13fb6572011-08-16 20:02:59 +0000178
Greg Clayton8b409152012-10-09 16:54:55 +0000179 command = "./dotest.py %s %s -v %s -f " % (compilers, archs, "" if no_trace else "-t")
Johnny Chen13fb6572011-08-16 20:02:59 +0000180
Johnny Chenc5fa0052011-07-29 22:54:56 +0000181
182 print "Running %s" % (command + filters)
183 os.system(command + filters)
184
185if __name__ == '__main__':
186 main()