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 logging | 5 import logging |
6 import datetime | 6 import datetime |
7 import functools | 7 import functools |
8 | 8 |
9 from recipe_engine import recipe_api | 9 from recipe_engine import recipe_api |
10 | 10 |
| 11 from . import results_merger |
11 | 12 |
12 # Minimally supported version of swarming.py script (reported by --version). | 13 # Minimally supported version of swarming.py script (reported by --version). |
13 MINIMAL_SWARMING_VERSION = (0, 8, 6) | 14 MINIMAL_SWARMING_VERSION = (0, 8, 6) |
14 | 15 |
15 | 16 |
16 def parse_time(value): | 17 def parse_time(value): |
17 """Converts serialized time from the API to datetime.datetime.""" | 18 """Converts serialized time from the API to datetime.datetime.""" |
18 # When microseconds are 0, the '.123456' suffix is elided. This means the | 19 # When microseconds are 0, the '.123456' suffix is elided. This means the |
19 # serialized format is not consistent, which confuses the hell out of python. | 20 # serialized format is not consistent, which confuses the hell out of python. |
20 # TODO(maruel): Remove third format once we enforce version >=0.8.2. | 21 # TODO(maruel): Remove third format once we enforce version >=0.8.2. |
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 merged_results = chartjson_results_json | 764 merged_results = chartjson_results_json |
764 seen_first_shard = True | 765 seen_first_shard = True |
765 continue | 766 continue |
766 for key in chartjson_results_json: | 767 for key in chartjson_results_json: |
767 if key == 'charts': | 768 if key == 'charts': |
768 # Append each additional chart to our merged results | 769 # Append each additional chart to our merged results |
769 for add_key in chartjson_results_json[key]: | 770 for add_key in chartjson_results_json[key]: |
770 merged_results[key][add_key] = chartjson_results_json[key][add_key] | 771 merged_results[key][add_key] = chartjson_results_json[key][add_key] |
771 return merged_results | 772 return merged_results |
772 | 773 |
| 774 def _merge_isolated_script_shards(self, task, step_result): |
773 | 775 |
774 def _merge_isolated_script_shards(self, task, step_result): | 776 shard_results_list = [] |
775 # This code is unfortunately specialized to the "simplified" | |
776 # JSON format that used to be the standard for recipes. The | |
777 # isolated scripts should be changed to use the now-standard | |
778 # Chromium JSON test results format: | |
779 # https://www.chromium.org/developers/the-json-test-results-format | |
780 # . Note that gtests, above, don't seem to conform to this | |
781 # format yet, so it didn't seem like a good prerequisite to | |
782 # switch the isolated tests over when adding sharding support. | |
783 # | |
784 # These are the only keys we pay attention to in the output JSON. | |
785 merged_results = { | |
786 'successes': [], | |
787 'failures': [], | |
788 'valid': True, | |
789 } | |
790 for i in xrange(task.shards): | 777 for i in xrange(task.shards): |
791 path = self.m.path.join(str(i), 'output.json') | 778 path = self.m.path.join(str(i), 'output.json') |
792 if path not in step_result.raw_io.output_dir: | 779 if path not in step_result.raw_io.output_dir: |
793 raise Exception('no results from shard #%d' % i) | 780 raise Exception('no results from shard #%d' % i) |
794 results_raw = step_result.raw_io.output_dir[path] | 781 results_raw = step_result.raw_io.output_dir[path] |
795 try: | 782 try: |
796 results_json = self.m.json.loads(results_raw) | 783 results_json = self.m.json.loads(results_raw) |
| 784 shard_results_list.append(results_json) |
797 except Exception as e: | 785 except Exception as e: |
798 raise Exception('error decoding JSON results from shard #%d' % i) | 786 raise Exception('error decoding JSON results from shard #%d' % i) |
799 for key in merged_results: | 787 if not shard_results_list: |
800 if key in results_json: | 788 raise Exception('No shard results created') |
801 if isinstance(merged_results[key], list): | 789 return results_merger.merge_test_results(shard_results_list) |
802 merged_results[key].extend(results_json[key]) | |
803 elif isinstance(merged_results[key], bool): | |
804 merged_results[key] = merged_results[key] and results_json[key] | |
805 else: | |
806 raise recipe_api.InfraFailure( | |
807 'Unknown key type ' + type(merged_results[key]) + | |
808 ' when handling key ' + key + '.') # pragma: no cover | |
809 return merged_results | |
810 | 790 |
811 def _isolated_script_collect_step(self, task, **kwargs): | 791 def _isolated_script_collect_step(self, task, **kwargs): |
812 step_test_data = kwargs.pop('step_test_data', None) | 792 step_test_data = kwargs.pop('step_test_data', None) |
813 if not step_test_data: | 793 if not step_test_data: |
814 step_test_data = self.m.test_utils.test_api.canned_isolated_script_output( | 794 step_test_data = self.m.test_utils.test_api.canned_isolated_script_output( |
815 passing=True, is_win=self.m.platform.is_win, swarming=True) | 795 passing=True, is_win=self.m.platform.is_win, swarming=True) |
816 | 796 |
817 args=self.get_collect_cmd_args(task) | 797 args=self.get_collect_cmd_args(task) |
818 args.extend(['--task-output-dir', self.m.raw_io.output_dir()]) | 798 args.extend(['--task-output-dir', self.m.raw_io.output_dir()]) |
819 | 799 |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 | 1032 |
1053 def get_shard_view_url(self, index): | 1033 def get_shard_view_url(self, index): |
1054 """Returns URL of HTML page with shard details or None if not available. | 1034 """Returns URL of HTML page with shard details or None if not available. |
1055 | 1035 |
1056 Works only after the task has been successfully triggered. | 1036 Works only after the task has been successfully triggered. |
1057 """ | 1037 """ |
1058 if self._trigger_output and self._trigger_output.get('tasks'): | 1038 if self._trigger_output and self._trigger_output.get('tasks'): |
1059 for shard_dict in self._trigger_output['tasks'].itervalues(): | 1039 for shard_dict in self._trigger_output['tasks'].itervalues(): |
1060 if shard_dict['shard_index'] == index: | 1040 if shard_dict['shard_index'] == index: |
1061 return shard_dict['view_url'] | 1041 return shard_dict['view_url'] |
OLD | NEW |