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

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py

Issue 1783073002: Run auto-formatter on files in webkitpy/layout_tests/. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ran yapf -i --style '{based_on_style: pep8, column_limit: 132}' then did manual fix-up Created 4 years, 9 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
OLDNEW
1 # Copyright (C) 2010 Google Inc. All rights reserved. 1 # Copyright (C) 2010 Google Inc. All rights reserved.
2 # Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Sze ged 2 # Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Sze ged
3 # 3 #
4 # Redistribution and use in source and binary forms, with or without 4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are 5 # modification, are permitted provided that the following conditions are
6 # met: 6 # met:
7 # 7 #
8 # * Redistributions of source code must retain the above copyright 8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer. 9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above 10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer 11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the 12 # in the documentation and/or other materials provided with the
13 # distribution. 13 # distribution.
14 # * Neither the name of Google Inc. nor the names of its 14 # * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived from 15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission. 16 # this software without specific prior written permission.
17 # 17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 """ 29 """
31 The Manager runs a series of tests (TestType interface) against a set 30 The Manager runs a series of tests (TestType interface) against a set
32 of test files. If a test file fails a TestType, it returns a list of TestFailur e 31 of test files. If a test file fails a TestType, it returns a list of TestFailur e
33 objects to the Manager. The Manager then aggregates the TestFailures to 32 objects to the Manager. The Manager then aggregates the TestFailures to
34 create a final report. 33 create a final report.
35 """ 34 """
36 35
37 import datetime 36 import datetime
38 import json 37 import json
39 import logging 38 import logging
(...skipping 13 matching lines...) Expand all
53 from webkitpy.tool import grammar 52 from webkitpy.tool import grammar
54 53
55 _log = logging.getLogger(__name__) 54 _log = logging.getLogger(__name__)
56 55
57 # Builder base URL where we have the archived test results. 56 # Builder base URL where we have the archived test results.
58 BUILDER_BASE_URL = "http://build.chromium.org/buildbot/layout_test_results/" 57 BUILDER_BASE_URL = "http://build.chromium.org/buildbot/layout_test_results/"
59 58
60 TestExpectations = test_expectations.TestExpectations 59 TestExpectations = test_expectations.TestExpectations
61 60
62 61
63
64 class Manager(object): 62 class Manager(object):
65 """A class for managing running a series of tests on a series of layout 63 """A class for managing running a series of tests on a series of layout
66 test files.""" 64 test files."""
67 65
68 def __init__(self, port, options, printer): 66 def __init__(self, port, options, printer):
69 """Initialize test runner data structures. 67 """Initialize test runner data structures.
70 68
71 Args: 69 Args:
72 port: an object implementing port-specific 70 port: an object implementing port-specific
73 options: a dictionary of command line options 71 options: a dictionary of command line options
74 printer: a Printer object to record updates to. 72 printer: a Printer object to record updates to.
75 """ 73 """
76 self._port = port 74 self._port = port
77 self._filesystem = port.host.filesystem 75 self._filesystem = port.host.filesystem
78 self._options = options 76 self._options = options
79 self._printer = printer 77 self._printer = printer
80 self._expectations = None 78 self._expectations = None
81 79
82 self.HTTP_SUBDIR = 'http' + port.TEST_PATH_SEPARATOR 80 self.HTTP_SUBDIR = 'http' + port.TEST_PATH_SEPARATOR
83 self.INSPECTOR_SUBDIR = 'inspector' + port.TEST_PATH_SEPARATOR 81 self.INSPECTOR_SUBDIR = 'inspector' + port.TEST_PATH_SEPARATOR
84 self.PERF_SUBDIR = 'perf' 82 self.PERF_SUBDIR = 'perf'
85 self.WEBSOCKET_SUBDIR = 'websocket' + port.TEST_PATH_SEPARATOR 83 self.WEBSOCKET_SUBDIR = 'websocket' + port.TEST_PATH_SEPARATOR
86 self.VIRTUAL_HTTP_SUBDIR = port.TEST_PATH_SEPARATOR.join([ 84 self.VIRTUAL_HTTP_SUBDIR = port.TEST_PATH_SEPARATOR.join(['virtual', 'st able', 'http'])
87 'virtual', 'stable', 'http'])
88 self.LAYOUT_TESTS_DIRECTORY = 'LayoutTests' 85 self.LAYOUT_TESTS_DIRECTORY = 'LayoutTests'
89 self.ARCHIVED_RESULTS_LIMIT = 25 86 self.ARCHIVED_RESULTS_LIMIT = 25
90 self._http_server_started = False 87 self._http_server_started = False
91 self._wptserve_started = False 88 self._wptserve_started = False
92 self._websockets_server_started = False 89 self._websockets_server_started = False
93 90
94 self._results_directory = self._port.results_directory() 91 self._results_directory = self._port.results_directory()
95 self._finder = LayoutTestFinder(self._port, self._options) 92 self._finder = LayoutTestFinder(self._port, self._options)
96 self._runner = LayoutTestRunner(self._options, self._port, self._printer , self._results_directory, self._test_is_slow) 93 self._runner = LayoutTestRunner(self._options, self._port, self._printer , self._results_directory, self._test_is_slow)
97 94
98 def _collect_tests(self, args): 95 def _collect_tests(self, args):
99 return self._finder.find_tests(args, test_list=self._options.test_list, 96 return self._finder.find_tests(args, test_list=self._options.test_list, fastest_percentile=self._options.fastest)
100 fastest_percentile=self._options.fastest)
101 97
102 def _is_http_test(self, test): 98 def _is_http_test(self, test):
103 return ( 99 return (test.startswith(self.HTTP_SUBDIR) or self._is_websocket_test(tes t) or self.VIRTUAL_HTTP_SUBDIR in test)
104 test.startswith(self.HTTP_SUBDIR) or
105 self._is_websocket_test(test) or
106 self.VIRTUAL_HTTP_SUBDIR in test
107 )
108 100
109 def _is_inspector_test(self, test): 101 def _is_inspector_test(self, test):
110 return self.INSPECTOR_SUBDIR in test 102 return self.INSPECTOR_SUBDIR in test
111 103
112 def _is_websocket_test(self, test): 104 def _is_websocket_test(self, test):
113 if self._port.is_wpt_enabled() and self._port.is_wpt_test(test): 105 if self._port.is_wpt_enabled() and self._port.is_wpt_test(test):
114 return False 106 return False
115 107
116 return self.WEBSOCKET_SUBDIR in test 108 return self.WEBSOCKET_SUBDIR in test
117 109
(...skipping 11 matching lines...) Expand all
129 return tests_to_run, tests_to_skip 121 return tests_to_run, tests_to_skip
130 122
131 # Create a sorted list of test files so the subset chunk, 123 # Create a sorted list of test files so the subset chunk,
132 # if used, contains alphabetically consecutive tests. 124 # if used, contains alphabetically consecutive tests.
133 if self._options.order == 'natural': 125 if self._options.order == 'natural':
134 tests_to_run.sort(key=self._port.test_key) 126 tests_to_run.sort(key=self._port.test_key)
135 elif self._options.order == 'random': 127 elif self._options.order == 'random':
136 random.shuffle(tests_to_run) 128 random.shuffle(tests_to_run)
137 elif self._options.order == 'random-seeded': 129 elif self._options.order == 'random-seeded':
138 rnd = random.Random() 130 rnd = random.Random()
139 rnd.seed(4) # http://xkcd.com/221/ 131 rnd.seed(4) # http://xkcd.com/221/
140 rnd.shuffle(tests_to_run) 132 rnd.shuffle(tests_to_run)
141 133
142 tests_to_run, tests_in_other_chunks = self._finder.split_into_chunks(tes ts_to_run) 134 tests_to_run, tests_in_other_chunks = self._finder.split_into_chunks(tes ts_to_run)
143 self._expectations.add_extra_skipped_tests(tests_in_other_chunks) 135 self._expectations.add_extra_skipped_tests(tests_in_other_chunks)
144 tests_to_skip.update(tests_in_other_chunks) 136 tests_to_skip.update(tests_in_other_chunks)
145 137
146 return tests_to_run, tests_to_skip 138 return tests_to_run, tests_to_skip
147 139
148 def _test_input_for_file(self, test_file): 140 def _test_input_for_file(self, test_file):
149 return TestInput(test_file, 141 return TestInput(
142 test_file,
150 self._options.slow_time_out_ms if self._test_is_slow(test_file) else self._options.time_out_ms, 143 self._options.slow_time_out_ms if self._test_is_slow(test_file) else self._options.time_out_ms,
151 self._test_requires_lock(test_file), 144 self._test_requires_lock(test_file),
152 should_add_missing_baselines=(self._options.new_test_results and not self._test_is_expected_missing(test_file))) 145 should_add_missing_baselines=(self._options.new_test_results and not self._test_is_expected_missing(test_file)))
Dirk Pranke 2016/03/19 02:19:56 this is an interesting difference; I personally pr
153 146
154 def _test_requires_lock(self, test_file): 147 def _test_requires_lock(self, test_file):
155 """Return True if the test needs to be locked when 148 """Return True if the test needs to be locked when
156 running multiple copies of NRWTs. Perf tests are locked 149 running multiple copies of NRWTs. Perf tests are locked
157 because heavy load caused by running other tests in parallel 150 because heavy load caused by running other tests in parallel
158 might cause some of them to timeout.""" 151 might cause some of them to timeout."""
159 return self._is_http_test(test_file) or self._is_perf_test(test_file) 152 return self._is_http_test(test_file) or self._is_perf_test(test_file)
160 153
161 def _test_is_expected_missing(self, test_file): 154 def _test_is_expected_missing(self, test_file):
162 expectations = self._expectations.model().get_expectations(test_file) 155 expectations = self._expectations.model().get_expectations(test_file)
163 return test_expectations.MISSING in expectations or test_expectations.NE EDS_REBASELINE in expectations or test_expectations.NEEDS_MANUAL_REBASELINE in e xpectations 156 return test_expectations.MISSING in expectations or test_expectations.NE EDS_REBASELINE in expectations or test_expectations.NEEDS_MANUAL_REBASELINE in e xpectations
164 157
165 def _test_is_slow(self, test_file): 158 def _test_is_slow(self, test_file):
166 return test_expectations.SLOW in self._expectations.model().get_expectat ions(test_file) 159 return test_expectations.SLOW in self._expectations.model().get_expectat ions(test_file)
167 160
168 def needs_servers(self, test_names): 161 def needs_servers(self, test_names):
169 return any(self._test_requires_lock(test_name) for test_name in test_nam es) 162 return any(self._test_requires_lock(test_name) for test_name in test_nam es)
170 163
171 def _rename_results_folder(self): 164 def _rename_results_folder(self):
172 try: 165 try:
173 timestamp = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(self._ filesystem.mtime(self._filesystem.join(self._results_directory, "results.html")) )) 166 timestamp = time.strftime(
167 "%Y-%m-%d-%H-%M-%S",
168 time.localtime(self._filesystem.mtime(self._filesystem.join(self ._results_directory, "results.html"))))
Dirk Pranke 2016/03/19 02:19:56 I wonder why yapf broke the line here and autopep8
174 except (IOError, OSError), e: 169 except (IOError, OSError), e:
175 # It might be possible that results.html was not generated in previo us run, because the test 170 # It might be possible that results.html was not generated in previo us run, because the test
176 # run was interrupted even before testing started. In those cases, d on't archive the folder. 171 # run was interrupted even before testing started. In those cases, d on't archive the folder.
177 # Simply override the current folder contents with new results. 172 # Simply override the current folder contents with new results.
178 import errno 173 import errno
179 if e.errno == errno.EEXIST or e.errno == errno.ENOENT: 174 if e.errno == errno.EEXIST or e.errno == errno.ENOENT:
180 self._printer.write_update("No results.html file found in previo us run, skipping it.") 175 self._printer.write_update("No results.html file found in previo us run, skipping it.")
181 return None 176 return None
182 archived_name = ''.join((self._filesystem.basename(self._results_directo ry), "_", timestamp)) 177 archived_name = ''.join((self._filesystem.basename(self._results_directo ry), "_", timestamp))
183 archived_path = self._filesystem.join(self._filesystem.dirname(self._res ults_directory), archived_name) 178 archived_path = self._filesystem.join(self._filesystem.dirname(self._res ults_directory), archived_name)
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 should_retry_failures = len(paths) < len(test_names) 260 should_retry_failures = len(paths) < len(test_names)
266 else: 261 else:
267 should_retry_failures = self._options.retry_failures 262 should_retry_failures = self._options.retry_failures
268 263
269 enabled_pixel_tests_in_retry = False 264 enabled_pixel_tests_in_retry = False
270 try: 265 try:
271 self._start_servers(tests_to_run) 266 self._start_servers(tests_to_run)
272 267
273 num_workers = self._port.num_workers(int(self._options.child_process es)) 268 num_workers = self._port.num_workers(int(self._options.child_process es))
274 269
275 initial_results = self._run_tests( 270 initial_results = self._run_tests(tests_to_run, tests_to_skip, self. _options.repeat_each, self._options.iterations,
276 tests_to_run, tests_to_skip, self._options.repeat_each, self._op tions.iterations, 271 num_workers)
Dirk Pranke 2016/03/19 02:19:56 and yet here the formatting is the opposite for wh
277 num_workers)
278 272
279 # Don't retry failures when interrupted by user or failures limit ex ception. 273 # Don't retry failures when interrupted by user or failures limit ex ception.
280 should_retry_failures = should_retry_failures and not (initial_resul ts.interrupted or initial_results.keyboard_interrupted) 274 should_retry_failures = should_retry_failures and not (initial_resul ts.interrupted or
275 initial_resul ts.keyboard_interrupted)
281 276
282 tests_to_retry = self._tests_to_retry(initial_results) 277 tests_to_retry = self._tests_to_retry(initial_results)
283 all_retry_results = [] 278 all_retry_results = []
284 if should_retry_failures and tests_to_retry: 279 if should_retry_failures and tests_to_retry:
285 enabled_pixel_tests_in_retry = self._force_pixel_tests_if_needed () 280 enabled_pixel_tests_in_retry = self._force_pixel_tests_if_needed ()
286 281
287 for retry_attempt in xrange(1, self._options.num_retries + 1): 282 for retry_attempt in xrange(1, self._options.num_retries + 1):
288 if not tests_to_retry: 283 if not tests_to_retry:
289 break 284 break
290 285
291 _log.info('') 286 _log.info('')
292 _log.info('Retrying %s, attempt %d of %d...' % 287 _log.info('Retrying %s, attempt %d of %d...' % (grammar.plur alize('unexpected failure', len(tests_to_retry)),
293 (grammar.pluralize('unexpected failure', len(tests _to_retry)), 288 retry_attemp t, self._options.num_retries))
294 retry_attempt, self._options.num_retries))
295 289
296 retry_results = self._run_tests(tests_to_retry, 290 retry_results = self._run_tests(tests_to_retry,
297 tests_to_skip=set(), 291 tests_to_skip=set(),
298 repeat_each=1, 292 repeat_each=1,
299 iterations=1, 293 iterations=1,
300 num_workers=num_workers, 294 num_workers=num_workers,
301 retry_attempt=retry_attempt) 295 retry_attempt=retry_attempt)
302 all_retry_results.append(retry_results) 296 all_retry_results.append(retry_results)
303 297
304 tests_to_retry = self._tests_to_retry(retry_results) 298 tests_to_retry = self._tests_to_retry(retry_results)
305 299
306 if enabled_pixel_tests_in_retry: 300 if enabled_pixel_tests_in_retry:
307 self._options.pixel_tests = False 301 self._options.pixel_tests = False
308 finally: 302 finally:
309 self._stop_servers() 303 self._stop_servers()
310 self._clean_up_run() 304 self._clean_up_run()
311 305
312 # Some crash logs can take a long time to be written out so look 306 # Some crash logs can take a long time to be written out so look
313 # for new logs after the test run finishes. 307 # for new logs after the test run finishes.
314 self._printer.write_update("looking for new crash logs") 308 self._printer.write_update("looking for new crash logs")
315 self._look_for_new_crash_logs(initial_results, start_time) 309 self._look_for_new_crash_logs(initial_results, start_time)
316 for retry_attempt_results in all_retry_results: 310 for retry_attempt_results in all_retry_results:
317 self._look_for_new_crash_logs(retry_attempt_results, start_time) 311 self._look_for_new_crash_logs(retry_attempt_results, start_time)
318 312
319 _log.debug("summarizing results") 313 _log.debug("summarizing results")
320 summarized_full_results = test_run_results.summarize_results( 314 summarized_full_results = test_run_results.summarize_results(self._port, self._expectations, initial_results,
321 self._port, self._expectations, initial_results, all_retry_results, 315 all_retry_r esults, enabled_pixel_tests_in_retry)
322 enabled_pixel_tests_in_retry) 316 summarized_failing_results = test_run_results.summarize_results(self._po rt,
323 summarized_failing_results = test_run_results.summarize_results( 317 self._ex pectations,
324 self._port, self._expectations, initial_results, all_retry_results, 318 initial_ results,
325 enabled_pixel_tests_in_retry, only_include_failing=True) 319 all_retr y_results,
320 enabled_ pixel_tests_in_retry,
321 only_inc lude_failing=True)
326 322
327 exit_code = summarized_failing_results['num_regressions'] 323 exit_code = summarized_failing_results['num_regressions']
328 if exit_code > test_run_results.MAX_FAILURES_EXIT_STATUS: 324 if exit_code > test_run_results.MAX_FAILURES_EXIT_STATUS:
329 _log.warning('num regressions (%d) exceeds max exit status (%d)' % 325 _log.warning('num regressions (%d) exceeds max exit status (%d)' %
330 (exit_code, test_run_results.MAX_FAILURES_EXIT_STATUS)) 326 (exit_code, test_run_results.MAX_FAILURES_EXIT_STATUS))
331 exit_code = test_run_results.MAX_FAILURES_EXIT_STATUS 327 exit_code = test_run_results.MAX_FAILURES_EXIT_STATUS
332 328
333 if not self._options.dry_run: 329 if not self._options.dry_run:
334 self._write_json_files(summarized_full_results, summarized_failing_r esults, initial_results, running_all_tests) 330 self._write_json_files(summarized_full_results, summarized_failing_r esults, initial_results, running_all_tests)
335 331
336 if self._options.write_full_results_to: 332 if self._options.write_full_results_to:
337 self._filesystem.copyfile(self._filesystem.join(self._results_di rectory, "full_results.json"), 333 self._filesystem.copyfile(
338 self._options.write_full_results_to) 334 self._filesystem.join(self._results_directory, "full_results .json"), self._options.write_full_results_to)
339 335
340 self._upload_json_files() 336 self._upload_json_files()
341 337
342 results_path = self._filesystem.join(self._results_directory, "resul ts.html") 338 results_path = self._filesystem.join(self._results_directory, "resul ts.html")
343 self._copy_results_html_file(results_path) 339 self._copy_results_html_file(results_path)
344 if initial_results.keyboard_interrupted: 340 if initial_results.keyboard_interrupted:
345 exit_code = test_run_results.INTERRUPTED_EXIT_STATUS 341 exit_code = test_run_results.INTERRUPTED_EXIT_STATUS
346 else: 342 else:
347 if initial_results.interrupted: 343 if initial_results.interrupted:
348 exit_code = test_run_results.EARLY_EXIT_STATUS 344 exit_code = test_run_results.EARLY_EXIT_STATUS
349 if self._options.show_results and (exit_code or (self._options.f ull_results_html and initial_results.total_failures)): 345 if self._options.show_results and (exit_code or
346 (self._options.full_results_h tml and initial_results.total_failures)):
350 self._port.show_results_html_file(results_path) 347 self._port.show_results_html_file(results_path)
351 self._printer.print_results(time.time() - start_time, initial_re sults, summarized_failing_results) 348 self._printer.print_results(time.time() - start_time, initial_re sults, summarized_failing_results)
352 349
353 self._check_for_stale_w3c_dir() 350 self._check_for_stale_w3c_dir()
354 351
355 return test_run_results.RunDetails( 352 return test_run_results.RunDetails(exit_code, summarized_full_results, s ummarized_failing_results, initial_results,
356 exit_code, summarized_full_results, summarized_failing_results, 353 all_retry_results, enabled_pixel_test s_in_retry)
357 initial_results, all_retry_results, enabled_pixel_tests_in_retry)
358 354
359 def _run_tests(self, tests_to_run, tests_to_skip, repeat_each, iterations, 355 def _run_tests(self, tests_to_run, tests_to_skip, repeat_each, iterations, n um_workers, retry_attempt=0):
360 num_workers, retry_attempt=0):
361 356
362 test_inputs = [] 357 test_inputs = []
363 for _ in xrange(iterations): 358 for _ in xrange(iterations):
364 for test in tests_to_run: 359 for test in tests_to_run:
365 for _ in xrange(repeat_each): 360 for _ in xrange(repeat_each):
366 test_inputs.append(self._test_input_for_file(test)) 361 test_inputs.append(self._test_input_for_file(test))
367 return self._runner.run_tests(self._expectations, test_inputs, 362 return self._runner.run_tests(self._expectations, test_inputs, tests_to_ skip, num_workers, retry_attempt)
368 tests_to_skip, num_workers, retry_attempt)
369 363
370 def _start_servers(self, tests_to_run): 364 def _start_servers(self, tests_to_run):
371 if self._port.is_wpt_enabled() and any(self._port.is_wpt_test(test) for test in tests_to_run): 365 if self._port.is_wpt_enabled() and any(self._port.is_wpt_test(test) for test in tests_to_run):
372 self._printer.write_update('Starting WPTServe ...') 366 self._printer.write_update('Starting WPTServe ...')
373 self._port.start_wptserve() 367 self._port.start_wptserve()
374 self._wptserve_started = True 368 self._wptserve_started = True
375 369
376 if self._port.requires_http_server() or any((self._is_http_test(test) or self._is_inspector_test(test)) for test in tests_to_run): 370 if self._port.requires_http_server() or any((self._is_http_test(test) or self._is_inspector_test(test))
371 for test in tests_to_run):
377 self._printer.write_update('Starting HTTP server ...') 372 self._printer.write_update('Starting HTTP server ...')
378 self._port.start_http_server(additional_dirs={}, number_of_drivers=s elf._options.max_locked_shards) 373 self._port.start_http_server(additional_dirs={}, number_of_drivers=s elf._options.max_locked_shards)
379 self._http_server_started = True 374 self._http_server_started = True
380 375
381 if any(self._is_websocket_test(test) for test in tests_to_run): 376 if any(self._is_websocket_test(test) for test in tests_to_run):
382 self._printer.write_update('Starting WebSocket server ...') 377 self._printer.write_update('Starting WebSocket server ...')
383 self._port.start_websocket_server() 378 self._port.start_websocket_server()
384 self._websockets_server_started = True 379 self._websockets_server_started = True
385 380
386 def _stop_servers(self): 381 def _stop_servers(self):
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 if self._filesystem.isdir(file_path) and self._results_directory in file_path: 464 if self._filesystem.isdir(file_path) and self._results_directory in file_path:
470 results_directories.append(file_path) 465 results_directories.append(file_path)
471 self._delete_dirs(results_directories) 466 self._delete_dirs(results_directories)
472 467
473 # Port specific clean-up. 468 # Port specific clean-up.
474 self._port.clobber_old_port_specific_results() 469 self._port.clobber_old_port_specific_results()
475 470
476 def _tests_to_retry(self, run_results): 471 def _tests_to_retry(self, run_results):
477 # TODO(ojan): This should also check that result.type != test_expectatio ns.MISSING since retrying missing expectations is silly. 472 # TODO(ojan): This should also check that result.type != test_expectatio ns.MISSING since retrying missing expectations is silly.
478 # But that's a bit tricky since we only consider the last retry attempt for the count of unexpected regressions. 473 # But that's a bit tricky since we only consider the last retry attempt for the count of unexpected regressions.
479 return [result.test_name for result in run_results.unexpected_results_by _name.values() if result.type != test_expectations.PASS] 474 return [result.test_name
475 for result in run_results.unexpected_results_by_name.values() if result.type != test_expectations.PASS]
480 476
481 def _write_json_files(self, summarized_full_results, summarized_failing_resu lts, initial_results, running_all_tests): 477 def _write_json_files(self, summarized_full_results, summarized_failing_resu lts, initial_results, running_all_tests):
482 _log.debug("Writing JSON files in %s." % self._results_directory) 478 _log.debug("Writing JSON files in %s." % self._results_directory)
483 479
484 # FIXME: Upload stats.json to the server and delete times_ms. 480 # FIXME: Upload stats.json to the server and delete times_ms.
485 times_trie = json_results_generator.test_timings_trie(initial_results.re sults_by_name.values()) 481 times_trie = json_results_generator.test_timings_trie(initial_results.re sults_by_name.values())
486 times_json_path = self._filesystem.join(self._results_directory, "times_ ms.json") 482 times_json_path = self._filesystem.join(self._results_directory, "times_ ms.json")
487 json_results_generator.write_json(self._filesystem, times_trie, times_js on_path) 483 json_results_generator.write_json(self._filesystem, times_trie, times_js on_path)
488 484
489 # Save out the times data so we can use it for --fastest in the future. 485 # Save out the times data so we can use it for --fastest in the future.
490 if running_all_tests: 486 if running_all_tests:
491 bot_test_times_path = self._port.bot_test_times_path() 487 bot_test_times_path = self._port.bot_test_times_path()
492 self._filesystem.maybe_make_directory(self._filesystem.dirname(bot_t est_times_path)) 488 self._filesystem.maybe_make_directory(self._filesystem.dirname(bot_t est_times_path))
493 json_results_generator.write_json(self._filesystem, times_trie, bot_ test_times_path) 489 json_results_generator.write_json(self._filesystem, times_trie, bot_ test_times_path)
494 490
495 stats_trie = self._stats_trie(initial_results) 491 stats_trie = self._stats_trie(initial_results)
496 stats_path = self._filesystem.join(self._results_directory, "stats.json" ) 492 stats_path = self._filesystem.join(self._results_directory, "stats.json" )
497 self._filesystem.write_text_file(stats_path, json.dumps(stats_trie)) 493 self._filesystem.write_text_file(stats_path, json.dumps(stats_trie))
498 494
499 full_results_path = self._filesystem.join(self._results_directory, "full _results.json") 495 full_results_path = self._filesystem.join(self._results_directory, "full _results.json")
500 json_results_generator.write_json(self._filesystem, summarized_full_resu lts, full_results_path) 496 json_results_generator.write_json(self._filesystem, summarized_full_resu lts, full_results_path)
501 497
502 full_results_path = self._filesystem.join(self._results_directory, "fail ing_results.json") 498 full_results_path = self._filesystem.join(self._results_directory, "fail ing_results.json")
503 # We write failing_results.json out as jsonp because we need to load it from a file url for results.html and Chromium doesn't allow that. 499 # We write failing_results.json out as jsonp because we need to load it
500 # from a file url for results.html and Chromium doesn't allow that.
504 json_results_generator.write_json(self._filesystem, summarized_failing_r esults, full_results_path, callback="ADD_RESULTS") 501 json_results_generator.write_json(self._filesystem, summarized_failing_r esults, full_results_path, callback="ADD_RESULTS")
505 502
506 _log.debug("Finished writing JSON files.") 503 _log.debug("Finished writing JSON files.")
507 504
508 def _upload_json_files(self): 505 def _upload_json_files(self):
509 if not self._options.test_results_server: 506 if not self._options.test_results_server:
510 return 507 return
511 508
512 if not self._options.master_name: 509 if not self._options.master_name:
513 _log.error("--test-results-server was set, but --master-name was not . Not uploading JSON files.") 510 _log.error("--test-results-server was set, but --master-name was not . Not uploading JSON files.")
514 return 511 return
515 512
516 _log.debug("Uploading JSON files for builder: %s", self._options.builder _name) 513 _log.debug("Uploading JSON files for builder: %s", self._options.builder _name)
517 attrs = [("builder", self._options.builder_name), 514 attrs = [("builder", self._options.builder_name), ("testtype", self._opt ions.step_name),
518 ("testtype", self._options.step_name),
519 ("master", self._options.master_name)] 515 ("master", self._options.master_name)]
520 516
521 files = [(file, self._filesystem.join(self._results_directory, file)) fo r file in ["failing_results.json", "full_results.json", "times_ms.json"]] 517 files = [(file, self._filesystem.join(self._results_directory, file))
518 for file in ["failing_results.json", "full_results.json", "time s_ms.json"]]
522 519
523 url = "http://%s/testfile/upload" % self._options.test_results_server 520 url = "http://%s/testfile/upload" % self._options.test_results_server
524 # Set uploading timeout in case appengine server is having problems. 521 # Set uploading timeout in case appengine server is having problems.
525 # 120 seconds are more than enough to upload test results. 522 # 120 seconds are more than enough to upload test results.
526 uploader = FileUploader(url, 120) 523 uploader = FileUploader(url, 120)
527 try: 524 try:
528 response = uploader.upload_as_multipart_form_data(self._filesystem, files, attrs) 525 response = uploader.upload_as_multipart_form_data(self._filesystem, files, attrs)
529 if response: 526 if response:
530 if response.code == 200: 527 if response.code == 200:
531 _log.debug("JSON uploaded.") 528 _log.debug("JSON uploaded.")
(...skipping 12 matching lines...) Expand all
544 if self._filesystem.exists(results_file): 541 if self._filesystem.exists(results_file):
545 self._filesystem.copyfile(results_file, destination_path) 542 self._filesystem.copyfile(results_file, destination_path)
546 543
547 def _stats_trie(self, initial_results): 544 def _stats_trie(self, initial_results):
548 def _worker_number(worker_name): 545 def _worker_number(worker_name):
549 return int(worker_name.split('/')[1]) if worker_name else -1 546 return int(worker_name.split('/')[1]) if worker_name else -1
550 547
551 stats = {} 548 stats = {}
552 for result in initial_results.results_by_name.values(): 549 for result in initial_results.results_by_name.values():
553 if result.type != test_expectations.SKIP: 550 if result.type != test_expectations.SKIP:
554 stats[result.test_name] = {'results': (_worker_number(result.wor ker_name), result.test_number, result.pid, int(result.test_run_time * 1000), int (result.total_run_time * 1000))} 551 stats[result.test_name] = {'results': (_worker_number(result.wor ker_name), result.test_number, result.pid,
552 int(result.test_run_time * 1000), int(result.total_run_time * 1000))}
555 stats_trie = {} 553 stats_trie = {}
556 for name, value in stats.iteritems(): 554 for name, value in stats.iteritems():
557 json_results_generator.add_path_to_trie(name, value, stats_trie) 555 json_results_generator.add_path_to_trie(name, value, stats_trie)
558 return stats_trie 556 return stats_trie
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698