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

Side by Side Diff: tools/findit/crash_utils.py

Issue 430943003: [Findit] Plain objects to represent and parse stack trace. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed comments and changed variable names Created 6 years, 4 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
(Empty)
1 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import json
6 import time
7 import urllib
8
9
10 def NormalizePathLinux(path):
11 """Normalizes linux path.
12
13 Args:
14 path: A string representing a path.
15
16 Returns:
17 A tuple containing a component this path is in (e.g blink, skia, etc)
18 and a path in that component's repository.
19 """
20 normalized_path = path
21 # TODO(jeun): Integrate with parsing DEPS file.
22 if 'WebKit/' in path:
23 component = 'blink'
24 normalized_path = ''.join(path.split('WebKit/')[1:])
25 else:
26 component = 'chromium'
27
28 if normalized_path.startswith(
29 '/b/build/slave/ASAN_Release__symbolized_/build/'):
30 normalized_path = normalized_path.split(
31 '/b/build/slave/ASAN_Release__symbolized_/build/')[1]
32
33 if '../../' in normalized_path:
34 normalized_path = normalized_path.split('../../')[1]
35
36 if 'src/v8/' in normalized_path:
37 component = 'v8'
38 normalized_path = normalized_path.split('src/v8/')[1]
39
40 if './' in normalized_path:
41 normalized_path = normalized_path.split('./')[1]
42
43 if not normalized_path.startswith('src/') and (
44 not normalized_path.startswith('Source/')):
45 normalized_path = 'src/' + normalized_path
46
47 return (component, normalized_path)
48
49
50 def SplitRange(regression):
51 """Splits a range as retrieved from clusterfuzz.
52
53 Args:
54 regression: A string in format 'r1234:r5678'.
55
56 Returns:
57 A list containing two numbers represented in string, for example
58 ['1234','5678'].
59 """
60 temp = regression.split(':')
Martin Barbella 2014/08/06 21:12:24 s/temp/revisions/
jeun 2014/08/06 23:36:24 Done.
61
62 # If regression information is not available, return none.
63 if len(temp) != 2:
64 return None
65
66 start_range = temp[0]
67 end_range = temp[1]
68
69 # Check if the range starts with r, such as in 'r10000' format.
70 if start_range.startswith('r'):
71 start_range = start_range[1:]
72 if end_range.startswith('r'):
73 end_range = end_range[1:]
74
75 return [start_range, end_range]
76
77
78 def LoadJSON(json_string):
79 """Loads json object from string, or None.
80
81 Args:
82 json_string: A string to get object from.
83
84 Returns:
85 JSON object if the string represents a JSON object, None otherwise.
86 """
87 try:
88 data = json.loads(json_string)
89 except ValueError:
90 data = None
91 return data
92
93
94 def GetDataFromURL(url, retry=10, sleep_time=0.1):
Martin Barbella 2014/08/06 21:12:24 Using the name retry makes it sound like a boolean
jeun 2014/08/06 23:36:25 Done.
95 """Retrieves raw data from URL, tries 10 times.
96
97 Args:
98 url: URL to get data from.
99 retry: Number of times to retry connection.
100 sleep_time: Time in seconds to wait before retrying connection.
101
102 Returns:
103 None if the data retrieval fails, or the raw data.
104 """
105 data = None
106 for i in range(retry):
107 # Retrieves data from URL.
108 try:
109 data = urllib.urlopen(url)
110
111 # If retrieval is successful, break from the retry look.
112 if data:
113 break
114
115 # If retrieval fails, try after 0.1 second.
116 except IOError:
117 time.sleep(sleep_time)
118 continue
119
120 # If returned data has something in it, return the content.
121 if data:
122 return data.read()
123 else:
124 return None
125
126
127 def FindMinLineDistance(crashed_line_list, changed_line_numbers):
128 """Calculates how far the changed line is from one of the crashes.
129
130 Finds the minimum distance between the lines that the file crashed on
131 and the lines that the file changed. For example, if the file crashed on
132 line 200 and the CL changes line 203,204 and 205, the function returns 3.
133
134 Args:
135 crashed_line_list: A list of lines that the file crashed on.
136 changed_line_numbers: A list of lines that the file changed.
137
138 Returns:
139 The minimum distance. If either of the input lists is empty,
140 it returns inf.
141
142 """
143 min_distance = float('inf')
144
145 for line in crashed_line_list:
146 for distance in changed_line_numbers:
147 # Find the current distance and update the min if current distance is
148 # less than current min.
149 current_distance = abs(line - distance)
150 if current_distance < min_distance:
151 min_distance = current_distance
152
153 return min_distance
154
155
156 def GuessIfSamePath(path1, path2):
157 """Guesses if two paths represent same path.
158
159 Compares the name of the folders in the path (by split('/')), and checks
160 if they match either more than 3 or min of path lengths.
161
162 Args:
163 path1: First path.
164 path2: Second path to compare.
165
166 Returns:
167 True if it they are thought to be a same path, False otherwise.
168 """
169 path1 = path1.split('/')
170 path2 = path2.split('/')
171
172 intersection = set(path1).intersection(set(path2))
173 return len(intersection) >= (min(3, min(len(path1), len(path2))))
174
175
176 def FindMinStackFrameNum(stack_frame_index, priorities):
177 """Finds the minimum stack number, from the list of stack numbers.
178
179 Args:
180 stack_frame_index: A list of list containing stack position.
181 priorities: A list of of priority for each file.
182
183 Returns:
184 Inf if stack_frame_index is empty, minimum stack number otherwise.
185 """
186 # Get the indexes of the highest priority (or low priority number)
187 highest_priority = min(priorities)
188 highest_priority_indices = []
189 for i in range(len(priorities)):
190 if priorities[i] == highest_priority:
191 highest_priority_indices.append(i)
192
193 # Gather the list of stack frame numbers for the files that change the
194 # crash lines.
195 flattened = []
196 for i in highest_priority_indices:
197 flattened += stack_frame_index[i]
198
199 # If no stack frame information is available, return inf. Else, return min.
200 if not flattened:
201 return float('inf')
202 else:
203 return min(flattened)
204
205
206 def AddHyperlink(to_add, link):
207 """Returns a string with HTML link tag.
208
209 Args:
210 to_add: A string to add link.
211 link: A link to add to the string.
212
213 Returns:
214 A string with hyperlink added.
215 """
216 return '<a href="%s">%s<\\a>' % (link, to_add)
Martin Barbella 2014/08/06 21:12:24 Depending on how this is used, this is scary. Use
jeun 2014/08/06 23:36:25 added cgi.escape to link and changed the closing t
217
218
219 def PrettifyList(l):
220 """Returns a string representation of a list .
Martin Barbella 2014/08/06 21:12:24 Nit: there's an extra space before the period. Cou
jeun 2014/08/06 23:36:25 Added explanation on how the string is prettified.
221
222 Args:
223 l: A list to prettify.
224 Returns:
225 A string representation of the list.
226 """
227 return str(l)[1:-1]
228
229
230 def PrettifyFiles(file_list):
231 """Returns a string representation of a list of file names.
232
233 Args:
234 file_list: A list of tuple, (file_name, file_url).
235 Returns:
236 A string representation of file names with their urls.
237 """
238 ret = ['\n']
239 for file_name, file_url in file_list:
240 ret.append(' %s\n' % AddHyperlink(file_name, file_url))
241 return ''.join(ret)
242
243
244 def Intersection(crashed_line_list, stack_frame_index, changed_line_numbers):
245 """Finds the overlap betwee changed lines and crashed lines.
246
247 Finds the intersection of the lines that caused the crash and
248 lines that the file changes. The intersection looks within 3 lines
249 of the line that caused the crash.
250
251 Args:
252 crashed_line_list: A list of lines that the file crashed on.
253 stack_frame_index: A list of positions in stack for each of the lines.
254 changed_line_numbers: A list of lines that the file changed.
255
256 Returns:
257 line_intersection: Intersection between crashed_line_list and
258 changed_line_numbers.
259 stack_frame_index_intersection: Stack number for each of the intersections.
260 """
261 line_intersection = []
262 stack_frame_index_intersection = []
263
264 # Iterate through the crashed lines, and its occurence in stack.
265 for (line, stack_frame_index) in zip(crashed_line_list, stack_frame_index):
266
267 # Also check previous 3 lines.
268 line_minus_n = range(line - 3, line + 1)
269
270 for changed_line in changed_line_numbers:
271
272 # If a CL does not change crahsed line, check next line.
273 if changed_line not in line_minus_n:
274 continue
275
276 # If the changed line is exactly the crashed line, add that line.
277 if line in changed_line_numbers:
278 to_add = line
279
280 # If the changed line is in 3 lines of the crashed line, add the line.
281 else:
282 to_add = changed_line
283
284 # Avoid adding the same line twice.
285 if to_add not in line_intersection:
286 line_intersection.append(to_add)
287 stack_frame_index_intersection.append(stack_frame_index)
288
289 break
290
291 return (line_intersection, stack_frame_index_intersection)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698