1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# Copyright 2014 The Chromium Authors. All rights reserved.
2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# Use of this source code is governed by a BSD-style license that can be
3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# found in the LICENSE file.
4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez"""
6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezUnit tests for decorators.py.
7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez"""
8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# pylint: disable=W0613
10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport time
12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport traceback
13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport unittest
14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom devil.android import decorators
16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom devil.android import device_errors
17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom devil.utils import reraiser_thread
18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez_DEFAULT_TIMEOUT = 30
20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez_DEFAULT_RETRIES = 3
21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass DecoratorsTest(unittest.TestCase):
24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  _decorated_function_called_count = 0
25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testFunctionDecoratorDoesTimeouts(self):
27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the base decorator handles the timeout logic."""
28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DecoratorsTest._decorated_function_called_count = 0
29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetries
31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysTimesOut(timeout=None, retries=None):
32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      DecoratorsTest._decorated_function_called_count += 1
33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      time.sleep(100)
34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    start_time = time.time()
36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandTimeoutError):
37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysTimesOut(timeout=1, retries=0)
38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    elapsed_time = time.time() - start_time
39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertTrue(elapsed_time >= 1)
40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(1, DecoratorsTest._decorated_function_called_count)
41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testFunctionDecoratorDoesRetries(self):
43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the base decorator handles the retries logic."""
44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DecoratorsTest._decorated_function_called_count = 0
45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetries
47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesCommandFailedError(timeout=None, retries=None):
48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      DecoratorsTest._decorated_function_called_count += 1
49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise device_errors.CommandFailedError('testCommand failed')
50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandFailedError):
52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysRaisesCommandFailedError(timeout=30, retries=10)
53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(11, DecoratorsTest._decorated_function_called_count)
54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testFunctionDecoratorRequiresParams(self):
56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the base decorator requires timeout and retries params."""
57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetries
58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def requiresExplicitTimeoutAndRetries(timeout=None, retries=None):
59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return (timeout, retries)
60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(KeyError):
62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      requiresExplicitTimeoutAndRetries()
63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(KeyError):
64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      requiresExplicitTimeoutAndRetries(timeout=10)
65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(KeyError):
66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      requiresExplicitTimeoutAndRetries(retries=0)
67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    expected_timeout = 10
68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    expected_retries = 1
69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    (actual_timeout, actual_retries) = (
70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        requiresExplicitTimeoutAndRetries(timeout=expected_timeout,
71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                          retries=expected_retries))
72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(expected_timeout, actual_timeout)
73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(expected_retries, actual_retries)
74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testFunctionDecoratorTranslatesReraiserExceptions(self):
76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the explicit decorator translates reraiser exceptions."""
77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetries
78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesProvidedException(exception, timeout=None, retries=None):
79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise exception
80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    exception_desc = 'Reraiser thread timeout error'
82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandTimeoutError) as e:
83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysRaisesProvidedException(
84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          reraiser_thread.TimeoutError(exception_desc),
85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          timeout=10, retries=1)
86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(exception_desc, str(e.exception))
87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testConditionalRetriesDecoratorRetries(self):
89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def do_not_retry_no_adb_error(exc):
90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return not isinstance(exc, device_errors.NoAdbError)
91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    actual_tries = [0]
93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndConditionalRetries(do_not_retry_no_adb_error)
95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesCommandFailedError(timeout=None, retries=None):
96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      actual_tries[0] += 1
97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise device_errors.CommandFailedError('Command failed :(')
98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandFailedError):
100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysRaisesCommandFailedError(timeout=10, retries=10)
101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(11, actual_tries[0])
102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testConditionalRetriesDecoratorDoesntRetry(self):
104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def do_not_retry_no_adb_error(exc):
105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return not isinstance(exc, device_errors.NoAdbError)
106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    actual_tries = [0]
108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndConditionalRetries(do_not_retry_no_adb_error)
110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesNoAdbError(timeout=None, retries=None):
111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      actual_tries[0] += 1
112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise device_errors.NoAdbError()
113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.NoAdbError):
115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysRaisesNoAdbError(timeout=10, retries=10)
116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(1, actual_tries[0])
117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testDefaultsFunctionDecoratorDoesTimeouts(self):
119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the defaults decorator handles timeout logic."""
120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DecoratorsTest._decorated_function_called_count = 0
121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesDefaults(1, 0)
123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysTimesOut(timeout=None, retries=None):
124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      DecoratorsTest._decorated_function_called_count += 1
125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      time.sleep(100)
126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    start_time = time.time()
128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandTimeoutError):
129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysTimesOut()
130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    elapsed_time = time.time() - start_time
131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertTrue(elapsed_time >= 1)
132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(1, DecoratorsTest._decorated_function_called_count)
133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DecoratorsTest._decorated_function_called_count = 0
135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandTimeoutError):
136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysTimesOut(timeout=2)
137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    elapsed_time = time.time() - start_time
138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertTrue(elapsed_time >= 2)
139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(1, DecoratorsTest._decorated_function_called_count)
140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testDefaultsFunctionDecoratorDoesRetries(self):
142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the defaults decorator handles retries logic."""
143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DecoratorsTest._decorated_function_called_count = 0
144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesDefaults(30, 10)
146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesCommandFailedError(timeout=None, retries=None):
147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      DecoratorsTest._decorated_function_called_count += 1
148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise device_errors.CommandFailedError('testCommand failed')
149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandFailedError):
151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysRaisesCommandFailedError()
152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(11, DecoratorsTest._decorated_function_called_count)
153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DecoratorsTest._decorated_function_called_count = 0
155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandFailedError):
156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysRaisesCommandFailedError(retries=5)
157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(6, DecoratorsTest._decorated_function_called_count)
158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testDefaultsFunctionDecoratorPassesValues(self):
160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the defaults decorator passes timeout and retries kwargs."""
161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesDefaults(30, 10)
162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysReturnsTimeouts(timeout=None, retries=None):
163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return timeout
164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(30, alwaysReturnsTimeouts())
166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(120, alwaysReturnsTimeouts(timeout=120))
167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesDefaults(30, 10)
169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysReturnsRetries(timeout=None, retries=None):
170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return retries
171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(10, alwaysReturnsRetries())
173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(1, alwaysReturnsRetries(retries=1))
174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testDefaultsFunctionDecoratorTranslatesReraiserExceptions(self):
176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the explicit decorator translates reraiser exceptions."""
177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesDefaults(30, 10)
178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesProvidedException(exception, timeout=None, retries=None):
179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise exception
180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    exception_desc = 'Reraiser thread timeout error'
182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandTimeoutError) as e:
183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysRaisesProvidedException(
184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          reraiser_thread.TimeoutError(exception_desc))
185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(exception_desc, str(e.exception))
186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testExplicitFunctionDecoratorDoesTimeouts(self):
188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the explicit decorator handles timeout logic."""
189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DecoratorsTest._decorated_function_called_count = 0
190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithExplicitTimeoutAndRetries(1, 0)
192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysTimesOut():
193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      DecoratorsTest._decorated_function_called_count += 1
194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      time.sleep(100)
195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    start_time = time.time()
197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandTimeoutError):
198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysTimesOut()
199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    elapsed_time = time.time() - start_time
200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertTrue(elapsed_time >= 1)
201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(1, DecoratorsTest._decorated_function_called_count)
202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testExplicitFunctionDecoratorDoesRetries(self):
204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the explicit decorator handles retries logic."""
205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DecoratorsTest._decorated_function_called_count = 0
206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithExplicitTimeoutAndRetries(30, 10)
208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesCommandFailedError():
209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      DecoratorsTest._decorated_function_called_count += 1
210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise device_errors.CommandFailedError('testCommand failed')
211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandFailedError):
213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysRaisesCommandFailedError()
214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(11, DecoratorsTest._decorated_function_called_count)
215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testExplicitDecoratorTranslatesReraiserExceptions(self):
217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the explicit decorator translates reraiser exceptions."""
218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithExplicitTimeoutAndRetries(30, 10)
219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesProvidedException(exception):
220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise exception
221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    exception_desc = 'Reraiser thread timeout error'
223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandTimeoutError) as e:
224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      alwaysRaisesProvidedException(
225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          reraiser_thread.TimeoutError(exception_desc))
226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(exception_desc, str(e.exception))
227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  class _MethodDecoratorTestObject(object):
229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """An object suitable for testing the method decorator."""
230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def __init__(self, test_case, default_timeout=_DEFAULT_TIMEOUT,
232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                 default_retries=_DEFAULT_RETRIES):
233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      self._test_case = test_case
234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      self.default_timeout = default_timeout
235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      self.default_retries = default_retries
236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      self.function_call_counters = {
237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          'alwaysRaisesCommandFailedError': 0,
238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          'alwaysTimesOut': 0,
239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          'requiresExplicitTimeoutAndRetries': 0,
240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      }
241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesFromInstance(
243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        'default_timeout', 'default_retries')
244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysTimesOut(self, timeout=None, retries=None):
245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      self.function_call_counters['alwaysTimesOut'] += 1
246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      time.sleep(100)
247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      self._test_case.assertFalse(True, msg='Failed to time out?')
248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesFromInstance(
250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        'default_timeout', 'default_retries')
251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesCommandFailedError(self, timeout=None, retries=None):
252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      self.function_call_counters['alwaysRaisesCommandFailedError'] += 1
253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise device_errors.CommandFailedError('testCommand failed')
254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    # pylint: disable=no-self-use
256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesFromInstance(
258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        'default_timeout', 'default_retries')
259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysReturnsTimeout(self, timeout=None, retries=None):
260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return timeout
261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesFromInstance(
263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        'default_timeout', 'default_retries', min_default_timeout=100)
264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysReturnsTimeoutWithMin(self, timeout=None, retries=None):
265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return timeout
266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesFromInstance(
268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        'default_timeout', 'default_retries')
269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysReturnsRetries(self, timeout=None, retries=None):
270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return retries
271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    @decorators.WithTimeoutAndRetriesFromInstance(
273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        'default_timeout', 'default_retries')
274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def alwaysRaisesProvidedException(self, exception, timeout=None,
275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                      retries=None):
276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      raise exception
277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    # pylint: enable=no-self-use
279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testMethodDecoratorDoesTimeout(self):
281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the method decorator handles timeout logic."""
282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    test_obj = self._MethodDecoratorTestObject(self)
283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    start_time = time.time()
284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandTimeoutError):
285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      try:
286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        test_obj.alwaysTimesOut(timeout=1, retries=0)
287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      except:
288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        traceback.print_exc()
289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        raise
290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    elapsed_time = time.time() - start_time
291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertTrue(elapsed_time >= 1)
292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(1, test_obj.function_call_counters['alwaysTimesOut'])
293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testMethodDecoratorDoesRetries(self):
295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the method decorator handles retries logic."""
296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    test_obj = self._MethodDecoratorTestObject(self)
297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandFailedError):
298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      try:
299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        test_obj.alwaysRaisesCommandFailedError(retries=10)
300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      except:
301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        traceback.print_exc()
302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        raise
303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(
304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        11, test_obj.function_call_counters['alwaysRaisesCommandFailedError'])
305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testMethodDecoratorPassesValues(self):
307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Tests that the method decorator passes timeout and retries kwargs."""
308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    test_obj = self._MethodDecoratorTestObject(
309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        self, default_timeout=42, default_retries=31)
310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(42, test_obj.alwaysReturnsTimeout())
311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(41, test_obj.alwaysReturnsTimeout(timeout=41))
312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(31, test_obj.alwaysReturnsRetries())
313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(32, test_obj.alwaysReturnsRetries(retries=32))
314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testMethodDecoratorUsesMiniumumTimeout(self):
316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    test_obj = self._MethodDecoratorTestObject(
317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        self, default_timeout=42, default_retries=31)
318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(100, test_obj.alwaysReturnsTimeoutWithMin())
319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(41, test_obj.alwaysReturnsTimeoutWithMin(timeout=41))
320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  def testMethodDecoratorTranslatesReraiserExceptions(self):
322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    test_obj = self._MethodDecoratorTestObject(self)
323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    exception_desc = 'Reraiser thread timeout error'
325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with self.assertRaises(device_errors.CommandTimeoutError) as e:
326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      test_obj.alwaysRaisesProvidedException(
327645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          reraiser_thread.TimeoutError(exception_desc))
328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    self.assertEquals(exception_desc, str(e.exception))
329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezif __name__ == '__main__':
331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  unittest.main(verbosity=2)
332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
333