OLD | NEW |
1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2013 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 """Implements test sharding logic.""" | 5 """Implements test sharding logic.""" |
6 | 6 |
7 import logging | 7 import logging |
8 import threading | 8 import threading |
9 | 9 |
10 from pylib import android_commands | 10 from pylib import android_commands |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 try: | 177 try: |
178 index = threadsafe_counter.GetAndIncrement() | 178 index = threadsafe_counter.GetAndIncrement() |
179 logging.warning('Creating shard %s for device %s.', index, device) | 179 logging.warning('Creating shard %s for device %s.', index, device) |
180 runner = runner_factory(device, index) | 180 runner = runner_factory(device, index) |
181 runner.SetUp() | 181 runner.SetUp() |
182 out_runners.append(runner) | 182 out_runners.append(runner) |
183 except android_commands.errors.DeviceUnresponsiveError as e: | 183 except android_commands.errors.DeviceUnresponsiveError as e: |
184 logging.warning('Failed to create shard for %s: [%s]', device, e) | 184 logging.warning('Failed to create shard for %s: [%s]', device, e) |
185 | 185 |
186 | 186 |
187 def _RunAllTests(runners, tests, num_retries, timeout=None): | 187 def _RunAllTests(runners, test_collection_factory, num_retries, timeout=None): |
188 """Run all tests using the given TestRunners. | 188 """Run all tests using the given TestRunners. |
189 | 189 |
190 Args: | 190 Args: |
191 runners: a list of TestRunner objects. | 191 runners: a list of TestRunner objects. |
192 tests: a list of Tests to run using the given TestRunners. | 192 test_collection_factory: a callable to generate a _TestCollection object for |
| 193 each test runner. |
193 num_retries: number of retries for a test. | 194 num_retries: number of retries for a test. |
194 timeout: watchdog timeout in seconds, defaults to the default timeout. | 195 timeout: watchdog timeout in seconds, defaults to the default timeout. |
195 | 196 |
196 Returns: | 197 Returns: |
197 A tuple of (TestRunResults object, exit code) | 198 A tuple of (TestRunResults object, exit code) |
198 """ | 199 """ |
199 logging.warning('Running %s tests with %s test runners.' % | 200 logging.warning('Running tests with %s test runners.' % (len(runners))) |
200 (len(tests), len(runners))) | |
201 tests_collection = _TestCollection([_Test(t) for t in tests]) | |
202 results = [] | 201 results = [] |
203 exit_code = 0 | 202 exit_code = 0 |
204 watcher = watchdog_timer.WatchdogTimer(timeout) | 203 watcher = watchdog_timer.WatchdogTimer(timeout) |
| 204 |
205 workers = reraiser_thread.ReraiserThreadGroup( | 205 workers = reraiser_thread.ReraiserThreadGroup( |
206 [reraiser_thread.ReraiserThread( | 206 [reraiser_thread.ReraiserThread( |
207 _RunTestsFromQueue, | 207 _RunTestsFromQueue, |
208 [r, tests_collection, results, watcher, num_retries], | 208 [r, test_collection_factory(), results, watcher, num_retries], |
209 name=r.device[-4:]) | 209 name=r.device[-4:]) |
210 for r in runners]) | 210 for r in runners]) |
211 run_results = base_test_result.TestRunResults() | 211 run_results = base_test_result.TestRunResults() |
212 workers.StartAll() | 212 workers.StartAll() |
213 | 213 |
214 # Catch DeviceUnresponsiveErrors and set a warning exit code | 214 # Catch DeviceUnresponsiveErrors and set a warning exit code |
215 try: | 215 try: |
216 workers.JoinAll(watcher) | 216 workers.JoinAll(watcher) |
217 except android_commands.errors.DeviceUnresponsiveError as e: | 217 except android_commands.errors.DeviceUnresponsiveError as e: |
218 logging.error(e) | 218 logging.error(e) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 runners: a list of TestRunner objects. | 260 runners: a list of TestRunner objects. |
261 timeout: watchdog timeout in seconds, defaults to the default timeout. | 261 timeout: watchdog timeout in seconds, defaults to the default timeout. |
262 """ | 262 """ |
263 threads = reraiser_thread.ReraiserThreadGroup( | 263 threads = reraiser_thread.ReraiserThreadGroup( |
264 [reraiser_thread.ReraiserThread(r.TearDown, name=r.device[-4:]) | 264 [reraiser_thread.ReraiserThread(r.TearDown, name=r.device[-4:]) |
265 for r in runners]) | 265 for r in runners]) |
266 threads.StartAll() | 266 threads.StartAll() |
267 threads.JoinAll(watchdog_timer.WatchdogTimer(timeout)) | 267 threads.JoinAll(watchdog_timer.WatchdogTimer(timeout)) |
268 | 268 |
269 | 269 |
270 def ShardAndRunTests(runner_factory, devices, tests, build_type='Debug', | 270 def ReplicateAndRunTests(tests, *args, **kwargs): |
271 test_timeout=DEFAULT_TIMEOUT, | 271 """Replicates the tests for each device, so all devices run every test. |
272 setup_timeout=DEFAULT_TIMEOUT, | 272 |
273 num_retries=2): | 273 Args: |
| 274 tests: A list of tests to run. |
| 275 *args, **kwargs: Args and kwargs to RunTests which we pass through. |
| 276 |
| 277 Returns: |
| 278 A tuple of (base_test_result.TestRunResults object, exit code). |
| 279 """ |
| 280 |
| 281 if not tests: |
| 282 logging.error('No tests to run.') |
| 283 return (base_test_result.TestRunResults(), constants.ERROR_EXIT_CODE) |
| 284 |
| 285 logging.info('Will run %d tests: %s', len(tests), str(tests)) |
| 286 |
| 287 # Genereate a unique _TestCollection object for each test runner, but use |
| 288 # the same set of tests. |
| 289 TestCollectionFactory = lambda: _TestCollection([_Test(t) for t in tests]) |
| 290 return RunTests(TestCollectionFactory, *args, **kwargs) |
| 291 |
| 292 |
| 293 def ShardAndRunTests(tests, *args, **kwargs): |
| 294 """Distrbutes all tests over devices through a shared pool of tests. |
| 295 |
| 296 Args: |
| 297 tests: A list of tests to run. |
| 298 *args, **kwargs: Args and kwargs to RunTests which we pass through. |
| 299 |
| 300 Returns: |
| 301 A tuple of (base_test_result.TestRunResults object, exit code). |
| 302 """ |
| 303 |
| 304 if not tests: |
| 305 logging.error('No tests to run.') |
| 306 return (base_test_result.TestRunResults(), constants.ERROR_EXIT_CODE) |
| 307 |
| 308 logging.info('Will run %d tests: %s', len(tests), str(tests)) |
| 309 |
| 310 # Genereate a shared _TestCollection object for all test runners, so they draw |
| 311 # from a common pool of tests. |
| 312 shared_test_collection = _TestCollection([_Test(t) for t in tests]) |
| 313 TestCollectionFactory = lambda: shared_test_collection |
| 314 return RunTests(TestCollectionFactory, *args, **kwargs) |
| 315 |
| 316 |
| 317 def RunTests(test_collection_factory, runner_factory, devices, |
| 318 build_type='Debug', |
| 319 test_timeout=DEFAULT_TIMEOUT, |
| 320 setup_timeout=DEFAULT_TIMEOUT, |
| 321 num_retries=2): |
274 """Run all tests on attached devices, retrying tests that don't pass. | 322 """Run all tests on attached devices, retrying tests that don't pass. |
275 | 323 |
276 Args: | 324 Args: |
277 runner_factory: callable that takes a device and index and returns a | 325 runner_factory: callable that takes a device and index and returns a |
278 TestRunner object. | 326 TestRunner object. |
| 327 test_collection_factory: callable that is used to generate a _TestCollection |
| 328 object for each test runner. |
279 devices: list of attached device serial numbers as strings. | 329 devices: list of attached device serial numbers as strings. |
280 tests: list of tests to run. | 330 tests: list of tests to run. |
281 build_type: either 'Debug' or 'Release'. | 331 build_type: either 'Debug' or 'Release'. |
282 test_timeout: watchdog timeout in seconds for running tests, defaults to the | 332 test_timeout: watchdog timeout in seconds for running tests, defaults to the |
283 default timeout. | 333 default timeout. |
284 setup_timeout: watchdog timeout in seconds for creating and cleaning up | 334 setup_timeout: watchdog timeout in seconds for creating and cleaning up |
285 test runners, defaults to the default timeout. | 335 test runners, defaults to the default timeout. |
286 num_retries: number of retries for a test. | 336 num_retries: number of retries for a test. |
287 | 337 |
288 Returns: | 338 Returns: |
289 A tuple of (base_test_result.TestRunResults object, exit code). | 339 A tuple of (base_test_result.TestRunResults object, exit code). |
290 """ | 340 """ |
291 if not tests: | |
292 logging.error('No tests to run.') | |
293 return (base_test_result.TestRunResults(), constants.ERROR_EXIT_CODE) | |
294 | |
295 logging.info('Will run %d tests: %s', len(tests), str(tests)) | |
296 forwarder.Forwarder.KillHost(build_type) | 341 forwarder.Forwarder.KillHost(build_type) |
297 runners = _CreateRunners(runner_factory, devices, setup_timeout) | 342 runners = _CreateRunners(runner_factory, devices, setup_timeout) |
298 try: | 343 try: |
299 return _RunAllTests(runners, tests, num_retries, test_timeout) | 344 return _RunAllTests(runners, test_collection_factory, |
| 345 num_retries, test_timeout) |
300 finally: | 346 finally: |
301 try: | 347 try: |
302 _TearDownRunners(runners, setup_timeout) | 348 _TearDownRunners(runners, setup_timeout) |
303 except android_commands.errors.DeviceUnresponsiveError as e: | 349 except android_commands.errors.DeviceUnresponsiveError as e: |
304 logging.warning('Device unresponsive during TearDown: [%s]', e) | 350 logging.warning('Device unresponsive during TearDown: [%s]', e) |
305 finally: | 351 finally: |
306 forwarder.Forwarder.KillHost(build_type) | 352 forwarder.Forwarder.KillHost(build_type) |
OLD | NEW |