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

Side by Side Diff: appengine/findit/util_scripts/crash_queries/delta_test/delta_test.py

Issue 2400283003: [Findit] Add skeleton code for delta test script. (Closed)
Patch Set: Created 4 years, 2 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 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 import hashlib
6 import json
7 import logging
8 import os
9 import pickle
10 import subprocess
11
12 from crash_queries import crash_iterator
13
14 AZALEA_RESULTS_DIRECTORY = os.path.join(os.path.dirname(__file__),
15 'azalea_results')
16
17
18 class Delta(object):
19 """Stands for delta between two results."""
20
21 def __init__(self, result1, result2, fields):
22 self._result1 = result1
23 self._result2 = result2
24 self._fields = fields
25 self._delta_dict = {}
26 self._delta_str_dict = {}
27
28 @property
29 def delta_dict(self):
30 """Dict representation of delta."""
31 if self._delta_dict:
32 return self._delta_dict
33
34 for field in self._fields:
35 value1 = getattr(self._result1, field)
36 value2 = getattr(self._result2, field)
37 if value1 != value2:
38 if hasattr(value1, 'ToDict') and callable(value1.ToDict):
39 value1 = value1.ToDict()
40 value2 = value2.ToDict()
41 self._delta_dict[field] = (value1, value2)
42
43 return self._delta_dict
44
45 @property
46 def delta_str_dict(self):
47 """Converts delta of each field to a string."""
48 if self._delta_str_dict:
49 return self._delta_str_dict
50
51 for key, (value1, value2) in self.delta_dict.iteritems():
52 self._delta_str_dict[key] = '%s: %s, %s' % (key, value1, value2)
53
54 return self._delta_str_dict
55
56 def ToDict(self):
57 return self.delta_dict
58
59 def ToString(self):
wrengr 2016/10/11 22:57:43 Should also set the __str__ method
Sharu Jiang 2016/10/12 01:18:20 Done.
60 return '\n'.join(self.delta_str_dict.values())
61
62 def IsEmpty(self):
wrengr 2016/10/11 22:57:43 Should probably also set the __bool__ method
Sharu Jiang 2016/10/12 01:18:20 Done.
63 return not bool(self.delta_dict)
64
65
66 def GetDeltaFromTwoSetsOfCulprits(set1, set2):
67 """Gets delta from two sets of results.
68
69 Results are a list of (message, matches, component_name, cr_label)
70 Returns a list of delta results (results1, results2).
71 """
72 deltas = {}
73 for crash_id, culprit1 in set1.iteritems():
74 # Even when the command are exactly the same, it's possible that one set is
75 # loaded from local result file, another is just queried from database,
76 # sometimes some crash results would get deleted.
77 if crash_id not in set2:
78 continue
79
80 culprit2 = set2[crash_id]
81 delta = Delta(culprit1, culprit2, culprit1.fields)
82 if not delta.IsEmpty():
83 deltas[crash_id] = delta
84
85 return deltas
86
87
88 def GetResult(crashes, git_hash, result_path, verbose=False):
89 """Returns an evaluator function to compute delta between 2 findit githashes.
90
91 Args:
92 crashes (list): A list of crash infos.
93 git_hash (str): A git hash of findit repository.
94 result_path (str): file path for subprocess to write results on.
95 verbose (bool): If True, print all the findit results.
96
97 Return:
98 A dict mapping crash id to culprit for every crashes analyzed by
99 git_hash version.
100 """
101 if not crashes:
102 return {}
103
104 if verbose:
105 logging.info('\n\n***************************')
106 logging.info('Switch to git %s', git_hash)
107 logging.info('***************************\n\n')
108
109 dev_null_handle = open(os.devnull, 'w')
110 subprocess.check_call(
111 'cd %s; git checkout %s' % (os.path.dirname(__file__), git_hash),
112 stdout=dev_null_handle,
113 stderr=dev_null_handle,
114 shell=True)
115
116 if not os.path.exists(result_path):
117 # TODO(katesoina): Implement run-azalea.py.
118 command = 'python %s %s' % ('run-azalea.py', result_path) + (
119 ' -v' if verbose else '')
120 # Results is a dict with testcase_id as key, and findit results as
121 # value.
122 p = subprocess.Popen(
123 command,
124 stdin=subprocess.PIPE,
125 shell=True)
126
127 p.communicate(input=json.dumps(crashes))
128 else:
129 logging.info('\nLoading results from %s', result_path)
130
131 if not os.path.exists(result_path):
132 logging.info('Fail to get results.')
133 return {}
134
135 with open(result_path) as f:
136 return pickle.load(f)
137
138 return {}
139
140
141 def GenerateResultFileName(*args):
142 """Encodes args and returns the generated result file."""
143 return os.path.join(AZALEA_RESULTS_DIRECTORY,
144 hashlib.md5(pickle.dumps(args)).hexdigest())
145
146
147 def DeltaEvaluator(git_hash1, git_hash2,
148 client_id, start_date, end_date, batch_size,
149 property_values=None, verbose=False):
150 """Evaluates delta between git_hash1 and git_hash2 on a set of Testcases.
151
152 Args:
153 git_hash1 (str): A git hash of findit repository.
154 git_hash2 (str): A git hash of findit repository.
155 start_date (str): Run delta test on testcases after (including)
156 the start_date, format should be '%Y-%m-%d'.
157 end_date (str): Run delta test on testcases before (not including)
158 the end_date, format should be '%Y-%m-%d'.
159 client_id (CrashClient): Possible values are 'fracas', 'cracas',
160 'cluterfuzz'.
161 batch_size (int): Size of a batch that can be queried at one time.
162 property_values (dict): Property values to query.
163 batch_size (int): The size of crashes that can be queried at one time.
164 verbose (bool): If True, print all the findit results.
165 Return:
166 (deltas, crash_count).
167 deltas (dict): Mappings id to delta for each culprit value.
168 crash_count (int): Total count of all the crashes.
169 """
170 head_branch_name = subprocess.check_output(
171 ['git', 'rev-parse', '--abbrev-ref', 'HEAD']).replace('\n', '')
172 deltas = {}
173 try:
174 crash_count = 0
175 for index, crashes in enumerate(
176 crash_iterator.IterateCrashes(client_id,
177 property_values=property_values,
178 start_date=start_date,
179 end_date=end_date,
180 batch_size=batch_size,
181 batch_run=True)):
182
183 results = []
184 for git_hash in [git_hash1, git_hash2]:
185 result_path = GenerateResultFileName(client_id, property_values,
186 start_date, end_date,
187 batch_size, index, git_hash)
188 results.append(GetResult(crashes, git_hash, result_path,
189 verbose=verbose))
190
191 crash_count += len(crashes)
192 deltas.update(GetDeltaFromTwoSetsOfCulprits(*results))
193
194 return deltas, crash_count
195 finally:
196 dev_null_handle = open(os.devnull, 'w')
197 subprocess.check_call(['git', 'checkout', head_branch_name],
198 stdout=dev_null_handle,
199 stderr=dev_null_handle)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698