| 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 """ | 5 """ |
| 6 Unit tests for decorators.py. | 6 Unit tests for decorators.py. |
| 7 """ | 7 """ |
| 8 | 8 |
| 9 # pylint: disable=W0613 | 9 # pylint: disable=W0613 |
| 10 | 10 |
| 11 import os |
| 12 import sys |
| 11 import time | 13 import time |
| 12 import traceback | 14 import traceback |
| 13 import unittest | 15 import unittest |
| 14 | 16 |
| 17 from pylib import constants |
| 15 from pylib.device import decorators | 18 from pylib.device import decorators |
| 16 from pylib.device import device_errors | 19 from pylib.device import device_errors |
| 20 from pylib.utils import reraiser_thread |
| 21 |
| 22 # TODO(jbudorick) Remove once the DeviceUtils implementations are no longer |
| 23 # backed by AndroidCommands / android_testrunner. |
| 24 sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, 'third_party', |
| 25 'android_testrunner')) |
| 26 import errors as old_errors |
| 17 | 27 |
| 18 _DEFAULT_TIMEOUT = 30 | 28 _DEFAULT_TIMEOUT = 30 |
| 19 _DEFAULT_RETRIES = 3 | 29 _DEFAULT_RETRIES = 3 |
| 20 | 30 |
| 21 class DecoratorsTest(unittest.TestCase): | 31 class DecoratorsTest(unittest.TestCase): |
| 22 _decorated_function_called_count = 0 | 32 _decorated_function_called_count = 0 |
| 23 | 33 |
| 24 def testFunctionDecoratorDoesTimeouts(self): | 34 def testFunctionDecoratorDoesTimeouts(self): |
| 25 """Tests that the base decorator handles the timeout logic.""" | 35 """Tests that the base decorator handles the timeout logic.""" |
| 26 DecoratorsTest._decorated_function_called_count = 0 | 36 DecoratorsTest._decorated_function_called_count = 0 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 with self.assertRaises(KeyError): | 72 with self.assertRaises(KeyError): |
| 63 requiresExplicitTimeoutAndRetries(retries=0) | 73 requiresExplicitTimeoutAndRetries(retries=0) |
| 64 expected_timeout = 10 | 74 expected_timeout = 10 |
| 65 expected_retries = 1 | 75 expected_retries = 1 |
| 66 (actual_timeout, actual_retries) = ( | 76 (actual_timeout, actual_retries) = ( |
| 67 requiresExplicitTimeoutAndRetries(timeout=expected_timeout, | 77 requiresExplicitTimeoutAndRetries(timeout=expected_timeout, |
| 68 retries=expected_retries)) | 78 retries=expected_retries)) |
| 69 self.assertEquals(expected_timeout, actual_timeout) | 79 self.assertEquals(expected_timeout, actual_timeout) |
| 70 self.assertEquals(expected_retries, actual_retries) | 80 self.assertEquals(expected_retries, actual_retries) |
| 71 | 81 |
| 82 def testFunctionDecoratorTranslatesOldExceptions(self): |
| 83 """Tests that the explicit decorator translates old exceptions.""" |
| 84 @decorators.WithTimeoutAndRetries |
| 85 def alwaysRaisesProvidedException(exception, timeout=None, retries=None): |
| 86 raise exception |
| 87 |
| 88 exception_desc = 'Old response timeout error' |
| 89 with self.assertRaises(device_errors.CommandTimeoutError) as e: |
| 90 alwaysRaisesProvidedException( |
| 91 old_errors.WaitForResponseTimedOutError(exception_desc), |
| 92 timeout=10, retries=1) |
| 93 self.assertEquals(exception_desc, str(e.exception)) |
| 94 |
| 95 exception_desc = 'Old device error' |
| 96 with self.assertRaises(device_errors.DeviceUnreachableError) as e: |
| 97 alwaysRaisesProvidedException( |
| 98 old_errors.DeviceUnresponsiveError(exception_desc), |
| 99 timeout=10, retries=1) |
| 100 self.assertEquals(exception_desc, str(e.exception)) |
| 101 |
| 102 def testFunctionDecoratorTranslatesReraiserExceptions(self): |
| 103 """Tests that the explicit decorator translates reraiser exceptions.""" |
| 104 @decorators.WithTimeoutAndRetries |
| 105 def alwaysRaisesProvidedException(exception, timeout=None, retries=None): |
| 106 raise exception |
| 107 |
| 108 exception_desc = 'Reraiser thread timeout error' |
| 109 with self.assertRaises(device_errors.CommandTimeoutError) as e: |
| 110 alwaysRaisesProvidedException( |
| 111 reraiser_thread.TimeoutError(exception_desc), |
| 112 timeout=10, retries=1) |
| 113 self.assertEquals(exception_desc, str(e.exception)) |
| 114 |
| 72 def testDefaultsFunctionDecoratorDoesTimeouts(self): | 115 def testDefaultsFunctionDecoratorDoesTimeouts(self): |
| 73 """Tests that the defaults decorator handles timeout logic.""" | 116 """Tests that the defaults decorator handles timeout logic.""" |
| 74 DecoratorsTest._decorated_function_called_count = 0 | 117 DecoratorsTest._decorated_function_called_count = 0 |
| 75 @decorators.WithTimeoutAndRetriesDefaults(1, 0) | 118 @decorators.WithTimeoutAndRetriesDefaults(1, 0) |
| 76 def alwaysTimesOut(timeout=None, retries=None): | 119 def alwaysTimesOut(timeout=None, retries=None): |
| 77 DecoratorsTest._decorated_function_called_count += 1 | 120 DecoratorsTest._decorated_function_called_count += 1 |
| 78 time.sleep(100) | 121 time.sleep(100) |
| 79 | 122 |
| 80 start_time = time.time() | 123 start_time = time.time() |
| 81 with self.assertRaises(device_errors.CommandTimeoutError): | 124 with self.assertRaises(device_errors.CommandTimeoutError): |
| (...skipping 20 matching lines...) Expand all Loading... |
| 102 | 145 |
| 103 with self.assertRaises(device_errors.CommandFailedError): | 146 with self.assertRaises(device_errors.CommandFailedError): |
| 104 alwaysRaisesCommandFailedError() | 147 alwaysRaisesCommandFailedError() |
| 105 self.assertEquals(11, DecoratorsTest._decorated_function_called_count) | 148 self.assertEquals(11, DecoratorsTest._decorated_function_called_count) |
| 106 | 149 |
| 107 DecoratorsTest._decorated_function_called_count = 0 | 150 DecoratorsTest._decorated_function_called_count = 0 |
| 108 with self.assertRaises(device_errors.CommandFailedError): | 151 with self.assertRaises(device_errors.CommandFailedError): |
| 109 alwaysRaisesCommandFailedError(retries=5) | 152 alwaysRaisesCommandFailedError(retries=5) |
| 110 self.assertEquals(6, DecoratorsTest._decorated_function_called_count) | 153 self.assertEquals(6, DecoratorsTest._decorated_function_called_count) |
| 111 | 154 |
| 155 def testDefaultsFunctionDecoratorPassesValues(self): |
| 156 """Tests that the defaults decorator passes timeout and retries kwargs.""" |
| 157 @decorators.WithTimeoutAndRetriesDefaults(30, 10) |
| 158 def alwaysReturnsTimeouts(timeout=None, retries=None): |
| 159 return timeout |
| 160 |
| 161 self.assertEquals(30, alwaysReturnsTimeouts()) |
| 162 self.assertEquals(120, alwaysReturnsTimeouts(timeout=120)) |
| 163 |
| 164 @decorators.WithTimeoutAndRetriesDefaults(30, 10) |
| 165 def alwaysReturnsRetries(timeout=None, retries=None): |
| 166 return retries |
| 167 |
| 168 self.assertEquals(10, alwaysReturnsRetries()) |
| 169 self.assertEquals(1, alwaysReturnsRetries(retries=1)) |
| 170 |
| 171 def testDefaultsFunctionDecoratorTranslatesOldExceptions(self): |
| 172 """Tests that the explicit decorator translates old exceptions.""" |
| 173 @decorators.WithTimeoutAndRetriesDefaults(30, 10) |
| 174 def alwaysRaisesProvidedException(exception, timeout=None, retries=None): |
| 175 raise exception |
| 176 |
| 177 exception_desc = 'Old response timeout error' |
| 178 with self.assertRaises(device_errors.CommandTimeoutError) as e: |
| 179 alwaysRaisesProvidedException( |
| 180 old_errors.WaitForResponseTimedOutError(exception_desc)) |
| 181 self.assertEquals(exception_desc, str(e.exception)) |
| 182 |
| 183 exception_desc = 'Old device error' |
| 184 with self.assertRaises(device_errors.DeviceUnreachableError) as e: |
| 185 alwaysRaisesProvidedException( |
| 186 old_errors.DeviceUnresponsiveError(exception_desc)) |
| 187 self.assertEquals(exception_desc, str(e.exception)) |
| 188 |
| 189 def testDefaultsFunctionDecoratorTranslatesReraiserExceptions(self): |
| 190 """Tests that the explicit decorator translates reraiser exceptions.""" |
| 191 @decorators.WithTimeoutAndRetriesDefaults(30, 10) |
| 192 def alwaysRaisesProvidedException(exception, timeout=None, retries=None): |
| 193 raise exception |
| 194 |
| 195 exception_desc = 'Reraiser thread timeout error' |
| 196 with self.assertRaises(device_errors.CommandTimeoutError) as e: |
| 197 alwaysRaisesProvidedException( |
| 198 reraiser_thread.TimeoutError(exception_desc)) |
| 199 self.assertEquals(exception_desc, str(e.exception)) |
| 200 |
| 112 def testExplicitFunctionDecoratorDoesTimeouts(self): | 201 def testExplicitFunctionDecoratorDoesTimeouts(self): |
| 113 """Tests that the explicit decorator handles timeout logic.""" | 202 """Tests that the explicit decorator handles timeout logic.""" |
| 114 DecoratorsTest._decorated_function_called_count = 0 | 203 DecoratorsTest._decorated_function_called_count = 0 |
| 115 @decorators.WithExplicitTimeoutAndRetries(1, 0) | 204 @decorators.WithExplicitTimeoutAndRetries(1, 0) |
| 116 def alwaysTimesOut(): | 205 def alwaysTimesOut(): |
| 117 DecoratorsTest._decorated_function_called_count += 1 | 206 DecoratorsTest._decorated_function_called_count += 1 |
| 118 time.sleep(100) | 207 time.sleep(100) |
| 119 | 208 |
| 120 start_time = time.time() | 209 start_time = time.time() |
| 121 with self.assertRaises(device_errors.CommandTimeoutError): | 210 with self.assertRaises(device_errors.CommandTimeoutError): |
| 122 alwaysTimesOut() | 211 alwaysTimesOut() |
| 123 elapsed_time = time.time() - start_time | 212 elapsed_time = time.time() - start_time |
| 124 self.assertTrue(elapsed_time >= 1) | 213 self.assertTrue(elapsed_time >= 1) |
| 125 self.assertEquals(1, DecoratorsTest._decorated_function_called_count) | 214 self.assertEquals(1, DecoratorsTest._decorated_function_called_count) |
| 126 | 215 |
| 127 def testExplicitFunctionDecoratorDoesRetries(self): | 216 def testExplicitFunctionDecoratorDoesRetries(self): |
| 128 """Tests that the explicit decorator handles retries logic.""" | 217 """Tests that the explicit decorator handles retries logic.""" |
| 129 DecoratorsTest._decorated_function_called_count = 0 | 218 DecoratorsTest._decorated_function_called_count = 0 |
| 130 @decorators.WithExplicitTimeoutAndRetries(30, 10) | 219 @decorators.WithExplicitTimeoutAndRetries(30, 10) |
| 131 def alwaysRaisesCommandFailedError(): | 220 def alwaysRaisesCommandFailedError(): |
| 132 DecoratorsTest._decorated_function_called_count += 1 | 221 DecoratorsTest._decorated_function_called_count += 1 |
| 133 raise device_errors.CommandFailedError(['testCommand'], | 222 raise device_errors.CommandFailedError(['testCommand'], |
| 134 'testCommand failed') | 223 'testCommand failed') |
| 135 | 224 |
| 136 with self.assertRaises(device_errors.CommandFailedError): | 225 with self.assertRaises(device_errors.CommandFailedError): |
| 137 alwaysRaisesCommandFailedError() | 226 alwaysRaisesCommandFailedError() |
| 138 self.assertEquals(11, DecoratorsTest._decorated_function_called_count) | 227 self.assertEquals(11, DecoratorsTest._decorated_function_called_count) |
| 139 | 228 |
| 229 def testExplicitDecoratorTranslatesOldExceptions(self): |
| 230 """Tests that the explicit decorator translates old exceptions.""" |
| 231 @decorators.WithExplicitTimeoutAndRetries(30, 10) |
| 232 def alwaysRaisesProvidedException(exception): |
| 233 raise exception |
| 234 |
| 235 exception_desc = 'Old response timeout error' |
| 236 with self.assertRaises(device_errors.CommandTimeoutError) as e: |
| 237 alwaysRaisesProvidedException( |
| 238 old_errors.WaitForResponseTimedOutError(exception_desc)) |
| 239 self.assertEquals(exception_desc, str(e.exception)) |
| 240 |
| 241 exception_desc = 'Old device error' |
| 242 with self.assertRaises(device_errors.DeviceUnreachableError) as e: |
| 243 alwaysRaisesProvidedException( |
| 244 old_errors.DeviceUnresponsiveError(exception_desc)) |
| 245 self.assertEquals(exception_desc, str(e.exception)) |
| 246 |
| 247 def testExplicitDecoratorTranslatesReraiserExceptions(self): |
| 248 """Tests that the explicit decorator translates reraiser exceptions.""" |
| 249 @decorators.WithExplicitTimeoutAndRetries(30, 10) |
| 250 def alwaysRaisesProvidedException(exception): |
| 251 raise exception |
| 252 |
| 253 exception_desc = 'Reraiser thread timeout error' |
| 254 with self.assertRaises(device_errors.CommandTimeoutError) as e: |
| 255 alwaysRaisesProvidedException( |
| 256 reraiser_thread.TimeoutError(exception_desc)) |
| 257 self.assertEquals(exception_desc, str(e.exception)) |
| 258 |
| 140 class _MethodDecoratorTestObject(object): | 259 class _MethodDecoratorTestObject(object): |
| 141 """An object suitable for testing the method decorator.""" | 260 """An object suitable for testing the method decorator.""" |
| 142 | 261 |
| 143 def __init__(self, test_case, default_timeout=_DEFAULT_TIMEOUT, | 262 def __init__(self, test_case, default_timeout=_DEFAULT_TIMEOUT, |
| 144 default_retries=_DEFAULT_RETRIES): | 263 default_retries=_DEFAULT_RETRIES): |
| 145 self._test_case = test_case | 264 self._test_case = test_case |
| 146 self.default_timeout = default_timeout | 265 self.default_timeout = default_timeout |
| 147 self.default_retries = default_retries | 266 self.default_retries = default_retries |
| 148 self.function_call_counters = { | 267 self.function_call_counters = { |
| 149 'alwaysRaisesCommandFailedError': 0, | 268 'alwaysRaisesCommandFailedError': 0, |
| 150 'alwaysTimesOut': 0, | 269 'alwaysTimesOut': 0, |
| 151 'requiresExplicitTimeoutAndRetries': 0, | 270 'requiresExplicitTimeoutAndRetries': 0, |
| 152 } | 271 } |
| 153 | 272 |
| 154 @decorators.WithTimeoutAndRetriesFromInstance( | 273 @decorators.WithTimeoutAndRetriesFromInstance( |
| 155 'default_timeout', 'default_retries') | 274 'default_timeout', 'default_retries') |
| 156 def alwaysTimesOut(self, timeout=None, retries=None): | 275 def alwaysTimesOut(self, timeout=None, retries=None): |
| 157 self.function_call_counters['alwaysTimesOut'] += 1 | 276 self.function_call_counters['alwaysTimesOut'] += 1 |
| 158 time.sleep(100) | 277 time.sleep(100) |
| 159 self._test_case.assertFalse(True, msg='Failed to time out?') | 278 self._test_case.assertFalse(True, msg='Failed to time out?') |
| 160 | 279 |
| 161 @decorators.WithTimeoutAndRetriesFromInstance( | 280 @decorators.WithTimeoutAndRetriesFromInstance( |
| 162 'default_timeout', 'default_retries') | 281 'default_timeout', 'default_retries') |
| 163 def alwaysRaisesCommandFailedError(self, timeout=None, retries=None): | 282 def alwaysRaisesCommandFailedError(self, timeout=None, retries=None): |
| 164 self.function_call_counters['alwaysRaisesCommandFailedError'] += 1 | 283 self.function_call_counters['alwaysRaisesCommandFailedError'] += 1 |
| 165 raise device_errors.CommandFailedError(['testCommand'], | 284 raise device_errors.CommandFailedError(['testCommand'], |
| 166 'testCommand failed') | 285 'testCommand failed') |
| 167 | 286 |
| 287 # pylint: disable=R0201 |
| 288 |
| 289 @decorators.WithTimeoutAndRetriesFromInstance( |
| 290 'default_timeout', 'default_retries') |
| 291 def alwaysReturnsTimeout(self, timeout=None, retries=None): |
| 292 return timeout |
| 293 |
| 294 @decorators.WithTimeoutAndRetriesFromInstance( |
| 295 'default_timeout', 'default_retries') |
| 296 def alwaysReturnsRetries(self, timeout=None, retries=None): |
| 297 return retries |
| 298 |
| 299 @decorators.WithTimeoutAndRetriesFromInstance( |
| 300 'default_timeout', 'default_retries') |
| 301 def alwaysRaisesProvidedException(self, exception, timeout=None, |
| 302 retries=None): |
| 303 raise exception |
| 304 |
| 305 # pylint: enable=R0201 |
| 306 |
| 168 | 307 |
| 169 def testMethodDecoratorDoesTimeout(self): | 308 def testMethodDecoratorDoesTimeout(self): |
| 170 """Tests that the method decorator handles timeout logic.""" | 309 """Tests that the method decorator handles timeout logic.""" |
| 171 test_obj = self._MethodDecoratorTestObject(self) | 310 test_obj = self._MethodDecoratorTestObject(self) |
| 172 start_time = time.time() | 311 start_time = time.time() |
| 173 with self.assertRaises(device_errors.CommandTimeoutError): | 312 with self.assertRaises(device_errors.CommandTimeoutError): |
| 174 try: | 313 try: |
| 175 test_obj.alwaysTimesOut(timeout=1, retries=0) | 314 test_obj.alwaysTimesOut(timeout=1, retries=0) |
| 176 except: | 315 except: |
| 177 traceback.print_exc() | 316 traceback.print_exc() |
| 178 raise | 317 raise |
| 179 elapsed_time = time.time() - start_time | 318 elapsed_time = time.time() - start_time |
| 180 self.assertTrue(elapsed_time >= 1) | 319 self.assertTrue(elapsed_time >= 1) |
| 181 self.assertEquals(1, test_obj.function_call_counters['alwaysTimesOut']) | 320 self.assertEquals(1, test_obj.function_call_counters['alwaysTimesOut']) |
| 182 | 321 |
| 183 def testMethodDecoratorDoesRetries(self): | 322 def testMethodDecoratorDoesRetries(self): |
| 184 """ Tests that the method decorator handles retries logic.""" | 323 """Tests that the method decorator handles retries logic.""" |
| 185 test_obj = self._MethodDecoratorTestObject(self) | 324 test_obj = self._MethodDecoratorTestObject(self) |
| 186 with self.assertRaises(device_errors.CommandFailedError): | 325 with self.assertRaises(device_errors.CommandFailedError): |
| 187 try: | 326 try: |
| 188 test_obj.alwaysRaisesCommandFailedError(retries=10) | 327 test_obj.alwaysRaisesCommandFailedError(retries=10) |
| 189 except: | 328 except: |
| 190 traceback.print_exc() | 329 traceback.print_exc() |
| 191 raise | 330 raise |
| 192 self.assertEquals( | 331 self.assertEquals( |
| 193 11, test_obj.function_call_counters['alwaysRaisesCommandFailedError']) | 332 11, test_obj.function_call_counters['alwaysRaisesCommandFailedError']) |
| 194 | 333 |
| 334 def testMethodDecoratorPassesValues(self): |
| 335 """Tests that the method decorator passes timeout and retries kwargs.""" |
| 336 test_obj = self._MethodDecoratorTestObject( |
| 337 self, default_timeout=42, default_retries=31) |
| 338 self.assertEquals(42, test_obj.alwaysReturnsTimeout()) |
| 339 self.assertEquals(41, test_obj.alwaysReturnsTimeout(timeout=41)) |
| 340 self.assertEquals(31, test_obj.alwaysReturnsRetries()) |
| 341 self.assertEquals(32, test_obj.alwaysReturnsRetries(retries=32)) |
| 342 |
| 343 def testMethodDecoratorTranslatesOldExceptions(self): |
| 344 test_obj = self._MethodDecoratorTestObject(self) |
| 345 |
| 346 exception_desc = 'Old response timeout error' |
| 347 with self.assertRaises(device_errors.CommandTimeoutError) as e: |
| 348 test_obj.alwaysRaisesProvidedException( |
| 349 old_errors.WaitForResponseTimedOutError(exception_desc)) |
| 350 self.assertEquals(exception_desc, str(e.exception)) |
| 351 |
| 352 exception_desc = 'Old device error' |
| 353 with self.assertRaises(device_errors.DeviceUnreachableError) as e: |
| 354 test_obj.alwaysRaisesProvidedException( |
| 355 old_errors.DeviceUnresponsiveError(exception_desc)) |
| 356 self.assertEquals(exception_desc, str(e.exception)) |
| 357 |
| 358 def testMethodDecoratorTranslatesReraiserExceptions(self): |
| 359 test_obj = self._MethodDecoratorTestObject(self) |
| 360 |
| 361 exception_desc = 'Reraiser thread timeout error' |
| 362 with self.assertRaises(device_errors.CommandTimeoutError) as e: |
| 363 test_obj.alwaysRaisesProvidedException( |
| 364 reraiser_thread.TimeoutError(exception_desc)) |
| 365 self.assertEquals(exception_desc, str(e.exception)) |
| 195 | 366 |
| 196 if __name__ == '__main__': | 367 if __name__ == '__main__': |
| 197 unittest.main() | 368 unittest.main(verbosity=2) |
| 198 | 369 |
| 199 | |
| OLD | NEW |