| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 """Set of utilities to add commands to a buildbot factory. | 5 """Set of utilities to add commands to a buildbot factory. |
| 6 | 6 |
| 7 This is based on commands.py and adds swarm-specific commands.""" | 7 This is based on commands.py and adds swarm-specific commands.""" |
| 8 | 8 |
| 9 from buildbot.process.properties import WithProperties | |
| 10 from buildbot.steps import shell, source | 9 from buildbot.steps import shell, source |
| 11 from twisted.python import log | 10 from twisted.python import log |
| 12 | 11 |
| 13 from master import chromium_step | 12 from master import chromium_step |
| 14 from master.factory import commands | 13 from master.factory import commands |
| 15 | 14 |
| 16 from common import chromium_utils | 15 from common import chromium_utils |
| 17 | 16 |
| 18 import config | 17 import config |
| 19 | 18 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 | 80 |
| 82 'swarm_hashes' is already related to GetSwarmTests(). | 81 'swarm_hashes' is already related to GetSwarmTests(). |
| 83 """ | 82 """ |
| 84 # Only used for pass gtest filters specified by the user via 'testfilter'. | 83 # Only used for pass gtest filters specified by the user via 'testfilter'. |
| 85 swarm_tests = commands.GetSwarmTests(self) | 84 swarm_tests = commands.GetSwarmTests(self) |
| 86 # The 'swarm_hashes' build property has been set by the | 85 # The 'swarm_hashes' build property has been set by the |
| 87 # CalculateIsolatedSha1s build step. It will have all the steps that can be | 86 # CalculateIsolatedSha1s build step. It will have all the steps that can be |
| 88 # triggered. This implicitly takes account 'testfilter'. | 87 # triggered. This implicitly takes account 'testfilter'. |
| 89 swarm_tests_hash_mapping = commands.GetProp(self, 'swarm_hashes', {}) | 88 swarm_tests_hash_mapping = commands.GetProp(self, 'swarm_hashes', {}) |
| 90 | 89 |
| 90 # TODO(maruel): Move more logic out into |
| 91 # scripts/slave/swarming/trigger_swarm_shim.py. |
| 91 command = self.command[:] | 92 command = self.command[:] |
| 92 for swarm_test in self.tests: | 93 for swarm_test in self.tests: |
| 93 if swarm_tests_hash_mapping.get(swarm_test.test_name): | 94 if swarm_tests_hash_mapping.get(swarm_test.test_name): |
| 94 command.extend( | 95 command.extend( |
| 95 [ | 96 [ |
| 96 '--run_from_hash', | 97 '--task', |
| 97 swarm_tests_hash_mapping[swarm_test.test_name], | 98 swarm_tests_hash_mapping[swarm_test.test_name], |
| 98 swarm_test.test_name, | 99 swarm_test.test_name, |
| 99 '%d' % swarm_test.shards, | 100 '%d' % swarm_test.shards, |
| 100 # '*' is a special value to mean no filter. This is used so '' is | 101 # '*' is a special value to mean no filter. This is used so '' is |
| 101 # not used, as '' may be misinterpreted by the shell, especially | 102 # not used, as '' may be misinterpreted by the shell, especially |
| 102 # on Windows. | 103 # on Windows. |
| 103 swarm_tests.get(swarm_test.test_name) or '*', | 104 swarm_tests.get(swarm_test.test_name) or '*', |
| 104 ]) | 105 ]) |
| 105 else: | 106 else: |
| 106 log.msg('Given a swarm test, %s, that has no matching hash' % | 107 log.msg('Given a swarm test, %s, that has no matching hash' % |
| 107 swarm_test.test_name) | 108 swarm_test.test_name) |
| 108 | 109 |
| 109 self.setCommand(command) | 110 self.setCommand(command) |
| 110 shell.ShellCommand.start(self) | 111 shell.ShellCommand.start(self) |
| 111 | 112 |
| 112 | 113 |
| 113 class SwarmCommands(commands.FactoryCommands): | 114 class SwarmCommands(commands.FactoryCommands): |
| 114 """Encapsulates methods to add swarm commands to a buildbot factory""" | 115 """Encapsulates methods to add swarm commands to a buildbot factory""" |
| 115 def __init__(self, *args, **kwargs): | 116 def __init__(self, *args, **kwargs): |
| 116 super(SwarmCommands, self).__init__(*args, **kwargs) | 117 super(SwarmCommands, self).__init__(*args, **kwargs) |
| 117 self._swarming_client_dir = self.PathJoin('src', 'tools', 'swarming_client') | 118 self._swarming_client_dir = self.PathJoin('src', 'tools', 'swarming_client') |
| 118 | 119 |
| 119 def AddTriggerSwarmTestStep(self, swarm_server, isolation_outdir, tests, | 120 def AddTriggerSwarmTestStep(self, swarm_server, isolation_outdir, tests, |
| 120 doStepIf): | 121 doStepIf): |
| 121 assert all(t.__class__.__name__ == 'SwarmTest' for t in tests) | 122 assert all(t.__class__.__name__ == 'SwarmTest' for t in tests) |
| 122 script_path = self.PathJoin( | |
| 123 self._swarming_client_dir, 'swarm_trigger_step.py') | |
| 124 | |
| 125 swarm_request_name_prefix = WithProperties('%s-%s-', | |
| 126 'buildername:-None', | |
| 127 'buildnumber:-None') | |
| 128 | |
| 129 command = [ | 123 command = [ |
| 130 self._python, | 124 self._python, |
| 131 script_path, | 125 self.PathJoin(self._script_dir, 'swarming', 'trigger_swarm_shim.py'), |
| 132 '-o', WithProperties('%s', 'target_os:-%s' % self._target_platform), | 126 '--swarming', swarm_server, |
| 133 '-u', swarm_server, | 127 '--isolate-server', isolation_outdir, |
| 134 '-t', swarm_request_name_prefix, | |
| 135 '-d', isolation_outdir, | |
| 136 ] | 128 ] |
| 129 command = self.AddBuildProperties(command) |
| 137 assert all(i for i in command), command | 130 assert all(i for i in command), command |
| 138 self._factory.addStep( | 131 self._factory.addStep( |
| 139 SwarmShellForTriggeringTests, | 132 SwarmShellForTriggeringTests, |
| 140 name='swarm_trigger_tests', | 133 name='swarm_trigger_tests', |
| 141 description='Trigger swarm steps', | 134 description='Trigger swarm steps', |
| 142 command=command, | 135 command=command, |
| 143 tests=tests, | 136 tests=tests, |
| 144 doStepIf=doStepIf) | 137 doStepIf=doStepIf) |
| 145 | 138 |
| 146 def AddGetSwarmTestStep(self, swarm_server, test_name, num_shards): | 139 def AddGetSwarmTestStep(self, swarm_server, test_name, num_shards): |
| 147 """Adds the step to retrieve the Swarm job results asynchronously.""" | 140 """Adds the step to retrieve the Swarm job results asynchronously.""" |
| 148 # TODO(maruel): assert test_name.endswith('_swarm') once swarm retrieve | 141 # TODO(maruel): assert test_name.endswith('_swarm') once swarm retrieve |
| 149 # results steps have _swarm suffix. | 142 # results steps have _swarm suffix. |
| 150 script_path = self.PathJoin(self._script_dir, 'get_swarm_results.py') | 143 command = [ |
| 151 | 144 self._python, |
| 152 swarm_request_name = WithProperties('%s-%s-' + test_name, | 145 self.PathJoin(self._script_dir, 'swarming', 'get_swarm_results_shim.py'), |
| 153 'buildername:-None', | 146 '--swarming', swarm_server, |
| 154 'buildnumber:-None') | 147 '--shards', '%d' % num_shards, |
| 155 | 148 test_name, |
| 156 args = ['-u', swarm_server, '-s', '%d' % num_shards, swarm_request_name] | |
| 157 wrapper_args = [ | |
| 158 '--no-xvfb', '--annotate=gtest', '--test-type=%s' % test_name, | |
| 159 ] | 149 ] |
| 160 | 150 command = self.AddBuildProperties(command) |
| 161 command = self.GetPythonTestCommand(script_path, arg_list=args, | |
| 162 wrapper_args=wrapper_args) | |
| 163 | 151 |
| 164 # Swarm handles the timeouts due to no ouput being produced for 10 minutes, | 152 # Swarm handles the timeouts due to no ouput being produced for 10 minutes, |
| 165 # but we don't have access to the output until the whole test is done, which | 153 # but we don't have access to the output until the whole test is done, which |
| 166 # may take more than 10 minutes, so we increase the buildbot timeout. | 154 # may take more than 10 minutes, so we increase the buildbot timeout. |
| 167 timeout = 2 * 60 * 60 | 155 timeout = 2 * 60 * 60 |
| 168 | 156 self._factory.addStep( |
| 169 self.AddTestStep(chromium_step.AnnotatedCommand, | 157 shell.ShellCommand, |
| 170 test_name, | 158 name=test_name, |
| 171 command, | 159 description='%s Swarming' % test_name, |
| 172 timeout=timeout, | 160 command=command, |
| 173 do_step_if=TestStepFilterRetrieveSwarmResult) | 161 timeout=timeout, |
| 162 doStepIf=TestStepFilterRetrieveSwarmResult) |
| 174 | 163 |
| 175 def AddUpdateSwarmClientStep(self): | 164 def AddUpdateSwarmClientStep(self): |
| 176 """Checks out swarming_client so it can be used at the right revision.""" | 165 """Checks out swarming_client so it can be used at the right revision.""" |
| 177 def doSwarmingStepIf(b): | 166 def doSwarmingStepIf(b): |
| 178 return bool(commands.GetProp(b, 'use_swarming_client_revision', None)) | 167 return bool(commands.GetProp(b, 'use_swarming_client_revision', None)) |
| 179 def doSwarmStepIf(b): | 168 def doSwarmStepIf(b): |
| 180 return not doSwarmingStepIf(b) | 169 return not doSwarmingStepIf(b) |
| 181 | 170 |
| 182 # Emulate the path of a src/DEPS checkout, to keep things simpler. | 171 # Emulate the path of a src/DEPS checkout, to keep things simpler. |
| 183 relpath = 'build/src/tools/swarming_client' | 172 relpath = 'build/src/tools/swarming_client' |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 | 213 |
| 225 command = [self._python, script_path, '--drive', drive, | 214 command = [self._python, script_path, '--drive', drive, |
| 226 '--network_path', network_path] | 215 '--network_path', network_path] |
| 227 | 216 |
| 228 self._factory.addStep( | 217 self._factory.addStep( |
| 229 shell.ShellCommand, | 218 shell.ShellCommand, |
| 230 name='setup_windows_network_storage', | 219 name='setup_windows_network_storage', |
| 231 description='setup_windows_network_storage', | 220 description='setup_windows_network_storage', |
| 232 descriptionDone='setup_windows_network_storage', | 221 descriptionDone='setup_windows_network_storage', |
| 233 command=command) | 222 command=command) |
| OLD | NEW |