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

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py

Issue 2445963002: Remove all all-PASS testharness baselines after rebaselining. (Closed)
Patch Set: Created 4 years, 1 month 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
« no previous file with comments | « no previous file | third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.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 (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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 63
64 def __init__(self, options=None): 64 def __init__(self, options=None):
65 super(AbstractRebaseliningCommand, self).__init__(options=options) 65 super(AbstractRebaseliningCommand, self).__init__(options=options)
66 self._baseline_suffix_list = BASELINE_SUFFIX_LIST 66 self._baseline_suffix_list = BASELINE_SUFFIX_LIST
67 self.expectation_line_changes = ChangeSet() 67 self.expectation_line_changes = ChangeSet()
68 self._tool = None 68 self._tool = None
69 69
70 def _print_expectation_line_changes(self): 70 def _print_expectation_line_changes(self):
71 print(json.dumps(self.expectation_line_changes.to_dict())) 71 print(json.dumps(self.expectation_line_changes.to_dict()))
72 72
73 def _baseline_directory(self, builder_name):
74 port = self._tool.port_factory.get_from_builder_name(builder_name)
75 return port.baseline_version_dir()
76
77 def _test_root(self, test_name):
78 return self._tool.filesystem.splitext(test_name)[0]
79
80 def _file_name_for_actual_result(self, test_name, suffix):
81 return "%s-actual.%s" % (self._test_root(test_name), suffix)
82
83 def _file_name_for_expected_result(self, test_name, suffix):
84 return "%s-expected.%s" % (self._test_root(test_name), suffix)
85
73 86
74 class ChangeSet(object): 87 class ChangeSet(object):
75 """A record of TestExpectation lines to remove. 88 """A record of TestExpectation lines to remove.
76 89
77 TODO(qyearsley): Remove this class, track list of lines to remove directly 90 TODO(qyearsley): Remove this class, track list of lines to remove directly
78 in an attribute of AbstractRebaseliningCommand. 91 in an attribute of AbstractRebaseliningCommand.
79 """ 92 """
80 def __init__(self, lines_to_remove=None): 93 def __init__(self, lines_to_remove=None):
81 self.lines_to_remove = lines_to_remove or {} 94 self.lines_to_remove = lines_to_remove or {}
82 95
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 def __init__(self): 133 def __init__(self):
121 super(BaseInternalRebaselineCommand, self).__init__(options=[ 134 super(BaseInternalRebaselineCommand, self).__init__(options=[
122 self.results_directory_option, 135 self.results_directory_option,
123 self.suffixes_option, 136 self.suffixes_option,
124 optparse.make_option("--builder", help="Builder to pull new baseline s from."), 137 optparse.make_option("--builder", help="Builder to pull new baseline s from."),
125 optparse.make_option("--test", help="Test to rebaseline."), 138 optparse.make_option("--test", help="Test to rebaseline."),
126 optparse.make_option("--build-number", default=None, type="int", 139 optparse.make_option("--build-number", default=None, type="int",
127 help="Optional build number; if not given, the latest build is used."), 140 help="Optional build number; if not given, the latest build is used."),
128 ]) 141 ])
129 142
130 def _baseline_directory(self, builder_name):
131 port = self._tool.port_factory.get_from_builder_name(builder_name)
132 return port.baseline_version_dir()
133
134 def _test_root(self, test_name):
135 return self._tool.filesystem.splitext(test_name)[0]
136
137 def _file_name_for_actual_result(self, test_name, suffix):
138 return "%s-actual.%s" % (self._test_root(test_name), suffix)
139
140 def _file_name_for_expected_result(self, test_name, suffix):
141 return "%s-expected.%s" % (self._test_root(test_name), suffix)
142
143 143
144 class CopyExistingBaselinesInternal(BaseInternalRebaselineCommand): 144 class CopyExistingBaselinesInternal(BaseInternalRebaselineCommand):
145 name = "copy-existing-baselines-internal" 145 name = "copy-existing-baselines-internal"
146 help_text = ("Copy existing baselines down one level in the baseline order t o ensure " 146 help_text = ("Copy existing baselines down one level in the baseline order t o ensure "
147 "new baselines don't break existing passing platforms.") 147 "new baselines don't break existing passing platforms.")
148 148
149 @memoized 149 @memoized
150 def _immediate_predecessors_in_fallback(self, path_to_rebaseline): 150 def _immediate_predecessors_in_fallback(self, path_to_rebaseline):
151 port_names = self._tool.port_factory.all_port_names() 151 port_names = self._tool.port_factory.all_port_names()
152 immediate_predecessors = [] 152 immediate_predecessors = []
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 class RebaselineTest(BaseInternalRebaselineCommand): 216 class RebaselineTest(BaseInternalRebaselineCommand):
217 name = "rebaseline-test-internal" 217 name = "rebaseline-test-internal"
218 help_text = "Rebaseline a single test from a buildbot. Only intended for use by other webkit-patch commands." 218 help_text = "Rebaseline a single test from a buildbot. Only intended for use by other webkit-patch commands."
219 219
220 def _save_baseline(self, data, target_baseline): 220 def _save_baseline(self, data, target_baseline):
221 if not data: 221 if not data:
222 _log.debug("No baseline data to save.") 222 _log.debug("No baseline data to save.")
223 return 223 return
224 224
225 filesystem = self._tool.filesystem 225 filesystem = self._tool.filesystem
226 if is_all_pass_testharness_result(data):
227 _log.debug("The new baseline is a passing testharness result with "
228 "no console warnings or errors, so it will not be saved." )
229 if filesystem.exists(target_baseline):
230 filesystem.remove(target_baseline)
231 return
232
233 filesystem.maybe_make_directory(filesystem.dirname(target_baseline)) 226 filesystem.maybe_make_directory(filesystem.dirname(target_baseline))
234 filesystem.write_binary_file(target_baseline, data) 227 filesystem.write_binary_file(target_baseline, data)
235 228
236 def _rebaseline_test(self, builder_name, test_name, suffix, results_url): 229 def _rebaseline_test(self, builder_name, test_name, suffix, results_url):
237 baseline_directory = self._baseline_directory(builder_name) 230 baseline_directory = self._baseline_directory(builder_name)
238 231
239 source_baseline = "%s/%s" % (results_url, self._file_name_for_actual_res ult(test_name, suffix)) 232 source_baseline = "%s/%s" % (results_url, self._file_name_for_actual_res ult(test_name, suffix))
240 target_baseline = self._tool.filesystem.join(baseline_directory, self._f ile_name_for_expected_result(test_name, suffix)) 233 target_baseline = self._tool.filesystem.join(baseline_directory, self._f ile_name_for_expected_result(test_name, suffix))
241 234
242 _log.debug("Retrieving source %s for target %s.", source_baseline, targe t_baseline) 235 _log.debug("Retrieving source %s for target %s.", source_baseline, targe t_baseline)
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 510
518 if lines_to_remove: 511 if lines_to_remove:
519 self._update_expectations_files(lines_to_remove) 512 self._update_expectations_files(lines_to_remove)
520 513
521 if options.optimize: 514 if options.optimize:
522 # TODO(wkorman): Consider changing temporary branch to base off of H EAD rather than 515 # TODO(wkorman): Consider changing temporary branch to base off of H EAD rather than
523 # origin/master to ensure we run baseline optimization processes wit h the same code as 516 # origin/master to ensure we run baseline optimization processes wit h the same code as
524 # auto-rebaseline itself. 517 # auto-rebaseline itself.
525 self._run_in_parallel(self._optimize_baselines(test_prefix_list, opt ions.verbose)) 518 self._run_in_parallel(self._optimize_baselines(test_prefix_list, opt ions.verbose))
526 519
520 self._remove_all_pass_testharness_baselines(test_prefix_list)
521
527 self._tool.scm().add_all(pathspec=self._layout_tests_dir()) 522 self._tool.scm().add_all(pathspec=self._layout_tests_dir())
528 523
524 def _remove_all_pass_testharness_baselines(self, test_prefix_list):
525 """Removes all of the all-PASS baselines for the given builders and test s.
526
527 In general, for testharness.js tests, the absence of a baseline
528 indicates that the test is expected to pass. When rebaselining,
529 new all-PASS baselines may be downloaded, but they should not be kept.
wkorman 2016/10/25 00:14:20 Is removing restoring the repo to the baselines-do
qyearsley 2016/10/25 00:33:04 I think it could be either removing an existing fi
530 """
531 filesystem = self._tool.filesystem
532 baseline_paths = self._all_baseline_paths(test_prefix_list)
533 for path in baseline_paths:
534 if not (filesystem.exists(path) and
535 filesystem.splitext(path)[1] == '.txt'):
536 continue
537 contents = filesystem.read_text_file(path)
wkorman 2016/10/25 00:14:20 How many of these do we expect there to be typical
qyearsley 2016/10/25 00:33:04 Right -- hypothetically there could be hundreds of
538 if is_all_pass_testharness_result(contents):
539 _log.info('Removing all-PASS testharness baseline: %s', path)
540 filesystem.remove(path)
541
542 def _all_baseline_paths(self, test_prefix_list):
543 """Return file paths for all baselines for the given tests and builders.
544
545 Args:
546 test_prefix_list: A dict mapping test prefixes, which could be
547 directories or full test paths, to builds to baseline suffixes.
548 TODO(qyearsley): If a class is added to replace test_prefix_list ,
549 then this can be made a method on that class.
550
551 Returns:
552 A list of absolute paths to baseline files.
qyearsley 2016/10/25 00:33:04 Currently this actually returns potential places w
wkorman 2016/10/25 00:37:17 Seems reasonable, this method is only used in this
qyearsley 2016/10/25 20:13:34 I was thinking of filtering out files that don't e
553 """
554 filesystem = self._tool.filesystem
555 baseline_paths = []
556 port = self._tool.port_factory.get()
557
558 for test_prefix in test_prefix_list:
559 tests = port.tests([test_prefix])
560 all_suffixes = set()
561
562 for build, suffixes in test_prefix_list[test_prefix].iteritems():
563 all_suffixes.update(suffixes)
564 port_baseline_dir = self._baseline_directory(build.builder_name)
565 baseline_paths.extend([
566 filesystem.join(port_baseline_dir, self._file_name_for_expec ted_result(test, suffix))
567 for test in tests for suffix in suffixes
568 ])
569
570 baseline_paths.extend([
571 filesystem.join(self._layout_tests_dir(), self._file_name_for_ex pected_result(test, suffix))
572 for test in tests for suffix in all_suffixes
573 ])
574
575 return baseline_paths
576
529 def _layout_tests_dir(self): 577 def _layout_tests_dir(self):
530 return self._tool.port_factory.get().layout_tests_dir() 578 return self._tool.port_factory.get().layout_tests_dir()
531 579
532 def _suffixes_for_actual_failures(self, test, build, existing_suffixes): 580 def _suffixes_for_actual_failures(self, test, build, existing_suffixes):
533 """Gets the baseline suffixes for actual mismatch failures in some resul ts. 581 """Gets the baseline suffixes for actual mismatch failures in some resul ts.
534 582
535 Args: 583 Args:
536 test: A full test path string. 584 test: A full test path string.
537 build: A Build object. 585 build: A Build object.
538 existing_suffixes: A collection of all suffixes to consider. 586 existing_suffixes: A collection of all suffixes to consider.
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 for test in args: 705 for test in args:
658 if test not in test_prefix_list: 706 if test not in test_prefix_list:
659 test_prefix_list[test] = {} 707 test_prefix_list[test] = {}
660 build = Build(builder) 708 build = Build(builder)
661 test_prefix_list[test][build] = suffixes_to_update 709 test_prefix_list[test][build] = suffixes_to_update
662 710
663 if options.verbose: 711 if options.verbose:
664 _log.debug("rebaseline-json: " + str(test_prefix_list)) 712 _log.debug("rebaseline-json: " + str(test_prefix_list))
665 713
666 self.rebaseline(options, test_prefix_list) 714 self.rebaseline(options, test_prefix_list)
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698