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

Side by Side Diff: appengine/findit/crash/results.py

Issue 2157433002: [Findit] Pass changed files info to Fracas, 2 face design. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 4 years, 5 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 2016 The Chromium Authors. All rights reserved. 1 # Copyright 2016 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 _INFINITY = 1000
6
7 5
8 class Result(object): 6 class Result(object):
9 """Represents findit culprit result.""" 7 """Represents findit culprit result."""
10 8
11 def __init__(self, changelog, dep_path, 9 def __init__(self, changelog, dep_path,
12 confidence=None, reason=None): 10 confidence=None, reasons=None, changed_files=None):
13 self.changelog = changelog 11 self.changelog = changelog
14 self.dep_path = dep_path 12 self.dep_path = dep_path
15 self.confidence = confidence 13 self.confidence = confidence
16 self.reason = reason 14 self.reasons = reasons
15 self.changed_files = changed_files
17 16
18 self.file_to_stack_infos = {} 17 self.file_to_stack_infos = {}
18 self.file_to_analysis_info = {}
19 19
20 def ToDict(self): 20 def ToDict(self):
21 return { 21 return {
22 'url': self.changelog.commit_url, 22 'url': self.changelog.commit_url,
23 'review_url': self.changelog.code_review_url, 23 'review_url': self.changelog.code_review_url,
24 'revision': self.changelog.revision, 24 'revision': self.changelog.revision,
25 'project_path': self.dep_path, 25 'project_path': self.dep_path,
26 'author': self.changelog.author_email, 26 'author': self.changelog.author_email,
27 'time': str(self.changelog.author_time), 27 'time': str(self.changelog.author_time),
28 'reason': self.reason, 28 'reasons': self.reasons,
29 'changed_files': self.changed_files,
29 'confidence': self.confidence, 30 'confidence': self.confidence,
30 } 31 }
31 32
32 def ToString(self): 33 def ToString(self):
33 if not self.file_to_stack_infos: 34 if not self.file_to_stack_infos:
34 return '' 35 return ''
35 36
36 lines = [] 37 lines = []
37 for file_path, stack_infos in self.file_to_stack_infos.iteritems(): 38 for file_path, stack_infos in self.file_to_stack_infos.iteritems():
38 line_parts = [] 39 line_parts = []
39 for frame, _ in stack_infos: 40 for frame, _ in stack_infos:
40 line_parts.append('frame #%d' % frame.index) 41 line_parts.append('frame #%d' % frame.index)
41 42
42 lines.append('Changed file %s crashed in %s' % ( 43 lines.append('Changed file %s crashed in %s' % (
43 file_path, ', '.join(line_parts))) 44 file_path, ', '.join(line_parts)))
44 45
45 return '\n'.join(lines) 46 return '\n'.join(lines)
46 47
47 def __str__(self): 48 def __str__(self):
48 return self.ToString() 49 return self.ToString()
49 50
50 51
51 class MatchResult(Result): 52 class MatchResult(Result):
52 """Represents findit culprit result got from match algorithm.""" 53 """Represents findit culprit result got from match algorithm."""
53 54
54 def __init__(self, changelog, dep_path, 55 def __init__(self, changelog, dep_path,
stgao 2016/07/15 23:25:28 Seems not needed.
Sharu Jiang 2016/07/18 00:31:58 Done.
55 confidence=None, reason=None): 56 confidence=None, reasons=None):
56 super(MatchResult, self).__init__( 57 super(MatchResult, self).__init__(
57 changelog, dep_path, confidence, reason) 58 changelog, dep_path, confidence, reasons)
58
59 self.min_distance = _INFINITY
60 59
61 def Update(self, file_path, stack_infos, blame): 60 def Update(self, file_path, stack_infos, blame):
62 """Updates a match result with file path and its stack_infos and blame. 61 """Updates a match result with file path and its stack_infos and blame.
63 62
64 When a file_path is found both shown in stacktrace and touched by 63 When a file_path is found both shown in stacktrace and touched by
65 the revision of this result, update result with the information of 64 the revision of this result, update result with the information of
66 this file. 65 this file.
67 66
68 Inserts the file path and its stack infos, and updates the min distance 67 Inserts the file path and its stack infos, and updates the min distance
69 if less distance is found between touched lines of this result and 68 if less distance is found between touched lines of this result and
70 crashed lines in the file path. 69 crashed lines in the file path.
71 70
72 Args: 71 Args:
73 file_path (str): File path of the crashed file. 72 file_path (str): File path of the crashed file.
74 stack_infos (list): List of (StackFrame, callstack priority) tuples, 73 stack_infos (list): List of stack_info dicts, represents frames of this
75 represents frames of this file and the callstack priorities of those 74 file and the callstack priorities of those frames.
76 frames.
77 blame (Blame): Blame oject of this file. 75 blame (Blame): Blame oject of this file.
78 """ 76 """
79 self.file_to_stack_infos[file_path] = stack_infos 77 self.file_to_stack_infos[file_path] = stack_infos
80 78
81 if not blame: 79 if not blame:
82 return 80 return
83 81
82 min_distance = float('inf')
83 min_distance_frame = None
84 for region in blame: 84 for region in blame:
85 if region.revision != self.changelog.revision: 85 if region.revision != self.changelog.revision:
86 continue 86 continue
87 87
88 region_lines = range(region.start, region.start + region.count) 88 region_lines = range(region.start, region.start + region.count)
89 89
90 for frame, _ in stack_infos: 90 for frame, _ in stack_infos:
91 self.min_distance = min(self.min_distance, self._DistanceOfTwoRegions( 91 distance = self._DistanceOfTwoRegions(frame.crashed_line_numbers,
92 frame.crashed_line_numbers, region_lines)) 92 region_lines)
93 if distance < min_distance:
94 min_distance = distance
95 min_distance_frame = frame
96
97 self.file_to_analysis_info[file_path] = {
98 'min_distance': min_distance,
99 'min_distance_frame': min_distance_frame,
100 }
93 101
94 def _DistanceOfTwoRegions(self, region1, region2): 102 def _DistanceOfTwoRegions(self, region1, region2):
95 if set(region1).intersection(set(region2)): 103 if set(region1).intersection(set(region2)):
96 return 0 104 return 0
97 105
98 if region1[-1] < region2[0]: 106 if region1[-1] < region2[0]:
99 return region2[0] - region1[-1] 107 return region2[0] - region1[-1]
100 108
101 return region1[0] - region2[-1] 109 return region1[0] - region2[-1]
102 110
103 111
104 class MatchResults(dict): 112 class MatchResults(dict):
105 """A dict indexing MatchResult with its revision.""" 113 """A dict indexing MatchResult with its revision."""
106 114
107 def __init__(self, ignore_cls=None): 115 def __init__(self, ignore_cls=None):
108 super(MatchResults, self).__init__() 116 super(MatchResults, self).__init__()
109 self.ignore_cls = ignore_cls 117 self.ignore_cls = ignore_cls
110 118
111 def GenerateMatchResults(self, file_path, dep_path, 119 def GenerateMatchResults(self, file_path, dep_path,
112 stack_infos, changelogs, blame): 120 stack_infos, changelogs, blame):
113 """Generates match results. 121 """Generates match results.
114 122
115 Match results are generated based on newly found file path, its stack_infos, 123 Match results are generated based on newly found file path, its stack_infos,
116 and all the changelogs that touched this file in the dep in regression 124 and all the changelogs that touched this file in the dep in regression
117 ranges, those reverted changelogs should be ignored. 125 ranges, those reverted changelogs should be ignored.
118 126
119 Args: 127 Args:
120 file_path (str): File path of the crashed file. 128 file_path (str): File path of the crashed file.
121 dep_path (str): Path of the dependency of the file. 129 dep_path (str): Path of the dependency of the file.
122 stack_infos (list): List of (StackFrame, callstack priority) tuples, 130 stack_infos (list): List of stack_info dicts, represents frames of this
123 represents frames of this file and the callstack priorities of those 131 file and the callstack priorities of those frames.
124 frames.
125 changelogs (list): List of Changelog objects in the dep in regression 132 changelogs (list): List of Changelog objects in the dep in regression
126 range which touched the file. 133 range which touched the file.
127 blame (Blame): Blame of the file. 134 blame (Blame): Blame of the file.
128 """ 135 """
129 for changelog in changelogs: 136 for changelog in changelogs:
130 if self.ignore_cls and changelog.revision in self.ignore_cls: 137 if self.ignore_cls and changelog.revision in self.ignore_cls:
131 continue 138 continue
132 139
133 if changelog.revision not in self: 140 if changelog.revision not in self:
134 self[changelog.revision] = MatchResult(changelog, dep_path) 141 self[changelog.revision] = MatchResult(changelog, dep_path)
135 142
136 match_result = self[changelog.revision] 143 match_result = self[changelog.revision]
137
138 match_result.Update(file_path, stack_infos, blame) 144 match_result.Update(file_path, stack_infos, blame)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698