OLD | NEW |
| (Empty) |
1 # Copyright 2015 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 base64 | |
6 import collections | |
7 import json | |
8 | |
9 DEPS = [ | |
10 'auto_bisect_staging', | |
11 'recipe_engine/properties', | |
12 'test_utils', | |
13 'chromium_tests', | |
14 'recipe_engine/raw_io', | |
15 'recipe_engine/step', | |
16 'halt', | |
17 'recipe_engine/json', | |
18 ] | |
19 | |
20 def RunSteps(api): | |
21 mastername = api.m.properties.get('mastername') | |
22 buildername = api.m.properties.get('buildername') | |
23 # TODO(akuegel): Explicitly load the configs for the builders and don't rely | |
24 # on builders.py in chromium_tests recipe module. | |
25 bot_config = api.chromium_tests.create_bot_config_object( | |
26 mastername, buildername) | |
27 api.chromium_tests.configure_build(bot_config) | |
28 api.m.chromium_tests.prepare_checkout(bot_config) | |
29 api.auto_bisect_staging.perform_bisect(do_not_nest_wait_for_revision=True) | |
30 | |
31 def GenTests(api): | |
32 basic_test = api.test('basic') | |
33 broken_bad_rev_test = api.test('broken_bad_revision_test') | |
34 broken_good_rev_test = api.test('broken_good_revision_test') | |
35 return_code_test = api.test('basic_return_code_test') | |
36 basic_test += api.properties.generic( | |
37 mastername='tryserver.chromium.perf', | |
38 buildername='linux_perf_bisect') | |
39 broken_bad_rev_test += api.properties.generic( | |
40 mastername='tryserver.chromium.perf', | |
41 buildername='linux_perf_bisect') | |
42 broken_good_rev_test += api.properties.generic( | |
43 mastername='tryserver.chromium.perf', | |
44 buildername='linux_perf_bisect') | |
45 return_code_test += api.properties.generic( | |
46 mastername='tryserver.chromium.perf', | |
47 buildername='linux_perf_bisect') | |
48 | |
49 bisect_config = { | |
50 'test_type': 'perf', | |
51 'command': ('tools/perf/run_benchmark -v ' | |
52 '--browser=release page_cycler.intl_ar_fa_he'), | |
53 'good_revision': '306475', | |
54 'bad_revision': '306478', | |
55 'metric': 'warm_times/page_load_time', | |
56 'repeat_count': '2', | |
57 'max_time_minutes': '5', | |
58 'bug_id': '425582', | |
59 'gs_bucket': 'chrome-perf', | |
60 'builder_host': 'master4.golo.chromium.org', | |
61 'builder_port': '8341', | |
62 'dummy_initial_confidence': '95', | |
63 'poll_sleep': 0, | |
64 'dummy_builds': True, | |
65 'dummy_tests': True, | |
66 'dummy_job_names': True, | |
67 'bypass_stats_check': True, | |
68 } | |
69 invalid_cp_bisect_config = dict(bisect_config) | |
70 invalid_cp_bisect_config['good_revision'] = 'XXX' | |
71 | |
72 basic_test += api.properties(bisect_config=bisect_config) | |
73 broken_bad_rev_test += api.properties(bisect_config=bisect_config) | |
74 broken_good_rev_test += api.properties(bisect_config=bisect_config) | |
75 | |
76 # This data represents fake results for a basic scenario, the items in it are | |
77 # passed to the `_gen_step_data_for_revision` that patches the necessary steps | |
78 # with step_data instances. | |
79 def test_data(): | |
80 return [ | |
81 { | |
82 'refrange': True, | |
83 'hash': 'a6298e4afedbf2cd461755ea6f45b0ad64222222', | |
84 'commit_pos': '306478', | |
85 'test_results': { | |
86 'results': { | |
87 'mean': 20, | |
88 'std_err': 1, | |
89 'values': [19, 20, 21], | |
90 }, | |
91 'retcodes':[0], | |
92 }, | |
93 'cl_info': { | |
94 'author': 'DummyAuthor', | |
95 'email': 'dummy@nowhere.com', | |
96 'subject': 'Some random CL', | |
97 'date': '01/01/2015', | |
98 'body': ('A long description for a CL.\n' | |
99 'Containing multiple lines'), | |
100 }, | |
101 }, | |
102 { | |
103 'hash': '00316c9ddfb9d7b4e1ed2fff9fe6d964d2111111', | |
104 'commit_pos': '306477', | |
105 'test_results': { | |
106 'results': { | |
107 'mean': 15, | |
108 'std_err': 1, | |
109 'values': [14, 15, 16], | |
110 }, | |
111 'retcodes':[0], | |
112 } | |
113 }, | |
114 { | |
115 'hash': 'fc6dfc7ff5b1073408499478969261b826441144', | |
116 'commit_pos': '306476', | |
117 'test_results': { | |
118 'results': { | |
119 'mean': 70, | |
120 'std_err': 2, | |
121 'values': [68, 70, 72], | |
122 }, | |
123 'retcodes':[0], | |
124 } | |
125 }, | |
126 { | |
127 'refrange': True, | |
128 'hash': 'e28dc0d49c331def2a3bbf3ddd0096eb51551155', | |
129 'commit_pos': '306475', | |
130 'test_results': { | |
131 'results': { | |
132 'mean': 80, | |
133 'std_err': 10, | |
134 'values': [70, 70, 80, 90, 90], | |
135 }, | |
136 'retcodes':[0], | |
137 } | |
138 }, | |
139 ] | |
140 | |
141 basic_test_data = test_data() | |
142 for revision_data in basic_test_data: | |
143 for step_data in _get_step_data_for_revision(api, revision_data): | |
144 basic_test += step_data | |
145 basic_test += _get_revision_range_step_data(api, basic_test_data) | |
146 basic_test += _get_post_bisect_step_data(api) | |
147 yield basic_test | |
148 | |
149 broken_test_data = test_data() | |
150 broken_test_data[0].pop('cl_info') | |
151 | |
152 doctored_data = test_data() | |
153 doctored_data[0]['test_results']['results']['errors'] = ['Dummy error.'] | |
154 for revision_data in doctored_data: | |
155 revision_data.pop('cl_info', None) | |
156 skip_results = revision_data in doctored_data[1:-1] | |
157 for step_data in _get_step_data_for_revision(api, revision_data, | |
158 skip_results=skip_results): | |
159 broken_bad_rev_test += step_data | |
160 broken_bad_rev_test += _get_revision_range_step_data(api, doctored_data) | |
161 broken_bad_rev_test += _get_post_bisect_step_data(api) | |
162 yield broken_bad_rev_test | |
163 | |
164 doctored_data = test_data() | |
165 doctored_data[-1]['test_results']['results']['errors'] = ['Dummy error.'] | |
166 for revision_data in doctored_data: | |
167 revision_data.pop('cl_info', None) | |
168 skip_results = revision_data in doctored_data[1:-1] | |
169 for step_data in _get_step_data_for_revision(api, revision_data, | |
170 skip_results=skip_results): | |
171 broken_good_rev_test += step_data | |
172 broken_good_rev_test += _get_revision_range_step_data(api, doctored_data) | |
173 broken_good_rev_test += _get_post_bisect_step_data(api) | |
174 yield broken_good_rev_test | |
175 | |
176 def return_code_test_data(): | |
177 return [ | |
178 { | |
179 'refrange': True, | |
180 'hash': 'a6298e4afedbf2cd461755ea6f45b0ad64222222', | |
181 'commit_pos': '306478', | |
182 'test_results': { | |
183 'results': { | |
184 'mean': 1, | |
185 'std_err': 0, | |
186 'values': [], | |
187 }, | |
188 'retcodes':[1], | |
189 }, | |
190 'cl_info': { | |
191 'author': 'DummyAuthor', | |
192 'email': 'dummy@nowhere.com', | |
193 'subject': 'Some random CL', | |
194 'date': '01/01/2015', | |
195 'body': ('A long description for a CL.\n' | |
196 'Containing multiple lines'), | |
197 }, | |
198 }, | |
199 { | |
200 'hash': '00316c9ddfb9d7b4e1ed2fff9fe6d964d2111111', | |
201 'commit_pos': '306477', | |
202 'test_results': { | |
203 'results': { | |
204 'mean': 1, | |
205 'std_err': 0, | |
206 'values': [], | |
207 }, | |
208 'retcodes':[1], | |
209 } | |
210 }, | |
211 { | |
212 'hash': 'fc6dfc7ff5b1073408499478969261b826441144', | |
213 'commit_pos': '306476', | |
214 'test_results': { | |
215 'results': { | |
216 'mean': 1, | |
217 'std_err': 0, | |
218 'values': [], | |
219 }, | |
220 'retcodes':[1], | |
221 } | |
222 }, | |
223 { | |
224 'refrange': True, | |
225 'hash': 'e28dc0d49c331def2a3bbf3ddd0096eb51551155', | |
226 'commit_pos': '306475', | |
227 'test_results': { | |
228 'results': { | |
229 'mean': 0, | |
230 'std_err': 0, | |
231 'values': [], | |
232 }, | |
233 'retcodes':[0], | |
234 } | |
235 }, | |
236 ] | |
237 | |
238 bisect_config_ret_code = bisect_config.copy() | |
239 bisect_config_ret_code['test_type'] = 'return_code' | |
240 return_code_test += api.properties(bisect_config=bisect_config_ret_code) | |
241 return_code_test_data = return_code_test_data() | |
242 for revision_data in return_code_test_data: | |
243 for step_data in _get_step_data_for_revision(api, revision_data): | |
244 return_code_test += step_data | |
245 return_code_test += _get_revision_range_step_data(api, return_code_test_data) | |
246 return_code_test += _get_post_bisect_step_data(api) | |
247 yield return_code_test | |
248 | |
249 | |
250 def _get_revision_range_step_data(api, range_data): | |
251 """Gives canned output for fetch_intervening_revisions.py.""" | |
252 range_data.sort(key=lambda r: r['commit_pos']) | |
253 min_rev = range_data[0]['hash'] | |
254 max_rev = range_data[-1]['hash'] | |
255 output = [[r['hash'], 'ignored'] for r in range_data[1:]] | |
256 step_name = ('Expanding revision range.for revisions %s:%s' % | |
257 (min_rev, max_rev)) | |
258 return api.step_data(step_name, stdout=api.json.output(output)) | |
259 | |
260 | |
261 def _get_step_data_for_revision(api, revision_data, skip_results=False): | |
262 """Generator that produces step patches for fake results.""" | |
263 commit_pos_number = revision_data['commit_pos'] | |
264 commit_hash = revision_data['hash'] | |
265 test_results = revision_data['test_results'] | |
266 | |
267 if 'refrange' in revision_data: | |
268 parent_step = 'Resolving reference range.' | |
269 commit_pos = 'refs/heads/master@{#%s}' % commit_pos_number | |
270 step_name = parent_step + 'crrev get commit hash for ' + commit_pos | |
271 yield api.step_data( | |
272 step_name, | |
273 stdout=api.json.output({'git_sha': commit_hash})) | |
274 | |
275 if not skip_results: | |
276 step_name = ('gsutil Get test results for build %s') % (commit_hash) | |
277 if 'refrange' in revision_data: | |
278 parent_step = 'Gathering reference values.' | |
279 else: | |
280 parent_step = 'Working on revision %s.' % ('chromium@' + commit_hash[:10]) | |
281 yield _get_post_bisect_step_data(api, parent_step) | |
282 step_name = parent_step + step_name | |
283 yield api.step_data(step_name, stdout=api.raw_io.output(json.dumps( | |
284 test_results))) | |
285 | |
286 if 'cl_info' in revision_data: | |
287 step_name = 'Reading culprit cl information.' | |
288 stdout = api.json.output(revision_data['cl_info']) | |
289 yield api.step_data(step_name, stdout=stdout) | |
290 | |
291 | |
292 def _get_post_bisect_step_data(api, parent_step=''): | |
293 """Gets step data for perf_dashboard/resource/post_json.py.""" | |
294 response = {'status_code': 200} | |
295 return api.step_data(parent_step + 'Post bisect results', | |
296 stdout=api.json.output(response)) | |
OLD | NEW |