Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 starting the required helper servers, deciding the order and way to | 33 starting the required helper servers, deciding the order and way to |
| 34 run the tests, retrying fails tests and collecting the test results, | 34 run the tests, retrying fails tests and collecting the test results, |
| 35 including crash logs, and mismatches with expectations. | 35 including crash logs, and mismatches with expectations. |
| 36 | 36 |
| 37 The Manager object has a constructor and one main method called run. | 37 The Manager object has a constructor and one main method called run. |
| 38 """ | 38 """ |
| 39 | 39 |
| 40 import json | 40 import json |
| 41 import logging | 41 import logging |
| 42 import random | 42 import random |
| 43 import re | |
| 43 import sys | 44 import sys |
| 44 import time | 45 import time |
| 45 | 46 |
| 46 from webkitpy.common.net.file_uploader import FileUploader | 47 from webkitpy.common.net.file_uploader import FileUploader |
| 47 from webkitpy.layout_tests.controllers.layout_test_finder import LayoutTestFinde r | 48 from webkitpy.layout_tests.controllers.layout_test_finder import LayoutTestFinde r |
| 48 from webkitpy.layout_tests.controllers.layout_test_runner import LayoutTestRunne r | 49 from webkitpy.layout_tests.controllers.layout_test_runner import LayoutTestRunne r |
| 49 from webkitpy.layout_tests.controllers.test_result_writer import TestResultWrite r | 50 from webkitpy.layout_tests.controllers.test_result_writer import TestResultWrite r |
| 50 from webkitpy.layout_tests.layout_package import json_results_generator | 51 from webkitpy.layout_tests.layout_package import json_results_generator |
| 51 from webkitpy.layout_tests.models import test_expectations | 52 from webkitpy.layout_tests.models import test_expectations |
| 52 from webkitpy.layout_tests.models import test_failures | 53 from webkitpy.layout_tests.models import test_failures |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 82 self.HTTP_SUBDIR = 'http' + port.TEST_PATH_SEPARATOR | 83 self.HTTP_SUBDIR = 'http' + port.TEST_PATH_SEPARATOR |
| 83 self.INSPECTOR_SUBDIR = 'inspector' + port.TEST_PATH_SEPARATOR | 84 self.INSPECTOR_SUBDIR = 'inspector' + port.TEST_PATH_SEPARATOR |
| 84 self.PERF_SUBDIR = 'perf' | 85 self.PERF_SUBDIR = 'perf' |
| 85 self.WEBSOCKET_SUBDIR = 'websocket' + port.TEST_PATH_SEPARATOR | 86 self.WEBSOCKET_SUBDIR = 'websocket' + port.TEST_PATH_SEPARATOR |
| 86 self.LAYOUT_TESTS_DIRECTORY = 'LayoutTests' | 87 self.LAYOUT_TESTS_DIRECTORY = 'LayoutTests' |
| 87 self.ARCHIVED_RESULTS_LIMIT = 25 | 88 self.ARCHIVED_RESULTS_LIMIT = 25 |
| 88 self._http_server_started = False | 89 self._http_server_started = False |
| 89 self._wptserve_started = False | 90 self._wptserve_started = False |
| 90 self._websockets_server_started = False | 91 self._websockets_server_started = False |
| 91 | 92 |
| 93 self._random_seed = None | |
| 92 self._results_directory = self._port.results_directory() | 94 self._results_directory = self._port.results_directory() |
| 93 self._finder = LayoutTestFinder(self._port, self._options) | 95 self._finder = LayoutTestFinder(self._port, self._options) |
| 94 self._runner = LayoutTestRunner(self._options, self._port, self._printer , self._results_directory, self._test_is_slow) | 96 self._runner = LayoutTestRunner(self._options, self._port, self._printer , self._results_directory, self._test_is_slow) |
| 95 | 97 |
| 96 def run(self, args): | 98 def run(self, args): |
| 97 """Run the tests and return a RunDetails object with the results.""" | 99 """Run the tests and return a RunDetails object with the results.""" |
| 98 start_time = time.time() | 100 start_time = time.time() |
| 99 self._printer.write_update("Collecting tests ...") | 101 self._printer.write_update("Collecting tests ...") |
| 100 running_all_tests = False | 102 running_all_tests = False |
| 101 try: | 103 try: |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 112 | 114 |
| 113 # Check to make sure we're not skipping every test. | 115 # Check to make sure we're not skipping every test. |
| 114 if not tests_to_run: | 116 if not tests_to_run: |
| 115 _log.critical('No tests to run.') | 117 _log.critical('No tests to run.') |
| 116 return test_run_results.RunDetails(exit_code=test_run_results.NO_TES TS_EXIT_STATUS) | 118 return test_run_results.RunDetails(exit_code=test_run_results.NO_TES TS_EXIT_STATUS) |
| 117 | 119 |
| 118 exit_code = self._set_up_run(tests_to_run) | 120 exit_code = self._set_up_run(tests_to_run) |
| 119 if exit_code: | 121 if exit_code: |
| 120 return test_run_results.RunDetails(exit_code=exit_code) | 122 return test_run_results.RunDetails(exit_code=exit_code) |
| 121 | 123 |
| 124 # Write out the random seed and the order we are running the tests in. | |
| 125 if not self._options.dry_run: | |
| 126 if self._random_seed: | |
| 127 self._filesystem.write_text_file( | |
| 128 self._filesystem.join(self._results_directory, "random-seed. txt"), | |
| 129 "%s\n" % self._random_seed) | |
| 130 self._filesystem.write_text_file( | |
| 131 self._filesystem.join(self._results_directory, "tests-run-order. txt"), | |
| 132 "\n".join(tests_to_run)) | |
|
Dirk Pranke
2016/06/21 23:47:13
How does this relate to your "write a json file ou
mithro
2016/06/22 08:40:08
Logging the random seed into the json environment
| |
| 133 | |
| 122 # Don't retry failures if an explicit list of tests was passed in. | 134 # Don't retry failures if an explicit list of tests was passed in. |
| 123 if self._options.retry_failures is None: | 135 if self._options.retry_failures is None: |
| 124 should_retry_failures = len(paths) < len(test_names) | 136 should_retry_failures = len(paths) < len(test_names) |
| 125 else: | 137 else: |
| 126 should_retry_failures = self._options.retry_failures | 138 should_retry_failures = self._options.retry_failures |
| 127 | 139 |
| 128 enabled_pixel_tests_in_retry = False | 140 enabled_pixel_tests_in_retry = False |
| 129 try: | 141 try: |
| 130 self._start_servers(tests_to_run) | 142 self._start_servers(tests_to_run) |
| 131 | 143 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 tests_to_skip = self._finder.skip_tests(paths, test_names, self._expecta tions, self._http_tests(test_names)) | 257 tests_to_skip = self._finder.skip_tests(paths, test_names, self._expecta tions, self._http_tests(test_names)) |
| 246 tests_to_run = [test for test in test_names if test not in tests_to_skip ] | 258 tests_to_run = [test for test in test_names if test not in tests_to_skip ] |
| 247 | 259 |
| 248 if not tests_to_run: | 260 if not tests_to_run: |
| 249 return tests_to_run, tests_to_skip | 261 return tests_to_run, tests_to_skip |
| 250 | 262 |
| 251 # Create a sorted list of test files so the subset chunk, | 263 # Create a sorted list of test files so the subset chunk, |
| 252 # if used, contains alphabetically consecutive tests. | 264 # if used, contains alphabetically consecutive tests. |
| 253 if self._options.order == 'natural': | 265 if self._options.order == 'natural': |
| 254 tests_to_run.sort(key=self._port.test_key) | 266 tests_to_run.sort(key=self._port.test_key) |
| 255 elif self._options.order == 'random': | 267 elif self._options.order.startswith('random'): |
| 256 random.shuffle(tests_to_run) | |
| 257 elif self._options.order == 'random-seeded': | |
| 258 rnd = random.Random() | 268 rnd = random.Random() |
|
qyearsley
2016/06/22 17:30:16
This line could be removed (it appears below).
| |
| 259 rnd.seed(4) # http://xkcd.com/221/ | 269 |
| 270 groups = re.match('random-seeded(=([0-9]+))?', self._options.order) | |
|
qyearsley
2016/06/22 17:30:16
Instead of specifying seeds with an option like `-
Dirk Pranke
2016/06/24 01:53:40
+1 to splitting it into a separate argument.
| |
| 271 if not groups: | |
| 272 seed = int(time.time()) | |
| 273 elif not groups.group(2): | |
| 274 seed = 4 # http://xkcd.com/221/ | |
|
qyearsley
2016/06/22 17:30:16
It's probably not necessary to necessary to keep t
| |
| 275 else: | |
| 276 seed = int(groups.group(2)) | |
| 277 _log.info("Test random order seed: %i", seed) | |
| 278 self._random_seed = seed | |
| 279 | |
| 280 # Make sure the tests are in sorted before we randomize them. | |
| 281 tests_to_run.sort() | |
| 282 rnd = random.Random() | |
| 283 rnd.seed(seed) | |
| 260 rnd.shuffle(tests_to_run) | 284 rnd.shuffle(tests_to_run) |
| 261 | 285 |
| 262 tests_to_run, tests_in_other_chunks = self._finder.split_into_chunks(tes ts_to_run) | 286 tests_to_run, tests_in_other_chunks = self._finder.split_into_chunks(tes ts_to_run) |
| 263 self._expectations.add_extra_skipped_tests(tests_in_other_chunks) | 287 self._expectations.add_extra_skipped_tests(tests_in_other_chunks) |
| 264 tests_to_skip.update(tests_in_other_chunks) | 288 tests_to_skip.update(tests_in_other_chunks) |
| 265 | 289 |
| 266 return tests_to_run, tests_to_skip | 290 return tests_to_run, tests_to_skip |
| 267 | 291 |
| 268 def _test_input_for_file(self, test_file): | 292 def _test_input_for_file(self, test_file): |
| 269 return TestInput(test_file, | 293 return TestInput(test_file, |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 | 577 |
| 554 stats = {} | 578 stats = {} |
| 555 for result in initial_results.results_by_name.values(): | 579 for result in initial_results.results_by_name.values(): |
| 556 if result.type != test_expectations.SKIP: | 580 if result.type != test_expectations.SKIP: |
| 557 stats[result.test_name] = {'results': (_worker_number(result.wor ker_name), result.test_number, result.pid, int( | 581 stats[result.test_name] = {'results': (_worker_number(result.wor ker_name), result.test_number, result.pid, int( |
| 558 result.test_run_time * 1000), int(result.total_run_time * 10 00))} | 582 result.test_run_time * 1000), int(result.total_run_time * 10 00))} |
| 559 stats_trie = {} | 583 stats_trie = {} |
| 560 for name, value in stats.iteritems(): | 584 for name, value in stats.iteritems(): |
| 561 json_results_generator.add_path_to_trie(name, value, stats_trie) | 585 json_results_generator.add_path_to_trie(name, value, stats_trie) |
| 562 return stats_trie | 586 return stats_trie |
| OLD | NEW |