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

Side by Side Diff: scripts/slave/recipes/bisect.py

Issue 1044543002: Lint bisect-related modules; obey pylint. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Rebased Created 5 years, 8 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
« no previous file with comments | « scripts/slave/recipe_modules/math_utils/api.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 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 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 import base64 5 import base64
6 import collections 6 import collections
7 import json 7 import json
8 8
9 DEPS = [ 9 DEPS = [
10 'auto_bisect', 10 'auto_bisect',
11 'properties', 11 'properties',
12 'test_utils', 12 'test_utils',
13 'chromium_tests', 13 'chromium_tests',
14 'raw_io', 14 'raw_io',
15 ] 15 ]
16 16
17 AVAILABLE_BOTS = 1 # Change this for n-secting instead of bi-. 17 AVAILABLE_BOTS = 1 # Change this for n-secting instead of bi-.
18
18 19
19 def GenSteps(api): 20 def GenSteps(api):
20 _ensure_checkout(api) 21 _ensure_checkout(api)
21 # HORRIBLE hack to get buildbot web ui to let us pass stuff as properties 22 # HORRIBLE hack to get buildbot web ui to let us pass stuff as properties
22 bisect_config_b32_string = api.properties.get('bcb32') 23 bisect_config_b32_string = api.properties.get('bcb32')
23 if bisect_config_b32_string is not None: 24 if bisect_config_b32_string is not None:
24 bisect_config = bisect_config_b32_string.replace('0', '=') 25 bisect_config = bisect_config_b32_string.replace('0', '=')
25 bisect_config = base64.b32decode(bisect_config) 26 bisect_config = base64.b32decode(bisect_config)
26 bisect_config = json.loads(bisect_config) 27 bisect_config = json.loads(bisect_config)
27 else: 28 else:
28 bisect_config = api.properties.get('bisect_config') 29 bisect_config = api.properties.get('bisect_config')
29 assert isinstance(bisect_config, collections.Mapping) 30 assert isinstance(bisect_config, collections.Mapping)
30 bisector = api.auto_bisect.create_bisector(bisect_config) 31 bisector = api.auto_bisect.create_bisector(bisect_config)
31 _gather_reference_range(bisector) 32 _gather_reference_range(bisector)
32 _ensure_checkout(api) 33 _ensure_checkout(api)
33 if (not bisector.failed and bisector.check_improvement_direction() and 34 if (not bisector.failed and bisector.check_improvement_direction() and
34 bisector.check_regression_confidence()): 35 bisector.check_regression_confidence()):
35 if not bisector.check_bisect_finished(bisector.good_rev): 36 if not bisector.check_bisect_finished(bisector.good_rev):
36 _bisect_main_loop(bisector) 37 _bisect_main_loop(bisector)
37 else: #pragma: no cover 38 else: # pragma: no cover
38 bisector.bisect_over = True 39 bisector.bisect_over = True
39 bisector.print_result() 40 bisector.print_result()
40 41
41 42
42 def GenTests(api): 43 def GenTests(api):
43 basic_test = api.test('basic') 44 basic_test = api.test('basic')
44 encoded_config_test = api.test('encoded_config_test') 45 encoded_config_test = api.test('encoded_config_test')
45 broken_cp_test = api.test('broken_cp_test') 46 broken_cp_test = api.test('broken_cp_test')
46 broken_hash_test = api.test('broken_hash_test') 47 broken_hash_test = api.test('broken_hash_test')
47 invalid_config_test = api.test('invalid_config_test') 48 invalid_config_test = api.test('invalid_config_test')
48 basic_test += api.properties.generic(mastername='tryserver.chromium.perf', 49 basic_test += api.properties.generic(
49 buildername='linux_perf_bisect_builder') 50 mastername='tryserver.chromium.perf',
50 broken_cp_test += api.properties.generic(mastername='tryserver.chromium.perf', 51 buildername='linux_perf_bisect_builder')
51 buildername='linux_perf_bisect_builder') 52 broken_cp_test += api.properties.generic(
53 mastername='tryserver.chromium.perf',
54 buildername='linux_perf_bisect_builder')
52 broken_hash_test += api.properties.generic( 55 broken_hash_test += api.properties.generic(
53 mastername='tryserver.chromium.perf', 56 mastername='tryserver.chromium.perf',
54 buildername='linux_perf_bisect_builder') 57 buildername='linux_perf_bisect_builder')
55 invalid_config_test += api.properties.generic( 58 invalid_config_test += api.properties.generic(
56 mastername='tryserver.chromium.perf', 59 mastername='tryserver.chromium.perf',
57 buildername='linux_perf_bisect_builder') 60 buildername='linux_perf_bisect_builder')
58 encoded_config_test += api.properties.generic( 61 encoded_config_test += api.properties.generic(
59 mastername='tryserver.chromium.perf', 62 mastername='tryserver.chromium.perf',
60 buildername='linux_perf_bisect_builder') 63 buildername='linux_perf_bisect_builder')
61 bisect_config = { 64 bisect_config = {
62 'test_type': 'perf', 65 'test_type': 'perf',
63 'command': 'tools/perf/run_benchmark -v ' 66 'command': ('tools/perf/run_benchmark -v '
64 '--browser=release page_cycler.intl_ar_fa_he', 67 '--browser=release page_cycler.intl_ar_fa_he'),
65 'good_revision': '306475', 68 'good_revision': '306475',
66 'bad_revision': 'src@a6298e4afedbf2cd461755ea6f45b0ad64222222', 69 'bad_revision': 'src@a6298e4afedbf2cd461755ea6f45b0ad64222222',
67 'metric': 'warm_times/page_load_time', 70 'metric': 'warm_times/page_load_time',
68 'repeat_count': '2', 71 'repeat_count': '2',
69 'max_time_minutes': '5', 72 'max_time_minutes': '5',
70 'truncate_percent': '25', 73 'truncate_percent': '25',
71 'bug_id': '425582', 74 'bug_id': '425582',
72 'gs_bucket': 'chrome-perf', 75 'gs_bucket': 'chrome-perf',
73 'builder_host': 'master4.golo.chromium.org', 76 'builder_host': 'master4.golo.chromium.org',
74 'builder_port': '8341', 77 'builder_port': '8341',
75 'dummy_regression_confidence': '95', 78 'dummy_regression_confidence': '95',
76 'poll_sleep': 0, 79 'poll_sleep': 0,
77 'dummy_builds': True, 80 'dummy_builds': True,
78 } 81 }
79 invalid_cp_bisect_config = dict(bisect_config) 82 invalid_cp_bisect_config = dict(bisect_config)
80 invalid_cp_bisect_config ['good_revision'] = 'XXX' 83 invalid_cp_bisect_config['good_revision'] = 'XXX'
81 84
82 basic_test += api.properties(bisect_config=bisect_config) 85 basic_test += api.properties(bisect_config=bisect_config)
83 broken_cp_test += api.properties(bisect_config=bisect_config) 86 broken_cp_test += api.properties(bisect_config=bisect_config)
84 broken_hash_test += api.properties(bisect_config=bisect_config) 87 broken_hash_test += api.properties(bisect_config=bisect_config)
85 invalid_config_test += api.properties(bisect_config=invalid_cp_bisect_config) 88 invalid_config_test += api.properties(bisect_config=invalid_cp_bisect_config)
86 encoded_config_test += api.properties(bcb32=base64.b32encode(json.dumps( 89 encoded_config_test += api.properties(bcb32=base64.b32encode(json.dumps(
87 bisect_config)).replace('=', '0')) 90 bisect_config)).replace('=', '0'))
88 # This data represents fake results for a basic scenario, the items in it are 91 # This data represents fake results for a basic scenario, the items in it are
89 # passed to the `_gen_step_data_for_revision` that patches the necessary steps 92 # passed to the `_gen_step_data_for_revision` that patches the necessary steps
90 # with step_data instances. 93 # with step_data instances.
91 test_data = [ 94 test_data = [
92 { 95 {
93 'hash': 'a6298e4afedbf2cd461755ea6f45b0ad64222222', 96 'hash': 'a6298e4afedbf2cd461755ea6f45b0ad64222222',
94 'commit_pos': '306478', 97 'commit_pos': '306478',
95 'test_results': {'results':{ 98 'test_results': {'results':{
96 'mean': 20, 99 'mean': 20,
97 'std_err': 1, 100 'std_err': 1,
98 'values': [19, 20, 21], 101 'values': [19, 20, 21],
99 }}, 102 }},
100 'cl_info': 'S3P4R4T0R'.join(['DummyAuthor', 'dummy@nowhere.com', 103 'cl_info': 'S3P4R4T0R'.join(['DummyAuthor', 'dummy@nowhere.com',
101 'Some random CL', '01/01/2015', 104 'Some random CL', '01/01/2015',
102 'A long description for a CL.\n' 105 'A long description for a CL.\n'
103 'Containing multiple lines']) 106 'Containing multiple lines'])
104 }, 107 },
105 { 108 {
106 'hash': '00316c9ddfb9d7b4e1ed2fff9fe6d964d2111111', 109 'hash': '00316c9ddfb9d7b4e1ed2fff9fe6d964d2111111',
107 'commit_pos': '306477', 110 'commit_pos': '306477',
108 'test_results': {'results':{ 111 'test_results': {'results': {
109 'mean': 15, 112 'mean': 15,
110 'std_err': 1, 113 'std_err': 1,
111 'values': [14, 15, 16], 114 'values': [14, 15, 16],
112 }} 115 }}
113 }, 116 },
114 { 117 {
115 'hash': 'fc6dfc7ff5b1073408499478969261b826441144', 118 'hash': 'fc6dfc7ff5b1073408499478969261b826441144',
116 'commit_pos': '306476', 119 'commit_pos': '306476',
117 'test_results': {'results':{ 120 'test_results': {'results': {
118 'mean': 70, 121 'mean': 70,
119 'std_err': 2, 122 'std_err': 2,
120 'values': [68, 70, 72], 123 'values': [68, 70, 72],
121 }} 124 }}
122 }, 125 },
123 { 126 {
124 'hash': 'e28dc0d49c331def2a3bbf3ddd0096eb51551155', 127 'hash': 'e28dc0d49c331def2a3bbf3ddd0096eb51551155',
125 'commit_pos': '306475', 128 'commit_pos': '306475',
126 'test_results': {'results':{ 129 'test_results': {'results': {
127 'mean': 80, 130 'mean': 80,
128 'std_err': 10, 131 'std_err': 10,
129 'values': [70, 70, 80, 90, 90], 132 'values': [70, 70, 80, 90, 90],
130 }} 133 }}
131 }, 134 },
132 ] 135 ]
133 136
134
135
136 for revision_data in test_data: 137 for revision_data in test_data:
137 for step_data in _get_step_data_for_revision(api, revision_data): 138 for step_data in _get_step_data_for_revision(api, revision_data):
138 basic_test += step_data 139 basic_test += step_data
139 encoded_config_test += step_data 140 encoded_config_test += step_data
140 for step_data in _get_step_data_for_revision(api, revision_data, 141 for step_data in _get_step_data_for_revision(api, revision_data,
141 broken_cp='306475'): 142 broken_cp='306475'):
142 broken_cp_test += step_data 143 broken_cp_test += step_data
143 for step_data in _get_step_data_for_revision( 144 for step_data in _get_step_data_for_revision(
144 api, revision_data, 145 api, revision_data,
145 broken_hash='e28dc0d49c331def2a3bbf3ddd0096eb51551155'): 146 broken_hash='e28dc0d49c331def2a3bbf3ddd0096eb51551155'):
146 broken_hash_test += step_data 147 broken_hash_test += step_data
147 148
148 yield basic_test 149 yield basic_test
149 yield encoded_config_test 150 yield encoded_config_test
150 yield broken_hash_test 151 yield broken_hash_test
151 yield broken_cp_test 152 yield broken_cp_test
152 yield invalid_config_test 153 yield invalid_config_test
153 154
154 155
155
156
157
158 def _get_step_data_for_revision(api, revision_data, broken_cp=None, 156 def _get_step_data_for_revision(api, revision_data, broken_cp=None,
159 broken_hash=None): 157 broken_hash=None):
160 """Generator that produces step patches for fake results.""" 158 """Generator that produces step patches for fake results."""
161 commit_pos = revision_data['commit_pos'] 159 commit_pos = revision_data['commit_pos']
162 commit_hash = revision_data['hash'] 160 commit_hash = revision_data['hash']
163 test_results = revision_data['test_results'] 161 test_results = revision_data['test_results']
164 162
165 step_name ='resolving commit_pos ' + commit_pos 163 step_name = 'resolving commit_pos ' + commit_pos
166 if commit_pos == broken_cp: 164 if commit_pos == broken_cp:
167 yield api.step_data(step_name, stdout=api.raw_io.output('')) 165 yield api.step_data(step_name, stdout=api.raw_io.output(''))
168 else: 166 else:
169 yield api.step_data(step_name, stdout=api.raw_io.output('hash:' + 167 yield api.step_data(step_name, stdout=api.raw_io.output('hash:' +
170 commit_hash)) 168 commit_hash))
171 169
172 step_name ='resolving hash ' + commit_hash 170 step_name = 'resolving hash ' + commit_hash
173 if commit_hash == broken_hash: 171 if commit_hash == broken_hash:
174 yield api.step_data(step_name, stdout=api.raw_io.output('UnCastable')) 172 yield api.step_data(step_name, stdout=api.raw_io.output('UnCastable'))
175 else: 173 else:
176 commit_pos_str = 'refs/heads/master@{#%s}' % commit_pos 174 commit_pos_str = 'refs/heads/master@{#%s}' % commit_pos
177 yield api.step_data(step_name, stdout=api.raw_io.output(commit_pos_str)) 175 yield api.step_data(step_name, stdout=api.raw_io.output(commit_pos_str))
178 176
179 step_name ='gsutil Get test results for build ' + commit_hash 177 step_name = 'gsutil Get test results for build ' + commit_hash
180 yield api.step_data(step_name, stdout=api.raw_io.output(json.dumps( 178 yield api.step_data(step_name, stdout=api.raw_io.output(json.dumps(
181 test_results))) 179 test_results)))
182 180
183 step_name = 'Get test status for build ' + commit_hash 181 step_name = 'Get test status for build ' + commit_hash
184 yield api.step_data(step_name, stdout=api.raw_io.output('Complete')) 182 yield api.step_data(step_name, stdout=api.raw_io.output('Complete'))
185 183
186 step_name ='gsutil Get test status url for build ' + commit_hash 184 step_name = 'gsutil Get test status url for build ' + commit_hash
187 yield api.step_data(step_name, stdout=api.raw_io.output('dummy/url')) 185 yield api.step_data(step_name, stdout=api.raw_io.output('dummy/url'))
188 186
189 if 'cl_info' in revision_data: 187 if 'cl_info' in revision_data:
190 step_name = 'Reading culprit cl information.' 188 step_name = 'Reading culprit cl information.'
191 stdout = api.raw_io.output(revision_data['cl_info']) 189 stdout = api.raw_io.output(revision_data['cl_info'])
192 yield api.step_data(step_name, stdout=stdout) 190 yield api.step_data(step_name, stdout=stdout)
193 191
194 192
195 def _ensure_checkout(api): 193 def _ensure_checkout(api):
196 mastername = api.properties.get('mastername') 194 mastername = api.properties.get('mastername')
197 buildername = api.properties.get('buildername') 195 buildername = api.properties.get('buildername')
198 api.chromium_tests.sync_and_configure_build(mastername, buildername) 196 api.chromium_tests.sync_and_configure_build(mastername, buildername)
199 197
200 198
201 def _gather_reference_range(bisector): 199 def _gather_reference_range(bisector):
202 bisector.good_rev.start_job() 200 bisector.good_rev.start_job()
203 bisector.bad_rev.start_job() 201 bisector.bad_rev.start_job()
204 bisector.wait_for_all([bisector.good_rev, bisector.bad_rev]) 202 bisector.wait_for_all([bisector.good_rev, bisector.bad_rev])
205 bisector.compute_relative_change() 203 bisector.compute_relative_change()
206 204
207 205
208 def _bisect_main_loop(bisector): 206 def _bisect_main_loop(bisector):
209 """This is the main bisect loop. 207 """This is the main bisect loop.
210 208
211 It gets an evenly distributed number of revisions in the candidate range, 209 It gets an evenly distributed number of revisions in the candidate range,
212 then it starts them in parallel and waits for them to finish. 210 then it starts them in parallel and waits for them to finish.
213 """ 211 """
214 while not bisector.bisect_over: 212 while not bisector.bisect_over:
215 revisions_to_check = bisector.get_revisions_to_eval(AVAILABLE_BOTS) 213 revisions_to_check = bisector.get_revisions_to_eval(AVAILABLE_BOTS)
216 #TODO: Add a test case to remove this pragma 214 # TODO: Add a test case to remove this pragma
217 if not revisions_to_check: #pragma: no cover 215 if not revisions_to_check: # pragma: no cover
218 bisector.bisect_over = True 216 bisector.bisect_over = True
219 break 217 break
220 for r in revisions_to_check: 218 for r in revisions_to_check:
221 r.start_job() 219 r.start_job()
222 _wait_for_revisions(bisector, revisions_to_check) 220 _wait_for_revisions(bisector, revisions_to_check)
223 221
224 222
225 def _wait_for_revisions(bisector, revisions_to_check): 223 def _wait_for_revisions(bisector, revisions_to_check):
226 """Wait for possibly multiple revision evaluations. 224 """Wait for possibly multiple revision evaluations.
227 225
228 Waits for the first of such revisions to finish, it then checks if any of the 226 Waits for the first of such revisions to finish, it then checks if any of the
229 other revisions in progress has become superfluous and has them aborted. 227 other revisions in progress has become superfluous and has them aborted.
230 228
231 If such revision completes the bisect process it sets the flag so that the 229 If such revision completes the bisect process it sets the flag so that the
232 main loop stops. 230 main loop stops.
233 """ 231 """
234 while revisions_to_check: 232 while revisions_to_check:
235 completed_revision = bisector.wait_for_any(revisions_to_check) 233 completed_revision = bisector.wait_for_any(revisions_to_check)
236 revisions_to_check.remove(completed_revision) 234 revisions_to_check.remove(completed_revision)
237 if not completed_revision.aborted: 235 if not completed_revision.aborted:
238 if bisector.check_bisect_finished(completed_revision): 236 if bisector.check_bisect_finished(completed_revision):
239 bisector.bisect_over = True 237 bisector.bisect_over = True
240 bisector.abort_unnecessary_jobs() 238 bisector.abort_unnecessary_jobs()
OLDNEW
« no previous file with comments | « scripts/slave/recipe_modules/math_utils/api.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698