| 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 fnmatch | 5 import fnmatch |
| 6 import functools | |
| 7 import imp | 6 import imp |
| 8 import logging | 7 import logging |
| 9 import signal | 8 import signal |
| 10 import thread | 9 import thread |
| 11 import threading | 10 import threading |
| 12 | 11 |
| 13 from devil import base_error | |
| 14 from devil.android import device_errors | |
| 15 from devil.utils import signal_handler | 12 from devil.utils import signal_handler |
| 16 from pylib import valgrind_tools | 13 from pylib import valgrind_tools |
| 17 from pylib.base import base_test_result | 14 from pylib.base import base_test_result |
| 18 from pylib.base import test_run | 15 from pylib.base import test_run |
| 19 from pylib.base import test_collection | 16 from pylib.base import test_collection |
| 17 from pylib.local.device import local_device_environment |
| 20 | 18 |
| 21 | 19 |
| 22 def IncrementalInstall(device, apk_helper, installer_script): | 20 def IncrementalInstall(device, apk_helper, installer_script): |
| 23 """Performs an incremental install. | 21 """Performs an incremental install. |
| 24 | 22 |
| 25 Args: | 23 Args: |
| 26 device: Device to install on. | 24 device: Device to install on. |
| 27 apk_helper: ApkHelper instance for the _incremental.apk. | 25 apk_helper: ApkHelper instance for the _incremental.apk. |
| 28 installer_script: Path to the installer script for the incremental apk. | 26 installer_script: Path to the installer script for the incremental apk. |
| 29 """ | 27 """ |
| 30 try: | 28 try: |
| 31 install_wrapper = imp.load_source('install_wrapper', installer_script) | 29 install_wrapper = imp.load_source('install_wrapper', installer_script) |
| 32 except IOError: | 30 except IOError: |
| 33 raise Exception('Incremental install script not found: %s\n' % | 31 raise Exception('Incremental install script not found: %s\n' % |
| 34 installer_script) | 32 installer_script) |
| 35 params = install_wrapper.GetInstallParameters() | 33 params = install_wrapper.GetInstallParameters() |
| 36 | 34 |
| 37 from incremental_install import installer | 35 from incremental_install import installer |
| 38 installer.Install(device, apk_helper, split_globs=params['splits'], | 36 installer.Install(device, apk_helper, split_globs=params['splits'], |
| 39 native_libs=params['native_libs'], | 37 native_libs=params['native_libs'], |
| 40 dex_files=params['dex_files'], | 38 dex_files=params['dex_files'], |
| 41 permissions=None) # Auto-grant permissions from manifest. | 39 permissions=None) # Auto-grant permissions from manifest. |
| 42 | 40 |
| 43 | 41 |
| 44 def handle_shard_failures(f): | |
| 45 """A decorator that handles device failures for per-device functions. | |
| 46 | |
| 47 Args: | |
| 48 f: the function being decorated. The function must take at least one | |
| 49 argument, and that argument must be the device. | |
| 50 """ | |
| 51 return handle_shard_failures_with(None)(f) | |
| 52 | |
| 53 | |
| 54 def handle_shard_failures_with(on_failure): | |
| 55 """A decorator that handles device failures for per-device functions. | |
| 56 | |
| 57 This calls on_failure in the event of a failure. | |
| 58 | |
| 59 Args: | |
| 60 f: the function being decorated. The function must take at least one | |
| 61 argument, and that argument must be the device. | |
| 62 on_failure: A binary function to call on failure. | |
| 63 """ | |
| 64 def decorator(f): | |
| 65 @functools.wraps(f) | |
| 66 def wrapper(dev, *args, **kwargs): | |
| 67 try: | |
| 68 return f(dev, *args, **kwargs) | |
| 69 except device_errors.CommandTimeoutError: | |
| 70 logging.exception('Shard timed out: %s(%s)', f.__name__, str(dev)) | |
| 71 except device_errors.DeviceUnreachableError: | |
| 72 logging.exception('Shard died: %s(%s)', f.__name__, str(dev)) | |
| 73 except base_error.BaseError: | |
| 74 logging.exception('Shard failed: %s(%s)', f.__name__, str(dev)) | |
| 75 except SystemExit: | |
| 76 logging.exception('Shard killed: %s(%s)', f.__name__, str(dev)) | |
| 77 raise | |
| 78 if on_failure: | |
| 79 on_failure(dev, f.__name__) | |
| 80 return None | |
| 81 | |
| 82 return wrapper | |
| 83 | |
| 84 return decorator | |
| 85 | |
| 86 | |
| 87 class LocalDeviceTestRun(test_run.TestRun): | 42 class LocalDeviceTestRun(test_run.TestRun): |
| 88 | 43 |
| 89 def __init__(self, env, test_instance): | 44 def __init__(self, env, test_instance): |
| 90 super(LocalDeviceTestRun, self).__init__(env, test_instance) | 45 super(LocalDeviceTestRun, self).__init__(env, test_instance) |
| 91 self._tools = {} | 46 self._tools = {} |
| 92 | 47 |
| 93 #override | 48 #override |
| 94 def RunTests(self): | 49 def RunTests(self): |
| 95 tests = self._GetTests() | 50 tests = self._GetTests() |
| 96 | 51 |
| 97 exit_now = threading.Event() | 52 exit_now = threading.Event() |
| 98 | 53 |
| 99 @handle_shard_failures | 54 @local_device_environment.handle_shard_failures |
| 100 def run_tests_on_device(dev, tests, results): | 55 def run_tests_on_device(dev, tests, results): |
| 101 for test in tests: | 56 for test in tests: |
| 102 if exit_now.isSet(): | 57 if exit_now.isSet(): |
| 103 thread.exit() | 58 thread.exit() |
| 104 | 59 |
| 105 result = None | 60 result = None |
| 106 try: | 61 try: |
| 107 result = self._RunTest(dev, test) | 62 result = self._RunTest(dev, test) |
| 108 if isinstance(result, base_test_result.BaseTestResult): | 63 if isinstance(result, base_test_result.BaseTestResult): |
| 109 results.AddResult(result) | 64 results.AddResult(result) |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 | 174 |
| 220 def _RunTest(self, device, test): | 175 def _RunTest(self, device, test): |
| 221 raise NotImplementedError | 176 raise NotImplementedError |
| 222 | 177 |
| 223 def _ShouldShard(self): | 178 def _ShouldShard(self): |
| 224 raise NotImplementedError | 179 raise NotImplementedError |
| 225 | 180 |
| 226 | 181 |
| 227 class NoTestsError(Exception): | 182 class NoTestsError(Exception): |
| 228 """Error for when no tests are found.""" | 183 """Error for when no tests are found.""" |
| OLD | NEW |