OLD | NEW |
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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 output = commands.Execute(job.command, job.verbose, job.timeout) | 58 output = commands.Execute(job.command, job.verbose, job.timeout) |
59 return (job.id, output, time.time() - start_time) | 59 return (job.id, output, time.time() - start_time) |
60 | 60 |
61 class Runner(object): | 61 class Runner(object): |
62 | 62 |
63 def __init__(self, suites, progress_indicator, context): | 63 def __init__(self, suites, progress_indicator, context): |
64 self.datapath = os.path.join("out", "testrunner_data") | 64 self.datapath = os.path.join("out", "testrunner_data") |
65 self.perf_data_manager = perfdata.PerfDataManager(self.datapath) | 65 self.perf_data_manager = perfdata.PerfDataManager(self.datapath) |
66 self.perfdata = self.perf_data_manager.GetStore(context.arch, context.mode) | 66 self.perfdata = self.perf_data_manager.GetStore(context.arch, context.mode) |
67 self.perf_failures = False | 67 self.perf_failures = False |
| 68 self.printed_allocations = False |
68 self.tests = [ t for s in suites for t in s.tests ] | 69 self.tests = [ t for s in suites for t in s.tests ] |
69 if not context.no_sorting: | 70 if not context.no_sorting: |
70 for t in self.tests: | 71 for t in self.tests: |
71 t.duration = self.perfdata.FetchPerfData(t) or 1.0 | 72 t.duration = self.perfdata.FetchPerfData(t) or 1.0 |
72 self.tests.sort(key=lambda t: t.duration, reverse=True) | 73 self.tests.sort(key=lambda t: t.duration, reverse=True) |
73 self._CommonInit(len(self.tests), progress_indicator, context) | 74 self._CommonInit(len(self.tests), progress_indicator, context) |
74 | 75 |
75 def _CommonInit(self, num_tests, progress_indicator, context): | 76 def _CommonInit(self, num_tests, progress_indicator, context): |
76 self.indicator = progress_indicator | 77 self.indicator = progress_indicator |
77 progress_indicator.runner = self | 78 progress_indicator.runner = self |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 # as unexpected even if it flakily passes in order to include it in the | 143 # as unexpected even if it flakily passes in order to include it in the |
143 # output. | 144 # output. |
144 self.indicator.HasRun(test, has_unexpected_output or test.run > 1) | 145 self.indicator.HasRun(test, has_unexpected_output or test.run > 1) |
145 if has_unexpected_output: | 146 if has_unexpected_output: |
146 # Rerun test failures after the indicator has processed the results. | 147 # Rerun test failures after the indicator has processed the results. |
147 self._MaybeRerun(pool, test) | 148 self._MaybeRerun(pool, test) |
148 # Update the perf database if the test succeeded. | 149 # Update the perf database if the test succeeded. |
149 return not has_unexpected_output | 150 return not has_unexpected_output |
150 | 151 |
151 def _ProcessTestPredictable(self, test, result, pool): | 152 def _ProcessTestPredictable(self, test, result, pool): |
| 153 def HasDifferentAllocations(output1, output2): |
| 154 def AllocationStr(stdout): |
| 155 for line in reversed((stdout or "").splitlines()): |
| 156 if line.startswith("### Allocations = "): |
| 157 self.printed_allocations = True |
| 158 return line |
| 159 return "" |
| 160 return (AllocationStr(output1.stdout) != AllocationStr(output2.stdout)) |
| 161 |
152 # Always pass the test duration for the database update. | 162 # Always pass the test duration for the database update. |
153 test.duration = result[2] | 163 test.duration = result[2] |
154 if test.run == 1 and result[1].HasTimedOut(): | 164 if test.run == 1 and result[1].HasTimedOut(): |
155 # If we get a timeout in the first run, we are already in an | 165 # If we get a timeout in the first run, we are already in an |
156 # unpredictable state. Just report it as a failure and don't rerun. | 166 # unpredictable state. Just report it as a failure and don't rerun. |
157 self.indicator.AboutToRun(test) | 167 self.indicator.AboutToRun(test) |
158 test.output = result[1] | 168 test.output = result[1] |
159 self.remaining -= 1 | 169 self.remaining -= 1 |
160 self.failed.append(test) | 170 self.failed.append(test) |
161 self.indicator.HasRun(test, True) | 171 self.indicator.HasRun(test, True) |
162 if test.run > 1 and test.output != result[1]: | 172 if test.run > 1 and HasDifferentAllocations(test.output, result[1]): |
163 # From the second run on, check for differences. If a difference is | 173 # From the second run on, check for different allocations. If a |
164 # found, call the indicator twice to report both tests. All runs of each | 174 # difference is found, call the indicator twice to report both tests. |
165 # test are counted as one for the statistic. | 175 # All runs of each test are counted as one for the statistic. |
166 self.indicator.AboutToRun(test) | 176 self.indicator.AboutToRun(test) |
167 self.remaining -= 1 | 177 self.remaining -= 1 |
168 self.failed.append(test) | 178 self.failed.append(test) |
169 self.indicator.HasRun(test, True) | 179 self.indicator.HasRun(test, True) |
170 self.indicator.AboutToRun(test) | 180 self.indicator.AboutToRun(test) |
171 test.output = result[1] | 181 test.output = result[1] |
172 self.indicator.HasRun(test, True) | 182 self.indicator.HasRun(test, True) |
173 elif test.run >= 3: | 183 elif test.run >= 3: |
174 # No difference on the third run -> report a success. | 184 # No difference on the third run -> report a success. |
175 self.indicator.AboutToRun(test) | 185 self.indicator.AboutToRun(test) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 pool.terminate() | 236 pool.terminate() |
227 self._RunPerfSafe(lambda: self.perf_data_manager.close()) | 237 self._RunPerfSafe(lambda: self.perf_data_manager.close()) |
228 if self.perf_failures: | 238 if self.perf_failures: |
229 # Nuke perf data in case of failures. This might not work on windows as | 239 # Nuke perf data in case of failures. This might not work on windows as |
230 # some files might still be open. | 240 # some files might still be open. |
231 print "Deleting perf test data due to db corruption." | 241 print "Deleting perf test data due to db corruption." |
232 shutil.rmtree(self.datapath) | 242 shutil.rmtree(self.datapath) |
233 if queued_exception: | 243 if queued_exception: |
234 raise queued_exception | 244 raise queued_exception |
235 | 245 |
| 246 # Make sure that any allocations were printed in predictable mode. |
| 247 assert not self.context.predictable or self.printed_allocations |
236 | 248 |
237 def GetCommand(self, test): | 249 def GetCommand(self, test): |
238 d8testflag = [] | 250 d8testflag = [] |
239 shell = test.suite.shell() | 251 shell = test.suite.shell() |
240 if shell == "d8": | 252 if shell == "d8": |
241 d8testflag = ["--test"] | 253 d8testflag = ["--test"] |
242 if utils.IsWindows(): | 254 if utils.IsWindows(): |
243 shell += ".exe" | 255 shell += ".exe" |
244 cmd = (self.context.command_prefix + | 256 cmd = (self.context.command_prefix + |
245 [os.path.abspath(os.path.join(self.context.shell_dir, shell))] + | 257 [os.path.abspath(os.path.join(self.context.shell_dir, shell))] + |
246 d8testflag + | 258 d8testflag + |
247 ["--random-seed=%s" % self.context.random_seed] + | 259 ["--random-seed=%s" % self.context.random_seed] + |
248 test.suite.GetFlagsForTestCase(test, self.context) + | 260 test.suite.GetFlagsForTestCase(test, self.context) + |
249 self.context.extra_flags) | 261 self.context.extra_flags) |
250 return cmd | 262 return cmd |
251 | 263 |
252 | 264 |
253 class BreakNowException(Exception): | 265 class BreakNowException(Exception): |
254 def __init__(self, value): | 266 def __init__(self, value): |
255 self.value = value | 267 self.value = value |
256 def __str__(self): | 268 def __str__(self): |
257 return repr(self.value) | 269 return repr(self.value) |
OLD | NEW |