[Android] Convert to DeviceUtils versions of WaitUntilFullyBooted and GetExternalStoragePath.
BUG=267773 Review URL: https://codereview.chromium.org/294113003 git-svn-id: http://src.chromium.org/svn/trunk/src/build@272434 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
This commit is contained in:
Родитель
300713d66e
Коммит
902f543dc7
|
@ -52,7 +52,7 @@ class BaseTestRunner(object):
|
|||
def _PushTestServerPortInfoToDevice(self):
|
||||
"""Pushes the latest port information to device."""
|
||||
self.device.old_interface.SetFileContents(
|
||||
self.device.old_interface.GetExternalStorage() + '/' +
|
||||
self.device.GetExternalStoragePath() + '/' +
|
||||
NET_TEST_SERVER_PORT_INFO_FILE,
|
||||
'%d:%d' % (self.test_server_spawner_port, self.test_server_port))
|
||||
|
||||
|
|
|
@ -21,12 +21,30 @@ sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, 'third_party',
|
|||
'android_testrunner'))
|
||||
import errors as old_errors
|
||||
|
||||
DEFAULT_TIMEOUT_ATTR = '_default_timeout'
|
||||
DEFAULT_RETRIES_ATTR = '_default_retries'
|
||||
|
||||
def _TimeoutRetryWrapper(f, timeout_func, retries_func):
|
||||
|
||||
def _TimeoutRetryWrapper(f, timeout_func, retries_func, pass_values=False):
|
||||
""" Wraps a funcion with timeout and retry handling logic.
|
||||
|
||||
Args:
|
||||
f: The function to wrap.
|
||||
timeout_func: A callable that returns the timeout value.
|
||||
retries_func: A callable that returns the retries value.
|
||||
pass_values: If True, passes the values returned by |timeout_func| and
|
||||
|retries_func| to the wrapped function as 'timeout' and
|
||||
'retries' kwargs, respectively.
|
||||
Returns:
|
||||
The wrapped function.
|
||||
"""
|
||||
@functools.wraps(f)
|
||||
def TimeoutRetryWrapper(*args, **kwargs):
|
||||
timeout = timeout_func(*args, **kwargs)
|
||||
retries = retries_func(*args, **kwargs)
|
||||
if pass_values:
|
||||
kwargs['timeout'] = timeout
|
||||
kwargs['retries'] = retries
|
||||
def impl():
|
||||
return f(*args, **kwargs)
|
||||
try:
|
||||
|
@ -41,15 +59,32 @@ def _TimeoutRetryWrapper(f, timeout_func, retries_func):
|
|||
|
||||
|
||||
def WithTimeoutAndRetries(f):
|
||||
"""A decorator that handles timeouts and retries."""
|
||||
"""A decorator that handles timeouts and retries.
|
||||
|
||||
'timeout' and 'retries' kwargs must be passed to the function.
|
||||
|
||||
Args:
|
||||
f: The function to decorate.
|
||||
Returns:
|
||||
The decorated function.
|
||||
"""
|
||||
get_timeout = lambda *a, **kw: kw['timeout']
|
||||
get_retries = lambda *a, **kw: kw['retries']
|
||||
return _TimeoutRetryWrapper(f, get_timeout, get_retries)
|
||||
|
||||
|
||||
def WithExplicitTimeoutAndRetries(timeout, retries):
|
||||
"""
|
||||
A decorator that handles timeouts and retries using the provided values.
|
||||
"""Returns a decorator that handles timeouts and retries.
|
||||
|
||||
The provided |timeout| and |retries| values are always used.
|
||||
|
||||
Args:
|
||||
timeout: The number of seconds to wait for the decorated function to
|
||||
return. Always used.
|
||||
retries: The number of times the decorated function should be retried on
|
||||
failure. Always used.
|
||||
Returns:
|
||||
The actual decorator.
|
||||
"""
|
||||
def decorator(f):
|
||||
get_timeout = lambda *a, **kw: timeout
|
||||
|
@ -59,26 +94,52 @@ def WithExplicitTimeoutAndRetries(timeout, retries):
|
|||
|
||||
|
||||
def WithTimeoutAndRetriesDefaults(default_timeout, default_retries):
|
||||
"""
|
||||
A decorator that handles timeouts and retries using the provided defaults.
|
||||
"""Returns a decorator that handles timeouts and retries.
|
||||
|
||||
The provided |default_timeout| and |default_retries| values are used only
|
||||
if timeout and retries values are not provided.
|
||||
|
||||
Args:
|
||||
default_timeout: The number of seconds to wait for the decorated function
|
||||
to return. Only used if a 'timeout' kwarg is not passed
|
||||
to the decorated function.
|
||||
default_retries: The number of times the decorated function should be
|
||||
retried on failure. Only used if a 'retries' kwarg is not
|
||||
passed to the decorated function.
|
||||
Returns:
|
||||
The actual decorator.
|
||||
"""
|
||||
def decorator(f):
|
||||
get_timeout = lambda *a, **kw: kw.get('timeout', default_timeout)
|
||||
get_retries = lambda *a, **kw: kw.get('retries', default_retries)
|
||||
return _TimeoutRetryWrapper(f, get_timeout, get_retries)
|
||||
return _TimeoutRetryWrapper(f, get_timeout, get_retries, pass_values=True)
|
||||
return decorator
|
||||
|
||||
|
||||
def WithTimeoutAndRetriesFromInstance(
|
||||
default_timeout_name, default_retries_name):
|
||||
"""
|
||||
A decorator that handles timeouts and retries using instance defaults.
|
||||
default_timeout_name=DEFAULT_TIMEOUT_ATTR,
|
||||
default_retries_name=DEFAULT_RETRIES_ATTR):
|
||||
"""Returns a decorator that handles timeouts and retries.
|
||||
|
||||
The provided |default_timeout_name| and |default_retries_name| are used to
|
||||
get the default timeout value and the default retries value from the object
|
||||
instance if timeout and retries values are not provided.
|
||||
|
||||
Note that this should only be used to decorate methods, not functions.
|
||||
|
||||
Args:
|
||||
default_timeout_name: The name of the default timeout attribute of the
|
||||
instance.
|
||||
default_retries_name: The name of the default retries attribute of the
|
||||
instance.
|
||||
Returns:
|
||||
The actual decorator.
|
||||
"""
|
||||
def decorator(f):
|
||||
def get_timeout(inst, *_args, **kwargs):
|
||||
return kwargs.get('timeout', getattr(inst, default_timeout_name))
|
||||
def get_retries(inst, *_args, **kwargs):
|
||||
return kwargs.get('retries', getattr(inst, default_retries_name))
|
||||
return _TimeoutRetryWrapper(f, get_timeout, get_retries)
|
||||
return _TimeoutRetryWrapper(f, get_timeout, get_retries, pass_values=True)
|
||||
return decorator
|
||||
|
||||
|
|
|
@ -8,12 +8,22 @@ Unit tests for decorators.py.
|
|||
|
||||
# pylint: disable=W0613
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import unittest
|
||||
|
||||
from pylib import constants
|
||||
from pylib.device import decorators
|
||||
from pylib.device import device_errors
|
||||
from pylib.utils import reraiser_thread
|
||||
|
||||
# TODO(jbudorick) Remove once the DeviceUtils implementations are no longer
|
||||
# backed by AndroidCommands / android_testrunner.
|
||||
sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, 'third_party',
|
||||
'android_testrunner'))
|
||||
import errors as old_errors
|
||||
|
||||
_DEFAULT_TIMEOUT = 30
|
||||
_DEFAULT_RETRIES = 3
|
||||
|
@ -69,6 +79,39 @@ class DecoratorsTest(unittest.TestCase):
|
|||
self.assertEquals(expected_timeout, actual_timeout)
|
||||
self.assertEquals(expected_retries, actual_retries)
|
||||
|
||||
def testFunctionDecoratorTranslatesOldExceptions(self):
|
||||
"""Tests that the explicit decorator translates old exceptions."""
|
||||
@decorators.WithTimeoutAndRetries
|
||||
def alwaysRaisesProvidedException(exception, timeout=None, retries=None):
|
||||
raise exception
|
||||
|
||||
exception_desc = 'Old response timeout error'
|
||||
with self.assertRaises(device_errors.CommandTimeoutError) as e:
|
||||
alwaysRaisesProvidedException(
|
||||
old_errors.WaitForResponseTimedOutError(exception_desc),
|
||||
timeout=10, retries=1)
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
exception_desc = 'Old device error'
|
||||
with self.assertRaises(device_errors.DeviceUnreachableError) as e:
|
||||
alwaysRaisesProvidedException(
|
||||
old_errors.DeviceUnresponsiveError(exception_desc),
|
||||
timeout=10, retries=1)
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
def testFunctionDecoratorTranslatesReraiserExceptions(self):
|
||||
"""Tests that the explicit decorator translates reraiser exceptions."""
|
||||
@decorators.WithTimeoutAndRetries
|
||||
def alwaysRaisesProvidedException(exception, timeout=None, retries=None):
|
||||
raise exception
|
||||
|
||||
exception_desc = 'Reraiser thread timeout error'
|
||||
with self.assertRaises(device_errors.CommandTimeoutError) as e:
|
||||
alwaysRaisesProvidedException(
|
||||
reraiser_thread.TimeoutError(exception_desc),
|
||||
timeout=10, retries=1)
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
def testDefaultsFunctionDecoratorDoesTimeouts(self):
|
||||
"""Tests that the defaults decorator handles timeout logic."""
|
||||
DecoratorsTest._decorated_function_called_count = 0
|
||||
|
@ -109,6 +152,52 @@ class DecoratorsTest(unittest.TestCase):
|
|||
alwaysRaisesCommandFailedError(retries=5)
|
||||
self.assertEquals(6, DecoratorsTest._decorated_function_called_count)
|
||||
|
||||
def testDefaultsFunctionDecoratorPassesValues(self):
|
||||
"""Tests that the defaults decorator passes timeout and retries kwargs."""
|
||||
@decorators.WithTimeoutAndRetriesDefaults(30, 10)
|
||||
def alwaysReturnsTimeouts(timeout=None, retries=None):
|
||||
return timeout
|
||||
|
||||
self.assertEquals(30, alwaysReturnsTimeouts())
|
||||
self.assertEquals(120, alwaysReturnsTimeouts(timeout=120))
|
||||
|
||||
@decorators.WithTimeoutAndRetriesDefaults(30, 10)
|
||||
def alwaysReturnsRetries(timeout=None, retries=None):
|
||||
return retries
|
||||
|
||||
self.assertEquals(10, alwaysReturnsRetries())
|
||||
self.assertEquals(1, alwaysReturnsRetries(retries=1))
|
||||
|
||||
def testDefaultsFunctionDecoratorTranslatesOldExceptions(self):
|
||||
"""Tests that the explicit decorator translates old exceptions."""
|
||||
@decorators.WithTimeoutAndRetriesDefaults(30, 10)
|
||||
def alwaysRaisesProvidedException(exception, timeout=None, retries=None):
|
||||
raise exception
|
||||
|
||||
exception_desc = 'Old response timeout error'
|
||||
with self.assertRaises(device_errors.CommandTimeoutError) as e:
|
||||
alwaysRaisesProvidedException(
|
||||
old_errors.WaitForResponseTimedOutError(exception_desc))
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
exception_desc = 'Old device error'
|
||||
with self.assertRaises(device_errors.DeviceUnreachableError) as e:
|
||||
alwaysRaisesProvidedException(
|
||||
old_errors.DeviceUnresponsiveError(exception_desc))
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
def testDefaultsFunctionDecoratorTranslatesReraiserExceptions(self):
|
||||
"""Tests that the explicit decorator translates reraiser exceptions."""
|
||||
@decorators.WithTimeoutAndRetriesDefaults(30, 10)
|
||||
def alwaysRaisesProvidedException(exception, timeout=None, retries=None):
|
||||
raise exception
|
||||
|
||||
exception_desc = 'Reraiser thread timeout error'
|
||||
with self.assertRaises(device_errors.CommandTimeoutError) as e:
|
||||
alwaysRaisesProvidedException(
|
||||
reraiser_thread.TimeoutError(exception_desc))
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
def testExplicitFunctionDecoratorDoesTimeouts(self):
|
||||
"""Tests that the explicit decorator handles timeout logic."""
|
||||
DecoratorsTest._decorated_function_called_count = 0
|
||||
|
@ -137,6 +226,36 @@ class DecoratorsTest(unittest.TestCase):
|
|||
alwaysRaisesCommandFailedError()
|
||||
self.assertEquals(11, DecoratorsTest._decorated_function_called_count)
|
||||
|
||||
def testExplicitDecoratorTranslatesOldExceptions(self):
|
||||
"""Tests that the explicit decorator translates old exceptions."""
|
||||
@decorators.WithExplicitTimeoutAndRetries(30, 10)
|
||||
def alwaysRaisesProvidedException(exception):
|
||||
raise exception
|
||||
|
||||
exception_desc = 'Old response timeout error'
|
||||
with self.assertRaises(device_errors.CommandTimeoutError) as e:
|
||||
alwaysRaisesProvidedException(
|
||||
old_errors.WaitForResponseTimedOutError(exception_desc))
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
exception_desc = 'Old device error'
|
||||
with self.assertRaises(device_errors.DeviceUnreachableError) as e:
|
||||
alwaysRaisesProvidedException(
|
||||
old_errors.DeviceUnresponsiveError(exception_desc))
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
def testExplicitDecoratorTranslatesReraiserExceptions(self):
|
||||
"""Tests that the explicit decorator translates reraiser exceptions."""
|
||||
@decorators.WithExplicitTimeoutAndRetries(30, 10)
|
||||
def alwaysRaisesProvidedException(exception):
|
||||
raise exception
|
||||
|
||||
exception_desc = 'Reraiser thread timeout error'
|
||||
with self.assertRaises(device_errors.CommandTimeoutError) as e:
|
||||
alwaysRaisesProvidedException(
|
||||
reraiser_thread.TimeoutError(exception_desc))
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
class _MethodDecoratorTestObject(object):
|
||||
"""An object suitable for testing the method decorator."""
|
||||
|
||||
|
@ -165,6 +284,26 @@ class DecoratorsTest(unittest.TestCase):
|
|||
raise device_errors.CommandFailedError(['testCommand'],
|
||||
'testCommand failed')
|
||||
|
||||
# pylint: disable=R0201
|
||||
|
||||
@decorators.WithTimeoutAndRetriesFromInstance(
|
||||
'default_timeout', 'default_retries')
|
||||
def alwaysReturnsTimeout(self, timeout=None, retries=None):
|
||||
return timeout
|
||||
|
||||
@decorators.WithTimeoutAndRetriesFromInstance(
|
||||
'default_timeout', 'default_retries')
|
||||
def alwaysReturnsRetries(self, timeout=None, retries=None):
|
||||
return retries
|
||||
|
||||
@decorators.WithTimeoutAndRetriesFromInstance(
|
||||
'default_timeout', 'default_retries')
|
||||
def alwaysRaisesProvidedException(self, exception, timeout=None,
|
||||
retries=None):
|
||||
raise exception
|
||||
|
||||
# pylint: enable=R0201
|
||||
|
||||
|
||||
def testMethodDecoratorDoesTimeout(self):
|
||||
"""Tests that the method decorator handles timeout logic."""
|
||||
|
@ -181,7 +320,7 @@ class DecoratorsTest(unittest.TestCase):
|
|||
self.assertEquals(1, test_obj.function_call_counters['alwaysTimesOut'])
|
||||
|
||||
def testMethodDecoratorDoesRetries(self):
|
||||
""" Tests that the method decorator handles retries logic."""
|
||||
"""Tests that the method decorator handles retries logic."""
|
||||
test_obj = self._MethodDecoratorTestObject(self)
|
||||
with self.assertRaises(device_errors.CommandFailedError):
|
||||
try:
|
||||
|
@ -192,8 +331,39 @@ class DecoratorsTest(unittest.TestCase):
|
|||
self.assertEquals(
|
||||
11, test_obj.function_call_counters['alwaysRaisesCommandFailedError'])
|
||||
|
||||
def testMethodDecoratorPassesValues(self):
|
||||
"""Tests that the method decorator passes timeout and retries kwargs."""
|
||||
test_obj = self._MethodDecoratorTestObject(
|
||||
self, default_timeout=42, default_retries=31)
|
||||
self.assertEquals(42, test_obj.alwaysReturnsTimeout())
|
||||
self.assertEquals(41, test_obj.alwaysReturnsTimeout(timeout=41))
|
||||
self.assertEquals(31, test_obj.alwaysReturnsRetries())
|
||||
self.assertEquals(32, test_obj.alwaysReturnsRetries(retries=32))
|
||||
|
||||
def testMethodDecoratorTranslatesOldExceptions(self):
|
||||
test_obj = self._MethodDecoratorTestObject(self)
|
||||
|
||||
exception_desc = 'Old response timeout error'
|
||||
with self.assertRaises(device_errors.CommandTimeoutError) as e:
|
||||
test_obj.alwaysRaisesProvidedException(
|
||||
old_errors.WaitForResponseTimedOutError(exception_desc))
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
exception_desc = 'Old device error'
|
||||
with self.assertRaises(device_errors.DeviceUnreachableError) as e:
|
||||
test_obj.alwaysRaisesProvidedException(
|
||||
old_errors.DeviceUnresponsiveError(exception_desc))
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
def testMethodDecoratorTranslatesReraiserExceptions(self):
|
||||
test_obj = self._MethodDecoratorTestObject(self)
|
||||
|
||||
exception_desc = 'Reraiser thread timeout error'
|
||||
with self.assertRaises(device_errors.CommandTimeoutError) as e:
|
||||
test_obj.alwaysRaisesProvidedException(
|
||||
reraiser_thread.TimeoutError(exception_desc))
|
||||
self.assertEquals(exception_desc, str(e.exception))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
unittest.main(verbosity=2)
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ Eventually, this will be based on adb_wrapper.
|
|||
"""
|
||||
# pylint: disable=W0613
|
||||
|
||||
import time
|
||||
|
||||
import pylib.android_commands
|
||||
from pylib.device import adb_wrapper
|
||||
from pylib.device import decorators
|
||||
|
@ -70,9 +72,10 @@ class DeviceUtils(object):
|
|||
raise ValueError('Unsupported type passed for argument "device"')
|
||||
self._default_timeout = default_timeout
|
||||
self._default_retries = default_retries
|
||||
assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR))
|
||||
assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR))
|
||||
|
||||
@decorators.WithTimeoutAndRetriesFromInstance(
|
||||
'_default_timeout', '_default_retries')
|
||||
@decorators.WithTimeoutAndRetriesFromInstance()
|
||||
def IsOnline(self, timeout=None, retries=None):
|
||||
""" Checks whether the device is online.
|
||||
|
||||
|
@ -86,8 +89,7 @@ class DeviceUtils(object):
|
|||
"""
|
||||
return self.old_interface.IsOnline()
|
||||
|
||||
@decorators.WithTimeoutAndRetriesFromInstance(
|
||||
'_default_timeout', '_default_retries')
|
||||
@decorators.WithTimeoutAndRetriesFromInstance()
|
||||
def HasRoot(self, timeout=None, retries=None):
|
||||
""" Checks whether or not adbd has root privileges.
|
||||
|
||||
|
@ -99,8 +101,7 @@ class DeviceUtils(object):
|
|||
"""
|
||||
return self.old_interface.IsRootEnabled()
|
||||
|
||||
@decorators.WithTimeoutAndRetriesFromInstance(
|
||||
'_default_timeout', '_default_retries')
|
||||
@decorators.WithTimeoutAndRetriesFromInstance()
|
||||
def EnableRoot(self, timeout=None, retries=None):
|
||||
""" Restarts adbd with root privileges.
|
||||
|
||||
|
@ -114,12 +115,51 @@ class DeviceUtils(object):
|
|||
raise device_errors.CommandFailedError(
|
||||
'adb root', 'Could not enable root.')
|
||||
|
||||
@decorators.WithTimeoutAndRetriesFromInstance()
|
||||
def GetExternalStoragePath(self, timeout=None, retries=None):
|
||||
""" Get the device's path to its SD card.
|
||||
|
||||
Args:
|
||||
timeout: Same as for |IsOnline|.
|
||||
retries: Same as for |IsOnline|.
|
||||
Returns:
|
||||
The device's path to its SD card.
|
||||
"""
|
||||
try:
|
||||
return self.old_interface.GetExternalStorage()
|
||||
except AssertionError as e:
|
||||
raise device_errors.CommandFailedError(str(e))
|
||||
|
||||
@decorators.WithTimeoutAndRetriesFromInstance()
|
||||
def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None):
|
||||
""" Wait for the device to fully boot.
|
||||
|
||||
This means waiting for the device to boot, the package manager to be
|
||||
available, and the SD card to be ready. It can optionally mean waiting
|
||||
for wifi to come up, too.
|
||||
|
||||
Args:
|
||||
wifi: A boolean indicating if we should wait for wifi to come up or not.
|
||||
timeout: Same as for |IsOnline|.
|
||||
retries: Same as for |IsOnline|.
|
||||
Raises:
|
||||
CommandTimeoutError if one of the component waits times out.
|
||||
DeviceUnreachableError if the device becomes unresponsive.
|
||||
"""
|
||||
self.old_interface.WaitForSystemBootCompleted(timeout)
|
||||
self.old_interface.WaitForDevicePm()
|
||||
self.old_interface.WaitForSdCardReady(timeout)
|
||||
if wifi:
|
||||
while not 'Wi-Fi is enabled' in (
|
||||
self.old_interface.RunShellCommand('dumpsys wifi')):
|
||||
time.sleep(0.1)
|
||||
|
||||
def __str__(self):
|
||||
"""Returns the device serial."""
|
||||
return self.old_interface.GetDevice()
|
||||
|
||||
@staticmethod
|
||||
def parallel(devices):
|
||||
def parallel(devices=None, async=False):
|
||||
""" Creates a Parallelizer to operate over the provided list of devices.
|
||||
|
||||
If |devices| is either |None| or an empty list, the Parallelizer will
|
||||
|
@ -127,13 +167,18 @@ class DeviceUtils(object):
|
|||
|
||||
Args:
|
||||
devices: A list of either DeviceUtils instances or objects from
|
||||
from which DeviceUtils instances can be constructed.
|
||||
from which DeviceUtils instances can be constructed. If None,
|
||||
all attached devices will be used.
|
||||
async: If true, returns a Parallelizer that runs operations
|
||||
asynchronously.
|
||||
Returns:
|
||||
A Parallelizer operating over |devices|.
|
||||
"""
|
||||
if not devices or len(devices) == 0:
|
||||
devices = pylib.android_commands.AndroidCommands.GetAttachedDevices()
|
||||
return parallelizer.Parallelizer([
|
||||
devices = pylib.android_commands.GetAttachedDevices()
|
||||
parallelizer_type = (parallelizer.Parallelizer if async
|
||||
else parallelizer.SyncParallelizer)
|
||||
return parallelizer_type([
|
||||
d if isinstance(d, DeviceUtils) else DeviceUtils(d)
|
||||
for d in devices])
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ Unit tests for the contents of device_utils.py (mostly DeviceUtils).
|
|||
# pylint: disable=W0613
|
||||
|
||||
import random
|
||||
import time
|
||||
import unittest
|
||||
|
||||
from pylib import android_commands
|
||||
|
@ -70,9 +71,13 @@ class DeviceUtilsTest(unittest.TestCase):
|
|||
@staticmethod
|
||||
def _getTestAdbWrapper():
|
||||
devices = adb_wrapper.AdbWrapper.GetDevices()
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < device_utils._DEFAULT_TIMEOUT:
|
||||
if devices:
|
||||
return random.choice(devices)
|
||||
return None
|
||||
time.sleep(1)
|
||||
raise device_errors.DeviceUnreachableError(
|
||||
'No devices available for testing...')
|
||||
|
||||
@staticmethod
|
||||
def _getUnusedSerial():
|
||||
|
@ -143,6 +148,30 @@ class DeviceUtilsTest(unittest.TestCase):
|
|||
d.EnableRoot()
|
||||
self.assertTrue(d.HasRoot())
|
||||
|
||||
def testGetExternalStorage(self):
|
||||
a = self._getTestAdbWrapper()
|
||||
d = device_utils.DeviceUtils(a)
|
||||
|
||||
actual_external_storage = a.Shell('echo $EXTERNAL_STORAGE').splitlines()[0]
|
||||
if actual_external_storage and len(actual_external_storage) != 0:
|
||||
self.assertEquals(actual_external_storage, d.GetExternalStoragePath())
|
||||
|
||||
def testWaitUntilFullyBooted(self):
|
||||
a = self._getTestAdbWrapper()
|
||||
d = device_utils.DeviceUtils(a)
|
||||
|
||||
a.Reboot()
|
||||
while a.GetState() == 'device':
|
||||
time.sleep(0.1)
|
||||
d.WaitUntilFullyBooted(wifi=True)
|
||||
self.assertEquals(
|
||||
'1', a.Shell('getprop sys.boot_completed').splitlines()[0])
|
||||
self.assertTrue(
|
||||
a.Shell('pm path android').splitlines()[0].startswith('package:'))
|
||||
self.assertTrue(a.Shell('ls $EXTERNAL_STORAGE'))
|
||||
self.assertTrue(
|
||||
'Wi-Fi is enabled' in a.Shell('dumpsys wifi').splitlines())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, buffer=True)
|
||||
|
|
|
@ -85,9 +85,14 @@ class TestPackageApk(TestPackage):
|
|||
# Content shell creates a profile on the sdscard which accumulates cache
|
||||
# files over time.
|
||||
if self.suite_name == 'content_browsertests':
|
||||
try:
|
||||
device.old_interface.RunShellCommand(
|
||||
'rm -r %s/content_shell' % device.old_interface.GetExternalStorage(),
|
||||
'rm -r %s/content_shell' % device.GetExternalStoragePath(),
|
||||
timeout_time=60 * 2)
|
||||
except device_errors.CommandFailedError:
|
||||
# TODO(jbudorick) Handle this exception appropriately once the
|
||||
# conversions are done.
|
||||
pass
|
||||
|
||||
#override
|
||||
def CreateCommandLineFileOnDevice(self, device, test_filter, test_arguments):
|
||||
|
|
|
@ -12,6 +12,7 @@ import tempfile
|
|||
from pylib import cmd_helper
|
||||
from pylib import constants
|
||||
from pylib import pexpect
|
||||
from pylib.device import device_errors
|
||||
from pylib.gtest.test_package import TestPackage
|
||||
|
||||
|
||||
|
@ -62,14 +63,17 @@ class TestPackageExecutable(TestPackage):
|
|||
# /code/chrome if GCOV_PREFIX_STRIP=3
|
||||
try:
|
||||
depth = os.environ['NATIVE_COVERAGE_DEPTH_STRIP']
|
||||
export_string = ('export GCOV_PREFIX="%s/gcov"\n' %
|
||||
device.GetExternalStoragePath())
|
||||
export_string += 'export GCOV_PREFIX_STRIP=%s\n' % depth
|
||||
return export_string
|
||||
except KeyError:
|
||||
logging.info('NATIVE_COVERAGE_DEPTH_STRIP is not defined: '
|
||||
'No native coverage.')
|
||||
return ''
|
||||
export_string = ('export GCOV_PREFIX="%s/gcov"\n' %
|
||||
device.old_interface.GetExternalStorage())
|
||||
export_string += 'export GCOV_PREFIX_STRIP=%s\n' % depth
|
||||
return export_string
|
||||
except device_errors.CommandFailedError:
|
||||
logging.info('No external storage found: No native coverage.')
|
||||
return ''
|
||||
|
||||
#override
|
||||
def ClearApplicationState(self, device):
|
||||
|
|
|
@ -61,14 +61,15 @@ class TestRunner(base_test_runner.BaseTestRunner):
|
|||
|
||||
#override
|
||||
def PushDataDeps(self):
|
||||
self.device.old_interface.WaitForSdCardReady(20)
|
||||
self.device.WaitUntilFullyBooted(timeout=20)
|
||||
self.tool.CopyFiles()
|
||||
if os.path.exists(constants.ISOLATE_DEPS_DIR):
|
||||
device_dir = self.device.old_interface.GetExternalStorage()
|
||||
# TODO(frankf): linux_dumper_unittest_helper needs to be in the same dir
|
||||
# as breakpad_unittests exe. Find a better way to do this.
|
||||
if self.test_package.suite_name == 'breakpad_unittests':
|
||||
device_dir = constants.TEST_EXECUTABLE_DIR
|
||||
else:
|
||||
device_dir = self.device.GetExternalStoragePath()
|
||||
for p in os.listdir(constants.ISOLATE_DEPS_DIR):
|
||||
self.device.old_interface.PushIfNeeded(
|
||||
os.path.join(constants.ISOLATE_DEPS_DIR, p),
|
||||
|
|
|
@ -104,11 +104,11 @@ class TestRunner(base_test_runner.BaseTestRunner):
|
|||
test_data = _GetDataFilesForTestSuite(self.test_pkg.GetApkName())
|
||||
if test_data:
|
||||
# Make sure SD card is ready.
|
||||
self.device.old_interface.WaitForSdCardReady(20)
|
||||
self.device.WaitUntilFullyBooted(timeout=20)
|
||||
for p in test_data:
|
||||
self.device.old_interface.PushIfNeeded(
|
||||
os.path.join(constants.DIR_SOURCE_ROOT, p),
|
||||
os.path.join(self.device.old_interface.GetExternalStorage(), p))
|
||||
os.path.join(self.device.GetExternalStoragePath(), p))
|
||||
|
||||
# TODO(frankf): Specify test data in this file as opposed to passing
|
||||
# as command-line.
|
||||
|
@ -121,7 +121,7 @@ class TestRunner(base_test_runner.BaseTestRunner):
|
|||
self.device.old_interface.PushIfNeeded(
|
||||
host_test_files_path,
|
||||
'%s/%s/%s' % (
|
||||
self.device.old_interface.GetExternalStorage(),
|
||||
self.device.GetExternalStoragePath(),
|
||||
TestRunner._DEVICE_DATA_DIR,
|
||||
dst_layer))
|
||||
self.tool.CopyFiles()
|
||||
|
@ -184,7 +184,7 @@ class TestRunner(base_test_runner.BaseTestRunner):
|
|||
if self.coverage_dir:
|
||||
coverage_basename = '%s.ec' % test
|
||||
self.coverage_device_file = '%s/%s/%s' % (
|
||||
self.device.old_interface.GetExternalStorage(),
|
||||
self.device.GetExternalStoragePath(),
|
||||
TestRunner._DEVICE_COVERAGE_DIR, coverage_basename)
|
||||
self.coverage_host_file = os.path.join(
|
||||
self.coverage_dir, coverage_basename)
|
||||
|
|
|
@ -31,7 +31,7 @@ class VideoRecorder(object):
|
|||
device = pylib.device.device_utils.DeviceUtils(device)
|
||||
self._device = device
|
||||
self._device_file = (
|
||||
'%s/screen-recording.mp4' % device.old_interface.GetExternalStorage())
|
||||
'%s/screen-recording.mp4' % device.GetExternalStoragePath())
|
||||
self._host_file = host_file or ('screen-recording-%s.mp4' %
|
||||
device.old_interface.GetTimestamp())
|
||||
self._host_file = os.path.abspath(self._host_file)
|
||||
|
|
|
@ -416,6 +416,8 @@ class Emulator(object):
|
|||
if wait_for_boot:
|
||||
# Now that we checked for obvious problems, wait for a boot complete.
|
||||
# Waiting for the package manager is sometimes problematic.
|
||||
# TODO(jbudorick) Convert this once waiting for the package manager and
|
||||
# the external storage is no longer problematic.
|
||||
d = device_utils.DeviceUtils(self.device_serial)
|
||||
d.old_interface.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT)
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ class Parallelizer(object):
|
|||
"""
|
||||
self.pGet(None)
|
||||
|
||||
r = Parallelizer(self._orig_objs)
|
||||
r = type(self)(self._orig_objs)
|
||||
r._objs = [getattr(o, name) for o in self._objs]
|
||||
return r
|
||||
|
||||
|
@ -92,7 +92,7 @@ class Parallelizer(object):
|
|||
"""
|
||||
self.pGet(None)
|
||||
|
||||
r = Parallelizer(self._orig_objs)
|
||||
r = type(self)(self._orig_objs)
|
||||
r._objs = [o[index] for o in self._objs]
|
||||
return r
|
||||
|
||||
|
@ -116,7 +116,7 @@ class Parallelizer(object):
|
|||
if not callable(o):
|
||||
raise AttributeError("'%s' is not callable" % o.__name__)
|
||||
|
||||
r = Parallelizer(self._orig_objs)
|
||||
r = type(self)(self._orig_objs)
|
||||
r._objs = reraiser_thread.ReraiserThreadGroup(
|
||||
[reraiser_thread.ReraiserThread(
|
||||
o, args=args, kwargs=kwargs,
|
||||
|
|
|
@ -6,7 +6,6 @@ import logging
|
|||
import psutil
|
||||
import signal
|
||||
|
||||
from pylib import android_commands
|
||||
from pylib.device import device_errors
|
||||
from pylib.device import device_utils
|
||||
|
||||
|
@ -31,23 +30,17 @@ def _KillWebServers():
|
|||
logging.warning('Failed waiting for %s to die. %s', p.pid, e)
|
||||
|
||||
|
||||
|
||||
def CleanupLeftoverProcesses():
|
||||
"""Clean up the test environment, restarting fresh adb and HTTP daemons."""
|
||||
_KillWebServers()
|
||||
did_restart_host_adb = False
|
||||
for device_serial in android_commands.GetAttachedDevices():
|
||||
device = device_utils.DeviceUtils(device_serial)
|
||||
# Make sure we restart the host adb server only once.
|
||||
if not did_restart_host_adb:
|
||||
device_utils.RestartServer()
|
||||
did_restart_host_adb = True
|
||||
device.old_interface.RestartAdbdOnDevice()
|
||||
p = device_utils.DeviceUtils.parallel()
|
||||
p.old_interface.RestartAdbdOnDevice()
|
||||
try:
|
||||
device.EnableRoot()
|
||||
p.EnableRoot()
|
||||
except device_errors.CommandFailedError as e:
|
||||
# TODO(jbudorick) Handle this exception appropriately after interface
|
||||
# conversions are finished.
|
||||
logging.error(str(e))
|
||||
device.old_interface.WaitForDevicePm()
|
||||
p.WaitUntilFullyBooted()
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ class AddressSanitizerTool(BaseTool):
|
|||
'--device', self._device.old_interface.GetDevice(),
|
||||
'--lib', self._lib,
|
||||
'--extra-options', AddressSanitizerTool.EXTRA_OPTIONS])
|
||||
self._device.old_interface.WaitForDevicePm()
|
||||
self._device.WaitUntilFullyBooted()
|
||||
|
||||
def GetTestWrapper(self):
|
||||
return AddressSanitizerTool.WRAPPER_NAME
|
||||
|
|
Загрузка…
Ссылка в новой задаче