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

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py

Issue 2680393003: Preliminary refactoring to improve test expectation specifiers added by importer. (Closed)
Patch Set: Created 3 years, 10 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
« no previous file with comments | « no previous file | third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_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 2016 The Chromium Authors. All rights reserved. 1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Updates layout test expectations and baselines when updating w3c tests. 5 """Updates layout test expectations and baselines when updating w3c tests.
6 6
7 Specifically, this class fetches results from try bots for the current CL, then 7 Specifically, this class fetches results from try bots for the current CL, then
8 (1) downloads new baseline files for any tests that can be rebaselined, and 8 (1) downloads new baseline files for any tests that can be rebaselined, and
9 (2) updates the generic TestExpectations file for any other failing tests. 9 (2) updates the generic TestExpectations file for any other failing tests.
10 """ 10 """
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 rietveld = Rietveld(self.host.web) 47 rietveld = Rietveld(self.host.web)
48 builds = rietveld.latest_try_jobs(issue_number, self.get_try_bots()) 48 builds = rietveld.latest_try_jobs(issue_number, self.get_try_bots())
49 _log.debug('Latest try jobs: %r', builds) 49 _log.debug('Latest try jobs: %r', builds)
50 if not builds: 50 if not builds:
51 _log.error('No try job information was collected.') 51 _log.error('No try job information was collected.')
52 return 1 52 return 1
53 53
54 # Here we build up a dict of failing test results for all platforms. 54 # Here we build up a dict of failing test results for all platforms.
55 test_expectations = {} 55 test_expectations = {}
56 for build in builds: 56 for build in builds:
57 platform_results = self.get_failing_results_dict(build) 57 port_results = self.get_failing_results_dict(build)
58 test_expectations = self.merge_dicts(test_expectations, platform_res ults) 58 test_expectations = self.merge_dicts(test_expectations, port_results )
59 59
60 # And then we merge results for different platforms that had the same re sults. 60 # And then we merge results for different platforms that had the same re sults.
61 for test_name, platform_result in test_expectations.iteritems(): 61 for test_name, platform_result in test_expectations.iteritems():
62 # platform_result is a dict mapping platforms to results. 62 # platform_result is a dict mapping platforms to results.
63 test_expectations[test_name] = self.merge_same_valued_keys(platform_ result) 63 test_expectations[test_name] = self.merge_same_valued_keys(platform_ result)
64 64
65 test_expectations = self.download_text_baselines(test_expectations) 65 test_expectations = self.download_text_baselines(test_expectations)
66 test_expectation_lines = self.create_line_list(test_expectations) 66 test_expectation_lines = self.create_line_list(test_expectations)
67 self.write_to_test_expectations(test_expectation_lines) 67 self.write_to_test_expectations(test_expectation_lines)
68 return 0 68 return 0
(...skipping 11 matching lines...) Expand all
80 80
81 Retrieves a full list of layout test results from a builder result URL. 81 Retrieves a full list of layout test results from a builder result URL.
82 Collects the builder name, platform and a list of tests that did not 82 Collects the builder name, platform and a list of tests that did not
83 run as expected. 83 run as expected.
84 84
85 Args: 85 Args:
86 build: A Build object. 86 build: A Build object.
87 87
88 Returns: 88 Returns:
89 A dictionary with the structure: { 89 A dictionary with the structure: {
90 'key': { 90 'full-port-name': {
91 'expected': 'TIMEOUT', 91 'expected': 'TIMEOUT',
92 'actual': 'CRASH', 92 'actual': 'CRASH',
93 'bug': 'crbug.com/11111' 93 'bug': 'crbug.com/11111'
94 } 94 }
95 } 95 }
96 If there are no failing results or no results could be fetched, 96 If there are no failing results or no results could be fetched,
97 this will return an empty dict. 97 this will return an empty dictionary.
98 """ 98 """
99 layout_test_results = self.host.buildbot.fetch_results(build) 99 layout_test_results = self.host.buildbot.fetch_results(build)
100 if layout_test_results is None: 100 if layout_test_results is None:
101 _log.warning('No results for build %s', build) 101 _log.warning('No results for build %s', build)
102 return {} 102 return {}
103 platform = self.host.builders.port_name_for_builder_name(build.builder_n ame) 103 port_name = self.host.builders.port_name_for_builder_name(build.builder_ name)
104 test_results = layout_test_results.didnt_run_as_expected_results() 104 test_results = layout_test_results.didnt_run_as_expected_results()
105 failing_results_dict = self.generate_results_dict(platform, test_results ) 105 failing_results_dict = self.generate_results_dict(port_name, test_result s)
106 return failing_results_dict 106 return failing_results_dict
107 107
108 def generate_results_dict(self, full_port_name, test_results): 108 def generate_results_dict(self, full_port_name, test_results):
109 """Makes a dict with results for one platform. 109 """Makes a dict with results for one platform.
110 110
111 Args: 111 Args:
112 full_port_name: The full port name, e.g. "win-win10". 112 full_port_name: The full-qualified port name, e.g. "win-win10".
jeffcarp 2017/02/09 00:50:17 Should this be fully-qualified?
qyearsley 2017/02/09 17:01:55 Yep, it should be :-) The term "fully-qualified" w
113 test_results: A list of LayoutTestResult objects. 113 test_results: A list of LayoutTestResult objects.
114 114
115 Returns: 115 Returns:
116 A dict mapping to platform string (e.g. "Win10") to a dict with 116 A dict mapping the full port name to a dict with the results for
117 the results for that test and that platform. 117 the given test and platform.
118 """ 118 """
119 platform = self._port_name_to_platform_specifier(full_port_name)
120 test_dict = {} 119 test_dict = {}
121 for result in test_results: 120 for result in test_results:
122 test_dict[result.test_name()] = { 121 test_name = result.test_name()
123 platform: { 122 test_dict[test_name] = {
123 full_port_name: {
124 'expected': result.expected_results(), 124 'expected': result.expected_results(),
125 'actual': result.actual_results(), 125 'actual': result.actual_results(),
126 'bug': 'crbug.com/626703' 126 'bug': 'crbug.com/626703'
127 }} 127 }
128 }
128 return test_dict 129 return test_dict
129 130
130 def _port_name_to_platform_specifier(self, port_name): 131 def _port_name_to_platform_specifier(self, port_name):
131 """Maps a port name to the string used in test expectations lines. 132 """Maps a port name to the platform specifier used in expectation lines.
132 133
133 For example: 134 For example:
134 linux-trusty -> Trusty 135 linux-trusty -> Trusty
135 mac-mac10.11 -> Mac10.11. 136 mac-mac10.11 -> Mac10.11.
136 """ 137 """
137 # TODO(qyearsley): Do this in a more robust way with Port classes. 138 builder_name = self.host.builders.builder_name_for_port_name(port_name)
138 if '-' in port_name: 139 specifiers = self.host.builders.specifiers_for_builder(builder_name)
139 return port_name[port_name.find('-') + 1:].capitalize() 140 return specifiers[0]
140 return port_name
141 141
142 def merge_dicts(self, target, source, path=None): 142 def merge_dicts(self, target, source, path=None):
143 """Recursively merges nested dictionaries. 143 """Recursively merges nested dictionaries.
144 144
145 Args: 145 Args:
146 target: First dictionary, which is updated based on source. 146 target: First dictionary, which is updated based on source.
147 source: Second dictionary, not modified. 147 source: Second dictionary, not modified.
148 148
149 Returns: 149 Returns:
150 An updated target dictionary. 150 An updated target dictionary.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 'bug': 'crbug.com/11111' 257 'bug': 'crbug.com/11111'
258 } 258 }
259 } 259 }
260 } 260 }
261 261
262 Returns: 262 Returns:
263 A list of test expectations lines with the format: 263 A list of test expectations lines with the format:
264 ['BUG_URL [PLATFORM(S)] TEST_MAME [EXPECTATION(S)]'] 264 ['BUG_URL [PLATFORM(S)] TEST_MAME [EXPECTATION(S)]']
265 """ 265 """
266 line_list = [] 266 line_list = []
267 for test_name, platform_results in merged_results.iteritems(): 267 for test_name, port_results in merged_results.iteritems():
268 for platform in platform_results: 268 for port_names in port_results:
269 if test_name.startswith('external'): 269 if test_name.startswith('external'):
270 platform_list = [] 270 bug_part = port_results[port_names]['bug']
271 bug = [] 271 specifier_part = '[ %s ]' % ' '.join(self.to_list(port_names ))
272 expectations = [] 272 expectations_part = '[ %s ]' % ' '.join(self.get_expectation s(port_results[port_names]))
273 if isinstance(platform, tuple): 273 line = ' '.join([bug_part, specifier_part, test_name, expect ations_part])
274 platform_list = list(platform) 274 line_list.append(line)
275 else:
276 platform_list.append(platform)
277 bug.append(platform_results[platform]['bug'])
278 expectations = self.get_expectations(platform_results[platfo rm])
279 line = '%s [ %s ] %s [ %s ]' % (bug[0], ' '.join(platform_li st), test_name, ' '.join(expectations))
280 line_list.append(str(line))
281 return line_list 275 return line_list
282 276
277 @staticmethod
278 def to_list(tuple_or_value):
279 if isinstance(tuple_or_value, tuple):
280 return list(tuple_or_value)
281 return [tuple_or_value]
282
283 def write_to_test_expectations(self, line_list): 283 def write_to_test_expectations(self, line_list):
284 """Writes to TestExpectations. 284 """Writes to TestExpectations.
285 285
286 The place in the file where the new lines are inserted is after a 286 The place in the file where the new lines are inserted is after a
287 marker comment line. If this marker comment line is not found, it will 287 marker comment line. If this marker comment line is not found, it will
288 be added to the end of the file. 288 be added to the end of the file.
289 289
290 Args: 290 Args:
291 line_list: A list of lines to add to the TestExpectations file. 291 line_list: A list of lines to add to the TestExpectations file.
292 """ 292 """
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 376
377 Args: 377 Args:
378 test_path: A file path relative to the layout tests directory. 378 test_path: A file path relative to the layout tests directory.
379 This might correspond to a deleted file or a non-test. 379 This might correspond to a deleted file or a non-test.
380 """ 380 """
381 absolute_path = self.host.filesystem.join(self.finder.layout_tests_dir() , test_path) 381 absolute_path = self.host.filesystem.join(self.finder.layout_tests_dir() , test_path)
382 test_parser = TestParser(absolute_path, self.host) 382 test_parser = TestParser(absolute_path, self.host)
383 if not test_parser.test_doc: 383 if not test_parser.test_doc:
384 return False 384 return False
385 return test_parser.is_jstest() 385 return test_parser.is_jstest()
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698