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 |