| 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 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 | 696 |
| 697 # Show any remaining isolated outputs (such as logcats). | 697 # Show any remaining isolated outputs (such as logcats). |
| 698 # Note that collect_gtest_task.py uses the default summary.json, which | 698 # Note that collect_gtest_task.py uses the default summary.json, which |
| 699 # only has 'outputs_ref' instead of the deprecated 'isolated_out'. | 699 # only has 'outputs_ref' instead of the deprecated 'isolated_out'. |
| 700 for index, shard in enumerate(swarming_summary.get('shards', [])): | 700 for index, shard in enumerate(swarming_summary.get('shards', [])): |
| 701 outputs_ref = shard.get('outputs_ref') | 701 outputs_ref = shard.get('outputs_ref') |
| 702 if outputs_ref: | 702 if outputs_ref: |
| 703 link_name = 'shard #%d isolated out' % index | 703 link_name = 'shard #%d isolated out' % index |
| 704 p.links[link_name] = outputs_ref['view_url'] | 704 p.links[link_name] = outputs_ref['view_url'] |
| 705 | 705 |
| 706 |
| 707 def _merge_isolated_script_shards(self, task, step_result): |
| 708 # This code is unfortunately specialized to the "simplified" |
| 709 # JSON format that used to be the standard for recipes. The |
| 710 # isolated scripts should be changed to use the now-standard |
| 711 # Chromium JSON test results format: |
| 712 # https://www.chromium.org/developers/the-json-test-results-format |
| 713 # . Note that gtests, above, don't seem to conform to this |
| 714 # format yet, so it didn't seem like a good prerequisite to |
| 715 # switch the isolated tests over when adding sharding support. |
| 716 # |
| 717 # These are the only keys we pay attention to in the output JSON. |
| 718 merged_results = { |
| 719 'successes': [], |
| 720 'failures': [], |
| 721 'valid': True, |
| 722 } |
| 723 for i in xrange(task.shards): |
| 724 path = self.m.path.join(str(i), 'output.json') |
| 725 if path not in step_result.raw_io.output_dir: |
| 726 raise Exception('no results from shard #%d' % i) |
| 727 results_raw = step_result.raw_io.output_dir[path] |
| 728 results_json = self.m.json.loads(results_raw) |
| 729 for key in merged_results: |
| 730 if key in results_json: |
| 731 if isinstance(merged_results[key], list): |
| 732 merged_results[key].extend(results_json[key]) |
| 733 elif isinstance(merged_results[key], bool): |
| 734 merged_results[key] = merged_results[key] and results_json[key] |
| 735 else: |
| 736 raise recipe_api.InfraFailure( |
| 737 'Unknown key type ' + type(merged_results[key]) + |
| 738 ' when handling key ' + key + '.') # pragma: no cover |
| 739 return merged_results |
| 740 |
| 706 def _isolated_script_collect_step(self, task, **kwargs): | 741 def _isolated_script_collect_step(self, task, **kwargs): |
| 707 step_test_data = kwargs.pop('step_test_data', None) | 742 step_test_data = kwargs.pop('step_test_data', None) |
| 708 if not step_test_data: | 743 if not step_test_data: |
| 709 step_test_data = self.m.test_utils.test_api.canned_isolated_script_output( | 744 step_test_data = self.m.test_utils.test_api.canned_isolated_script_output( |
| 710 passing=True, is_win=self.m.platform.is_win, swarming=True) | 745 passing=True, is_win=self.m.platform.is_win, swarming=True) |
| 711 | 746 |
| 712 args=self.get_collect_cmd_args(task) | 747 args=self.get_collect_cmd_args(task) |
| 713 args.extend(['--task-output-dir', self.m.raw_io.output_dir()]) | 748 args.extend(['--task-output-dir', self.m.raw_io.output_dir()]) |
| 714 | 749 |
| 715 try: | 750 try: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 729 step_result = self.m.step.active_result | 764 step_result = self.m.step.active_result |
| 730 outdir_json = self.m.json.dumps(step_result.raw_io.output_dir, indent=2) | 765 outdir_json = self.m.json.dumps(step_result.raw_io.output_dir, indent=2) |
| 731 step_result.presentation.logs['outdir_json'] = outdir_json.splitlines() | 766 step_result.presentation.logs['outdir_json'] = outdir_json.splitlines() |
| 732 | 767 |
| 733 # Check if it's an internal failure. | 768 # Check if it's an internal failure. |
| 734 summary = self.m.json.loads( | 769 summary = self.m.json.loads( |
| 735 step_result.raw_io.output_dir['summary.json']) | 770 step_result.raw_io.output_dir['summary.json']) |
| 736 if any(shard['internal_failure'] for shard in summary['shards']): | 771 if any(shard['internal_failure'] for shard in summary['shards']): |
| 737 raise recipe_api.InfraFailure('Internal swarming failure.') | 772 raise recipe_api.InfraFailure('Internal swarming failure.') |
| 738 | 773 |
| 739 # TODO(nednguyen, kbr): Combine isolated script results from multiple | 774 # Always show the shards' links in the collect step. (It looks |
| 740 # shards rather than assuming that there is always just one shard. | 775 # like show_isolated_out_in_collect_step is false by default |
| 741 assert len(summary['shards']) == 1 | 776 # in recipe runs.) |
| 742 results_raw = step_result.raw_io.output_dir[ | 777 links = step_result.presentation.links |
| 743 self.m.path.join('0', 'output.json')] | 778 for index in xrange(task.shards): |
| 744 step_result.isolated_script_results = self.m.json.loads(results_raw) | 779 url = task.get_shard_view_url(index) |
| 780 if url: |
| 781 links['shard #%d' % index] = url |
| 782 |
| 783 step_result.isolated_script_results = \ |
| 784 self._merge_isolated_script_shards(task, step_result) |
| 745 | 785 |
| 746 self._display_pending(summary, step_result.presentation) | 786 self._display_pending(summary, step_result.presentation) |
| 747 except Exception as e: | 787 except Exception as e: |
| 748 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)] | 788 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)] |
| 749 self.m.step.active_result.isolated_script_results = None | 789 self.m.step.active_result.isolated_script_results = None |
| 750 | 790 |
| 751 def _get_step_name(self, prefix, task): | 791 def _get_step_name(self, prefix, task): |
| 752 """SwarmingTask -> name of a step of a waterfall. | 792 """SwarmingTask -> name of a step of a waterfall. |
| 753 | 793 |
| 754 Will take a task title (+ step name prefix) and append OS dimension to it. | 794 Will take a task title (+ step name prefix) and append OS dimension to it. |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 | 968 |
| 929 def get_shard_view_url(self, index): | 969 def get_shard_view_url(self, index): |
| 930 """Returns URL of HTML page with shard details or None if not available. | 970 """Returns URL of HTML page with shard details or None if not available. |
| 931 | 971 |
| 932 Works only after the task has been successfully triggered. | 972 Works only after the task has been successfully triggered. |
| 933 """ | 973 """ |
| 934 if self._trigger_output and self._trigger_output.get('tasks'): | 974 if self._trigger_output and self._trigger_output.get('tasks'): |
| 935 for shard_dict in self._trigger_output['tasks'].itervalues(): | 975 for shard_dict in self._trigger_output['tasks'].itervalues(): |
| 936 if shard_dict['shard_index'] == index: | 976 if shard_dict['shard_index'] == index: |
| 937 return shard_dict['view_url'] | 977 return shard_dict['view_url'] |
| OLD | NEW |