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
3 # found in the LICENSE file.
6 Unit tests for decorators.py.
9 # pylint: disable=W0613
17 from pylib
import constants
18 from pylib
.device
import decorators
19 from pylib
.device
import device_errors
20 from pylib
.utils
import reraiser_thread
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
31 class DecoratorsTest(unittest
.TestCase
):
32 _decorated_function_called_count
= 0
34 def testFunctionDecoratorDoesTimeouts(self
):
35 """Tests that the base decorator handles the timeout logic."""
36 DecoratorsTest
._decorated
_function
_called
_count
= 0
37 @decorators.WithTimeoutAndRetries
38 def alwaysTimesOut(timeout
=None, retries
=None):
39 DecoratorsTest
._decorated
_function
_called
_count
+= 1
42 start_time
= time
.time()
43 with self
.assertRaises(device_errors
.CommandTimeoutError
):
44 alwaysTimesOut(timeout
=1, retries
=0)
45 elapsed_time
= time
.time() - start_time
46 self
.assertTrue(elapsed_time
>= 1)
47 self
.assertEquals(1, DecoratorsTest
._decorated
_function
_called
_count
)
49 def testFunctionDecoratorDoesRetries(self
):
50 """Tests that the base decorator handles the retries logic."""
51 DecoratorsTest
._decorated
_function
_called
_count
= 0
52 @decorators.WithTimeoutAndRetries
53 def alwaysRaisesCommandFailedError(timeout
=None, retries
=None):
54 DecoratorsTest
._decorated
_function
_called
_count
+= 1
55 raise device_errors
.CommandFailedError('testCommand failed')
57 with self
.assertRaises(device_errors
.CommandFailedError
):
58 alwaysRaisesCommandFailedError(timeout
=30, retries
=10)
59 self
.assertEquals(11, DecoratorsTest
._decorated
_function
_called
_count
)
61 def testFunctionDecoratorRequiresParams(self
):
62 """Tests that the base decorator requires timeout and retries params."""
63 @decorators.WithTimeoutAndRetries
64 def requiresExplicitTimeoutAndRetries(timeout
=None, retries
=None):
65 return (timeout
, retries
)
67 with self
.assertRaises(KeyError):
68 requiresExplicitTimeoutAndRetries()
69 with self
.assertRaises(KeyError):
70 requiresExplicitTimeoutAndRetries(timeout
=10)
71 with self
.assertRaises(KeyError):
72 requiresExplicitTimeoutAndRetries(retries
=0)
75 (actual_timeout
, actual_retries
) = (
76 requiresExplicitTimeoutAndRetries(timeout
=expected_timeout
,
77 retries
=expected_retries
))
78 self
.assertEquals(expected_timeout
, actual_timeout
)
79 self
.assertEquals(expected_retries
, actual_retries
)
81 def testFunctionDecoratorTranslatesOldExceptions(self
):
82 """Tests that the explicit decorator translates old exceptions."""
83 @decorators.WithTimeoutAndRetries
84 def alwaysRaisesProvidedException(exception
, timeout
=None, retries
=None):
87 exception_desc
= 'Old response timeout error'
88 with self
.assertRaises(device_errors
.CommandTimeoutError
) as e
:
89 alwaysRaisesProvidedException(
90 old_errors
.WaitForResponseTimedOutError(exception_desc
),
91 timeout
=10, retries
=1)
92 self
.assertEquals(exception_desc
, str(e
.exception
))
94 exception_desc
= 'Old device error'
95 with self
.assertRaises(device_errors
.DeviceUnreachableError
) as e
:
96 alwaysRaisesProvidedException(
97 old_errors
.DeviceUnresponsiveError(exception_desc
),
98 timeout
=10, retries
=1)
99 self
.assertEquals(exception_desc
, str(e
.exception
))
101 def testFunctionDecoratorTranslatesReraiserExceptions(self
):
102 """Tests that the explicit decorator translates reraiser exceptions."""
103 @decorators.WithTimeoutAndRetries
104 def alwaysRaisesProvidedException(exception
, timeout
=None, retries
=None):
107 exception_desc
= 'Reraiser thread timeout error'
108 with self
.assertRaises(device_errors
.CommandTimeoutError
) as e
:
109 alwaysRaisesProvidedException(
110 reraiser_thread
.TimeoutError(exception_desc
),
111 timeout
=10, retries
=1)
112 self
.assertEquals(exception_desc
, str(e
.exception
))
114 def testDefaultsFunctionDecoratorDoesTimeouts(self
):
115 """Tests that the defaults decorator handles timeout logic."""
116 DecoratorsTest
._decorated
_function
_called
_count
= 0
117 @decorators.WithTimeoutAndRetriesDefaults(1, 0)
118 def alwaysTimesOut(timeout
=None, retries
=None):
119 DecoratorsTest
._decorated
_function
_called
_count
+= 1
122 start_time
= time
.time()
123 with self
.assertRaises(device_errors
.CommandTimeoutError
):
125 elapsed_time
= time
.time() - start_time
126 self
.assertTrue(elapsed_time
>= 1)
127 self
.assertEquals(1, DecoratorsTest
._decorated
_function
_called
_count
)
129 DecoratorsTest
._decorated
_function
_called
_count
= 0
130 with self
.assertRaises(device_errors
.CommandTimeoutError
):
131 alwaysTimesOut(timeout
=2)
132 elapsed_time
= time
.time() - start_time
133 self
.assertTrue(elapsed_time
>= 2)
134 self
.assertEquals(1, DecoratorsTest
._decorated
_function
_called
_count
)
136 def testDefaultsFunctionDecoratorDoesRetries(self
):
137 """Tests that the defaults decorator handles retries logic."""
138 DecoratorsTest
._decorated
_function
_called
_count
= 0
139 @decorators.WithTimeoutAndRetriesDefaults(30, 10)
140 def alwaysRaisesCommandFailedError(timeout
=None, retries
=None):
141 DecoratorsTest
._decorated
_function
_called
_count
+= 1
142 raise device_errors
.CommandFailedError('testCommand failed')
144 with self
.assertRaises(device_errors
.CommandFailedError
):
145 alwaysRaisesCommandFailedError()
146 self
.assertEquals(11, DecoratorsTest
._decorated
_function
_called
_count
)
148 DecoratorsTest
._decorated
_function
_called
_count
= 0
149 with self
.assertRaises(device_errors
.CommandFailedError
):
150 alwaysRaisesCommandFailedError(retries
=5)
151 self
.assertEquals(6, DecoratorsTest
._decorated
_function
_called
_count
)
153 def testDefaultsFunctionDecoratorPassesValues(self
):
154 """Tests that the defaults decorator passes timeout and retries kwargs."""
155 @decorators.WithTimeoutAndRetriesDefaults(30, 10)
156 def alwaysReturnsTimeouts(timeout
=None, retries
=None):
159 self
.assertEquals(30, alwaysReturnsTimeouts())
160 self
.assertEquals(120, alwaysReturnsTimeouts(timeout
=120))
162 @decorators.WithTimeoutAndRetriesDefaults(30, 10)
163 def alwaysReturnsRetries(timeout
=None, retries
=None):
166 self
.assertEquals(10, alwaysReturnsRetries())
167 self
.assertEquals(1, alwaysReturnsRetries(retries
=1))
169 def testDefaultsFunctionDecoratorTranslatesOldExceptions(self
):
170 """Tests that the explicit decorator translates old exceptions."""
171 @decorators.WithTimeoutAndRetriesDefaults(30, 10)
172 def alwaysRaisesProvidedException(exception
, timeout
=None, retries
=None):
175 exception_desc
= 'Old response timeout error'
176 with self
.assertRaises(device_errors
.CommandTimeoutError
) as e
:
177 alwaysRaisesProvidedException(
178 old_errors
.WaitForResponseTimedOutError(exception_desc
))
179 self
.assertEquals(exception_desc
, str(e
.exception
))
181 exception_desc
= 'Old device error'
182 with self
.assertRaises(device_errors
.DeviceUnreachableError
) as e
:
183 alwaysRaisesProvidedException(
184 old_errors
.DeviceUnresponsiveError(exception_desc
))
185 self
.assertEquals(exception_desc
, str(e
.exception
))
187 def testDefaultsFunctionDecoratorTranslatesReraiserExceptions(self
):
188 """Tests that the explicit decorator translates reraiser exceptions."""
189 @decorators.WithTimeoutAndRetriesDefaults(30, 10)
190 def alwaysRaisesProvidedException(exception
, timeout
=None, retries
=None):
193 exception_desc
= 'Reraiser thread timeout error'
194 with self
.assertRaises(device_errors
.CommandTimeoutError
) as e
:
195 alwaysRaisesProvidedException(
196 reraiser_thread
.TimeoutError(exception_desc
))
197 self
.assertEquals(exception_desc
, str(e
.exception
))
199 def testExplicitFunctionDecoratorDoesTimeouts(self
):
200 """Tests that the explicit decorator handles timeout logic."""
201 DecoratorsTest
._decorated
_function
_called
_count
= 0
202 @decorators.WithExplicitTimeoutAndRetries(1, 0)
203 def alwaysTimesOut():
204 DecoratorsTest
._decorated
_function
_called
_count
+= 1
207 start_time
= time
.time()
208 with self
.assertRaises(device_errors
.CommandTimeoutError
):
210 elapsed_time
= time
.time() - start_time
211 self
.assertTrue(elapsed_time
>= 1)
212 self
.assertEquals(1, DecoratorsTest
._decorated
_function
_called
_count
)
214 def testExplicitFunctionDecoratorDoesRetries(self
):
215 """Tests that the explicit decorator handles retries logic."""
216 DecoratorsTest
._decorated
_function
_called
_count
= 0
217 @decorators.WithExplicitTimeoutAndRetries(30, 10)
218 def alwaysRaisesCommandFailedError():
219 DecoratorsTest
._decorated
_function
_called
_count
+= 1
220 raise device_errors
.CommandFailedError('testCommand failed')
222 with self
.assertRaises(device_errors
.CommandFailedError
):
223 alwaysRaisesCommandFailedError()
224 self
.assertEquals(11, DecoratorsTest
._decorated
_function
_called
_count
)
226 def testExplicitDecoratorTranslatesOldExceptions(self
):
227 """Tests that the explicit decorator translates old exceptions."""
228 @decorators.WithExplicitTimeoutAndRetries(30, 10)
229 def alwaysRaisesProvidedException(exception
):
232 exception_desc
= 'Old response timeout error'
233 with self
.assertRaises(device_errors
.CommandTimeoutError
) as e
:
234 alwaysRaisesProvidedException(
235 old_errors
.WaitForResponseTimedOutError(exception_desc
))
236 self
.assertEquals(exception_desc
, str(e
.exception
))
238 exception_desc
= 'Old device error'
239 with self
.assertRaises(device_errors
.DeviceUnreachableError
) as e
:
240 alwaysRaisesProvidedException(
241 old_errors
.DeviceUnresponsiveError(exception_desc
))
242 self
.assertEquals(exception_desc
, str(e
.exception
))
244 def testExplicitDecoratorTranslatesReraiserExceptions(self
):
245 """Tests that the explicit decorator translates reraiser exceptions."""
246 @decorators.WithExplicitTimeoutAndRetries(30, 10)
247 def alwaysRaisesProvidedException(exception
):
250 exception_desc
= 'Reraiser thread timeout error'
251 with self
.assertRaises(device_errors
.CommandTimeoutError
) as e
:
252 alwaysRaisesProvidedException(
253 reraiser_thread
.TimeoutError(exception_desc
))
254 self
.assertEquals(exception_desc
, str(e
.exception
))
256 class _MethodDecoratorTestObject(object):
257 """An object suitable for testing the method decorator."""
259 def __init__(self
, test_case
, default_timeout
=_DEFAULT_TIMEOUT
,
260 default_retries
=_DEFAULT_RETRIES
):
261 self
._test
_case
= test_case
262 self
.default_timeout
= default_timeout
263 self
.default_retries
= default_retries
264 self
.function_call_counters
= {
265 'alwaysRaisesCommandFailedError': 0,
267 'requiresExplicitTimeoutAndRetries': 0,
270 @decorators.WithTimeoutAndRetriesFromInstance(
271 'default_timeout', 'default_retries')
272 def alwaysTimesOut(self
, timeout
=None, retries
=None):
273 self
.function_call_counters
['alwaysTimesOut'] += 1
275 self
._test
_case
.assertFalse(True, msg
='Failed to time out?')
277 @decorators.WithTimeoutAndRetriesFromInstance(
278 'default_timeout', 'default_retries')
279 def alwaysRaisesCommandFailedError(self
, timeout
=None, retries
=None):
280 self
.function_call_counters
['alwaysRaisesCommandFailedError'] += 1
281 raise device_errors
.CommandFailedError('testCommand failed')
283 # pylint: disable=no-self-use
285 @decorators.WithTimeoutAndRetriesFromInstance(
286 'default_timeout', 'default_retries')
287 def alwaysReturnsTimeout(self
, timeout
=None, retries
=None):
290 @decorators.WithTimeoutAndRetriesFromInstance(
291 'default_timeout', 'default_retries')
292 def alwaysReturnsRetries(self
, timeout
=None, retries
=None):
295 @decorators.WithTimeoutAndRetriesFromInstance(
296 'default_timeout', 'default_retries')
297 def alwaysRaisesProvidedException(self
, exception
, timeout
=None,
301 # pylint: enable=no-self-use
304 def testMethodDecoratorDoesTimeout(self
):
305 """Tests that the method decorator handles timeout logic."""
306 test_obj
= self
._MethodDecoratorTestObject
(self
)
307 start_time
= time
.time()
308 with self
.assertRaises(device_errors
.CommandTimeoutError
):
310 test_obj
.alwaysTimesOut(timeout
=1, retries
=0)
312 traceback
.print_exc()
314 elapsed_time
= time
.time() - start_time
315 self
.assertTrue(elapsed_time
>= 1)
316 self
.assertEquals(1, test_obj
.function_call_counters
['alwaysTimesOut'])
318 def testMethodDecoratorDoesRetries(self
):
319 """Tests that the method decorator handles retries logic."""
320 test_obj
= self
._MethodDecoratorTestObject
(self
)
321 with self
.assertRaises(device_errors
.CommandFailedError
):
323 test_obj
.alwaysRaisesCommandFailedError(retries
=10)
325 traceback
.print_exc()
328 11, test_obj
.function_call_counters
['alwaysRaisesCommandFailedError'])
330 def testMethodDecoratorPassesValues(self
):
331 """Tests that the method decorator passes timeout and retries kwargs."""
332 test_obj
= self
._MethodDecoratorTestObject
(
333 self
, default_timeout
=42, default_retries
=31)
334 self
.assertEquals(42, test_obj
.alwaysReturnsTimeout())
335 self
.assertEquals(41, test_obj
.alwaysReturnsTimeout(timeout
=41))
336 self
.assertEquals(31, test_obj
.alwaysReturnsRetries())
337 self
.assertEquals(32, test_obj
.alwaysReturnsRetries(retries
=32))
339 def testMethodDecoratorTranslatesOldExceptions(self
):
340 test_obj
= self
._MethodDecoratorTestObject
(self
)
342 exception_desc
= 'Old response timeout error'
343 with self
.assertRaises(device_errors
.CommandTimeoutError
) as e
:
344 test_obj
.alwaysRaisesProvidedException(
345 old_errors
.WaitForResponseTimedOutError(exception_desc
))
346 self
.assertEquals(exception_desc
, str(e
.exception
))
348 exception_desc
= 'Old device error'
349 with self
.assertRaises(device_errors
.DeviceUnreachableError
) as e
:
350 test_obj
.alwaysRaisesProvidedException(
351 old_errors
.DeviceUnresponsiveError(exception_desc
))
352 self
.assertEquals(exception_desc
, str(e
.exception
))
354 def testMethodDecoratorTranslatesReraiserExceptions(self
):
355 test_obj
= self
._MethodDecoratorTestObject
(self
)
357 exception_desc
= 'Reraiser thread timeout error'
358 with self
.assertRaises(device_errors
.CommandTimeoutError
) as e
:
359 test_obj
.alwaysRaisesProvidedException(
360 reraiser_thread
.TimeoutError(exception_desc
))
361 self
.assertEquals(exception_desc
, str(e
.exception
))
363 if __name__
== '__main__':
364 unittest
.main(verbosity
=2)