Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: scripts/slave/recipe_modules/swarming/api.py

Issue 2073923002: Support sharding for swarmed isolated script tests. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Add test for a shard failing to produce output.json. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 results_raw = step_result.raw_io.output_dir[
Vadim Sh. 2016/06/17 00:31:11 I think at the very minimum we can acknowledge in
725 self.m.path.join(str(i), 'output.json')]
726 results_json = self.m.json.loads(results_raw)
727 for key in merged_results:
728 if key in results_json:
729 if isinstance(merged_results[key], list):
730 merged_results[key].extend(results_json[key])
731 elif isinstance(merged_results[key], bool):
732 merged_results[key] = merged_results[key] and results_json[key]
733 else:
734 raise recipe_api.InfraFailure(
735 'Unknown key type ' + type(merged_results[key]) +
736 ' when handling key ' + key + '.') # pragma: no cover
737 return merged_results
738
706 def _isolated_script_collect_step(self, task, **kwargs): 739 def _isolated_script_collect_step(self, task, **kwargs):
707 step_test_data = kwargs.pop('step_test_data', None) 740 step_test_data = kwargs.pop('step_test_data', None)
708 if not step_test_data: 741 if not step_test_data:
709 step_test_data = self.m.test_utils.test_api.canned_isolated_script_output( 742 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) 743 passing=True, is_win=self.m.platform.is_win, swarming=True)
711 744
712 args=self.get_collect_cmd_args(task) 745 args=self.get_collect_cmd_args(task)
713 args.extend(['--task-output-dir', self.m.raw_io.output_dir()]) 746 args.extend(['--task-output-dir', self.m.raw_io.output_dir()])
714 747
715 try: 748 try:
(...skipping 13 matching lines...) Expand all
729 step_result = self.m.step.active_result 762 step_result = self.m.step.active_result
730 outdir_json = self.m.json.dumps(step_result.raw_io.output_dir, indent=2) 763 outdir_json = self.m.json.dumps(step_result.raw_io.output_dir, indent=2)
731 step_result.presentation.logs['outdir_json'] = outdir_json.splitlines() 764 step_result.presentation.logs['outdir_json'] = outdir_json.splitlines()
732 765
733 # Check if it's an internal failure. 766 # Check if it's an internal failure.
734 summary = self.m.json.loads( 767 summary = self.m.json.loads(
735 step_result.raw_io.output_dir['summary.json']) 768 step_result.raw_io.output_dir['summary.json'])
736 if any(shard['internal_failure'] for shard in summary['shards']): 769 if any(shard['internal_failure'] for shard in summary['shards']):
737 raise recipe_api.InfraFailure('Internal swarming failure.') 770 raise recipe_api.InfraFailure('Internal swarming failure.')
738 771
739 # TODO(nednguyen, kbr): Combine isolated script results from multiple 772 # Always show the shards' links in the collect step. (It looks
740 # shards rather than assuming that there is always just one shard. 773 # like show_isolated_out_in_collect_step is false by default
741 assert len(summary['shards']) == 1 774 # in recipe runs.)
742 results_raw = step_result.raw_io.output_dir[ 775 links = step_result.presentation.links
743 self.m.path.join('0', 'output.json')] 776 for index in xrange(task.shards):
744 step_result.isolated_script_results = self.m.json.loads(results_raw) 777 url = task.get_shard_view_url(index)
778 if url:
779 links['shard #%d' % index] = url
780
781 step_result.isolated_script_results = \
782 self._merge_isolated_script_shards(task, step_result)
745 783
746 self._display_pending(summary, step_result.presentation) 784 self._display_pending(summary, step_result.presentation)
747 except Exception as e: 785 except Exception as e:
748 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)] 786 self.m.step.active_result.presentation.logs['no_results_exc'] = [str(e)]
749 self.m.step.active_result.isolated_script_results = None 787 self.m.step.active_result.isolated_script_results = None
750 788
751 def _get_step_name(self, prefix, task): 789 def _get_step_name(self, prefix, task):
752 """SwarmingTask -> name of a step of a waterfall. 790 """SwarmingTask -> name of a step of a waterfall.
753 791
754 Will take a task title (+ step name prefix) and append OS dimension to it. 792 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
928 966
929 def get_shard_view_url(self, index): 967 def get_shard_view_url(self, index):
930 """Returns URL of HTML page with shard details or None if not available. 968 """Returns URL of HTML page with shard details or None if not available.
931 969
932 Works only after the task has been successfully triggered. 970 Works only after the task has been successfully triggered.
933 """ 971 """
934 if self._trigger_output and self._trigger_output.get('tasks'): 972 if self._trigger_output and self._trigger_output.get('tasks'):
935 for shard_dict in self._trigger_output['tasks'].itervalues(): 973 for shard_dict in self._trigger_output['tasks'].itervalues():
936 if shard_dict['shard_index'] == index: 974 if shard_dict['shard_index'] == index:
937 return shard_dict['view_url'] 975 return shard_dict['view_url']
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698