OLD | NEW |
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 """API for the bisect recipe module. | 5 """API for the bisect recipe module. |
6 | 6 |
7 This API is meant to enable the bisect recipe to bisect any chromium-supported | 7 This API is meant to enable the bisect recipe to bisect any chromium-supported |
8 platform for any test that can be run via buildbot, perf or otherwise. | 8 platform for any test that can be run via buildbot, perf or otherwise. |
9 """ | 9 """ |
10 | 10 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 """ | 127 """ |
128 step_name = 'Reading culprit cl information.' | 128 step_name = 'Reading culprit cl information.' |
129 # Use gitiles to get commit information. | 129 # Use gitiles to get commit information. |
130 if revision.depot_name == 'android-chrome': # pragma: no cover | 130 if revision.depot_name == 'android-chrome': # pragma: no cover |
131 commit_url = depot_config.DEPOT_DEPS_NAME[revision.depot_name]['url'] | 131 commit_url = depot_config.DEPOT_DEPS_NAME[revision.depot_name]['url'] |
132 return self._commit_info(revision.commit_hash, commit_url, step_name) | 132 return self._commit_info(revision.commit_hash, commit_url, step_name) |
133 result = self.m.python( | 133 result = self.m.python( |
134 step_name, | 134 step_name, |
135 self.resource('fetch_revision_info.py'), | 135 self.resource('fetch_revision_info.py'), |
136 [revision.commit_hash, revision.depot_name], | 136 [revision.commit_hash, revision.depot_name], |
137 stdout=self.m.json.output()) | 137 stdout=self.m.json.output(), |
| 138 step_test_data=lambda: self._test_data['cl_info'][revision.commit_hash], |
| 139 ) |
138 return result.stdout | 140 return result.stdout |
139 | 141 |
140 def _commit_info(self, commit_hash, url, step_name=None): # pragma: no cover | 142 def _commit_info(self, commit_hash, url, step_name=None): # pragma: no cover |
141 """Fetches information about a given commit. | 143 """Fetches information about a given commit. |
142 | 144 |
143 Args: | 145 Args: |
144 commit_hash (str): A git commit hash. | 146 commit_hash (str): A git commit hash. |
145 url (str): The URL of a repository, e.g. | 147 url (str): The URL of a repository, e.g. |
146 "https://chromium.googlesource.com/chromium/src". | 148 "https://chromium.googlesource.com/chromium/src". |
147 step_name (str): Optional step name. | 149 step_name (str): Optional step name. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 '--build-properties', | 198 '--build-properties', |
197 self.m.json.dumps(dict(self.m.properties.legacy())), | 199 self.m.json.dumps(dict(self.m.properties.legacy())), |
198 ] | 200 ] |
199 self.m.chromium.runtest( | 201 self.m.chromium.runtest( |
200 self.m.path['checkout'].join('tools', 'run-bisect-perf-regression.py'), | 202 self.m.path['checkout'].join('tools', 'run-bisect-perf-regression.py'), |
201 ['-w', self.m.path['cache'].join('bisect')] + args, | 203 ['-w', self.m.path['cache'].join('bisect')] + args, |
202 name='Running Bisection', | 204 name='Running Bisection', |
203 xvfb=True, **kwargs) | 205 xvfb=True, **kwargs) |
204 | 206 |
205 def run_local_test_run(self, test_config_params, | 207 def run_local_test_run(self, test_config_params, |
206 skip_download=False): # pragma: no cover | 208 skip_download=False, **kwargs): # pragma: no cover |
207 """Starts a test run on the same machine. | 209 """Starts a test run on the same machine. |
208 | 210 |
209 This is for the merged director/tester flow. | 211 This is for the merged director/tester flow. |
210 """ | 212 """ |
211 if self.m.platform.is_win: | 213 if self.m.platform.is_win: |
212 self.m.chromium.taskkill() | 214 self.m.chromium.taskkill() |
213 | 215 |
214 if skip_download: | 216 if skip_download: |
215 update_step = None | 217 update_step = None |
216 else: | 218 else: |
217 update_step = self._SyncRevisionToTest(test_config_params) | 219 update_step = self._SyncRevisionToTest(test_config_params) |
218 self.start_test_run_for_bisect(update_step, self.bot_db, | 220 return self.start_test_run_for_bisect( |
219 test_config_params, run_locally=True, | 221 update_step, self.bot_db, test_config_params, run_locally=True, |
220 skip_download=skip_download) | 222 skip_download=skip_download, **kwargs) |
221 | 223 |
222 def ensure_checkout(self, *args, **kwargs): | 224 def ensure_checkout(self, *args, **kwargs): |
223 if self.working_dir: | 225 if self.working_dir: |
224 kwargs.setdefault('cwd', self.working_dir) | 226 kwargs.setdefault('cwd', self.working_dir) |
225 | 227 |
226 return self.m.bot_update.ensure_checkout(*args, **kwargs) | 228 return self.m.bot_update.ensure_checkout(*args, **kwargs) |
227 | 229 |
228 def _SyncRevisionToTest(self, test_config_params): # pragma: no cover | 230 def _SyncRevisionToTest(self, test_config_params): # pragma: no cover |
229 if not self.internal_bisect: | 231 if not self.internal_bisect: |
230 return self.ensure_checkout( | 232 return self.ensure_checkout( |
231 root_solution_revision=test_config_params['revision']) | 233 root_solution_revision=test_config_params['revision']) |
232 else: | 234 else: |
233 return self._SyncRevisionsForAndroidChrome( | 235 return self._SyncRevisionsForAndroidChrome( |
234 test_config_params['revision_ladder']) | 236 test_config_params['revision_ladder']) |
235 | 237 |
236 def _SyncRevisionsForAndroidChrome(self, revision_ladder): # pragma: no cover | 238 def _SyncRevisionsForAndroidChrome(self, revision_ladder): # pragma: no cover |
237 """Syncs android-chrome and chromium repos to particular revision.""" | 239 """Syncs android-chrome and chromium repos to particular revision.""" |
238 revisions = [] | 240 revisions = [] |
239 for d, r in revision_ladder.iteritems(): | 241 for d, r in revision_ladder.iteritems(): |
240 revisions.append('%s@%s' % (depot_config.DEPOT_DEPS_NAME[d]['src'], r)) | 242 revisions.append('%s@%s' % (depot_config.DEPOT_DEPS_NAME[d]['src'], r)) |
241 params = ['sync', '--verbose', '--nohooks', '--force', | 243 params = ['sync', '--verbose', '--nohooks', '--force', |
242 '--delete_unversioned_trees'] | 244 '--delete_unversioned_trees'] |
243 for revision in revisions: | 245 for revision in revisions: |
244 params.extend(['--revision', revision]) | 246 params.extend(['--revision', revision]) |
245 self.m.gclient('sync %s' % '-'.join(revisions), params) | 247 self.m.gclient('sync %s' % '-'.join(revisions), params) |
246 return None | 248 return None |
247 | 249 |
248 def start_test_run_for_bisect(self, update_step, bot_db, | 250 def start_test_run_for_bisect(self, update_step, bot_db, |
249 test_config_params, run_locally=False, | 251 test_config_params, run_locally=False, |
250 skip_download=False): | 252 skip_download=False, **kwargs): |
251 mastername = self.m.properties.get('mastername') | 253 mastername = self.m.properties.get('mastername') |
252 buildername = self.m.properties.get('buildername') | 254 buildername = self.m.properties.get('buildername') |
253 bot_config = bot_db.get_bot_config(mastername, buildername) | 255 bot_config = bot_db.get_bot_config(mastername, buildername) |
254 build_archive_url = test_config_params['parent_build_archive_url'] | 256 build_archive_url = test_config_params['parent_build_archive_url'] |
255 if not run_locally: | |
256 self.m.bisect_tester.upload_job_url() | |
257 if not skip_download: | 257 if not skip_download: |
258 if self.m.chromium.c.TARGET_PLATFORM == 'android': | 258 if self.m.chromium.c.TARGET_PLATFORM == 'android': |
259 # The best way to ensure the old build directory is not used is to | 259 # The best way to ensure the old build directory is not used is to |
260 # remove it. | 260 # remove it. |
261 build_dir = self.m.chromium.c.build_dir.join( | 261 build_dir = self.m.chromium.c.build_dir.join( |
262 self.m.chromium.c.build_config_fs) | 262 self.m.chromium.c.build_config_fs) |
263 self.m.file.rmtree('build directory', build_dir) | 263 self.m.file.rmtree('build directory', build_dir) |
264 | 264 |
265 # The way android builders on tryserver.chromium.perf are archived is | 265 # The way android builders on tryserver.chromium.perf are archived is |
266 # different from builders on chromium.perf. In order to support both | 266 # different from builders on chromium.perf. In order to support both |
(...skipping 22 matching lines...) Expand all Loading... |
289 shutil.move(sys.argv[1], sys.argv[2]) | 289 shutil.move(sys.argv[1], sys.argv[2]) |
290 """, | 290 """, |
291 args=[zip_dir, build_dir]) | 291 args=[zip_dir, build_dir]) |
292 else: | 292 else: |
293 self.m.chromium_tests.download_and_unzip_build( | 293 self.m.chromium_tests.download_and_unzip_build( |
294 mastername, buildername, update_step, bot_db, | 294 mastername, buildername, update_step, bot_db, |
295 build_archive_url=build_archive_url, | 295 build_archive_url=build_archive_url, |
296 build_revision=test_config_params['parent_got_revision'], | 296 build_revision=test_config_params['parent_got_revision'], |
297 override_bot_type='tester') | 297 override_bot_type='tester') |
298 | 298 |
299 tests = [self.m.chromium_tests.steps.BisectTest(test_config_params)] | 299 tests = [ |
| 300 self.m.chromium_tests.steps.BisectTest( |
| 301 test_config_params, **kwargs)] |
300 | 302 |
301 if not tests: # pragma: no cover | 303 if not tests: # pragma: no cover |
302 return | 304 return |
303 self.m.chromium_swarming.configure_swarming( | 305 self.m.chromium_swarming.configure_swarming( |
304 'chromium', precommit=False, mastername=mastername) | 306 'chromium', precommit=False, mastername=mastername) |
305 test_runner = self.m.chromium_tests.create_test_runner(self.m, tests) | 307 test_runner = self.m.chromium_tests.create_test_runner(self.m, tests) |
306 | 308 |
307 bot_config_object = self.m.chromium_tests.create_bot_config_object( | 309 bot_config_object = self.m.chromium_tests.create_bot_config_object( |
308 mastername, buildername) | 310 mastername, buildername) |
309 with self.m.chromium_tests.wrap_chromium_tests(bot_config_object, tests): | 311 with self.m.chromium_tests.wrap_chromium_tests(bot_config_object, tests): |
310 if self.m.chromium.c.TARGET_PLATFORM == 'android' and not skip_download: | 312 if self.m.chromium.c.TARGET_PLATFORM == 'android' and not skip_download: |
311 deploy_apks = [] | 313 deploy_apks = [] |
312 deploy_args = [] | 314 deploy_args = [] |
313 if self.internal_bisect: # pragma: no cover | 315 if self.internal_bisect: # pragma: no cover |
314 deploy_args = list(bot_config['deploy_args']) | 316 deploy_args = list(bot_config['deploy_args']) |
315 deploy_apks = bot_config.get('deploy_apks') | 317 deploy_apks = bot_config.get('deploy_apks') |
316 if deploy_apks: | 318 if deploy_apks: |
317 deploy_args.extend([ | 319 deploy_args.extend([ |
318 '--apks', | 320 '--apks', |
319 ','.join(str(self.m.chromium_android.apk_path(apk)) | 321 ','.join(str(self.m.chromium_android.apk_path(apk)) |
320 for apk in deploy_apks)]) | 322 for apk in deploy_apks)]) |
321 else: | 323 else: |
322 if bot_config.get('webview'): | 324 if bot_config.get('webview'): |
323 deploy_apks = ['SystemWebView.apk', 'SystemWebViewShell.apk'] | 325 deploy_apks = ['SystemWebView.apk', 'SystemWebViewShell.apk'] |
324 else: | 326 else: |
325 deploy_apks = ['ChromePublic.apk'] | 327 deploy_apks = ['ChromePublic.apk'] |
326 self.deploy_apk_on_device( | 328 self.deploy_apk_on_device( |
327 self.full_deploy_script, deploy_apks, deploy_args) | 329 self.full_deploy_script, deploy_apks, deploy_args) |
328 test_runner() | 330 test_runner() |
| 331 return tests[0].run_results |
329 | 332 |
330 def deploy_apk_on_device(self, deploy_script, deploy_apks, deploy_args): | 333 def deploy_apk_on_device(self, deploy_script, deploy_apks, deploy_args): |
331 """Installs apk on the android device.""" | 334 """Installs apk on the android device.""" |
332 if deploy_script: # pragma: no cover | 335 if deploy_script: # pragma: no cover |
333 self.full_deploy_on_device(deploy_script, deploy_args) | 336 self.full_deploy_on_device(deploy_script, deploy_args) |
334 else: | 337 else: |
335 for apk in deploy_apks: | 338 for apk in deploy_apks: |
336 self.m.chromium_android.adb_install_apk(apk) | 339 self.m.chromium_android.adb_install_apk(apk) |
337 | 340 |
338 def full_deploy_on_device(self, deploy_script, args=None): # pragma: no cover | 341 def full_deploy_on_device(self, deploy_script, args=None): # pragma: no cover |
(...skipping 29 matching lines...) Expand all Loading... |
368 api: The recipe api object. | 371 api: The recipe api object. |
369 update_step: Extra update_step to, used for some job types. | 372 update_step: Extra update_step to, used for some job types. |
370 bot_db: A BotConfigAndTestDB object, used for some job types. | 373 bot_db: A BotConfigAndTestDB object, used for some job types. |
371 kwargs: Args to use only for legacy bisect. | 374 kwargs: Args to use only for legacy bisect. |
372 """ | 375 """ |
373 flags = {} | 376 flags = {} |
374 if kwargs.get('do_not_nest_wait_for_revision'): | 377 if kwargs.get('do_not_nest_wait_for_revision'): |
375 flags['do_not_nest_wait_for_revision'] = kwargs.pop( | 378 flags['do_not_nest_wait_for_revision'] = kwargs.pop( |
376 'do_not_nest_wait_for_revision') | 379 'do_not_nest_wait_for_revision') |
377 if bot_db is None: # pragma: no cover | 380 if bot_db is None: # pragma: no cover |
378 self.bot_db = api.chromium_tests.create_bot_db_from_master_dict( | 381 self.bot_db = api.chromium_tests.create_bot_db_from_master_dict('', None) |
379 '', None, None) | |
380 else: | 382 else: |
381 self.bot_db = bot_db | 383 self.bot_db = bot_db |
382 | 384 |
383 context = {} | 385 context = {} |
384 if self.working_dir: | 386 if self.working_dir: |
385 context['cwd'] = self.working_dir | 387 context['cwd'] = self.working_dir |
386 | 388 |
387 with api.step.context(context): | 389 with api.step.context(context): |
388 affected_files = self.m.tryserver.get_files_affected_by_patch() | 390 affected_files = self.m.tryserver.get_files_affected_by_patch() |
389 # Skip device setup for internal bisect as it is taken care in | 391 # Skip device setup for internal bisect as it is taken care in |
(...skipping 24 matching lines...) Expand all Loading... |
414 affected_files, update_step, self.bot_db) | 416 affected_files, update_step, self.bot_db) |
415 finally: | 417 finally: |
416 if api.chromium.c.TARGET_PLATFORM == 'android': | 418 if api.chromium.c.TARGET_PLATFORM == 'android': |
417 if self.internal_bisect: # pragma: no cover | 419 if self.internal_bisect: # pragma: no cover |
418 api.chromium_android.init_and_sync( | 420 api.chromium_android.init_and_sync( |
419 gclient_config=api.chromium_android.c.internal_dir_name, | 421 gclient_config=api.chromium_android.c.internal_dir_name, |
420 use_bot_update=True) | 422 use_bot_update=True) |
421 else: | 423 else: |
422 self.ensure_checkout() | 424 self.ensure_checkout() |
423 api.chromium_android.common_tests_final_steps() | 425 api.chromium_android.common_tests_final_steps() |
| 426 |
| 427 def stat_compare(self, values_a, values_b, metric, |
| 428 output_format='chartjson', **kwargs): |
| 429 """Compares samples using catapult's statistics implementation. |
| 430 |
| 431 Args: |
| 432 values_a, values_b: lists of paths to the json files containing the values |
| 433 produced by the test. |
| 434 metric: the name of the metric as sent by dashboard. |
| 435 output_format: either 'chartjson' or 'valueset' |
| 436 |
| 437 Returns: |
| 438 a dict containing 'result' which may be True, False or 'needMoreData', as |
| 439 well as details about each sample ('debug_values', 'mean' and 'std_dev'). |
| 440 |
| 441 """ |
| 442 args = [','.join(map(str, values_a)), |
| 443 ','.join(map(str, values_b)), |
| 444 metric, |
| 445 '--' + output_format] |
| 446 |
| 447 script = self.m.path['catapult'].join( |
| 448 'tracing', 'bin', 'compare_samples') |
| 449 return self.m.python( |
| 450 'Compare samples', |
| 451 script=script, |
| 452 args=args, |
| 453 stdout=self.m.json.output(), |
| 454 **kwargs).stdout |
OLD | NEW |