Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2010 Google Inc. All rights reserved. | 1 # Copyright (c) 2010 Google Inc. All rights reserved. |
| 2 # | 2 # |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 self._builder_names = set() | 155 self._builder_names = set() |
| 156 self._test_prefix_map = collections.defaultdict(list) | 156 self._test_prefix_map = collections.defaultdict(list) |
| 157 | 157 |
| 158 def __iter__(self): | 158 def __iter__(self): |
| 159 return iter(self._iter_combinations()) | 159 return iter(self._iter_combinations()) |
| 160 | 160 |
| 161 def __bool__(self): | 161 def __bool__(self): |
| 162 return bool(self._test_prefix_map) | 162 return bool(self._test_prefix_map) |
| 163 | 163 |
| 164 def _iter_combinations(self): | 164 def _iter_combinations(self): |
| 165 """Iterates through (test, build) combinations.""" | 165 """Iterates through (test, build, port) combinations.""" |
| 166 for test_prefix, builds in self._test_prefix_map.iteritems(): | 166 for test_prefix, build_port_pairs in self._test_prefix_map.iteritems(): |
| 167 for test in self._port.tests([test_prefix]): | 167 for test in self._port.tests([test_prefix]): |
| 168 for build in builds: | 168 for build, port_name in build_port_pairs: |
| 169 yield (test, build) | 169 yield (test, build, port_name) |
| 170 | 170 |
| 171 def __str__(self): | 171 def __str__(self): |
| 172 if not self._test_prefix_map: | 172 if not self._test_prefix_map: |
| 173 return '<Empty TestBaselineSet>' | 173 return '<Empty TestBaselineSet>' |
| 174 return '<TestBaselineSet with:\n ' + '\n '.join('%s: %s' % pair for pa ir in self._iter_combinations()) + '>' | 174 return ('<TestBaselineSet with:\n ' + |
| 175 '\n '.join('%s: %s, %s' % triple for triple in self._iter_combi nations()) + | |
| 176 '>') | |
| 175 | 177 |
| 176 def add(self, test_prefix, build): | 178 def add(self, test_prefix, build, port_name=None): |
| 177 """Adds an entry for baselines to download for some set of tests. | 179 """Adds an entry for baselines to download for some set of tests. |
| 178 | 180 |
| 179 Args: | 181 Args: |
| 180 test_prefix: This can be a full test path, or directory of tests, or a path with globs. | 182 test_prefix: This can be a full test path, or directory of tests, or a path with globs. |
| 181 build: A Build object. This specifies where to fetch baselines from. | 183 build: A Build object. This specifies where to fetch baselines from. |
| 184 port_name: This specifies what platform the baseline is for. | |
| 182 """ | 185 """ |
| 186 port_name = port_name or self._host.builders.port_name_for_builder_name( build.builder_name) | |
| 183 self._builder_names.add(build.builder_name) | 187 self._builder_names.add(build.builder_name) |
| 184 self._test_prefix_map[test_prefix].append(build) | 188 self._test_prefix_map[test_prefix].append((build, port_name)) |
| 185 | 189 |
| 186 def all_builders(self): | 190 def all_builders(self): |
| 187 """Returns all builder names in in this collection.""" | 191 """Returns all builder names in in this collection.""" |
| 188 return self._builder_names | 192 return self._builder_names |
| 189 | 193 |
| 190 | 194 |
| 191 class CopyExistingBaselinesInternal(AbstractRebaseliningCommand): | 195 class CopyExistingBaselinesInternal(AbstractRebaseliningCommand): |
| 192 name = 'copy-existing-baselines-internal' | 196 name = 'copy-existing-baselines-internal' |
| 193 help_text = ('Copy existing baselines down one level in the baseline order t o ensure ' | 197 help_text = ('Copy existing baselines down one level in the baseline order t o ensure ' |
| 194 "new baselines don't break existing passing platforms.") | 198 "new baselines don't break existing passing platforms.") |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 434 return set(builders_to_fallback_paths) | 438 return set(builders_to_fallback_paths) |
| 435 | 439 |
| 436 def _rebaseline_commands(self, test_baseline_set, options): | 440 def _rebaseline_commands(self, test_baseline_set, options): |
| 437 path_to_webkit_patch = self._tool.path() | 441 path_to_webkit_patch = self._tool.path() |
| 438 cwd = self._tool.git().checkout_root | 442 cwd = self._tool.git().checkout_root |
| 439 copy_baseline_commands = [] | 443 copy_baseline_commands = [] |
| 440 rebaseline_commands = [] | 444 rebaseline_commands = [] |
| 441 lines_to_remove = {} | 445 lines_to_remove = {} |
| 442 | 446 |
| 443 builders_to_fetch_from = self._builders_to_fetch_from(test_baseline_set. all_builders()) | 447 builders_to_fetch_from = self._builders_to_fetch_from(test_baseline_set. all_builders()) |
| 444 for test, build in test_baseline_set: | 448 for test, build, port_name in test_baseline_set: |
| 445 if build.builder_name not in builders_to_fetch_from: | 449 if build.builder_name not in builders_to_fetch_from: |
| 446 continue | 450 continue |
| 447 | 451 |
| 448 port_name = self._tool.builders.port_name_for_builder_name(build.bui lder_name) | |
| 449 | |
| 450 suffixes = self._suffixes_for_actual_failures(test, build) | 452 suffixes = self._suffixes_for_actual_failures(test, build) |
| 451 if not suffixes: | 453 if not suffixes: |
| 452 # If we're not going to rebaseline the test because it's passing on this | 454 # If we're not going to rebaseline the test because it's passing on this |
| 453 # builder, we still want to remove the line from TestExpectation s. | 455 # builder, we still want to remove the line from TestExpectation s. |
| 454 if test not in lines_to_remove: | 456 if test not in lines_to_remove: |
| 455 lines_to_remove[test] = [] | 457 lines_to_remove[test] = [] |
| 456 lines_to_remove[test].append(port_name) | 458 lines_to_remove[test].append(port_name) |
| 457 continue | 459 continue |
| 458 | 460 |
| 459 args = [] | 461 args = [] |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 494 _log.debug('"%s" is not a JSON object, ignoring', line) | 496 _log.debug('"%s" is not a JSON object, ignoring', line) |
| 495 if not updated: | 497 if not updated: |
| 496 # TODO(qyearsley): This probably should be an error. See http:// crbug.com/649412. | 498 # TODO(qyearsley): This probably should be an error. See http:// crbug.com/649412. |
| 497 _log.debug('Could not add file based off output "%s"', stdout) | 499 _log.debug('Could not add file based off output "%s"', stdout) |
| 498 return change_set | 500 return change_set |
| 499 | 501 |
| 500 def _optimize_baselines(self, test_baseline_set, verbose=False): | 502 def _optimize_baselines(self, test_baseline_set, verbose=False): |
| 501 """Returns a list of commands to run in parallel to de-duplicate baselin es.""" | 503 """Returns a list of commands to run in parallel to de-duplicate baselin es.""" |
| 502 tests_to_suffixes = collections.defaultdict(set) | 504 tests_to_suffixes = collections.defaultdict(set) |
| 503 builders_to_fetch_from = self._builders_to_fetch_from(test_baseline_set. all_builders()) | 505 builders_to_fetch_from = self._builders_to_fetch_from(test_baseline_set. all_builders()) |
| 504 for test, build in test_baseline_set: | 506 for test, build, _ in test_baseline_set: |
| 505 if build.builder_name not in builders_to_fetch_from: | 507 if build.builder_name not in builders_to_fetch_from: |
| 506 continue | 508 continue |
| 507 tests_to_suffixes[test].update(self._suffixes_for_actual_failures(te st, build)) | 509 tests_to_suffixes[test].update(self._suffixes_for_actual_failures(te st, build)) |
| 508 | 510 |
| 509 optimize_commands = [] | 511 optimize_commands = [] |
| 510 for test, suffixes in tests_to_suffixes.iteritems(): | 512 for test, suffixes in tests_to_suffixes.iteritems(): |
| 511 # No need to optimize baselines for a test with no failures. | 513 # No need to optimize baselines for a test with no failures. |
| 512 if not suffixes: | 514 if not suffixes: |
| 513 continue | 515 continue |
| 514 # FIXME: We should propagate the platform options as well. | 516 # FIXME: We should propagate the platform options as well. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 | 577 |
| 576 Args: | 578 Args: |
| 577 options: An object with the command line options. | 579 options: An object with the command line options. |
| 578 test_baseline_set: A TestBaselineSet instance, which represents | 580 test_baseline_set: A TestBaselineSet instance, which represents |
| 579 a set of tests/platform combinations to rebaseline. | 581 a set of tests/platform combinations to rebaseline. |
| 580 """ | 582 """ |
| 581 if self._tool.git().has_working_directory_changes(pathspec=self._layout_ tests_dir()): | 583 if self._tool.git().has_working_directory_changes(pathspec=self._layout_ tests_dir()): |
| 582 _log.error('There are uncommitted changes in the layout tests direct ory; aborting.') | 584 _log.error('There are uncommitted changes in the layout tests direct ory; aborting.') |
| 583 return | 585 return |
| 584 | 586 |
| 585 for test in sorted({t for t, _ in test_baseline_set}): | 587 for test in sorted({t for t, _, _ in test_baseline_set}): |
| 586 _log.info('Rebaselining %s', test) | 588 _log.info('Rebaselining %s', test) |
| 587 | 589 |
| 588 copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = sel f._rebaseline_commands( | 590 copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = sel f._rebaseline_commands( |
| 589 test_baseline_set, options) | 591 test_baseline_set, options) |
| 590 lines_to_remove = {} | 592 lines_to_remove = {} |
| 591 | 593 |
| 592 self._run_in_parallel(copy_baseline_commands) | 594 self._run_in_parallel(copy_baseline_commands) |
| 593 lines_to_remove = self._run_in_parallel(rebaseline_commands) | 595 lines_to_remove = self._run_in_parallel(rebaseline_commands) |
| 594 | 596 |
| 595 for test in extra_lines_to_remove: | 597 for test in extra_lines_to_remove: |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 638 """Returns file paths for all baselines for the given tests and builders . | 640 """Returns file paths for all baselines for the given tests and builders . |
| 639 | 641 |
| 640 Args: | 642 Args: |
| 641 test_baseline_set: A TestBaselineSet instance. | 643 test_baseline_set: A TestBaselineSet instance. |
| 642 | 644 |
| 643 Returns: | 645 Returns: |
| 644 A list of absolute paths where baselines could possibly exist. | 646 A list of absolute paths where baselines could possibly exist. |
| 645 """ | 647 """ |
| 646 filesystem = self._tool.filesystem | 648 filesystem = self._tool.filesystem |
| 647 baseline_paths = set() | 649 baseline_paths = set() |
| 648 for test, build in test_baseline_set: | 650 for test, build, _ in test_baseline_set: |
|
wkorman
2017/04/03 20:41:52
Is this ok re: we won't start doing multiples of t
qyearsley
2017/04/04 18:56:45
Good idea to check this; right now it looks like i
| |
| 649 filenames = [self._file_name_for_expected_result(test, suffix) for s uffix in BASELINE_SUFFIX_LIST] | 651 filenames = [self._file_name_for_expected_result(test, suffix) for s uffix in BASELINE_SUFFIX_LIST] |
| 650 port_baseline_dir = self._baseline_directory(build.builder_name) | 652 port_baseline_dir = self._baseline_directory(build.builder_name) |
| 651 baseline_paths.update({filesystem.join(port_baseline_dir, filename) for filename in filenames}) | 653 baseline_paths.update({filesystem.join(port_baseline_dir, filename) for filename in filenames}) |
| 652 baseline_paths.update({filesystem.join(self._layout_tests_dir(), fil ename) for filename in filenames}) | 654 baseline_paths.update({filesystem.join(self._layout_tests_dir(), fil ename) for filename in filenames}) |
| 653 return sorted(baseline_paths) | 655 return sorted(baseline_paths) |
| 654 | 656 |
| 655 def _layout_tests_dir(self): | 657 def _layout_tests_dir(self): |
| 656 return self._tool.port_factory.get().layout_tests_dir() | 658 return self._tool.port_factory.get().layout_tests_dir() |
| 657 | 659 |
| 658 def _suffixes_for_actual_failures(self, test, build): | 660 def _suffixes_for_actual_failures(self, test, build): |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 | 760 |
| 759 test_baseline_set = TestBaselineSet(tool) | 761 test_baseline_set = TestBaselineSet(tool) |
| 760 | 762 |
| 761 for builder in builders_to_check: | 763 for builder in builders_to_check: |
| 762 for test_prefix in args: | 764 for test_prefix in args: |
| 763 test_baseline_set.add(test_prefix, Build(builder)) | 765 test_baseline_set.add(test_prefix, Build(builder)) |
| 764 | 766 |
| 765 _log.debug('Rebaselining: %s', test_baseline_set) | 767 _log.debug('Rebaselining: %s', test_baseline_set) |
| 766 | 768 |
| 767 self.rebaseline(options, test_baseline_set) | 769 self.rebaseline(options, test_baseline_set) |
| OLD | NEW |