OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 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 """Dispatches tests, either sharding or replicating them. | 5 """Dispatches tests, either sharding or replicating them. |
6 | 6 |
7 Performs the following steps: | 7 Performs the following steps: |
8 * Create a test collection factory, using the given tests | 8 * Create a test collection factory, using the given tests |
9 - If sharding: test collection factory returns the same shared test collection | 9 - If sharding: test collection factory returns the same shared test collection |
10 to all test runners | 10 to all test runners |
11 - If replciating: test collection factory returns a unique test collection to | 11 - If replciating: test collection factory returns a unique test collection to |
12 each test runner, with the same set of tests in each. | 12 each test runner, with the same set of tests in each. |
13 * Create a test runner for each device. | 13 * Create a test runner for each device. |
14 * Run each test runner in its own thread, grabbing tests from the test | 14 * Run each test runner in its own thread, grabbing tests from the test |
15 collection until there are no tests left. | 15 collection until there are no tests left. |
16 """ | 16 """ |
17 | 17 |
18 # TODO(jbudorick) Deprecate and remove this class after any relevant parts have | 18 # TODO(jbudorick) Deprecate and remove this class after any relevant parts have |
19 # been ported to the new environment / test instance model. | 19 # been ported to the new environment / test instance model. |
20 | 20 |
21 import logging | 21 import logging |
22 import threading | 22 import threading |
23 | 23 |
| 24 from pylib import android_commands |
24 from pylib import constants | 25 from pylib import constants |
25 from pylib.base import base_test_result | 26 from pylib.base import base_test_result |
26 from pylib.base import test_collection | 27 from pylib.base import test_collection |
27 from pylib.device import device_errors | 28 from pylib.device import device_errors |
28 from pylib.utils import reraiser_thread | 29 from pylib.utils import reraiser_thread |
29 from pylib.utils import watchdog_timer | 30 from pylib.utils import watchdog_timer |
30 | 31 |
31 | 32 |
32 DEFAULT_TIMEOUT = 7 * 60 # seven minutes | 33 DEFAULT_TIMEOUT = 7 * 60 # seven minutes |
33 | 34 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 new_test_run_results = base_test_result.TestRunResults() | 95 new_test_run_results = base_test_result.TestRunResults() |
95 for test_result in test_run_results.GetAll(): | 96 for test_result in test_run_results.GetAll(): |
96 test_result.SetName('%s_%s' % (runner.device_serial[-4:], | 97 test_result.SetName('%s_%s' % (runner.device_serial[-4:], |
97 test_result.GetName())) | 98 test_result.GetName())) |
98 new_test_run_results.AddResult(test_result) | 99 new_test_run_results.AddResult(test_result) |
99 return new_test_run_results | 100 return new_test_run_results |
100 | 101 |
101 for test in collection: | 102 for test in collection: |
102 watcher.Reset() | 103 watcher.Reset() |
103 try: | 104 try: |
104 if not runner.device.IsOnline(): | 105 if runner.device_serial not in android_commands.GetAttachedDevices(): |
105 # Device is unresponsive, stop handling tests on this device. | 106 # Device is unresponsive, stop handling tests on this device. |
106 msg = 'Device %s is unresponsive.' % runner.device_serial | 107 msg = 'Device %s is unresponsive.' % runner.device_serial |
107 logging.warning(msg) | 108 logging.warning(msg) |
108 raise device_errors.DeviceUnreachableError(msg) | 109 raise device_errors.DeviceUnreachableError(msg) |
109 result, retry = runner.RunTest(test.test) | 110 result, retry = runner.RunTest(test.test) |
110 if tag_results_with_device: | 111 if tag_results_with_device: |
111 result = TagTestRunResults(result) | 112 result = TagTestRunResults(result) |
112 test.tries += 1 | 113 test.tries += 1 |
113 if retry and test.tries <= num_retries: | 114 if retry and test.tries <= num_retries: |
114 # Retry non-passing results, only record passing results. | 115 # Retry non-passing results, only record passing results. |
(...skipping 27 matching lines...) Expand all Loading... |
142 device: The device serial number to set up. | 143 device: The device serial number to set up. |
143 out_runners: List to add the successfully set up TestRunner object. | 144 out_runners: List to add the successfully set up TestRunner object. |
144 threadsafe_counter: A _ThreadSafeCounter object used to get shard indices. | 145 threadsafe_counter: A _ThreadSafeCounter object used to get shard indices. |
145 """ | 146 """ |
146 try: | 147 try: |
147 index = threadsafe_counter.GetAndIncrement() | 148 index = threadsafe_counter.GetAndIncrement() |
148 logging.warning('Creating shard %s for device %s.', index, device) | 149 logging.warning('Creating shard %s for device %s.', index, device) |
149 runner = runner_factory(device, index) | 150 runner = runner_factory(device, index) |
150 runner.SetUp() | 151 runner.SetUp() |
151 out_runners.append(runner) | 152 out_runners.append(runner) |
152 except device_errors.DeviceUnreachableError as e: | 153 except (device_errors.DeviceUnreachableError, |
| 154 # TODO(jbudorick) Remove this once the underlying implementations |
| 155 # for the above are switched or wrapped. |
| 156 android_commands.errors.DeviceUnresponsiveError) as e: |
153 logging.warning('Failed to create shard for %s: [%s]', device, e) | 157 logging.warning('Failed to create shard for %s: [%s]', device, e) |
154 | 158 |
155 | 159 |
156 def _RunAllTests(runners, test_collection_factory, num_retries, timeout=None, | 160 def _RunAllTests(runners, test_collection_factory, num_retries, timeout=None, |
157 tag_results_with_device=False): | 161 tag_results_with_device=False): |
158 """Run all tests using the given TestRunners. | 162 """Run all tests using the given TestRunners. |
159 | 163 |
160 Args: | 164 Args: |
161 runners: A list of TestRunner objects. | 165 runners: A list of TestRunner objects. |
162 test_collection_factory: A callable to generate a TestCollection object for | 166 test_collection_factory: A callable to generate a TestCollection object for |
(...skipping 21 matching lines...) Expand all Loading... |
184 [r, tc, results, watcher, num_retries, tag_results_with_device], | 188 [r, tc, results, watcher, num_retries, tag_results_with_device], |
185 name=r.device_serial[-4:]) | 189 name=r.device_serial[-4:]) |
186 for r, tc in zip(runners, test_collections)] | 190 for r, tc in zip(runners, test_collections)] |
187 | 191 |
188 workers = reraiser_thread.ReraiserThreadGroup(threads) | 192 workers = reraiser_thread.ReraiserThreadGroup(threads) |
189 workers.StartAll() | 193 workers.StartAll() |
190 | 194 |
191 # Catch DeviceUnreachableErrors and set a warning exit code | 195 # Catch DeviceUnreachableErrors and set a warning exit code |
192 try: | 196 try: |
193 workers.JoinAll(watcher) | 197 workers.JoinAll(watcher) |
194 except device_errors.DeviceUnreachableError as e: | 198 except (device_errors.DeviceUnreachableError, |
| 199 # TODO(jbudorick) Remove this once the underlying implementations |
| 200 # for the above are switched or wrapped. |
| 201 android_commands.errors.DeviceUnresponsiveError) as e: |
195 logging.error(e) | 202 logging.error(e) |
196 | 203 |
197 if not all((len(tc) == 0 for tc in test_collections)): | 204 if not all((len(tc) == 0 for tc in test_collections)): |
198 logging.error('Only ran %d tests (all devices are likely offline).' % | 205 logging.error('Only ran %d tests (all devices are likely offline).' % |
199 len(results)) | 206 len(results)) |
200 for tc in test_collections: | 207 for tc in test_collections: |
201 run_results.AddResults(base_test_result.BaseTestResult( | 208 run_results.AddResults(base_test_result.BaseTestResult( |
202 t, base_test_result.ResultType.UNKNOWN) for t in tc.test_names()) | 209 t, base_test_result.ResultType.UNKNOWN) for t in tc.test_names()) |
203 | 210 |
204 for r in results: | 211 for r in results: |
(...skipping 17 matching lines...) Expand all Loading... |
222 | 229 |
223 Returns: | 230 Returns: |
224 A list of TestRunner objects. | 231 A list of TestRunner objects. |
225 """ | 232 """ |
226 logging.warning('Creating %s test runners.' % len(devices)) | 233 logging.warning('Creating %s test runners.' % len(devices)) |
227 runners = [] | 234 runners = [] |
228 counter = _ThreadSafeCounter() | 235 counter = _ThreadSafeCounter() |
229 threads = reraiser_thread.ReraiserThreadGroup( | 236 threads = reraiser_thread.ReraiserThreadGroup( |
230 [reraiser_thread.ReraiserThread(_SetUp, | 237 [reraiser_thread.ReraiserThread(_SetUp, |
231 [runner_factory, d, runners, counter], | 238 [runner_factory, d, runners, counter], |
232 name=str(d)[-4:]) | 239 name=d[-4:]) |
233 for d in devices]) | 240 for d in devices]) |
234 threads.StartAll() | 241 threads.StartAll() |
235 threads.JoinAll(watchdog_timer.WatchdogTimer(timeout)) | 242 threads.JoinAll(watchdog_timer.WatchdogTimer(timeout)) |
236 return runners | 243 return runners |
237 | 244 |
238 | 245 |
239 def _TearDownRunners(runners, timeout=None): | 246 def _TearDownRunners(runners, timeout=None): |
240 """Calls TearDown() for each test runner in parallel. | 247 """Calls TearDown() for each test runner in parallel. |
241 | 248 |
242 Args: | 249 Args: |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 | 326 |
320 logging.info('Will run %d tests (%s): %s', | 327 logging.info('Will run %d tests (%s): %s', |
321 len(tests_expanded), log_string, str(tests_expanded)) | 328 len(tests_expanded), log_string, str(tests_expanded)) |
322 runners = _CreateRunners(runner_factory, devices, setup_timeout) | 329 runners = _CreateRunners(runner_factory, devices, setup_timeout) |
323 try: | 330 try: |
324 return _RunAllTests(runners, test_collection_factory, | 331 return _RunAllTests(runners, test_collection_factory, |
325 num_retries, test_timeout, tag_results_with_device) | 332 num_retries, test_timeout, tag_results_with_device) |
326 finally: | 333 finally: |
327 try: | 334 try: |
328 _TearDownRunners(runners, setup_timeout) | 335 _TearDownRunners(runners, setup_timeout) |
329 except device_errors.DeviceUnreachableError as e: | 336 except (device_errors.DeviceUnreachableError, |
| 337 # TODO(jbudorick) Remove this once the underlying implementations |
| 338 # for the above are switched or wrapped. |
| 339 android_commands.errors.DeviceUnresponsiveError) as e: |
330 logging.warning('Device unresponsive during TearDown: [%s]', e) | 340 logging.warning('Device unresponsive during TearDown: [%s]', e) |
331 except Exception as e: | 341 except Exception as e: |
332 logging.error('Unexpected exception caught during TearDown: %s' % str(e)) | 342 logging.error('Unexpected exception caught during TearDown: %s' % str(e)) |
OLD | NEW |