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 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 330 # idempotent. As of this writing, Telemetry itself downloads some | 330 # idempotent. As of this writing, Telemetry itself downloads some |
| 331 # data from remote servers; additionally, some tests like the | 331 # data from remote servers; additionally, some tests like the |
| 332 # pixel_tests download reference images from cloud storage. It's | 332 # pixel_tests download reference images from cloud storage. It's |
| 333 # safest to assume that these tests aren't idempotent, though we | 333 # safest to assume that these tests aren't idempotent, though we |
| 334 # should work toward making them so. | 334 # should work toward making them so. |
| 335 task = self.task(title, isolated_hash, extra_args=extra_args, | 335 task = self.task(title, isolated_hash, extra_args=extra_args, |
| 336 idempotent=False, **kwargs) | 336 idempotent=False, **kwargs) |
| 337 task.collect_step = self._telemetry_gpu_collect_step | 337 task.collect_step = self._telemetry_gpu_collect_step |
| 338 return task | 338 return task |
| 339 | 339 |
| 340 def isolated_script_task(self, title, isolated_hash, extra_args=None, | |
| 341 idempotent=None, **kwargs): | |
| 342 """Returns a new SwarmingTask to run an isolated script test on Swarming. | |
| 343 | |
| 344 Swarming recipe module knows how collect JSON file with test execution | |
| 345 summary produced by isolated script tests launcher. Since isolated script | |
| 346 tests do not support sharding, no merging of the results is performed. | |
| 347 Parsed JSON summary is returned from the collect step. | |
| 348 | |
| 349 For meaning of the rest of the arguments see 'task' method. | |
| 350 """ | |
| 351 extra_args = list(extra_args or []) | |
| 352 | |
| 353 # Ensure --isolated-script-test-output is not already passed. We are going | |
| 354 # to overwrite it. | |
| 355 bad_args = any( | |
| 356 x.startswith('--isolated-script-test-output=') for x in extra_args) | |
| 357 if bad_args: # pragma: no cover | |
| 358 raise ValueError('--isolated-script-test-output should not be used.') | |
| 359 | |
| 360 # Append it. output.json name is expected by collect_gtest_task.py. | |
| 361 extra_args.append( | |
| 362 '--isolated-script-test-output=${ISOLATED_OUTDIR}/output.json') | |
| 363 | |
| 364 task = self.task(title, isolated_hash, extra_args=extra_args, | |
| 365 idempotent=idempotent, **kwargs) | |
| 366 task.collect_step = self._isolated_script_collect_step | |
| 367 return task | |
| 368 | |
| 340 def check_client_version(self, step_test_data=None): | 369 def check_client_version(self, step_test_data=None): |
| 341 """Yields steps to verify compatibility with swarming_client version.""" | 370 """Yields steps to verify compatibility with swarming_client version.""" |
| 342 return self.m.swarming_client.ensure_script_version( | 371 return self.m.swarming_client.ensure_script_version( |
| 343 'swarming.py', MINIMAL_SWARMING_VERSION, step_test_data) | 372 'swarming.py', MINIMAL_SWARMING_VERSION, step_test_data) |
| 344 | 373 |
| 345 def trigger_task(self, task, **kwargs): | 374 def trigger_task(self, task, **kwargs): |
| 346 """Triggers one task. | 375 """Triggers one task. |
| 347 | 376 |
| 348 It the task is sharded, will trigger all shards. This steps justs posts | 377 It the task is sharded, will trigger all shards. This steps justs posts |
| 349 the task and immediately returns. Use 'collect_task' to wait for a task to | 378 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... | |
| 638 if step_result.retcode == 0 and results_raw == '': | 667 if step_result.retcode == 0 and results_raw == '': |
| 639 step_result.telemetry_results = {'per_page_values': [], 'pages': []} | 668 step_result.telemetry_results = {'per_page_values': [], 'pages': []} |
| 640 else: | 669 else: |
| 641 step_result.telemetry_results = self.m.json.loads(results_raw) | 670 step_result.telemetry_results = self.m.json.loads(results_raw) |
| 642 | 671 |
| 643 self._display_pending(summary, step_result.presentation) | 672 self._display_pending(summary, step_result.presentation) |
| 644 except Exception as e: | 673 except Exception as e: |
| 645 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)] | 674 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)] |
| 646 self.m.step.active_result.telemetry_results = None | 675 self.m.step.active_result.telemetry_results = None |
| 647 | 676 |
| 677 def _isolated_script_collect_step(self, task, **kwargs): | |
| 678 step_test_data = kwargs.pop('step_test_data', None) | |
| 679 if not step_test_data: | |
| 680 step_test_data = self.m.test_utils.test_api.canned_isolated_script_output( | |
| 681 passing=True, is_win=self.m.platform.is_win, swarming=True) | |
| 682 | |
| 683 args=self.get_collect_cmd_args(task) | |
| 684 args.extend(['--task-output-dir', self.m.raw_io.output_dir()]) | |
| 685 | |
| 686 try: | |
| 687 self.m.python( | |
| 688 name=self._get_step_name('', task), | |
| 689 script=self.m.swarming_client.path.join('swarming.py'), | |
| 690 args=args, step_test_data=lambda: step_test_data, | |
| 691 **kwargs) | |
| 692 finally: | |
| 693 # Regardless of the outcome of the test (pass or fail), we try to parse | |
| 694 # the results. If any error occurs while parsing results, then we set them | |
| 695 # to None, which will be treated as invalid test results by | |
| 696 # SwarmingTelemetryGPUTest class in recipe_modules/chromium/steps.py. Note | |
|
Paweł Hajdan Jr.
2015/10/26 17:00:41
Why does this refer to a specific class? There may
Ken Russell (switch to Gerrit)
2015/10/26 21:35:13
I suspect this is just a leftover comment.
nednguyen
2015/10/27 00:54:29
Done.
Paweł Hajdan Jr.
2015/10/27 11:12:52
It's better now, but I'd still prefer these refere
nednguyen
2015/10/27 16:36:48
Done.
| |
| 697 # that try-except block below will not mask the recipe_api.StepFailure | |
| 698 # exception from the collect step above. Instead it is being allowed to | |
| 699 # propagate after the results have been parsed. | |
| 700 try: | |
| 701 step_result = self.m.step.active_result | |
| 702 outdir_json = self.m.json.dumps(step_result.raw_io.output_dir, indent=2) | |
| 703 step_result.presentation.logs['outdir_json'] = outdir_json.splitlines() | |
| 704 | |
| 705 # Check if it's an internal failure. | |
| 706 summary = self.m.json.loads( | |
| 707 step_result.raw_io.output_dir['summary.json']) | |
| 708 if any(shard['internal_failure'] for shard in summary['shards']): | |
| 709 raise recipe_api.InfraFailure('Internal swarming failure.') | |
| 710 | |
| 711 # TODO(nednguyen, kbr): Combine isolated script results from multiple | |
| 712 # shards rather than assuming that there is always just one shard. | |
| 713 assert len(summary['shards']) == 1 | |
| 714 results_raw = step_result.raw_io.output_dir[ | |
| 715 self.m.path.join('0', 'output.json')] | |
| 716 step_result.isolated_script_results = self.m.json.loads(results_raw) | |
| 717 | |
| 718 self._display_pending(summary, step_result.presentation) | |
| 719 except Exception as e: | |
| 720 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)] | |
| 721 self.m.step.active_result.telemetry_results = None | |
| 648 | 722 |
| 649 def _get_step_name(self, prefix, task): | 723 def _get_step_name(self, prefix, task): |
| 650 """SwarmingTask -> name of a step of a waterfall. | 724 """SwarmingTask -> name of a step of a waterfall. |
| 651 | 725 |
| 652 Will take a task title (+ step name prefix) and optionally append | 726 Will take a task title (+ step name prefix) and optionally append |
| 653 OS dimension to it in case the task is triggered on OS that is different | 727 OS dimension to it in case the task is triggered on OS that is different |
| 654 from OS this recipe is running on. It shortens step names for the most | 728 from OS this recipe is running on. It shortens step names for the most |
| 655 common case of triggering a task on the same OS as one that recipe | 729 common case of triggering a task on the same OS as one that recipe |
| 656 is running on. | 730 is running on. |
| 657 | 731 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 827 | 901 |
| 828 def get_shard_view_url(self, index): | 902 def get_shard_view_url(self, index): |
| 829 """Returns URL of HTML page with shard details or None if not available. | 903 """Returns URL of HTML page with shard details or None if not available. |
| 830 | 904 |
| 831 Works only after the task has been successfully triggered. | 905 Works only after the task has been successfully triggered. |
| 832 """ | 906 """ |
| 833 if self._trigger_output and self._trigger_output.get('tasks'): | 907 if self._trigger_output and self._trigger_output.get('tasks'): |
| 834 for shard_dict in self._trigger_output['tasks'].itervalues(): | 908 for shard_dict in self._trigger_output['tasks'].itervalues(): |
| 835 if shard_dict['shard_index'] == index: | 909 if shard_dict['shard_index'] == index: |
| 836 return shard_dict['view_url'] | 910 return shard_dict['view_url'] |
| OLD | NEW |