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