Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: tools/testrunner/local/execution.py

Issue 360113003: Let test runner rerun failures to test for flakes. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/run-tests.py ('k') | tools/testrunner/objects/context.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2012 the V8 project authors. All rights reserved. 1 # Copyright 2012 the V8 project authors. All rights reserved.
2 # Redistribution and use in source and binary forms, with or without 2 # Redistribution and use in source and binary forms, with or without
3 # modification, are permitted provided that the following conditions are 3 # modification, are permitted provided that the following conditions are
4 # met: 4 # met:
5 # 5 #
6 # * Redistributions of source code must retain the above copyright 6 # * Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer. 7 # notice, this list of conditions and the following disclaimer.
8 # * Redistributions in binary form must reproduce the above 8 # * Redistributions in binary form must reproduce the above
9 # copyright notice, this list of conditions and the following 9 # copyright notice, this list of conditions and the following
10 # disclaimer in the documentation and/or other materials provided 10 # disclaimer in the documentation and/or other materials provided
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 74
75 def _CommonInit(self, num_tests, progress_indicator, context): 75 def _CommonInit(self, num_tests, progress_indicator, context):
76 self.indicator = progress_indicator 76 self.indicator = progress_indicator
77 progress_indicator.runner = self 77 progress_indicator.runner = self
78 self.context = context 78 self.context = context
79 self.succeeded = 0 79 self.succeeded = 0
80 self.total = num_tests 80 self.total = num_tests
81 self.remaining = num_tests 81 self.remaining = num_tests
82 self.failed = [] 82 self.failed = []
83 self.crashed = 0 83 self.crashed = 0
84 self.reran_tests = 0
84 85
85 def _RunPerfSafe(self, fun): 86 def _RunPerfSafe(self, fun):
86 try: 87 try:
87 fun() 88 fun()
88 except Exception, e: 89 except Exception, e:
89 print("PerfData exception: %s" % e) 90 print("PerfData exception: %s" % e)
90 self.perf_failures = True 91 self.perf_failures = True
91 92
93 def _GetJob(self, test):
94 command = self.GetCommand(test)
95 timeout = self.context.timeout
96 if ("--stress-opt" in test.flags or
97 "--stress-opt" in self.context.mode_flags or
98 "--stress-opt" in self.context.extra_flags):
99 timeout *= 4
100 if test.dependency is not None:
101 dep_command = [ c.replace(test.path, test.dependency) for c in command ]
102 else:
103 dep_command = None
104 return Job(command, dep_command, test.id, timeout, self.context.verbose)
105
106 def _MaybeRerun(self, pool, test):
107 if test.run <= self.context.rerun_failures_count:
108 # Possibly rerun this test if its run count is below the maximum per
109 # test.
110 if test.run == 1:
111 # Count the overall number of reran tests on the first rerun.
112 if self.reran_tests < self.context.rerun_failures_max:
113 self.reran_tests += 1
114 else:
115 # Don't rerun this if the overall number of rerun tests has been
116 # reached.
117 return
118 if test.run >= 2 and test.duration > self.context.timeout / 20:
119 # Rerun slow tests at most once.
120 return
121
122 # Rerun this test.
123 test.duration = None
124 test.output = None
125 test.run += 1
126 pool.add([self._GetJob(test)])
127 self.remaining += 1
128
92 def Run(self, jobs): 129 def Run(self, jobs):
93 self.indicator.Starting() 130 self.indicator.Starting()
94 self._RunInternal(jobs) 131 self._RunInternal(jobs)
95 self.indicator.Done() 132 self.indicator.Done()
96 if self.failed or self.remaining: 133 if self.failed or self.remaining:
97 return 1 134 return 1
98 return 0 135 return 0
99 136
100 def _RunInternal(self, jobs): 137 def _RunInternal(self, jobs):
101 pool = Pool(jobs) 138 pool = Pool(jobs)
102 test_map = {} 139 test_map = {}
103 # TODO(machenbach): Instead of filling the queue completely before 140 # TODO(machenbach): Instead of filling the queue completely before
104 # pool.imap_unordered, make this a generator that already starts testing 141 # pool.imap_unordered, make this a generator that already starts testing
105 # while the queue is filled. 142 # while the queue is filled.
106 queue = [] 143 queue = []
107 queued_exception = None 144 queued_exception = None
108 for test in self.tests: 145 for test in self.tests:
109 assert test.id >= 0 146 assert test.id >= 0
110 test_map[test.id] = test 147 test_map[test.id] = test
111 try: 148 try:
112 command = self.GetCommand(test) 149 queue.append([self._GetJob(test)])
113 except Exception, e: 150 except Exception, e:
114 # If this failed, save the exception and re-raise it later (after 151 # If this failed, save the exception and re-raise it later (after
115 # all other tests have had a chance to run). 152 # all other tests have had a chance to run).
116 queued_exception = e 153 queued_exception = e
117 continue 154 continue
118 timeout = self.context.timeout
119 if ("--stress-opt" in test.flags or
120 "--stress-opt" in self.context.mode_flags or
121 "--stress-opt" in self.context.extra_flags):
122 timeout *= 4
123 if test.dependency is not None:
124 dep_command = [ c.replace(test.path, test.dependency) for c in command ]
125 else:
126 dep_command = None
127 job = Job(command, dep_command, test.id, timeout, self.context.verbose)
128 queue.append([job])
129 try: 155 try:
130 it = pool.imap_unordered(RunTest, queue) 156 it = pool.imap_unordered(RunTest, queue)
131 for result in it: 157 for result in it:
132 test = test_map[result[0]] 158 test = test_map[result[0]]
133 self.indicator.AboutToRun(test) 159 self.indicator.AboutToRun(test)
134 test.output = result[1] 160 test.output = result[1]
135 test.duration = result[2] 161 test.duration = result[2]
136 has_unexpected_output = test.suite.HasUnexpectedOutput(test) 162 has_unexpected_output = test.suite.HasUnexpectedOutput(test)
137 if has_unexpected_output: 163 if has_unexpected_output:
138 self.failed.append(test) 164 self.failed.append(test)
139 if test.output.HasCrashed(): 165 if test.output.HasCrashed():
140 self.crashed += 1 166 self.crashed += 1
141 else: 167 else:
142 self._RunPerfSafe(lambda: self.perfdata.UpdatePerfData(test)) 168 self._RunPerfSafe(lambda: self.perfdata.UpdatePerfData(test))
143 self.succeeded += 1 169 self.succeeded += 1
144 self.remaining -= 1 170 self.remaining -= 1
145 self.indicator.HasRun(test, has_unexpected_output) 171 self.indicator.HasRun(test, has_unexpected_output)
172 if has_unexpected_output:
173 # Rerun test failures after the indicator has processed the results.
174 self._MaybeRerun(pool, test)
146 finally: 175 finally:
147 pool.terminate() 176 pool.terminate()
148 self._RunPerfSafe(lambda: self.perf_data_manager.close()) 177 self._RunPerfSafe(lambda: self.perf_data_manager.close())
149 if self.perf_failures: 178 if self.perf_failures:
150 # Nuke perf data in case of failures. This might not work on windows as 179 # Nuke perf data in case of failures. This might not work on windows as
151 # some files might still be open. 180 # some files might still be open.
152 print "Deleting perf test data due to db corruption." 181 print "Deleting perf test data due to db corruption."
153 shutil.rmtree(self.datapath) 182 shutil.rmtree(self.datapath)
154 if queued_exception: 183 if queued_exception:
155 raise queued_exception 184 raise queued_exception
(...skipping 13 matching lines...) Expand all
169 test.suite.GetFlagsForTestCase(test, self.context) + 198 test.suite.GetFlagsForTestCase(test, self.context) +
170 self.context.extra_flags) 199 self.context.extra_flags)
171 return cmd 200 return cmd
172 201
173 202
174 class BreakNowException(Exception): 203 class BreakNowException(Exception):
175 def __init__(self, value): 204 def __init__(self, value):
176 self.value = value 205 self.value = value
177 def __str__(self): 206 def __str__(self):
178 return repr(self.value) 207 return repr(self.value)
OLDNEW
« no previous file with comments | « tools/run-tests.py ('k') | tools/testrunner/objects/context.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698