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

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: Fix nits. 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 confidence=None, reason=None):
56 super(MatchResult, self).__init__(
57 changelog, dep_path, confidence, reason)
58
59 self.min_distance = _INFINITY
60
61 def Update(self, file_path, stack_infos, blame): 55 def Update(self, file_path, stack_infos, blame):
62 """Updates a match result with file path and its stack_infos and blame. 56 """Updates a match result with file path and its stack_infos and blame.
63 57
64 When a file_path is found both shown in stacktrace and touched by 58 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 59 the revision of this result, update result with the information of
66 this file. 60 this file.
67 61
68 Inserts the file path and its stack infos, and updates the min distance 62 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 63 if less distance is found between touched lines of this result and
70 crashed lines in the file path. 64 crashed lines in the file path.
71 65
72 Args: 66 Args:
73 file_path (str): File path of the crashed file. 67 file_path (str): File path of the crashed file.
74 stack_infos (list): List of (StackFrame, callstack priority) tuples, 68 stack_infos (list): List of stack_info dicts, represents frames of this
75 represents frames of this file and the callstack priorities of those 69 file and the callstack priorities of those frames.
76 frames.
77 blame (Blame): Blame oject of this file. 70 blame (Blame): Blame oject of this file.
78 """ 71 """
79 self.file_to_stack_infos[file_path] = stack_infos 72 self.file_to_stack_infos[file_path] = stack_infos
80 73
81 if not blame: 74 if not blame:
82 return 75 return
83 76
77 min_distance = float('inf')
78 min_distance_frame = None
84 for region in blame: 79 for region in blame:
85 if region.revision != self.changelog.revision: 80 if region.revision != self.changelog.revision:
86 continue 81 continue
87 82
88 region_lines = range(region.start, region.start + region.count) 83 region_lines = range(region.start, region.start + region.count)
89 84
90 for frame, _ in stack_infos: 85 for frame, _ in stack_infos:
91 self.min_distance = min(self.min_distance, self._DistanceOfTwoRegions( 86 distance = self._DistanceOfTwoRegions(frame.crashed_line_numbers,
92 frame.crashed_line_numbers, region_lines)) 87 region_lines)
88 if distance < min_distance:
89 min_distance = distance
90 min_distance_frame = frame
91
92 self.file_to_analysis_info[file_path] = {
93 'min_distance': min_distance,
94 'min_distance_frame': min_distance_frame,
95 }
93 96
94 def _DistanceOfTwoRegions(self, region1, region2): 97 def _DistanceOfTwoRegions(self, region1, region2):
95 if set(region1).intersection(set(region2)): 98 if set(region1).intersection(set(region2)):
96 return 0 99 return 0
97 100
98 if region1[-1] < region2[0]: 101 if region1[-1] < region2[0]:
99 return region2[0] - region1[-1] 102 return region2[0] - region1[-1]
100 103
101 return region1[0] - region2[-1] 104 return region1[0] - region2[-1]
102 105
103 106
104 class MatchResults(dict): 107 class MatchResults(dict):
105 """A dict indexing MatchResult with its revision.""" 108 """A dict indexing MatchResult with its revision."""
106 109
107 def __init__(self, ignore_cls=None): 110 def __init__(self, ignore_cls=None):
108 super(MatchResults, self).__init__() 111 super(MatchResults, self).__init__()
109 self.ignore_cls = ignore_cls 112 self.ignore_cls = ignore_cls
110 113
111 def GenerateMatchResults(self, file_path, dep_path, 114 def GenerateMatchResults(self, file_path, dep_path,
112 stack_infos, changelogs, blame): 115 stack_infos, changelogs, blame):
113 """Generates match results. 116 """Generates match results.
114 117
115 Match results are generated based on newly found file path, its stack_infos, 118 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 119 and all the changelogs that touched this file in the dep in regression
117 ranges, those reverted changelogs should be ignored. 120 ranges, those reverted changelogs should be ignored.
118 121
119 Args: 122 Args:
120 file_path (str): File path of the crashed file. 123 file_path (str): File path of the crashed file.
121 dep_path (str): Path of the dependency of the file. 124 dep_path (str): Path of the dependency of the file.
122 stack_infos (list): List of (StackFrame, callstack priority) tuples, 125 stack_infos (list): List of stack_info dicts, represents frames of this
123 represents frames of this file and the callstack priorities of those 126 file and the callstack priorities of those frames.
124 frames.
125 changelogs (list): List of Changelog objects in the dep in regression 127 changelogs (list): List of Changelog objects in the dep in regression
126 range which touched the file. 128 range which touched the file.
127 blame (Blame): Blame of the file. 129 blame (Blame): Blame of the file.
128 """ 130 """
129 for changelog in changelogs: 131 for changelog in changelogs:
130 if self.ignore_cls and changelog.revision in self.ignore_cls: 132 if self.ignore_cls and changelog.revision in self.ignore_cls:
131 continue 133 continue
132 134
133 if changelog.revision not in self: 135 if changelog.revision not in self:
134 self[changelog.revision] = MatchResult(changelog, dep_path) 136 self[changelog.revision] = MatchResult(changelog, dep_path)
135 137
136 match_result = self[changelog.revision] 138 match_result = self[changelog.revision]
137
138 match_result.Update(file_path, stack_infos, blame) 139 match_result.Update(file_path, stack_infos, blame)
OLDNEW
« no previous file with comments | « appengine/findit/crash/parse_util.py ('k') | appengine/findit/crash/scorers/aggregated_scorer.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698