Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 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 datetime | 5 import datetime |
| 6 import functools | 6 import functools |
| 7 | 7 |
| 8 from recipe_engine.types import freeze | 8 from recipe_engine.types import freeze |
| 9 from recipe_engine import recipe_api | 9 from recipe_engine import recipe_api |
| 10 | 10 |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 # idempotent. As of this writing, Telemetry itself downloads some | 339 # idempotent. As of this writing, Telemetry itself downloads some |
| 340 # data from remote servers; additionally, some tests like the | 340 # data from remote servers; additionally, some tests like the |
| 341 # pixel_tests download reference images from cloud storage. It's | 341 # pixel_tests download reference images from cloud storage. It's |
| 342 # safest to assume that these tests aren't idempotent, though we | 342 # safest to assume that these tests aren't idempotent, though we |
| 343 # should work toward making them so. | 343 # should work toward making them so. |
| 344 task = self.task(title, isolated_hash, extra_args=extra_args, | 344 task = self.task(title, isolated_hash, extra_args=extra_args, |
| 345 idempotent=False, **kwargs) | 345 idempotent=False, **kwargs) |
| 346 task.collect_step = self._telemetry_gpu_collect_step | 346 task.collect_step = self._telemetry_gpu_collect_step |
| 347 return task | 347 return task |
| 348 | 348 |
| 349 def isolated_script_task(self, title, isolated_hash, extra_args=None, | |
| 350 idempotent=False, **kwargs): | |
|
nednguyen
2015/10/27 00:58:09
Pawel: changing the default of this from False to
Paweł Hajdan Jr.
2015/10/27 11:12:52
False makes sense to me. I don't see any _existing
| |
| 351 """Returns a new SwarmingTask to run an isolated script test on Swarming. | |
| 352 | |
| 353 Swarming recipe module knows how collect JSON file with test execution | |
| 354 summary produced by isolated script tests launcher. Since isolated script | |
| 355 tests do not support sharding, no merging of the results is performed. | |
| 356 Parsed JSON summary is returned from the collect step. | |
| 357 | |
| 358 For meaning of the rest of the arguments see 'task' method. | |
| 359 """ | |
| 360 extra_args = list(extra_args or []) | |
| 361 | |
| 362 # Ensure --isolated-script-test-output is not already passed. We are going | |
| 363 # to overwrite it. | |
| 364 bad_args = any( | |
| 365 x.startswith('--isolated-script-test-output=') for x in extra_args) | |
| 366 if bad_args: # pragma: no cover | |
| 367 raise ValueError('--isolated-script-test-output should not be used.') | |
| 368 | |
| 369 # Append it. output.json name is expected by collect_gtest_task.py. | |
| 370 extra_args.append( | |
| 371 '--isolated-script-test-output=${ISOLATED_OUTDIR}/output.json') | |
| 372 | |
| 373 task = self.task(title, isolated_hash, extra_args=extra_args, | |
| 374 idempotent=idempotent, **kwargs) | |
| 375 task.collect_step = self._isolated_script_collect_step | |
| 376 return task | |
| 377 | |
| 349 def check_client_version(self, step_test_data=None): | 378 def check_client_version(self, step_test_data=None): |
| 350 """Yields steps to verify compatibility with swarming_client version.""" | 379 """Yields steps to verify compatibility with swarming_client version.""" |
| 351 return self.m.swarming_client.ensure_script_version( | 380 return self.m.swarming_client.ensure_script_version( |
| 352 'swarming.py', MINIMAL_SWARMING_VERSION, step_test_data) | 381 'swarming.py', MINIMAL_SWARMING_VERSION, step_test_data) |
| 353 | 382 |
| 354 def trigger_task(self, task, **kwargs): | 383 def trigger_task(self, task, **kwargs): |
| 355 """Triggers one task. | 384 """Triggers one task. |
| 356 | 385 |
| 357 It the task is sharded, will trigger all shards. This steps justs posts | 386 It the task is sharded, will trigger all shards. This steps justs posts |
| 358 the task and immediately returns. Use 'collect_task' to wait for a task to | 387 the task and immediately returns. Use 'collect_task' to wait for a task to |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 if step_result.retcode == 0 and results_raw == '': | 676 if step_result.retcode == 0 and results_raw == '': |
| 648 step_result.telemetry_results = {'per_page_values': [], 'pages': []} | 677 step_result.telemetry_results = {'per_page_values': [], 'pages': []} |
| 649 else: | 678 else: |
| 650 step_result.telemetry_results = self.m.json.loads(results_raw) | 679 step_result.telemetry_results = self.m.json.loads(results_raw) |
| 651 | 680 |
| 652 self._display_pending(summary, step_result.presentation) | 681 self._display_pending(summary, step_result.presentation) |
| 653 except Exception as e: | 682 except Exception as e: |
| 654 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)] | 683 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)] |
| 655 self.m.step.active_result.telemetry_results = None | 684 self.m.step.active_result.telemetry_results = None |
| 656 | 685 |
| 686 def _isolated_script_collect_step(self, task, **kwargs): | |
| 687 step_test_data = kwargs.pop('step_test_data', None) | |
| 688 if not step_test_data: | |
| 689 step_test_data = self.m.test_utils.test_api.canned_isolated_script_output( | |
| 690 passing=True, is_win=self.m.platform.is_win, swarming=True) | |
| 691 | |
| 692 args=self.get_collect_cmd_args(task) | |
| 693 args.extend(['--task-output-dir', self.m.raw_io.output_dir()]) | |
| 694 | |
| 695 try: | |
| 696 self.m.python( | |
| 697 name=self._get_step_name('', task), | |
| 698 script=self.m.swarming_client.path.join('swarming.py'), | |
| 699 args=args, step_test_data=lambda: step_test_data, | |
| 700 **kwargs) | |
| 701 finally: | |
| 702 # Regardless of the outcome of the test (pass or fail), we try to parse | |
| 703 # the results. If any error occurs while parsing results, then we set them | |
| 704 # to None, which will be treated as invalid test results by | |
| 705 # SwarmingIsolatedScriptTest class in recipe_modules/chromium/steps.py. | |
| 706 # Note that try-except block below will not mask the | |
| 707 # recipe_api.StepFailure exception from the collect step above. Instead | |
| 708 # it is being allowed to propagate after the results have been parsed. | |
| 709 try: | |
| 710 step_result = self.m.step.active_result | |
| 711 outdir_json = self.m.json.dumps(step_result.raw_io.output_dir, indent=2) | |
| 712 step_result.presentation.logs['outdir_json'] = outdir_json.splitlines() | |
| 713 | |
| 714 # Check if it's an internal failure. | |
| 715 summary = self.m.json.loads( | |
| 716 step_result.raw_io.output_dir['summary.json']) | |
| 717 if any(shard['internal_failure'] for shard in summary['shards']): | |
| 718 raise recipe_api.InfraFailure('Internal swarming failure.') | |
| 719 | |
| 720 # TODO(nednguyen, kbr): Combine isolated script results from multiple | |
| 721 # shards rather than assuming that there is always just one shard. | |
| 722 assert len(summary['shards']) == 1 | |
| 723 results_raw = step_result.raw_io.output_dir[ | |
| 724 self.m.path.join('0', 'output.json')] | |
| 725 step_result.isolated_script_results = self.m.json.loads(results_raw) | |
| 726 | |
| 727 self._display_pending(summary, step_result.presentation) | |
| 728 except Exception as e: | |
| 729 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)] | |
| 730 self.m.step.active_result.telemetry_results = None | |
| 657 | 731 |
| 658 def _get_step_name(self, prefix, task): | 732 def _get_step_name(self, prefix, task): |
| 659 """SwarmingTask -> name of a step of a waterfall. | 733 """SwarmingTask -> name of a step of a waterfall. |
| 660 | 734 |
| 661 Will take a task title (+ step name prefix) and optionally append | 735 Will take a task title (+ step name prefix) and optionally append |
| 662 OS dimension to it in case the task is triggered on OS that is different | 736 OS dimension to it in case the task is triggered on OS that is different |
| 663 from OS this recipe is running on. It shortens step names for the most | 737 from OS this recipe is running on. It shortens step names for the most |
| 664 common case of triggering a task on the same OS as one that recipe | 738 common case of triggering a task on the same OS as one that recipe |
| 665 is running on. | 739 is running on. |
| 666 | 740 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 836 | 910 |
| 837 def get_shard_view_url(self, index): | 911 def get_shard_view_url(self, index): |
| 838 """Returns URL of HTML page with shard details or None if not available. | 912 """Returns URL of HTML page with shard details or None if not available. |
| 839 | 913 |
| 840 Works only after the task has been successfully triggered. | 914 Works only after the task has been successfully triggered. |
| 841 """ | 915 """ |
| 842 if self._trigger_output and self._trigger_output.get('tasks'): | 916 if self._trigger_output and self._trigger_output.get('tasks'): |
| 843 for shard_dict in self._trigger_output['tasks'].itervalues(): | 917 for shard_dict in self._trigger_output['tasks'].itervalues(): |
| 844 if shard_dict['shard_index'] == index: | 918 if shard_dict['shard_index'] == index: |
| 845 return shard_dict['view_url'] | 919 return shard_dict['view_url'] |
| OLD | NEW |