OLD | NEW |
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 itertools | 5 import itertools |
6 import os | 6 import os |
7 import posixpath | 7 import posixpath |
8 | 8 |
9 from devil.android import device_errors | 9 from devil.android import device_errors |
10 from devil.android import device_temp_file | 10 from devil.android import device_temp_file |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 for f in files: | 45 for f in files: |
46 device_file = posixpath.join(device_dir, f) | 46 device_file = posixpath.join(device_dir, f) |
47 host_file = os.path.join(host_dir, *f.split(posixpath.sep)) | 47 host_file = os.path.join(host_dir, *f.split(posixpath.sep)) |
48 host_file_base, ext = os.path.splitext(host_file) | 48 host_file_base, ext = os.path.splitext(host_file) |
49 for i in itertools.count(): | 49 for i in itertools.count(): |
50 host_file = '%s_%d%s' % (host_file_base, i, ext) | 50 host_file = '%s_%d%s' % (host_file_base, i, ext) |
51 if not os.path.exists(host_file): | 51 if not os.path.exists(host_file): |
52 break | 52 break |
53 device.PullFile(device_file, host_file) | 53 device.PullFile(device_file, host_file) |
54 | 54 |
| 55 |
| 56 def _ExtractTestsFromFilter(gtest_filter): |
| 57 """Returns the list of tests specified by the given filter. |
| 58 |
| 59 Returns: |
| 60 None if the device should be queried for the test list instead. |
| 61 """ |
| 62 # Empty means all tests, - means exclude filter. |
| 63 if not gtest_filter or '-' in gtest_filter: |
| 64 return None |
| 65 |
| 66 patterns = gtest_filter.split(':') |
| 67 # For a single pattern, allow it even if it has a wildcard so long as the |
| 68 # wildcard comes at the end and there is at least one . to prove the scope is |
| 69 # not too large. |
| 70 # This heuristic is not necessarily faster, but normally is. |
| 71 if len(patterns) == 1 and patterns[0].endswith('*'): |
| 72 no_suffix = patterns[0].rstrip('*') |
| 73 if '*' not in no_suffix and '.' in no_suffix: |
| 74 return patterns |
| 75 |
| 76 if '*' in gtest_filter: |
| 77 return None |
| 78 return patterns |
| 79 |
| 80 |
55 class _ApkDelegate(object): | 81 class _ApkDelegate(object): |
56 def __init__(self, test_instance): | 82 def __init__(self, test_instance): |
57 self._activity = test_instance.activity | 83 self._activity = test_instance.activity |
58 self._apk_helper = test_instance.apk_helper | 84 self._apk_helper = test_instance.apk_helper |
59 self._package = test_instance.package | 85 self._package = test_instance.package |
60 self._runner = test_instance.runner | 86 self._runner = test_instance.runner |
61 self._permissions = test_instance.permissions | 87 self._permissions = test_instance.permissions |
62 | 88 |
63 self._component = '%s/%s' % (self._package, self._runner) | 89 self._component = '%s/%s' % (self._package, self._runner) |
64 self._extras = test_instance.extras | 90 self._extras = test_instance.extras |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 device_count = len(self._env.devices) | 240 device_count = len(self._env.devices) |
215 shards = [] | 241 shards = [] |
216 for i in xrange(0, device_count): | 242 for i in xrange(0, device_count): |
217 unbounded_shard = tests[i::device_count] | 243 unbounded_shard = tests[i::device_count] |
218 shards += [unbounded_shard[j:j+_MAX_SHARD_SIZE] | 244 shards += [unbounded_shard[j:j+_MAX_SHARD_SIZE] |
219 for j in xrange(0, len(unbounded_shard), _MAX_SHARD_SIZE)] | 245 for j in xrange(0, len(unbounded_shard), _MAX_SHARD_SIZE)] |
220 return shards | 246 return shards |
221 | 247 |
222 #override | 248 #override |
223 def _GetTests(self): | 249 def _GetTests(self): |
| 250 # When the exact list of tests to run is given via command-line (e.g. when |
| 251 # locally iterating on a specific test), skip querying the device (which |
| 252 # takes ~3 seconds). |
| 253 tests = _ExtractTestsFromFilter(self._test_instance.gtest_filter) |
| 254 if tests: |
| 255 return tests |
| 256 |
| 257 # Even when there's only one device, it still makes sense to retrieve the |
| 258 # test list so that tests can be split up and run in batches rather than all |
| 259 # at once (since test output is not streamed). |
224 @local_device_test_run.handle_shard_failures_with( | 260 @local_device_test_run.handle_shard_failures_with( |
225 on_failure=self._env.BlacklistDevice) | 261 on_failure=self._env.BlacklistDevice) |
226 def list_tests(dev): | 262 def list_tests(dev): |
227 tests = self._delegate.Run( | 263 tests = self._delegate.Run( |
228 None, dev, flags='--gtest_list_tests', timeout=10) | 264 None, dev, flags='--gtest_list_tests', timeout=10) |
229 tests = gtest_test_instance.ParseGTestListTests(tests) | 265 tests = gtest_test_instance.ParseGTestListTests(tests) |
230 tests = self._test_instance.FilterTests(tests) | 266 tests = self._test_instance.FilterTests(tests) |
231 return tests | 267 return tests |
232 | 268 |
| 269 # Query all devices in case one fails. |
233 test_lists = self._env.parallel_devices.pMap(list_tests).pGet(None) | 270 test_lists = self._env.parallel_devices.pMap(list_tests).pGet(None) |
234 tests = list(sorted(set().union(*[set(tl) for tl in test_lists if tl]))) | 271 # TODO(agrieve): Make this fail rather than return an empty list when |
235 return tests | 272 # all devices fail. |
| 273 return list(sorted(set().union(*[set(tl) for tl in test_lists if tl]))) |
236 | 274 |
237 #override | 275 #override |
238 def _RunTest(self, device, test): | 276 def _RunTest(self, device, test): |
239 # Run the test. | 277 # Run the test. |
240 timeout = (self._test_instance.shard_timeout | 278 timeout = (self._test_instance.shard_timeout |
241 * self.GetTool(device).GetTimeoutScale()) | 279 * self.GetTool(device).GetTimeoutScale()) |
242 output = self._delegate.Run( | 280 output = self._delegate.Run( |
243 test, device, timeout=timeout, retries=0) | 281 test, device, timeout=timeout, retries=0) |
244 for s in self._servers[str(device)]: | 282 for s in self._servers[str(device)]: |
245 s.Reset() | 283 s.Reset() |
246 if self._test_instance.app_files: | 284 if self._test_instance.app_files: |
247 self._delegate.PullAppFiles(device, self._test_instance.app_files, | 285 self._delegate.PullAppFiles(device, self._test_instance.app_files, |
248 self._test_instance.app_file_dir) | 286 self._test_instance.app_file_dir) |
249 self._delegate.Clear(device) | 287 self._delegate.Clear(device) |
250 | 288 |
251 # Parse the output. | 289 # Parse the output. |
252 # TODO(jbudorick): Transition test scripts away from parsing stdout. | 290 # TODO(jbudorick): Transition test scripts away from parsing stdout. |
253 results = self._test_instance.ParseGTestOutput(output) | 291 results = self._test_instance.ParseGTestOutput(output) |
254 return results | 292 return results |
255 | 293 |
256 #override | 294 #override |
257 def TearDown(self): | 295 def TearDown(self): |
258 @local_device_test_run.handle_shard_failures | 296 @local_device_test_run.handle_shard_failures |
259 def individual_device_tear_down(dev): | 297 def individual_device_tear_down(dev): |
260 for s in self._servers.get(str(dev), []): | 298 for s in self._servers.get(str(dev), []): |
261 s.TearDown() | 299 s.TearDown() |
262 | 300 |
263 self._env.parallel_devices.pMap(individual_device_tear_down) | 301 self._env.parallel_devices.pMap(individual_device_tear_down) |
OLD | NEW |