| 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 |