blob: e8ca91b5ae76926188e1382995b4c27540c04af5 [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]
116 if not test_dir.endswith('test'):
117 print "This script expects to reside in lldb's test directory."
118 sys.exit(-1)
119
Johnny Chenc5fa0052011-07-29 22:54:56 +0000120 index = 1
121 while index < len(sys.argv):
Johnny Chen02dfe4a2011-11-30 19:46:37 +0000122 if sys.argv[index].startswith('-h'):
123 usage()
124
Johnny Chenc5fa0052011-07-29 22:54:56 +0000125 if sys.argv[index].startswith('-'):
126 # We should continue processing...
127 pass
128 else:
129 # End of option processing.
130 break
131
Johnny Chen6884bdd2012-05-09 21:00:03 +0000132 if sys.argv[index] == '-F':
Johnny Chencf0bc6d2012-05-07 22:59:00 +0000133 # Increment by 1 to fetch the filename component spec.
134 index += 1
135 if index >= len(sys.argv) or sys.argv[index].startswith('-'):
136 usage()
137 filename_components.append(sys.argv[index])
Johnny Chencf0bc6d2012-05-07 22:59:00 +0000138 elif sys.argv[index] == '-n':
Johnny Chenc5fa0052011-07-29 22:54:56 +0000139 no_trace = True
Filipe Cabecinhas1b8de0a2012-05-09 19:02:19 +0000140
141 index += 1
Johnny Chenc5fa0052011-07-29 22:54:56 +0000142
Johnny Chen4fda4672012-01-24 01:53:02 +0000143 if index < len(sys.argv):
144 # Get the specified session directory.
145 session_dir = sys.argv[index]
146 else:
147 # Use heuristic to find the latest session directory.
148 name = datetime.datetime.now().strftime("%Y-%m-%d-")
149 dirs = [d for d in os.listdir(os.getcwd()) if d.startswith(name)]
Filipe Cabecinhas1b8de0a2012-05-09 19:02:19 +0000150 if len(dirs) == 0:
151 print "No default session directory found, please specify it explicitly."
152 usage()
Johnny Chen4fda4672012-01-24 01:53:02 +0000153 session_dir = max(dirs, key=os.path.getmtime)
154 if not session_dir or not os.path.exists(session_dir):
155 print "No default session directory found, please specify it explicitly."
156 usage()
Johnny Chenc5fa0052011-07-29 22:54:56 +0000157
158 #print "The test directory:", test_dir
159 session_dir_path = where(session_dir, test_dir)
160
Johnny Chen4fda4672012-01-24 01:53:02 +0000161 print "Using session dir path:", session_dir_path
Johnny Chenc5fa0052011-07-29 22:54:56 +0000162 os.chdir(test_dir)
163 os.path.walk(session_dir_path, redo, ".log")
164
Johnny Chen4fda4672012-01-24 01:53:02 +0000165 if not redo_specs:
Johnny Chen8aa684d2012-05-16 18:32:05 +0000166 print "No failures/errors recorded within the session directory, please specify a different session directory.\n"
Johnny Chen4fda4672012-01-24 01:53:02 +0000167 usage()
168
Johnny Chenc5fa0052011-07-29 22:54:56 +0000169 filters = " -f ".join(redo_specs)
Johnny Chen13fb6572011-08-16 20:02:59 +0000170 compilers = (" -C %s" % "^".join(comp_specs)) if comp_specs else None
171 archs = (" -A %s" % "^".join(arch_specs)) if arch_specs else None
172
173 command = "./dotest.py %s %s -v %s -f " % (compilers if compilers else "",
174 archs if archs else "",
175 "" if no_trace else "-t")
176
Johnny Chenc5fa0052011-07-29 22:54:56 +0000177
178 print "Running %s" % (command + filters)
179 os.system(command + filters)
180
181if __name__ == '__main__':
182 main()