| Index: build/android/pylib/device/decorators_test.py
|
| diff --git a/build/android/pylib/device/decorators_test.py b/build/android/pylib/device/decorators_test.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b75618b09e60d3160869dfd4130fd70f5e795a95
|
| --- /dev/null
|
| +++ b/build/android/pylib/device/decorators_test.py
|
| @@ -0,0 +1,365 @@
|
| +# Copyright 2014 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""
|
| +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
|
| +
|
| +class DecoratorsTest(unittest.TestCase):
|
| + _decorated_function_called_count = 0
|
| +
|
| + def testFunctionDecoratorDoesTimeouts(self):
|
| + """Tests that the base decorator handles the timeout logic."""
|
| + DecoratorsTest._decorated_function_called_count = 0
|
| + @decorators.WithTimeoutAndRetries
|
| + def alwaysTimesOut(timeout=None, retries=None):
|
| + DecoratorsTest._decorated_function_called_count += 1
|
| + time.sleep(100)
|
| +
|
| + start_time = time.time()
|
| + with self.assertRaises(device_errors.CommandTimeoutError):
|
| + alwaysTimesOut(timeout=1, retries=0)
|
| + elapsed_time = time.time() - start_time
|
| + self.assertTrue(elapsed_time >= 1)
|
| + self.assertEquals(1, DecoratorsTest._decorated_function_called_count)
|
| +
|
| + def testFunctionDecoratorDoesRetries(self):
|
| + """Tests that the base decorator handles the retries logic."""
|
| + DecoratorsTest._decorated_function_called_count = 0
|
| + @decorators.WithTimeoutAndRetries
|
| + def alwaysRaisesCommandFailedError(timeout=None, retries=None):
|
| + DecoratorsTest._decorated_function_called_count += 1
|
| + raise device_errors.CommandFailedError('testCommand failed')
|
| +
|
| + with self.assertRaises(device_errors.CommandFailedError):
|
| + alwaysRaisesCommandFailedError(timeout=30, retries=10)
|
| + self.assertEquals(11, DecoratorsTest._decorated_function_called_count)
|
| +
|
| + def testFunctionDecoratorRequiresParams(self):
|
| + """Tests that the base decorator requires timeout and retries params."""
|
| + @decorators.WithTimeoutAndRetries
|
| + def requiresExplicitTimeoutAndRetries(timeout=None, retries=None):
|
| + return (timeout, retries)
|
| +
|
| + with self.assertRaises(KeyError):
|
| + requiresExplicitTimeoutAndRetries()
|
| + with self.assertRaises(KeyError):
|
| + requiresExplicitTimeoutAndRetries(timeout=10)
|
| + with self.assertRaises(KeyError):
|
| + requiresExplicitTimeoutAndRetries(retries=0)
|
| + expected_timeout = 10
|
| + expected_retries = 1
|
| + (actual_timeout, actual_retries) = (
|
| + requiresExplicitTimeoutAndRetries(timeout=expected_timeout,
|
| + retries=expected_retries))
|
| + 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
|
| + @decorators.WithTimeoutAndRetriesDefaults(1, 0)
|
| + def alwaysTimesOut(timeout=None, retries=None):
|
| + DecoratorsTest._decorated_function_called_count += 1
|
| + time.sleep(100)
|
| +
|
| + start_time = time.time()
|
| + with self.assertRaises(device_errors.CommandTimeoutError):
|
| + alwaysTimesOut()
|
| + elapsed_time = time.time() - start_time
|
| + self.assertTrue(elapsed_time >= 1)
|
| + self.assertEquals(1, DecoratorsTest._decorated_function_called_count)
|
| +
|
| + DecoratorsTest._decorated_function_called_count = 0
|
| + with self.assertRaises(device_errors.CommandTimeoutError):
|
| + alwaysTimesOut(timeout=2)
|
| + elapsed_time = time.time() - start_time
|
| + self.assertTrue(elapsed_time >= 2)
|
| + self.assertEquals(1, DecoratorsTest._decorated_function_called_count)
|
| +
|
| + def testDefaultsFunctionDecoratorDoesRetries(self):
|
| + """Tests that the defaults decorator handles retries logic."""
|
| + DecoratorsTest._decorated_function_called_count = 0
|
| + @decorators.WithTimeoutAndRetriesDefaults(30, 10)
|
| + def alwaysRaisesCommandFailedError(timeout=None, retries=None):
|
| + DecoratorsTest._decorated_function_called_count += 1
|
| + raise device_errors.CommandFailedError('testCommand failed')
|
| +
|
| + with self.assertRaises(device_errors.CommandFailedError):
|
| + alwaysRaisesCommandFailedError()
|
| + self.assertEquals(11, DecoratorsTest._decorated_function_called_count)
|
| +
|
| + DecoratorsTest._decorated_function_called_count = 0
|
| + with self.assertRaises(device_errors.CommandFailedError):
|
| + 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
|
| + @decorators.WithExplicitTimeoutAndRetries(1, 0)
|
| + def alwaysTimesOut():
|
| + DecoratorsTest._decorated_function_called_count += 1
|
| + time.sleep(100)
|
| +
|
| + start_time = time.time()
|
| + with self.assertRaises(device_errors.CommandTimeoutError):
|
| + alwaysTimesOut()
|
| + elapsed_time = time.time() - start_time
|
| + self.assertTrue(elapsed_time >= 1)
|
| + self.assertEquals(1, DecoratorsTest._decorated_function_called_count)
|
| +
|
| + def testExplicitFunctionDecoratorDoesRetries(self):
|
| + """Tests that the explicit decorator handles retries logic."""
|
| + DecoratorsTest._decorated_function_called_count = 0
|
| + @decorators.WithExplicitTimeoutAndRetries(30, 10)
|
| + def alwaysRaisesCommandFailedError():
|
| + DecoratorsTest._decorated_function_called_count += 1
|
| + raise device_errors.CommandFailedError('testCommand failed')
|
| +
|
| + with self.assertRaises(device_errors.CommandFailedError):
|
| + 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."""
|
| +
|
| + def __init__(self, test_case, default_timeout=_DEFAULT_TIMEOUT,
|
| + default_retries=_DEFAULT_RETRIES):
|
| + self._test_case = test_case
|
| + self.default_timeout = default_timeout
|
| + self.default_retries = default_retries
|
| + self.function_call_counters = {
|
| + 'alwaysRaisesCommandFailedError': 0,
|
| + 'alwaysTimesOut': 0,
|
| + 'requiresExplicitTimeoutAndRetries': 0,
|
| + }
|
| +
|
| + @decorators.WithTimeoutAndRetriesFromInstance(
|
| + 'default_timeout', 'default_retries')
|
| + def alwaysTimesOut(self, timeout=None, retries=None):
|
| + self.function_call_counters['alwaysTimesOut'] += 1
|
| + time.sleep(100)
|
| + self._test_case.assertFalse(True, msg='Failed to time out?')
|
| +
|
| + @decorators.WithTimeoutAndRetriesFromInstance(
|
| + 'default_timeout', 'default_retries')
|
| + def alwaysRaisesCommandFailedError(self, timeout=None, retries=None):
|
| + self.function_call_counters['alwaysRaisesCommandFailedError'] += 1
|
| + raise device_errors.CommandFailedError('testCommand failed')
|
| +
|
| + # pylint: disable=no-self-use
|
| +
|
| + @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=no-self-use
|
| +
|
| +
|
| + def testMethodDecoratorDoesTimeout(self):
|
| + """Tests that the method decorator handles timeout logic."""
|
| + test_obj = self._MethodDecoratorTestObject(self)
|
| + start_time = time.time()
|
| + with self.assertRaises(device_errors.CommandTimeoutError):
|
| + try:
|
| + test_obj.alwaysTimesOut(timeout=1, retries=0)
|
| + except:
|
| + traceback.print_exc()
|
| + raise
|
| + elapsed_time = time.time() - start_time
|
| + self.assertTrue(elapsed_time >= 1)
|
| + self.assertEquals(1, test_obj.function_call_counters['alwaysTimesOut'])
|
| +
|
| + def testMethodDecoratorDoesRetries(self):
|
| + """Tests that the method decorator handles retries logic."""
|
| + test_obj = self._MethodDecoratorTestObject(self)
|
| + with self.assertRaises(device_errors.CommandFailedError):
|
| + try:
|
| + test_obj.alwaysRaisesCommandFailedError(retries=10)
|
| + except:
|
| + traceback.print_exc()
|
| + raise
|
| + 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(verbosity=2)
|
| +
|
|
|