OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/python | |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """A module for helper functions for the layouttest analyzer.""" | |
dennis_jeffrey
2011/08/24 17:40:47
'Helper functions for the layout test analyzer.'
imasaki1
2011/08/25 23:57:03
Done.
| |
7 | |
8 import copy | |
9 from datetime import datetime | |
10 from email.mime.multipart import MIMEMultipart | |
11 from email.mime.text import MIMEText | |
12 import os | |
13 import pickle | |
14 import smtplib | |
15 import time | |
16 import urllib | |
17 | |
18 from bug import Bug | |
19 from test_expectations_history import TestExpectationsHistory | |
20 | |
21 | |
22 class AnalyzerResultMap: | |
23 """A class to deal with joined result produed by the analyzer. | |
24 | |
25 The join is done between layouttests and the test_expectations object | |
26 (based on the test expectation file). The instance variable |result_map| | |
27 contains the following keys: 'whole','skip','nonskip'. The value of 'whole' | |
28 contains information about all layouttests. The value of 'skip' contains | |
29 information about skipped layouttests where it has 'SKIP' in its entry in | |
30 the test expectation file. The value of 'nonskip' contains all information | |
31 about non skipped layout tests, which are in the test expectation file but | |
32 no skipped. The information is exactly same as the one parsed by the | |
dennis_jeffrey
2011/08/24 17:40:47
'no skipped' --> 'not skipped'
imasaki1
2011/08/25 23:57:03
Done.
| |
33 analyzer. | |
34 """ | |
35 | |
36 def __init__(self, test_info_map): | |
37 """Initialize the Result based on test_info_map. | |
dennis_jeffrey
2011/08/24 17:40:47
'Result' --> 'AnalyzerResultMap'
imasaki1
2011/08/25 23:57:03
Done.
| |
38 | |
39 Test_info_map contains all layouttest information. The job here is to | |
40 classify them to 'whole', 'skip' or 'nonskip' based on that information. | |
dennis_jeffrey
2011/08/24 17:40:47
'them to' --> 'them as'
imasaki1
2011/08/25 23:57:03
Done.
| |
41 | |
42 Args: | |
43 test_info_map: the result map of layouttests.JoinWithTestExpectation, | |
44 The key of the map is testname such as 'media/media-foo.html'. | |
45 The value of the map is a map that contains the following keys: desc | |
46 (description), te_info (test expectation information), which is | |
47 a list of test expectation information map. The key of the map is | |
48 test expectation keywords such as "SKIP". | |
dennis_jeffrey
2011/08/24 17:40:47
You first mention that the map contains keys "desc
imasaki1
2011/08/25 23:57:03
Added more comments, here.
| |
49 """ | |
50 self.result_map = {} | |
51 self.result_map['whole'] = {} | |
52 self.result_map['skip'] = {} | |
53 self.result_map['nonskip'] = {} | |
54 if test_info_map is not None: | |
dennis_jeffrey
2011/08/24 17:40:47
I think we can just use "if test_info_map:"
imasaki1
2011/08/25 23:57:03
Done.
| |
55 for (k, v) in test_info_map.iteritems(): | |
56 self.result_map['whole'][k] = v | |
57 if 'te_info' in v: | |
58 skip = False | |
59 for e in v['te_info']: | |
60 if 'SKIP' in e: | |
61 skip = True | |
62 break | |
dennis_jeffrey
2011/08/24 17:40:47
I think we can shorten lines 58-62 above using the
imasaki1
2011/08/25 23:57:03
Done.
| |
63 if skip: | |
64 self.result_map['skip'][k] = v | |
65 else: | |
66 self.result_map['nonskip'][k] = v | |
67 | |
68 @staticmethod | |
69 def GetDiffString(diff_map_element, type_str): | |
70 """Get difference string out of diff map element | |
dennis_jeffrey
2011/08/24 17:40:47
What do you mean by a "difference string"? Also,
imasaki1
2011/08/25 23:57:03
Done.
| |
71 | |
72 This is used for generating email message. | |
dennis_jeffrey
2011/08/24 17:40:47
'email message' -->
'email messages'
imasaki1
2011/08/25 23:57:03
Done.
| |
73 | |
74 Args: | |
75 diff_map_element: the compared map generated by |CompareResultMaps()| | |
dennis_jeffrey
2011/08/24 17:40:47
Add a period or comma at the end of this line. If
imasaki1
2011/08/25 23:57:03
Done.
| |
76 also, this is for each test group ('whole', 'skip', 'nonskip') | |
dennis_jeffrey
2011/08/24 17:40:47
Add period at end of this sentence.
imasaki1
2011/08/25 23:57:03
Done.
| |
77 | |
dennis_jeffrey
2011/08/24 17:40:47
What about the "type_str" arg?
imasaki1
2011/08/25 23:57:03
Done.
| |
78 Return: | |
dennis_jeffrey
2011/08/24 17:40:47
'Returns:'
imasaki1
2011/08/25 23:57:03
Done.
| |
79 a string including diff information. | |
dennis_jeffrey
2011/08/24 17:40:47
what do you mean by "diff information"?
imasaki1
2011/08/25 23:57:03
Done.
| |
80 """ | |
81 diff = len(diff_map_element[0]) - len(diff_map_element[1]) | |
dennis_jeffrey
2011/08/24 17:40:47
I thought diff_map_element is a dictionary with ke
imasaki1
2011/08/25 23:57:03
no. It is a tuple with two lists. I will modify th
dennis_jeffrey
2011/08/26 19:01:26
Got it. Thanks.
| |
82 if diff == 0: | |
83 return 'No Change' | |
84 color = '' | |
85 if diff > 0 and type_str != 'whole': | |
86 color = 'red' | |
87 else: | |
88 color = 'green' | |
89 str = '<font color="%s">+%d</font>' % (color, diff) | |
dennis_jeffrey
2011/08/24 17:40:47
was it intentional to have a '+' within the string
imasaki1
2011/08/25 23:57:03
Good catch I will add only when diff is negative.
| |
90 str1 = '' | |
91 for (name, v) in diff_map_element[0]: | |
92 str1 += name + "," | |
dennis_jeffrey
2011/08/24 17:40:47
use single quotes in the string
imasaki1
2011/08/25 23:57:03
Done.
| |
93 str1 = str1[:-1] | |
94 str2 = '' | |
95 for (name, v) in diff_map_element[1]: | |
96 str2 += name + "," | |
97 str2 = str2[:-1] | |
98 if str1 or str2: | |
99 str += ":" | |
100 if str1: | |
101 str += '<font color="%s">%s</font> ' % (color, str1) | |
102 if str2: | |
103 str += '<font color="%s">%s</font>' % (color, str2) | |
104 return str | |
105 | |
106 def ConvertToString(self, prev_time, diff_map, bug_anno_map): | |
107 """Convert this result to HTML display for email. | |
108 | |
109 Args: | |
110 prev_time: the previous time string that are compared against. | |
111 diff_map: the compared map generated by |CompareResultMaps()|. | |
112 anno_map: a annotation map where keys are bug names and values are | |
dennis_jeffrey
2011/08/24 17:40:47
'anno_map' --> 'bug_anno_map'
imasaki1
2011/08/25 23:57:03
Done.
| |
113 annotation for the bug. | |
dennis_jeffrey
2011/08/24 17:40:47
'annotation' --> 'annotations'
imasaki1
2011/08/25 23:57:03
Done.
| |
114 | |
115 Returns: | |
116 a analyzer result string in HTML format. | |
117 """ | |
118 d = len(self.result_map['whole'].keys()) - ( | |
119 len(self.result_map['skip'].keys())) | |
120 # Passing rate is calculated like the followings. | |
dennis_jeffrey
2011/08/24 17:40:47
I think this comment is not necessary; we can see
imasaki1
2011/08/25 23:57:03
Removed. Also, this part is replaced by function c
| |
121 passing_rate = 100 - len(self.result_map['nonskip'].keys()) * 100 / d | |
122 str = ('<b>Statistics (Diff Compared to %s):</b><ul>' | |
123 '<li>The number of tests: %d (%s)</li>' | |
124 '<li>The number of failing skipped tests: %d (%s)</li>' | |
125 '<li>The number of failing non-skipped tests: %d (%s)</li>' | |
126 '<li>Passing rate: %d %%</li></ul>') % ( | |
127 prev_time, | |
128 len(self.result_map['whole'].keys()), | |
129 AnalyzerResultMap.GetDiffString(diff_map['whole'], 'whole'), | |
130 len(self.result_map['skip'].keys()), | |
131 AnalyzerResultMap.GetDiffString(diff_map['skip'], 'skip'), | |
132 len(self.result_map['nonskip'].keys()), | |
133 AnalyzerResultMap.GetDiffString(diff_map['nonskip'], 'nonskip'), | |
134 passing_rate) | |
135 str += '<b>Current issues about failing non-skipped tests:</b>' | |
136 for (bug_txt, test_info_list) in ( | |
137 self.GetListOfBugsForNonSkippedTests().iteritems()): | |
138 if not bug_txt in bug_anno_map: | |
139 bug_anno_map[bug_txt] = '<font color="red">Needs investigation!</font>' | |
140 str += '<ul>%s (%s)' % (Bug(bug_txt).ToString(), bug_anno_map[bug_txt]) | |
dennis_jeffrey
2011/08/24 17:40:47
Do you use a Bug object anywhere else? If so, tha
imasaki1
2011/08/25 23:57:03
I am planning to implement several more functions
| |
141 for test_info in test_info_list: | |
142 (test_name, te_info) = test_info | |
143 gpu_link = '' | |
144 if 'GPU' in te_info: | |
145 gpu_link = 'group=%40ToT%20GPU%20Mesa%20-%20chromium.org&' | |
146 dashboard_link = ('http://test-results.appspot.com/dashboards/' | |
147 'flakiness_dashboard.html#%stests=' | |
148 '%s' % (gpu_link, test_name)) | |
dennis_jeffrey
2011/08/24 17:40:47
nit: indent the above 2 lines some more so they li
imasaki1
2011/08/25 23:57:03
Done.
| |
149 str += '<li><a href="%s">%s</a> (%s) </li>' % ( | |
150 dashboard_link, test_name, ' '.join(te_info.keys())) | |
151 str += '</ul>\n' | |
152 return str | |
153 | |
154 def CompareResultMaps(self, result_map2): | |
dennis_jeffrey
2011/08/24 17:40:47
How about 'other_result_map' instead of 'result_ma
imasaki1
2011/08/25 23:57:03
Done.
| |
155 """Compare this result map with the other to see if any difference. | |
dennis_jeffrey
2011/08/24 17:40:47
'any difference' --> 'there are any differences'
imasaki1
2011/08/25 23:57:03
Done.
| |
156 | |
157 The comparison is done for layouttests which belong to 'whole', 'skip', | |
158 or 'nonskip'. | |
159 | |
160 Args: | |
161 result_map2: another result map to be compared againt this result. | |
dennis_jeffrey
2011/08/24 17:40:47
'this result' --> 'the result map of the current o
imasaki1
2011/08/25 23:57:03
Done.
| |
162 | |
163 Returns: | |
164 a comp_result_map, which contains 'whole', 'skip' and 'nonskip' as keys. | |
dennis_jeffrey
2011/08/24 17:40:47
We shouldn't say 'comp_result_map' in the descript
imasaki1
2011/08/25 23:57:03
Modified comment here.
| |
165 The values are the result of |GetDiffBetweenMaps()| that have two | |
166 tuples, where one is for a list of current tests diff and the other | |
dennis_jeffrey
2011/08/24 17:40:47
'tests diff' --> 'test diffs'
imasaki1
2011/08/25 23:57:03
Deleted.
| |
167 one is for a list of previous test diff. | |
dennis_jeffrey
2011/08/24 17:40:47
'diff' --> 'diffs'
imasaki1
2011/08/25 23:57:03
Deleted
| |
168 For example (test expectaion information is omitted for simplicity), | |
169 comp_result_map['whole'][0] = ['foo1.html'] | |
170 comp_result_map['whole'][1] = ['foo2.html'] | |
171 This means that current result has 'foo1.html' but not in previous | |
172 result. This also means the previous result has 'foo2.html' but not | |
173 current one. | |
dennis_jeffrey
2011/08/24 17:40:47
Should we add a comment somewhere explicitly sayin
imasaki1
2011/08/25 23:57:03
Done.
| |
174 """ | |
175 comp_result_map = {} | |
176 for name in ['whole', 'skip', 'nonskip']: | |
177 if name == 'nonskip': | |
178 # Look into expectation to get diff only for non-skipped tests. | |
179 lookintoTestExpectaionInfo = True | |
dennis_jeffrey
2011/08/24 17:40:47
'lookintoTestExpectaionInfo' -->
'lookIntoTestExpe
imasaki1
2011/08/25 23:57:03
Done.
| |
180 else: | |
181 # Otherwise, only test names are compared to get diff. | |
182 lookintoTestExpectaionInfo = False | |
183 comp_result_map[name] = GetDiffBetweenMaps( | |
184 self.result_map[name], result_map2.result_map[name], | |
185 lookintoTestExpectaionInfo) | |
186 return comp_result_map | |
187 | |
188 @staticmethod | |
189 def Load(file_path): | |
190 """Load the object from |file_path| using pickle library. | |
191 | |
192 Args: | |
193 file_path: the file path to be read the result from. | |
dennis_jeffrey
2011/08/24 17:40:47
'the string path to the file from which to read th
imasaki1
2011/08/25 23:57:03
Done.
| |
194 | |
195 Returns: | |
196 a AnalyzerResultMap object read from |file_path|. | |
197 """ | |
198 file_object = open(file_path) | |
199 analyzer_result_map = pickle.load(file_object) | |
200 file_object.close() | |
201 return analyzer_result_map | |
202 | |
203 def Save(self, file_path): | |
204 """Save the object to |file_path| using pickle library. | |
205 | |
206 Args: | |
207 file_path: the file path to be read the result from. | |
dennis_jeffrey
2011/08/24 17:40:47
'the string path to the file in which to store the
imasaki1
2011/08/25 23:57:03
Done.
| |
208 """ | |
209 file_object = open(file_path, "wb") | |
dennis_jeffrey
2011/08/24 17:40:47
use single quotes in strings
imasaki1
2011/08/25 23:57:03
Done.
| |
210 pickle.dump(self, file_object) | |
211 file_object.close() | |
212 | |
213 def GetListOfBugsForNonSkippedTests(self): | |
214 """Get a lit of bugs for non-skipped layout tessts. | |
dennis_jeffrey
2011/08/24 17:40:47
'lit' --> 'list'
'tessts' --> 'tests'
imasaki1
2011/08/25 23:57:03
Done.
| |
215 | |
216 This is used for generating email content. | |
dennis_jeffrey
2011/08/24 17:40:47
Add a "Returns:" section to this docstring
imasaki1
2011/08/25 23:57:03
Done.
| |
217 """ | |
218 bug_map = {} | |
219 for (name, v) in self.result_map['nonskip'].iteritems(): | |
220 for te_info in v['te_info']: | |
dennis_jeffrey
2011/08/24 17:40:47
only indent lines 220-228 by 2 spaces underneath l
imasaki1
2011/08/25 23:57:03
Done.
| |
221 main_te_info = {} | |
222 for k in te_info.keys(): | |
223 if k != 'Comments' and k != 'Bugs': | |
224 main_te_info[k] = True | |
225 for bug in te_info['Bugs']: | |
226 if bug not in bug_map: | |
227 bug_map[bug] = [] | |
228 bug_map[bug].append((name, main_te_info)) | |
229 return bug_map | |
230 | |
231 | |
232 def SendStatusEmail(prev_time, analyzer_result_map, prev_analyzer_result_map, | |
233 bug_anno_map, receiver_email_address): | |
234 """Send status email. | |
235 | |
236 Args: | |
237 prev_time: the date string such as '2011-10-09-11'. This format has been | |
238 used in this analyzer. | |
239 analyzer_result_map: current analyzer result. | |
240 prev_analyzer_result_map: previous analyzer reusult, which is read from | |
241 a file. | |
242 bug_anno_map: bug annotation map where bug name and annotations are | |
243 stored. | |
244 receiver_email_address: reciever's email address. | |
dennis_jeffrey
2011/08/24 17:40:47
reciever's -->
receiver's
imasaki1
2011/08/25 23:57:03
Done.
| |
245 """ | |
246 diff_map = analyzer_result_map.CompareResultMaps(prev_analyzer_result_map) | |
247 str = analyzer_result_map.ConvertToString(prev_time, diff_map, bug_anno_map) | |
248 # Add diff info about skipped/non-skipped test. | |
249 prev_time = datetime.strptime(prev_time, "%Y-%m-%d-%H") | |
dennis_jeffrey
2011/08/24 17:40:47
use single quotes in strings
imasaki1
2011/08/25 23:57:03
Done.
| |
250 prev_time = time.mktime(prev_time.timetuple()) | |
251 testname_map = {} | |
252 for (k, v) in diff_map['skip'][0]: | |
253 testname_map[k] = True | |
254 for (k, v) in diff_map['skip'][1]: | |
255 testname_map[k] = True | |
256 for (k, v) in diff_map['nonskip'][0]: | |
257 testname_map[k] = True | |
258 for (k, v) in diff_map['nonskip'][1]: | |
259 testname_map[k] = True | |
dennis_jeffrey
2011/08/24 17:40:47
How about something like this?
for type in ['skip
imasaki1
2011/08/25 23:57:03
Done.
| |
260 now = time.time() | |
261 | |
262 rev_infos = TestExpectationsHistory.GetDiffBetweenTimes(now, prev_time, | |
263 testname_map.keys()) | |
264 if len(rev_infos) > 0: | |
dennis_jeffrey
2011/08/24 17:40:47
if rev_infos:
imasaki1
2011/08/25 23:57:03
Done.
| |
265 str += '<br><b>Revision Information:</b>' | |
266 for rev_info in rev_infos: | |
267 (old_rev, new_rev, author, date, message, target_lines) = rev_info | |
268 l = urllib.unquote('http://trac.webkit.org/changeset?new=%d%40trunk%2F' | |
269 'LayoutTests%2Fplatform%2Fchromium%2F' | |
270 'test_expectations.txt&old=%d%40trunk%2FLayoutTests%2F' | |
271 'platform%2Fchromium%2Ftest_expectations.txt') | |
272 link = l % (new_rev, old_rev) | |
dennis_jeffrey
2011/08/24 17:40:47
Maybe combine the above 2 statements so that we do
imasaki1
2011/08/25 23:57:03
Done.
| |
273 str += '<ul><a href="%s">%s->%s</a>\n' % (link, old_rev, new_rev) | |
274 str += '<li>%s</li>\n' % author | |
275 str += '<li>%s</li>\n<ul>' % date | |
276 for line in target_lines: | |
277 str += '<li>%s</li>\n' % line | |
278 str += '</ul></ul>' | |
279 localtime = time.asctime(time.localtime(time.time())) | |
280 # TODO(imasaki): remove my name from here. | |
281 SendEmail('imasaki@chromium.org', 'Kenji Imasaki', | |
282 [receiver_email_address], ['Layout Test Analyzer Result'], | |
283 'Layout Test Analyzer Result : ' + localtime, str) | |
284 | |
285 | |
286 def SendEmail(sender_email_address, sender_name, receivers_email_addresses, | |
dennis_jeffrey
2011/08/24 17:40:47
This seems to only be called at line 281 above. D
imasaki1
2011/08/25 23:57:03
I prefer to separate pure email function and statu
| |
287 receivers_names, subject, message): | |
288 """Send email using localhost's mail server. | |
289 | |
290 Args: | |
291 sender_email_address: sender's email address. | |
292 sender_name: sender's name. | |
293 receivers_email_addresses: receiver's email addresses. | |
294 receivers_names: receiver's names. | |
295 subject: subject string. | |
296 message: email message. | |
297 """ | |
298 whole_message = ''.join([ | |
299 'From: %s<%s>\n' % (sender_name, sender_email_address), | |
300 'To: %s<%s>\n' % (receivers_names[0], | |
301 receivers_email_addresses[0]), | |
302 'Subject: %s\n' % subject, message]) | |
303 | |
304 try: | |
305 html_top = """ | |
dennis_jeffrey
2011/08/24 17:40:47
only indent all the lines within the 'try' by 2 sp
imasaki1
2011/08/25 23:57:03
Done.
| |
306 <html> | |
307 <head></head> | |
308 <body> | |
309 """ | |
310 html_bot = """ | |
311 </body> | |
312 </html> | |
313 """ | |
314 html = html_top + message + html_bot | |
315 msg = MIMEMultipart('alternative') | |
316 msg['Subject'] = subject | |
317 msg['From'] = sender_email_address | |
318 msg['To'] = receivers_email_addresses[0] | |
319 part1 = MIMEText(html, 'html') | |
320 smtpObj = smtplib.SMTP('localhost') | |
321 msg.attach(part1) | |
322 smtpObj.sendmail(sender_email_address, | |
323 receivers_email_addresses, | |
324 msg.as_string()) | |
dennis_jeffrey
2011/08/24 17:40:47
nit: indent the above 2 lines by 1 fewer space eac
imasaki1
2011/08/25 23:57:03
Done.
| |
325 print 'Successfully sent email' | |
326 except smtplib.SMTPException: | |
327 print 'Error: unable to send email' | |
dennis_jeffrey
2011/08/24 17:40:47
only indent line by 2 spaces, not 4
dennis_jeffrey
2011/08/24 17:40:47
Maybe we should also capture the exception message
imasaki1
2011/08/25 23:57:03
Done.
imasaki1
2011/08/25 23:57:03
Done.
| |
328 | |
329 | |
330 def FindLatestTime(time_list): | |
331 """Find latest time from |time_list|. | |
332 | |
333 The current status is compared to the status of the latest file in | |
334 |RESULT_DIR|. | |
335 | |
336 Args: | |
337 time_list: a list of time string in the form of '2011-10-23-23' | |
338 | |
339 Returns: | |
340 a string representing latest time among the time_list. | |
dennis_jeffrey
2011/08/24 17:40:47
add this: 'or None if |time_list| is empty.'
imasaki1
2011/08/25 23:57:03
Done.
| |
341 """ | |
342 latest_date = None | |
343 for t in time_list: | |
344 item_date = datetime.strptime(t, "%Y-%m-%d-%H") | |
345 if latest_date == None or latest_date < item_date: | |
346 latest_date = item_date | |
347 return latest_date.strftime("%Y-%m-%d-%H") | |
dennis_jeffrey
2011/08/24 17:40:47
Be careful: if time_list is empty, lastest_date wi
imasaki1
2011/08/25 23:57:03
Done.
| |
348 | |
349 | |
350 def FindLatestResult(result_dir): | |
351 """Find the latest result in |result_dir| and read and return them. | |
352 | |
353 This is used for comparison of analyzer result between current analyzer | |
354 and most known latest result. | |
355 | |
356 Args: | |
357 result_dir: the result directory. | |
358 | |
359 Returns: | |
360 a tuple of filename (latest_time) of the and the latest analyzer result. | |
361 """ | |
362 dirList = os.listdir(result_dir) | |
363 file_name = FindLatestTime(dirList) | |
dennis_jeffrey
2011/08/24 17:40:47
Why not remove FindLatestTime and just put that co
imasaki1
2011/08/25 23:57:03
I used this in the unit test. This needs to be sep
| |
364 file_path = os.path.join(result_dir, file_name) | |
365 return (file_name, AnalyzerResultMap.Load(file_path)) | |
366 | |
367 | |
368 def GetTestExpectationDiffBetweenLists(list1, list2): | |
369 """Get test expectation diff between lists. | |
370 | |
371 Args: | |
372 list1: a list of test expectation information. | |
373 list2: a list of test expectation information. | |
374 | |
375 Returns: | |
376 a list of the difference between test expectation information. | |
dennis_jeffrey
2011/08/24 17:40:47
'difference between test' -->
'differences between
imasaki1
2011/08/25 23:57:03
Done.
| |
377 """ | |
378 result_list = [] | |
379 for l1 in list1: | |
380 found = False | |
381 for l2 in list2: | |
382 if l1 == l2: | |
383 found = True | |
384 break | |
385 if not found: | |
386 result_list.append(l1) | |
387 return result_list | |
dennis_jeffrey
2011/08/24 17:40:47
This function seems to only identify the elements
imasaki1
2011/08/25 23:57:03
Deleted.
| |
388 | |
389 | |
390 def GetDiffBetweenMaps(map1, map2, lookintoTestExpectaionInfo=False): | |
dennis_jeffrey
2011/08/24 17:40:47
'lookintoTestExpectaionInfo' -->
'lookIntoTestExpe
imasaki1
2011/08/25 23:57:03
Done.
| |
391 """Get difference between maps. | |
392 | |
393 Args: | |
394 map1: analyzer result map to be compared. | |
395 map2: analyzer result map to be compared. | |
396 lookintoTestExpectaionInfo: a boolean to indicate whether you compare | |
dennis_jeffrey
2011/08/24 17:40:47
'a boolean to indicate whether to compare test exp
imasaki1
2011/08/25 23:57:03
Done.
| |
397 test expetation information as well as testnames. | |
398 | |
399 Returns: | |
400 a tuple of |name1_list| and |name2_list|. |Name1_list| contains all test | |
401 name and the test expectation information in |map1| but not in |map2|. | |
402 |Name2_list| contains all test name and the test expectation | |
403 information in |map2| but not in |map1|. | |
404 """ | |
405 name1_list = [] | |
406 # Compare map1 with map2. | |
407 for (name, v1) in map1.iteritems(): | |
408 if name in map2: | |
409 if lookintoTestExpectaionInfo and 'te_info' in v1: | |
410 te_diff = GetTestExpectationDiffBetweenLists(v1['te_info'], | |
411 map2[name]['te_info']) | |
412 if te_diff: | |
413 name1_list.append((name, te_diff)) | |
414 else: | |
415 name1_list.append((name, v1)) | |
416 | |
417 name2_list = [] | |
418 # Compare map1 with map2. | |
419 for (name, v2) in map2.iteritems(): | |
420 if name in map1: | |
421 if lookintoTestExpectaionInfo and 'te_info' in v2: | |
422 # Look into te_info. | |
423 te_diff = GetTestExpectationDiffBetweenLists(v2['te_info'], | |
424 map1[name]['te_info']) | |
425 if te_diff: | |
426 name2_list.append((name, te_diff)) | |
427 else: | |
428 name2_list.append((name, v2)) | |
dennis_jeffrey
2011/08/24 17:40:47
There's a big chunk of code in this function that'
imasaki1
2011/08/25 23:57:03
Done.
| |
429 return (name1_list, name2_list) | |
OLD | NEW |