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

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: Created 8 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
OLDNEW
1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2011 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
(...skipping 56 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|
dennis_jeffrey 2012/02/29 17:50:32 indent this line by 1 more space
imasaki1 2012/03/02 19:12:07 Done.
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))
dennis_jeffrey 2012/02/29 17:50:32 Another way to do this without splitting and joini
imasaki1 2012/03/02 19:12:07 I prefer to leave as it is. but, thanks for the co
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: Please see |options|.
dennis_jeffrey 2012/02/29 17:50:32 Since "options" is not defined in this file, it mi
imasaki1 2012/03/02 19:12:07 Done.
186 194
187 Returns: 195 Returns:
188 a analyzer result string in HTML format. 196 a analyzer result string in HTML format.
189 """ 197 """
190 return_str = '' 198 return_str = ''
191 if diff_map: 199 if diff_map:
192 return_str += ('<b>Statistics (Diff Compared to %s):</b><ul>' 200 return_str += (
193 '<li>The number of tests: %d (%s)</li>' 201 '<b>Statistics (Diff Compared to %s):</b><ul>'
194 '<li>The number of failing skipped tests: %d (%s)</li>' 202 '<li>The number of tests: %d (%s)</li>'
195 '<li>The number of failing non-skipped tests: %d (%s)</li>' 203 '<li>The number of failing skipped tests: %d (%s)</li>'
196 '<li>Passing rate: %d %%</li></ul>') % ( 204 '<li>The number of failing non-skipped tests: %d (%s)</li>'
197 prev_time, len(self.result_map['whole'].keys()), 205 '<li>Passing rate: %d %%</li></ul>') % (
198 AnalyzerResultMap.GetDiffString(diff_map['whole'], 'whole'), 206 prev_time, len(self.result_map['whole'].keys()),
199 len(self.result_map['skip'].keys()), 207 AnalyzerResultMap.GetDiffString(diff_map['whole'], 'whole'),
200 AnalyzerResultMap.GetDiffString(diff_map['skip'], 'skip'), 208 len(self.result_map['skip'].keys()),
201 len(self.result_map['nonskip'].keys()), 209 AnalyzerResultMap.GetDiffString(diff_map['skip'], 'skip'),
202 AnalyzerResultMap.GetDiffString(diff_map['nonskip'], 210 len(self.result_map['nonskip'].keys()),
203 'nonskip'), 211 AnalyzerResultMap.GetDiffString(diff_map['nonskip'], 'nonskip'),
204 self.GetPassingRate()) 212 self.GetPassingRate())
205 return_str += '<b>Current issues about failing non-skipped tests:</b>' 213 if issue_detail_mode:
206 for (bug_txt, test_info_list) in ( 214 return_str += '<b>Current issues about failing non-skipped tests:</b>'
207 self.GetListOfBugsForNonSkippedTests().iteritems()): 215 for (bug_txt, test_info_list) in (
208 if not bug_txt in bug_anno_map: 216 self.GetListOfBugsForNonSkippedTests().iteritems()):
209 bug_anno_map[bug_txt] = '<font color="red">Needs investigation!</font>' 217 if not bug_txt in bug_anno_map:
210 return_str += '<ul>%s (%s)' % (Bug(bug_txt), bug_anno_map[bug_txt]) 218 bug_anno_map[bug_txt] = ''
211 for test_info in test_info_list: 219 else:
212 (test_name, te_info) = test_info 220 bug_anno_map[bug_txt] = '(' + bug_anno_map[bug_txt] + ')'
213 gpu_link = '' 221 return_str += '<ul>%s %s' % (Bug(bug_txt), bug_anno_map[bug_txt])
214 if 'GPU' in te_info: 222 for test_info in test_info_list:
215 gpu_link = 'group=%40ToT%20GPU%20Mesa%20-%20chromium.org&' 223 (test_name, te_info) = test_info
216 dashboard_link = ('http://test-results.appspot.com/dashboards/' 224 gpu_link = ''
217 'flakiness_dashboard.html#%stests=%s') % ( 225 if 'GPU' in te_info:
218 gpu_link, test_name) 226 gpu_link = 'group=%40ToT%20GPU%20Mesa%20-%20chromium.org&'
219 return_str += '<li><a href="%s">%s</a> (%s) </li>' % ( 227 dashboard_link = ('http://test-results.appspot.com/dashboards/'
220 dashboard_link, test_name, ' '.join(te_info.keys())) 228 'flakiness_dashboard.html#%stests=%s') % (
221 return_str += '</ul>\n' 229 gpu_link, test_name)
230 return_str += '<li><a href="%s">%s</a> (%s) </li>' % (
231 dashboard_link, test_name, ' '.join(te_info.keys()))
232 return_str += '</ul>\n'
222 return return_str 233 return return_str
223 234
224 def CompareToOtherResultMap(self, other_result_map): 235 def CompareToOtherResultMap(self, other_result_map):
225 """Compare this result map with the other to see if there are any diff. 236 """Compare this result map with the other to see if there are any diff.
226 237
227 The comparison is done for layouttests which belong to 'whole', 'skip', 238 The comparison is done for layouttests which belong to 'whole', 'skip',
228 or 'nonskip'. 239 or 'nonskip'.
229 240
230 Args: 241 Args:
231 other_result_map: another result map to be compared against the result 242 other_result_map: another result map to be compared against the result
232 map of the current object. 243 map of the current object.
233 244
234 Returns: 245 Returns:
235 a map that has 'whole', 'skip' and 'nonskip' as keys. 246 a map that has 'whole', 'skip' and 'nonskip' as keys.
236 Please refer to |diff_map| in |SendStatusEmail()|. 247 Please refer to |diff_map| in |SendStatusEmail()|.
237 """ 248 """
238 comp_result_map = {} 249 comp_result_map = {}
239 for name in ['whole', 'skip', 'nonskip']: 250 for name in ['whole', 'skip', 'nonskip']:
240 if name == 'nonskip': 251 if name == 'nonskip':
241 # Look into expectation to get diff only for non-skipped tests. 252 # Look into expectation to get diff only for non-skipped tests.
242 lookIntoTestExpectationInfo = True 253 lookIntoTestExpectationInfo = True
243 else: 254 else:
244 # Otherwise, only test names are compared to get diff. 255 # Otherwise, only test names are compared to get diff.
245 lookIntoTestExpectationInfo = False 256 lookIntoTestExpectationInfo = False
246 comp_result_map[name] = GetDiffBetweenMaps( 257 comp_result_map[name] = GetDiffBetweenMaps(
247 self.result_map[name], other_result_map.result_map[name], 258 self.result_map[name], other_result_map.result_map[name],
248 lookIntoTestExpectationInfo) 259 lookIntoTestExpectationInfo)
249 return comp_result_map 260 return comp_result_map
250 261
251 @staticmethod 262 @staticmethod
252 def Load(file_path): 263 def Load(file_path):
253 """Load the object from |file_path| using pickle library. 264 """Load the object from |file_path| using pickle library.
254 265
255 Args: 266 Args:
256 file_path: the string path to the file from which to read the result. 267 file_path: the string path to the file from which to read the result.
257 268
258 Returns: 269 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 335 bug_anno_map: bug annotation map where bug name and annotations are
325 stored. 336 stored.
326 receiver_email_address: receiver's email address. 337 receiver_email_address: receiver's email address.
327 test_group_name: string representing the test group name (e.g., 'media'). 338 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 339 appended_text_to_email: a text which is appended at the end of the status
329 email. 340 email.
330 email_content: an email content string that will be shown on the dashboard. 341 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 342 rev_str: a revision string that contains revision information that is sent
332 out in the status email. It is obtained by calling 343 out in the status email. It is obtained by calling
333 |GetRevisionString()|. 344 |GetRevisionString()|.
334 email_only_change_mode: please refer to |options|. 345 email_only_change_mode: please refer to |options|.
dennis_jeffrey 2012/02/29 17:50:32 Similar comment as line 193 above.
imasaki1 2012/03/02 19:12:07 Done.
335 """ 346 """
336 if rev_str: 347 if rev_str:
337 email_content += '<br><b>Revision Information:</b>' 348 email_content += '<br><b>Revision Information:</b>'
338 email_content += rev_str 349 email_content += rev_str
339 localtime = time.asctime(time.localtime(time.time())) 350 localtime = time.asctime(time.localtime(time.time()))
340 change_str = '' 351 change_str = ''
341 if email_only_change_mode: 352 if email_only_change_mode:
342 change_str = 'Status Change ' 353 change_str = 'Status Change '
343 subject = 'Layout Test Analyzer Result %s(%s): %s' % (change_str, 354 subject = 'Layout Test Analyzer Result %s(%s): %s' % (change_str,
344 test_group_name, 355 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' 403 link = urllib.unquote('http://trac.webkit.org/changeset?new=%d%40trunk'
393 '%2FLayoutTests%2Fplatform%2Fchromium%2F' 404 '%2FLayoutTests%2Fplatform%2Fchromium%2F'
394 'test_expectations.txt&old=%d%40trunk%2F' 405 'test_expectations.txt&old=%d%40trunk%2F'
395 'LayoutTests%2Fplatform%2Fchromium%2F' 406 'LayoutTests%2Fplatform%2Fchromium%2F'
396 'test_expectations.txt') % (new_rev, old_rev) 407 'test_expectations.txt') % (new_rev, old_rev)
397 rev_str += '<ul><a href="%s">%s->%s</a>\n' % (link, old_rev, new_rev) 408 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) 409 simple_rev_str = '<a href="%s">%s->%s</a>,' % (link, old_rev, new_rev)
399 rev_str += '<li>%s</li>\n' % author 410 rev_str += '<li>%s</li>\n' % author
400 rev_str += '<li>%s</li>\n<ul>' % date 411 rev_str += '<li>%s</li>\n<ul>' % date
401 for line in target_lines: 412 for line in target_lines:
402 rev_str += '<li>%s</li>\n' % line 413 # Find *.html pattern (test name) and replace it with the link to
414 # frakiness dashboard.
dennis_jeffrey 2012/02/29 17:50:32 frakiness --> flakiness
imasaki1 2012/03/02 19:12:07 Done.
415 test_name_pattern = r'(\S+.html)'
416 match = re.search(test_name_pattern, line)
417 if match:
418 test_name = match.group(1)
419 gpu_link = ''
420 if 'GPU' in line:
421 gpu_link = 'group=%40ToT%20GPU%20Mesa%20-%20chromium.org&'
422 dashboard_link = ('http://test-results.appspot.com/dashboards/'
423 'flakiness_dashboard.html#%stests=%s') % (
424 gpu_link, test_name)
425 line = line.replace(test_name, "<a href='%s'>%s</a>" % (
dennis_jeffrey 2012/02/29 17:50:32 nit: I recommend swapping the single quotes and do
imasaki1 2012/03/02 19:12:07 Done.
426 dashboard_link, test_name))
427 # Find bug text and replace it with the link to the bug.
428 bug = Bug(line)
429 new_line = '<li>%s</li>\n' % line.replace(bug.bug_txt, bug.__str__())
dennis_jeffrey 2012/02/29 17:50:32 could we replace bug.__str__() with str(bug)?
imasaki1 2012/03/02 19:12:07 Done.
430 rev_str += new_line
403 rev_str += '</ul></ul>' 431 rev_str += '</ul></ul>'
404 return (rev_str, simple_rev_str, rev, rev_date) 432 return (rev_str, simple_rev_str, rev, rev_date)
405 433
406 434
407 def SendEmail(sender_email_address, receivers_email_addresses, subject, 435 def SendEmail(sender_email_address, receivers_email_addresses, subject,
408 message): 436 message):
409 """Send email using localhost's mail server. 437 """Send email using localhost's mail server.
410 438
411 Args: 439 Args:
412 sender_email_address: sender's email address. 440 sender_email_address: sender's email address.
413 receivers_email_addresses: receiver's email addresses. 441 receivers_email_addresses: receiver's email addresses.
414 subject: subject string. 442 subject: subject string.
415 message: email message. 443 message: email message.
444 """
445 try:
446 html_top = """
447 <html>
448 <head></head>
449 <body>
416 """ 450 """
417 try: 451 html_bot = """
418 html_top = """ 452 </body>
419 <html> 453 </html>
420 <head></head> 454 """
421 <body> 455 html = html_top + message + html_bot
422 """ 456 msg = MIMEMultipart('alternative')
423 html_bot = """ 457 msg['Subject'] = subject
424 </body> 458 msg['From'] = sender_email_address
425 </html> 459 msg['To'] = receivers_email_addresses[0]
426 """ 460 part1 = MIMEText(html, 'html')
427 html = html_top + message + html_bot 461 smtp_obj = smtplib.SMTP('localhost')
428 msg = MIMEMultipart('alternative') 462 msg.attach(part1)
429 msg['Subject'] = subject 463 smtp_obj.sendmail(sender_email_address, receivers_email_addresses,
430 msg['From'] = sender_email_address 464 msg.as_string())
431 msg['To'] = receivers_email_addresses[0] 465 print 'Successfully sent email'
432 part1 = MIMEText(html, 'html') 466 except smtplib.SMTPException, ex:
433 smtp_obj = smtplib.SMTP('localhost') 467 print 'Authentication failed:', ex
434 msg.attach(part1) 468 print 'Error: unable to send email'
435 smtp_obj.sendmail(sender_email_address, receivers_email_addresses, 469 except (socket.gaierror, socket.error, socket.herror), ex:
436 msg.as_string()) 470 print ex
437 print 'Successfully sent email' 471 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 472
445 473
446 def FindLatestTime(time_list): 474 def FindLatestTime(time_list):
447 """Find latest time from |time_list|. 475 """Find latest time from |time_list|.
448 476
449 The current status is compared to the status of the latest file in 477 The current status is compared to the status of the latest file in
450 |RESULT_DIR|. 478 |RESULT_DIR|.
451 479
452 Args: 480 Args:
453 time_list: a list of time string in the form of 'Year-Month-Day-Hour' 481 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. 482 (e.g., 2011-10-23-23). Strings not in this format are ignored.
455 483
456 Returns: 484 Returns:
457 a string representing latest time among the time_list or None if 485 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|. 486 |time_list| is empty or no valid date string in |time_list|.
459 """ 487 """
460 if not time_list: 488 if not time_list:
461 return None 489 return None
462 latest_date = None 490 latest_date = None
463 for time_element in time_list: 491 for time_element in time_list:
464 try: 492 try:
465 item_date = datetime.strptime(time_element, '%Y-%m-%d-%H') 493 item_date = datetime.strptime(time_element, '%Y-%m-%d-%H')
466 if latest_date == None or latest_date < item_date: 494 if latest_date is None or latest_date < item_date:
467 latest_date = item_date 495 latest_date = item_date
468 except ValueError: 496 except ValueError:
469 # Do nothing. 497 # Do nothing.
470 pass 498 pass
471 if latest_date: 499 if latest_date:
472 return latest_date.strftime('%Y-%m-%d-%H') 500 return latest_date.strftime('%Y-%m-%d-%H')
473 else: 501 else:
474 return None 502 return None
475 503
476 504
(...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|. 567 a list of tuples (name, te_info) that are in |map1| but not in |map2|.
540 """ 568 """
541 name_list = [] 569 name_list = []
542 for (name, value1) in map1.iteritems(): 570 for (name, value1) in map1.iteritems():
543 if name in map2: 571 if name in map2:
544 if lookIntoTestExpectationInfo and 'te_info' in value1: 572 if lookIntoTestExpectationInfo and 'te_info' in value1:
545 list1 = value1['te_info'] 573 list1 = value1['te_info']
546 list2 = map2[name]['te_info'] 574 list2 = map2[name]['te_info']
547 te_diff = [item for item in list1 if not item in list2] 575 te_diff = [item for item in list1 if not item in list2]
548 if te_diff: 576 if te_diff:
549 name_list.append((name, te_diff)) 577 name_list.append((name, te_diff))
550 else: 578 else:
551 name_list.append((name, value1)) 579 name_list.append((name, value1))
552 return name_list 580 return name_list
553 581
554 return (GetDiffBetweenMapsHelper(map1, map2, lookIntoTestExpectationInfo), 582 return (GetDiffBetweenMapsHelper(map1, map2, lookIntoTestExpectationInfo),
555 GetDiffBetweenMapsHelper(map2, map1, lookIntoTestExpectationInfo)) 583 GetDiffBetweenMapsHelper(map2, map1, lookIntoTestExpectationInfo))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698