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

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

Issue 2414523002: [Findit] Reorganizing findit_for_*.py (Closed)
Patch Set: Finally fixed the mock tests! Created 4 years, 1 month 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
« no previous file with comments | « appengine/findit/crash/crash_report.py ('k') | appengine/findit/crash/findit.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 # found in the LICENSE file.
4
5 from collections import namedtuple
6
7 # TODO(http://crbug.com/659346): We do call this code from various
8 # unittests, just not from culprit_test.py; so we need to add some extra
9 # unittests there.
10 class Culprit(namedtuple('Culprit',
11 ['project', 'components', 'cls', 'regression_range', 'algorithm']
12 )): # pragma: no cover
13 """The result of successfully identifying the culprit of a crash report.
14
15 Args:
16 project (str): the most-suspected project
17 components (list of str): the suspected crbug components.
18 cls (list of ??): the suspected CLs.
19 regression_range (tuple): a pair of the last-good and first-bad versions.
20 algorithm (str): What algorithm was used to produce this object.
21 """
22 __slots__ = ()
23
24 @property
25 def fields(self):
26 return self._fields
27
28 # TODO(http://crbug/644476): better name for this method.
29 def ToDicts(self):
30 """Convert this object to a pair of anonymous dicts for JSON.
31
32 Returns:
33 (analysis_result_dict, tag_dict)
34 The analysis result is a dict like below:
35 {
36 # Indicate if Findit found any suspects_cls, project,
37 # components or regression_range.
38 "found": true,
39 "suspected_project": "chromium-v8", # Which project is most suspected.
40 "feedback_url": "https://.."
41 "suspected_cls": [
42 {
43 "revision": "commit-hash",
44 "url": "https://chromium.googlesource.com/chromium/src/+/...",
45 "review_url": "https://codereview.chromium.org/issue-number",
46 "project_path": "third_party/pdfium",
47 "author": "who@chromium.org",
48 "time": "2015-08-17 03:38:16",
49 "reason": "a plain string with '\n' as line break to expla..."
50 "reason": [('MinDistance', 1, 'minimum distance is 0.'),
51 ('TopFrame', 0.9, 'top frame is2nd frame.')],
52 "changed_files": [
53 {"file": "file_name1.cc",
54 "blame_url": "https://...",
55 "info": "minimum distance (LOC) 0, frame #2"},
56 {"file": "file_name2.cc",
57 "blame_url": "https://...",
58 "info": "minimum distance (LOC) 20, frame #4"},
59 ...
60 ],
61 "confidence": 0.60
62 },
63 ...,
64 ],
65 "regression_range": [ # Detected regression range.
66 "53.0.2765.0",
67 "53.0.2766.0"
68 ],
69 "suspected_components": [ # A list of crbug components to file bugs.
70 "Blink>JavaScript"
71 ]
72 }
73
74 The code review url might not always be available, because not all
75 commits go through code review. In that case, commit url should
76 be used instead.
77
78 The tag dict are allowed key/value pairs to tag the analysis result
79 for query and monitoring purpose on Findit side. For allowed keys,
80 please refer to crash_analysis.py and fracas_crash_analysis.py:
81 For results with normal culprit-finding algorithm: {
82 'found_suspects': True,
83 'has_regression_range': True,
84 'solution': 'core_algorithm',
85 }
86 For results using git blame without a regression range: {
87 'found_suspects': True,
88 'has_regression_range': False,
89 'solution': 'blame',
90 }
91 If nothing is found: {
92 'found_suspects': False,
93 }
94 """
95 # TODO(http://crbug.com/644411): reformulate the JSON stuff so we
96 # can drop fields which are empty; so that, in turn, we can get rid
97 # of the NullCulprit class.
98 return (
99 {
100 'found': (bool(self.project) or
101 bool(self.components) or
102 bool(self.cls) or
103 bool(self.regression_range)),
104 'regression_range': self.regression_range,
105 'suspected_project': self.project,
106 'suspected_components': self.components,
107 'suspected_cls': [cl.ToDict() for cl in self.cls],
108 },
109 {
110 'found_suspects': bool(self.cls),
111 'found_project': bool(self.project),
112 'found_components': bool(self.components),
113 'has_regression_range': bool(self.regression_range),
114 'solution': self.algorithm,
115 }
116 )
117
118
119 # TODO(http://crbug.com/659346): We do call this code from various
120 # unittests, just not from culprit_test.py; so we need to add some extra
121 # unittests there.
122 # TODO(http://crbug.com/659359): eliminate the need for this class.
123 class NullCulprit(object): # pragma: no cover
124 """The result of failing to identify the culprit of a crash report.
125
126 This class serves as a helper so that we can avoid returning None. It
127 has all the same properties and methods as the Culprit class, but
128 returns the empty string, the empty list, or None, as appropriate. The
129 main difference compared to using Culprit with all those falsy values
130 is that the result of the ToDicts method is more minimalistic.
131
132 Ideally we'd like to be able to refactor things to avoid the need
133 for this class. Mostly that means (1) refactoring the unittests to
134 allow |Findit.FindCulprit| to return None, and (2) reformulating
135 |Culprit.ToDicts| to create minimal dicts and reformulating the JSON
136 protocol to support that.
137 """
138 __slots__ = ()
139
140 @property
141 def fields(self):
142 raise NotImplementedError()
143
144 @property
145 def project(self):
146 return ''
147
148 @property
149 def components(self):
150 return []
151
152 @property
153 def cls(self):
154 return []
155
156 @property
157 def regression_range(self):
158 # TODO(http://crbug.com/659359): or maybe return |(None,None)| instead...
159 return None
160
161 @property
162 def algorithm(self):
163 # TODO(http://crbug.com/659359): or maybe return the empty string instead...
164 return None
165
166 def ToDicts(self):
167 return (
168 {'found': False},
169 {'found_suspects': False,
170 'has_regression_range': False}
171 )
OLDNEW
« no previous file with comments | « appengine/findit/crash/crash_report.py ('k') | appengine/findit/crash/findit.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698