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

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: Added functionality in stacktrace to easily add new parse rules for different chrome builds 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):
stgao 2014/08/01 17:22:20 Could we include this function only in this patch?
jeun 2014/08/06 18:22:59 I am not sure what is the best way of doing this,
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
stgao 2014/08/01 17:22:20 style issue: comment.
jeun 2014/08/06 18:22:59 Done.
22 if 'WebKit/' in path:
23 component = 'blink'
24 normalized_path = 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(':')
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):
95 """Retrieves raw data from URL, tries 10 times.
96
97 Args:
98 url: url to get data from
99
100 Returns:
101 None if the data retrieval fails, or the raw data.
102 """
103 data = None
104 for i in range(10):
stgao 2014/08/01 17:22:20 For the retry, it might be better to make it as a
jeun 2014/08/06 18:22:59 Done.
105
106 # Retrieves data from URL
107 try:
108 data = urllib.urlopen(url)
109
110 # If retrieval is successful, break from the retry look
111 if data:
112 break
113
114 # If retrieval fails, try after 0.1 second
115 except IOError:
116 time.sleep(0.1)
stgao 2014/08/01 17:22:20 Sleep interval could be parameterized too.
jeun 2014/08/06 18:22:59 Done.
117 continue
118
119 # If returned data has something in it, return the content
120 if data:
121 return data.read()
122 else:
123 return None
124
125
126 def FindMinLineDistance(crashed_line_list, changed_line_numbers):
127 """Calculates how far the changed line is from one of the crashes.
128
129 Finds the minimum distance between the lines that the file crashed on
130 and the lines that the file changed. For example, if the file crashed on
131 line 200 and the CL changes line 203,204 and 205, the function returns 3.
132
133 Args:
134 crashed_line_list: list of lines that the file crashed on
135 changed_line_numbers: list of lines that the file changed
136
137 Returns:
138 the minimum distance. If either of the input lists is empty,
139 it returns inf.
140
141 """
142 min_distance = float('inf')
143
144 for line in crashed_line_list:
145 for distance in changed_line_numbers:
146 # Find the current distance and update the min if current distance is
147 # less than current min
148 current_distance = abs(line - distance)
149 if current_distance < min_distance:
150 min_distance = current_distance
151
152 return min_distance
153
154
155 def GuessIfSamePath(path1, path2):
156 """Guesses if two paths represent same path.
157
158 Compares the name of the folders in the path (by split('/')), and checks
159 if they match either more than 3 or min of path lengths
160
161 Args:
162 path1: First path
163 path2: Second path to compare
164
165 Returns:
166 True if it they are thought to be a same path, False otherwise
167 """
168 path1 = path1.split('/')
169 path2 = path2.split('/')
170
171 intersection = set(path1).intersection(set(path2))
172 return len(intersection) >= (min(3, min(len(path1), len(path2))))
173
174
175 def FindMinStackFrameNum(stack_frame_index, priorities):
176 """Finds the minimum stack number, from the list of stack numbers.
177
178 Args:
179 stack_frame_index: a list of list containing stack position
180 priorities: a list of of priority for each file
181
182 Returns:
183 inf if stack_frame_index is empty, minimum stack number otherwise
184 """
185 # Get the indexes of the highest priority (or low priority number)
186 highest_priority = min(priorities)
187 highest_priority_indices = []
188 for i in range(len(priorities)):
189 if priorities[i] == highest_priority:
190 highest_priority_indices.append(i)
191
192 # Gather the list of stack frame numbers for the files that change the
193 # crash lines
194 flattened = []
195 for i in highest_priority_indices:
196 flattened += stack_frame_index[i]
197
198 # If no stack frame information is available, return inf. Else, return min
199 if not flattened:
200 return float('inf')
201 else:
202 return min(flattened)
203
204
205 def AddHyperlink(to_add, link):
206 """Returns a string with HTML link tag.
207
208 Args:
209 to_add: a string to add link
210 link: a link to add to the string
211
212 Returns:
213 a string with hyperlink added
214 """
215 return '<a href="%s">%s<\\a>' % (link, to_add)
216
217
218 def PrettifyList(l):
219 """Returns a string representation of a list of ints.
220
221 Args:
222 l: an int list to prettify
223 Returns:
224 a string representation of list
225 """
226 return str(l)[1:-1]
227
228
229 def PrettifyFiles(file_list):
230 """Returns a string representation of a list of file names.
231
232 Args:
233 file_list: a list of tuple, (file_name, file_url)
234 Returns:
235 a string representation of file names
236 """
237 ret = ['\n']
238 for file_name, file_url in file_list:
239 ret.append(' %s\n' % AddHyperlink(file_name, file_url))
240 return ''.join(ret)
241
242
243 def Intersection(crashed_line_list, stack_frame_index, changed_line_numbers):
244 """Finds the overlap betwee changed lines and crashed lines.
245
246 Finds the intersection of the lines that caused the crash and
247 lines that the file changes. The intersection looks within 3 lines
248 of the line that caused the crash.
249
250 Args:
251 crashed_line_list: list of lines that the file crashed on
252 stack_frame_index: list of positions in stack for each of the lines
253 changed_line_numbers: list of lines that the file changed
254
255 Returns:
256 line_intersection: intersection between crashed_line_list and
257 changed_line_numbers
258 stack_frame_index_intersection: stack number for each of the intersections
259 """
260 line_intersection = []
261 stack_frame_index_intersection = []
262
263 # Iterate through the crashed lines, and its occurence in stack
264 for (line, stack_frame_index) in zip(crashed_line_list, stack_frame_index):
265
266 # Also check previous 3 lines
267 line_minus_n = range(line - 3, line + 1)
268
269 for changed_line in changed_line_numbers:
270
271 # If a CL does not change crahsed line, check next line
272 if changed_line not in line_minus_n:
273 continue
274
275 # If the changed line is exactly the crashed line, add that line
276 if line in changed_line_numbers:
277 to_add = line
278
279 # If the changed line is within 3 lines of the crashed line, add the line
280 else:
281 to_add = changed_line
282
283 # Avoid adding the same line twiece
284 if to_add not in line_intersection:
285 line_intersection.append(to_add)
286 stack_frame_index_intersection.append(stack_frame_index)
287
288 break
289
290 return (line_intersection, stack_frame_index_intersection)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698