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

Side by Side Diff: media/tools/layout_tests/layouttest_analyzer_helpers.py

Issue 9476021: Updating Layout test analyzer to add control to show issue detail or not. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Modification based on CR comments. Created 8 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) 2011 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 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 """Helper functions for the layout test analyzer.""" 5 """Helper functions for the layout test analyzer."""
6 6
7 from datetime import datetime 7 from datetime import datetime
8 from email.mime.multipart import MIMEMultipart 8 from email.mime.multipart import MIMEMultipart
9 from email.mime.text import MIMEText 9 from email.mime.text import MIMEText
10 import fileinput 10 import fileinput
11 import os 11 import os
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 @staticmethod 67 @staticmethod
68 def GetDiffString(diff_map_element, type_str): 68 def GetDiffString(diff_map_element, type_str):
69 """Get difference string out of diff map element. 69 """Get difference string out of diff map element.
70 70
71 The difference string shows difference between two analyzer results 71 The difference string shows difference between two analyzer results
72 (for example, a result for now and a result for sometime in the past) 72 (for example, a result for now and a result for sometime in the past)
73 in HTML format (with colors). This is used for generating email messages. 73 in HTML format (with colors). This is used for generating email messages.
74 74
75 Args: 75 Args:
76 diff_map_element: An element of the compared map generated by 76 diff_map_element: An element of the compared map generated by
77 |CompareResultMaps()|. The element has two lists of test cases. One 77 |CompareResultMaps()|. The element has two lists of test cases. One
78 is for test names that are in the current result but NOT in the 78 is for test names that are in the current result but NOT in the
79 previous result. The other is for test names that are in the previous 79 previous result. The other is for test names that are in the previous
80 results but NOT in the current result. Please refer to comments in 80 results but NOT in the current result. Please refer to comments in
81 |CompareResultMaps()| for details. 81 |CompareResultMaps()| for details.
82 type_str: a string indicating the test group to which |diff_map_element| 82 type_str: a string indicating the test group to which |diff_map_element|
83 belongs; used for color determination. Must be 'whole', 'skip', or 83 belongs; used for color determination. Must be 'whole', 'skip', or
84 'nonskip'. 84 'nonskip'.
85 85
86 Returns: 86 Returns:
87 a string in HTML format (with colors) to show difference between two 87 a string in HTML format (with colors) to show difference between two
88 analyzer results. 88 analyzer results.
89 """ 89 """
90 diff = len(diff_map_element[0]) - len(diff_map_element[1]) 90 diff = len(diff_map_element[0]) - len(diff_map_element[1])
91 if diff == 0: 91 if diff == 0:
92 return 'No Change' 92 return 'No Change'
93 color = '' 93 color = ''
94 if diff > 0 and type_str != 'whole': 94 if diff > 0 and type_str != 'whole':
95 color = 'red' 95 color = 'red'
96 else: 96 else:
97 color = 'green' 97 color = 'green'
98 diff_sign = '' 98 diff_sign = ''
99 if diff > 0: 99 if diff > 0:
100 diff_sign = '+' 100 diff_sign = '+'
101 whole_str = '<font color="%s">%s%d</font>' % (color, diff_sign, diff) 101 whole_str = '<font color="%s">%s%d</font>' % (color, diff_sign, diff)
102 colors = ['red', 'green']
103 if type_str == 'whole':
104 # Bug 107773 - when we increase the number of tests,
105 # the name of the tests are in red, it should be green
106 # since it is good thing.
107 colors = ['green', 'red']
102 str1 = '' 108 str1 = ''
103 for (name, _) in diff_map_element[0]: 109 for (name, _) in diff_map_element[0]:
104 str1 += '<font color="red">%s,</font> ' % name 110 str1 += '<font color="%s">%s,</font>' % (colors[0], name)
105 str1 = str1[:-1]
106 str2 = '' 111 str2 = ''
107 for (name, _) in diff_map_element[1]: 112 for (name, _) in diff_map_element[1]:
108 str2 += '<font color="green">%s,</font> ' % name 113 str2 += '<font color="%s">%s,</font>' % (colors[1], name)
109 str2 = str2[:-1]
110 if str1 or str2: 114 if str1 or str2:
111 whole_str += ':' 115 whole_str += ':'
112 if str1: 116 if str1:
113 whole_str += str1 117 whole_str += str1
114 if str2: 118 if str2:
115 whole_str += str2 119 whole_str += str2
120 # Remove the last occurrence of ','.
121 whole_str = ''.join(whole_str.rsplit(',', 1))
116 return whole_str 122 return whole_str
117 123
118 def GetPassingRate(self): 124 def GetPassingRate(self):
119 """Get passing rate. 125 """Get passing rate.
120 126
121 Returns: 127 Returns:
122 layout test passing rate of this result in percent. 128 layout test passing rate of this result in percent.
123 129
124 Raises: 130 Raises:
125 ValueEror when the number of tests in test group "whole" is equal or less 131 ValueEror when the number of tests in test group "whole" is equal
126 than that of "skip". 132 or less than that of "skip".
127 """ 133 """
128 delta = len(self.result_map['whole'].keys()) - ( 134 delta = len(self.result_map['whole'].keys()) - (
129 len(self.result_map['skip'].keys())) 135 len(self.result_map['skip'].keys()))
130 if delta <= 0: 136 if delta <= 0:
131 raise ValueError('The number of tests in test group "whole" is equal or ' 137 raise ValueError('The number of tests in test group "whole" is equal or '
132 'less than that of "skip"') 138 'less than that of "skip"')
133 return 100 - len(self.result_map['nonskip'].keys()) * 100 / delta 139 return 100 - len(self.result_map['nonskip'].keys()) * 100 / delta
134 140
135 def ConvertToCSVText(self, current_time): 141 def ConvertToCSVText(self, current_time):
136 """Convert |self.result_map| into stats and issues text in CSV format. 142 """Convert |self.result_map| into stats and issues text in CSV format.
137 143
138 Both are used as inputs for Google spreadsheet. 144 Both are used as inputs for Google spreadsheet.
139 145
140 Args: 146 Args:
141 current_time: a string depicting a time in year-month-day-hour 147 current_time: a string depicting a time in year-month-day-hour
142 format (e.g., 2011-11-08-16). 148 format (e.g., 2011-11-08-16).
143 149
144 Returns: 150 Returns:
145 a tuple of stats and issues_txt 151 a tuple of stats and issues_txt
146 stats: analyzer result in CSV format that shows: 152 stats: analyzer result in CSV format that shows:
147 (current_time, the number of tests, the number of skipped tests, 153 (current_time, the number of tests, the number of skipped tests,
148 the number of failing tests, passing rate) 154 the number of failing tests, passing rate)
149 For example, 155 For example,
150 "2011-11-10-15,204,22,12,94" 156 "2011-11-10-15,204,22,12,94"
151 issues_txt: issues listed in CSV format that shows: 157 issues_txt: issues listed in CSV format that shows:
152 (BUGWK or BUGCR, bug number, the test expectation entry, 158 (BUGWK or BUGCR, bug number, the test expectation entry,
153 the name of the test) 159 the name of the test)
154 For example, 160 For example,
155 "BUGWK,71543,TIMEOUT PASS,media/media-element-play-after-eos.html, 161 "BUGWK,71543,TIMEOUT PASS,media/media-element-play-after-eos.html,
156 BUGCR,97657,IMAGE CPU MAC TIMEOUT PASS,media/audio-repaint.html," 162 BUGCR,97657,IMAGE CPU MAC TIMEOUT PASS,media/audio-repaint.html,"
157 """ 163 """
158 stats = ','.join([current_time, str(len(self.result_map['whole'].keys())), 164 stats = ','.join([current_time, str(len(self.result_map['whole'].keys())),
159 str(len(self.result_map['skip'].keys())), 165 str(len(self.result_map['skip'].keys())),
160 str(len(self.result_map['nonskip'].keys())), 166 str(len(self.result_map['nonskip'].keys())),
161 str(self.GetPassingRate())]) 167 str(self.GetPassingRate())])
162 issues_txt = '' 168 issues_txt = ''
163 for bug_txt, test_info_list in ( 169 for bug_txt, test_info_list in (
164 self.GetListOfBugsForNonSkippedTests().iteritems()): 170 self.GetListOfBugsForNonSkippedTests().iteritems()):
165 matches = re.match(r'(BUG(CR|WK))(\d+)', bug_txt) 171 matches = re.match(r'(BUG(CR|WK))(\d+)', bug_txt)
166 bug_suffix = '' 172 bug_suffix = ''
167 bug_no = '' 173 bug_no = ''
168 if matches: 174 if matches:
169 bug_suffix = matches.group(1) 175 bug_suffix = matches.group(1)
170 bug_no = matches.group(3) 176 bug_no = matches.group(3)
171 issues_txt += bug_suffix + ',' + bug_no + ',' 177 issues_txt += bug_suffix + ',' + bug_no + ','
172 for test_info in test_info_list: 178 for test_info in test_info_list:
173 test_name, te_info = test_info 179 test_name, te_info = test_info
174 issues_txt += ' '.join(te_info.keys()) + ',' + test_name + ',' 180 issues_txt += ' '.join(te_info.keys()) + ',' + test_name + ','
175 issues_txt += '\n' 181 issues_txt += '\n'
176 return stats, issues_txt 182 return stats, issues_txt
177 183
178 def ConvertToString(self, prev_time, diff_map, bug_anno_map): 184 def ConvertToString(self, prev_time, diff_map, bug_anno_map,
185 issue_detail_mode):
179 """Convert this result to HTML display for email. 186 """Convert this result to HTML display for email.
180 187
181 Args: 188 Args:
182 prev_time: the previous time string that are compared against. 189 prev_time: the previous time string that are compared against.
183 diff_map: the compared map generated by |CompareResultMaps()|. 190 diff_map: the compared map generated by |CompareResultMaps()|.
184 bug_anno_map: a annotation map where keys are bug names and values are 191 bug_anno_map: a annotation map where keys are bug names and values are
185 annotations for the bug. 192 annotations for the bug.
193 issue_detail_mode: includes the issue details in the output string if
194 this is True.
186 195
187 Returns: 196 Returns:
188 a analyzer result string in HTML format. 197 a analyzer result string in HTML format.
189 """ 198 """
190 return_str = '' 199 return_str = ''
191 if diff_map: 200 if diff_map:
192 return_str += ('<b>Statistics (Diff Compared to %s):</b><ul>' 201 return_str += (
193 '<li>The number of tests: %d (%s)</li>' 202 '<b>Statistics (Diff Compared to %s):</b><ul>'
194 '<li>The number of failing skipped tests: %d (%s)</li>' 203 '<li>The number of tests: %d (%s)</li>'
195 '<li>The number of failing non-skipped tests: %d (%s)</li>' 204 '<li>The number of failing skipped tests: %d (%s)</li>'
196 '<li>Passing rate: %d %%</li></ul>') % ( 205 '<li>The number of failing non-skipped tests: %d (%s)</li>'
197 prev_time, len(self.result_map['whole'].keys()), 206 '<li>Passing rate: %d %%</li></ul>') % (
198 AnalyzerResultMap.GetDiffString(diff_map['whole'], 'whole'), 207 prev_time, len(self.result_map['whole'].keys()),
199 len(self.result_map['skip'].keys()), 208 AnalyzerResultMap.GetDiffString(diff_map['whole'], 'whole'),
200 AnalyzerResultMap.GetDiffString(diff_map['skip'], 'skip'), 209 len(self.result_map['skip'].keys()),
201 len(self.result_map['nonskip'].keys()), 210 AnalyzerResultMap.GetDiffString(diff_map['skip'], 'skip'),
202 AnalyzerResultMap.GetDiffString(diff_map['nonskip'], 211 len(self.result_map['nonskip'].keys()),
203 'nonskip'), 212 AnalyzerResultMap.GetDiffString(diff_map['nonskip'], 'nonskip'),
204 self.GetPassingRate()) 213 self.GetPassingRate())
205 return_str += '<b>Current issues about failing non-skipped tests:</b>' 214 if issue_detail_mode:
206 for (bug_txt, test_info_list) in ( 215 return_str += '<b>Current issues about failing non-skipped tests:</b>'
207 self.GetListOfBugsForNonSkippedTests().iteritems()): 216 for (bug_txt, test_info_list) in (
208 if not bug_txt in bug_anno_map: 217 self.GetListOfBugsForNonSkippedTests().iteritems()):
209 bug_anno_map[bug_txt] = '<font color="red">Needs investigation!</font>' 218 if not bug_txt in bug_anno_map:
210 return_str += '<ul>%s (%s)' % (Bug(bug_txt), bug_anno_map[bug_txt]) 219 bug_anno_map[bug_txt] = ''
211 for test_info in test_info_list: 220 else:
212 (test_name, te_info) = test_info 221 bug_anno_map[bug_txt] = '(' + bug_anno_map[bug_txt] + ')'
213 gpu_link = '' 222 return_str += '<ul>%s %s' % (Bug(bug_txt), bug_anno_map[bug_txt])
214 if 'GPU' in te_info: 223 for test_info in test_info_list:
215 gpu_link = 'group=%40ToT%20GPU%20Mesa%20-%20chromium.org&' 224 (test_name, te_info) = test_info
216 dashboard_link = ('http://test-results.appspot.com/dashboards/' 225 gpu_link = ''
217 'flakiness_dashboard.html#%stests=%s') % ( 226 if 'GPU' in te_info:
218 gpu_link, test_name) 227 gpu_link = 'group=%40ToT%20GPU%20Mesa%20-%20chromium.org&'
219 return_str += '<li><a href="%s">%s</a> (%s) </li>' % ( 228 dashboard_link = ('http://test-results.appspot.com/dashboards/'
220 dashboard_link, test_name, ' '.join(te_info.keys())) 229 'flakiness_dashboard.html#%stests=%s') % (
221 return_str += '</ul>\n' 230 gpu_link, test_name)
231 return_str += '<li><a href="%s">%s</a> (%s) </li>' % (
232 dashboard_link, test_name, ' '.join(te_info.keys()))
233 return_str += '</ul>\n'
222 return return_str 234 return return_str
223 235
224 def CompareToOtherResultMap(self, other_result_map): 236 def CompareToOtherResultMap(self, other_result_map):
225 """Compare this result map with the other to see if there are any diff. 237 """Compare this result map with the other to see if there are any diff.
226 238
227 The comparison is done for layouttests which belong to 'whole', 'skip', 239 The comparison is done for layouttests which belong to 'whole', 'skip',
228 or 'nonskip'. 240 or 'nonskip'.
229 241
230 Args: 242 Args:
231 other_result_map: another result map to be compared against the result 243 other_result_map: another result map to be compared against the result
232 map of the current object. 244 map of the current object.
233 245
234 Returns: 246 Returns:
235 a map that has 'whole', 'skip' and 'nonskip' as keys. 247 a map that has 'whole', 'skip' and 'nonskip' as keys.
236 Please refer to |diff_map| in |SendStatusEmail()|. 248 Please refer to |diff_map| in |SendStatusEmail()|.
237 """ 249 """
238 comp_result_map = {} 250 comp_result_map = {}
239 for name in ['whole', 'skip', 'nonskip']: 251 for name in ['whole', 'skip', 'nonskip']:
240 if name == 'nonskip': 252 if name == 'nonskip':
241 # Look into expectation to get diff only for non-skipped tests. 253 # Look into expectation to get diff only for non-skipped tests.
242 lookIntoTestExpectationInfo = True 254 lookIntoTestExpectationInfo = True
243 else: 255 else:
244 # Otherwise, only test names are compared to get diff. 256 # Otherwise, only test names are compared to get diff.
245 lookIntoTestExpectationInfo = False 257 lookIntoTestExpectationInfo = False
246 comp_result_map[name] = GetDiffBetweenMaps( 258 comp_result_map[name] = GetDiffBetweenMaps(
247 self.result_map[name], other_result_map.result_map[name], 259 self.result_map[name], other_result_map.result_map[name],
248 lookIntoTestExpectationInfo) 260 lookIntoTestExpectationInfo)
249 return comp_result_map 261 return comp_result_map
250 262
251 @staticmethod 263 @staticmethod
252 def Load(file_path): 264 def Load(file_path):
253 """Load the object from |file_path| using pickle library. 265 """Load the object from |file_path| using pickle library.
254 266
255 Args: 267 Args:
256 file_path: the string path to the file from which to read the result. 268 file_path: the string path to the file from which to read the result.
257 269
258 Returns: 270 Returns:
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 bug_anno_map: bug annotation map where bug name and annotations are 336 bug_anno_map: bug annotation map where bug name and annotations are
325 stored. 337 stored.
326 receiver_email_address: receiver's email address. 338 receiver_email_address: receiver's email address.
327 test_group_name: string representing the test group name (e.g., 'media'). 339 test_group_name: string representing the test group name (e.g., 'media').
328 appended_text_to_email: a text which is appended at the end of the status 340 appended_text_to_email: a text which is appended at the end of the status
329 email. 341 email.
330 email_content: an email content string that will be shown on the dashboard. 342 email_content: an email content string that will be shown on the dashboard.
331 rev_str: a revision string that contains revision information that is sent 343 rev_str: a revision string that contains revision information that is sent
332 out in the status email. It is obtained by calling 344 out in the status email. It is obtained by calling
333 |GetRevisionString()|. 345 |GetRevisionString()|.
334 email_only_change_mode: please refer to |options|. 346 email_only_change_mode: send email only when there is a change if this is
347 True. Otherwise, always send email after each run.
335 """ 348 """
336 if rev_str: 349 if rev_str:
337 email_content += '<br><b>Revision Information:</b>' 350 email_content += '<br><b>Revision Information:</b>'
338 email_content += rev_str 351 email_content += rev_str
339 localtime = time.asctime(time.localtime(time.time())) 352 localtime = time.asctime(time.localtime(time.time()))
340 change_str = '' 353 change_str = ''
341 if email_only_change_mode: 354 if email_only_change_mode:
342 change_str = 'Status Change ' 355 change_str = 'Status Change '
343 subject = 'Layout Test Analyzer Result %s(%s): %s' % (change_str, 356 subject = 'Layout Test Analyzer Result %s(%s): %s' % (change_str,
344 test_group_name, 357 test_group_name,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 link = urllib.unquote('http://trac.webkit.org/changeset?new=%d%40trunk' 405 link = urllib.unquote('http://trac.webkit.org/changeset?new=%d%40trunk'
393 '%2FLayoutTests%2Fplatform%2Fchromium%2F' 406 '%2FLayoutTests%2Fplatform%2Fchromium%2F'
394 'test_expectations.txt&old=%d%40trunk%2F' 407 'test_expectations.txt&old=%d%40trunk%2F'
395 'LayoutTests%2Fplatform%2Fchromium%2F' 408 'LayoutTests%2Fplatform%2Fchromium%2F'
396 'test_expectations.txt') % (new_rev, old_rev) 409 'test_expectations.txt') % (new_rev, old_rev)
397 rev_str += '<ul><a href="%s">%s->%s</a>\n' % (link, old_rev, new_rev) 410 rev_str += '<ul><a href="%s">%s->%s</a>\n' % (link, old_rev, new_rev)
398 simple_rev_str = '<a href="%s">%s->%s</a>,' % (link, old_rev, new_rev) 411 simple_rev_str = '<a href="%s">%s->%s</a>,' % (link, old_rev, new_rev)
399 rev_str += '<li>%s</li>\n' % author 412 rev_str += '<li>%s</li>\n' % author
400 rev_str += '<li>%s</li>\n<ul>' % date 413 rev_str += '<li>%s</li>\n<ul>' % date
401 for line in target_lines: 414 for line in target_lines:
402 rev_str += '<li>%s</li>\n' % line 415 # Find *.html pattern (test name) and replace it with the link to
416 # flakiness dashboard.
417 test_name_pattern = r'(\S+.html)'
418 match = re.search(test_name_pattern, line)
419 if match:
420 test_name = match.group(1)
421 gpu_link = ''
422 if 'GPU' in line:
423 gpu_link = 'group=%40ToT%20GPU%20Mesa%20-%20chromium.org&'
424 dashboard_link = ('http://test-results.appspot.com/dashboards/'
425 'flakiness_dashboard.html#%stests=%s') % (
426 gpu_link, test_name)
427 line = line.replace(test_name, '<a href="%s">%s</a>' % (
428 dashboard_link, test_name))
429 # Find bug text and replace it with the link to the bug.
430 bug = Bug(line)
431 if bug.bug_txt:
432 line = '<li>%s</li>\n' % line.replace(bug.bug_txt, str(bug))
433 rev_str += line
403 rev_str += '</ul></ul>' 434 rev_str += '</ul></ul>'
404 return (rev_str, simple_rev_str, rev, rev_date) 435 return (rev_str, simple_rev_str, rev, rev_date)
405 436
406 437
407 def SendEmail(sender_email_address, receivers_email_addresses, subject, 438 def SendEmail(sender_email_address, receivers_email_addresses, subject,
408 message): 439 message):
409 """Send email using localhost's mail server. 440 """Send email using localhost's mail server.
410 441
411 Args: 442 Args:
412 sender_email_address: sender's email address. 443 sender_email_address: sender's email address.
413 receivers_email_addresses: receiver's email addresses. 444 receivers_email_addresses: receiver's email addresses.
414 subject: subject string. 445 subject: subject string.
415 message: email message. 446 message: email message.
447 """
448 try:
449 html_top = """
450 <html>
451 <head></head>
452 <body>
416 """ 453 """
417 try: 454 html_bot = """
418 html_top = """ 455 </body>
419 <html> 456 </html>
420 <head></head> 457 """
421 <body> 458 html = html_top + message + html_bot
422 """ 459 msg = MIMEMultipart('alternative')
423 html_bot = """ 460 msg['Subject'] = subject
424 </body> 461 msg['From'] = sender_email_address
425 </html> 462 msg['To'] = receivers_email_addresses[0]
426 """ 463 part1 = MIMEText(html, 'html')
427 html = html_top + message + html_bot 464 smtp_obj = smtplib.SMTP('localhost')
428 msg = MIMEMultipart('alternative') 465 msg.attach(part1)
429 msg['Subject'] = subject 466 smtp_obj.sendmail(sender_email_address, receivers_email_addresses,
430 msg['From'] = sender_email_address 467 msg.as_string())
431 msg['To'] = receivers_email_addresses[0] 468 print 'Successfully sent email'
432 part1 = MIMEText(html, 'html') 469 except smtplib.SMTPException, ex:
433 smtp_obj = smtplib.SMTP('localhost') 470 print 'Authentication failed:', ex
434 msg.attach(part1) 471 print 'Error: unable to send email'
435 smtp_obj.sendmail(sender_email_address, receivers_email_addresses, 472 except (socket.gaierror, socket.error, socket.herror), ex:
436 msg.as_string()) 473 print ex
437 print 'Successfully sent email' 474 print 'Error: unable to send email'
438 except smtplib.SMTPException, ex:
439 print 'Authentication failed:', ex
440 print 'Error: unable to send email'
441 except (socket.gaierror, socket.error, socket.herror), ex:
442 print ex
443 print 'Error: unable to send email'
444 475
445 476
446 def FindLatestTime(time_list): 477 def FindLatestTime(time_list):
447 """Find latest time from |time_list|. 478 """Find latest time from |time_list|.
448 479
449 The current status is compared to the status of the latest file in 480 The current status is compared to the status of the latest file in
450 |RESULT_DIR|. 481 |RESULT_DIR|.
451 482
452 Args: 483 Args:
453 time_list: a list of time string in the form of 'Year-Month-Day-Hour' 484 time_list: a list of time string in the form of 'Year-Month-Day-Hour'
454 (e.g., 2011-10-23-23). Strings not in this format are ignored. 485 (e.g., 2011-10-23-23). Strings not in this format are ignored.
455 486
456 Returns: 487 Returns:
457 a string representing latest time among the time_list or None if 488 a string representing latest time among the time_list or None if
458 |time_list| is empty or no valid date string in |time_list|. 489 |time_list| is empty or no valid date string in |time_list|.
459 """ 490 """
460 if not time_list: 491 if not time_list:
461 return None 492 return None
462 latest_date = None 493 latest_date = None
463 for time_element in time_list: 494 for time_element in time_list:
464 try: 495 try:
465 item_date = datetime.strptime(time_element, '%Y-%m-%d-%H') 496 item_date = datetime.strptime(time_element, '%Y-%m-%d-%H')
466 if latest_date == None or latest_date < item_date: 497 if latest_date is None or latest_date < item_date:
467 latest_date = item_date 498 latest_date = item_date
468 except ValueError: 499 except ValueError:
469 # Do nothing. 500 # Do nothing.
470 pass 501 pass
471 if latest_date: 502 if latest_date:
472 return latest_date.strftime('%Y-%m-%d-%H') 503 return latest_date.strftime('%Y-%m-%d-%H')
473 else: 504 else:
474 return None 505 return None
475 506
476 507
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 a list of tuples (name, te_info) that are in |map1| but not in |map2|. 570 a list of tuples (name, te_info) that are in |map1| but not in |map2|.
540 """ 571 """
541 name_list = [] 572 name_list = []
542 for (name, value1) in map1.iteritems(): 573 for (name, value1) in map1.iteritems():
543 if name in map2: 574 if name in map2:
544 if lookIntoTestExpectationInfo and 'te_info' in value1: 575 if lookIntoTestExpectationInfo and 'te_info' in value1:
545 list1 = value1['te_info'] 576 list1 = value1['te_info']
546 list2 = map2[name]['te_info'] 577 list2 = map2[name]['te_info']
547 te_diff = [item for item in list1 if not item in list2] 578 te_diff = [item for item in list1 if not item in list2]
548 if te_diff: 579 if te_diff:
549 name_list.append((name, te_diff)) 580 name_list.append((name, te_diff))
550 else: 581 else:
551 name_list.append((name, value1)) 582 name_list.append((name, value1))
552 return name_list 583 return name_list
553 584
554 return (GetDiffBetweenMapsHelper(map1, map2, lookIntoTestExpectationInfo), 585 return (GetDiffBetweenMapsHelper(map1, map2, lookIntoTestExpectationInfo),
555 GetDiffBetweenMapsHelper(map2, map1, lookIntoTestExpectationInfo)) 586 GetDiffBetweenMapsHelper(map2, map1, lookIntoTestExpectationInfo))
OLDNEW
« no previous file with comments | « media/tools/layout_tests/layouttest_analyzer.py ('k') | media/tools/layout_tests/layouttest_analyzer_helpers_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698