• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python
2#pylint: disable-msg=C0111
3"""Unit Tests for autotest.client.common_lib.test"""
4
5__author__ = 'gps@google.com (Gregory P. Smith)'
6
7import unittest
8import common
9from autotest_lib.client.common_lib import test
10from autotest_lib.client.common_lib.test_utils import mock
11from autotest_lib.client.common_lib import error as common_lib_error
12
13class TestTestCase(unittest.TestCase):
14    class _neutered_base_test(test.base_test):
15        """A child class of base_test to avoid calling the constructor."""
16        def __init__(self, *args, **kwargs):
17            class MockJob(object):
18                pass
19            class MockProfilerManager(object):
20                def active(self):
21                    return False
22                def present(self):
23                    return True
24            self.job = MockJob()
25            self.job.default_profile_only = False
26            self.job.profilers = MockProfilerManager()
27            self.job.test_retry = 0
28            self._new_keyval = False
29            self.iteration = 0
30            self.before_iteration_hooks = []
31            self.after_iteration_hooks = []
32
33
34    def setUp(self):
35        self.god = mock.mock_god()
36        self.test = self._neutered_base_test()
37
38
39    def tearDown(self):
40        self.god.unstub_all()
41
42
43
44class Test_base_test_execute(TestTestCase):
45    # Test the various behaviors of the base_test.execute() method.
46    def setUp(self):
47        TestTestCase.setUp(self)
48        self.god.stub_function(self.test, 'run_once_profiling')
49        self.god.stub_function(self.test, 'postprocess')
50        self.god.stub_function(self.test, 'process_failed_constraints')
51
52
53    def test_call_run_once(self):
54        # setup
55        self.god.stub_function(self.test, 'drop_caches_between_iterations')
56        self.god.stub_function(self.test, 'run_once')
57        self.god.stub_function(self.test, 'postprocess_iteration')
58        self.god.stub_function(self.test, 'analyze_perf_constraints')
59        before_hook = self.god.create_mock_function('before_hook')
60        after_hook = self.god.create_mock_function('after_hook')
61        self.test.register_before_iteration_hook(before_hook)
62        self.test.register_after_iteration_hook(after_hook)
63
64        # tests the test._call_run_once implementation
65        self.test.drop_caches_between_iterations.expect_call()
66        before_hook.expect_call(self.test)
67        self.test.run_once.expect_call(1, 2, arg='val')
68        self.test.postprocess_iteration.expect_call()
69        self.test.analyze_perf_constraints.expect_call([])
70        after_hook.expect_call(self.test)
71        self.test._call_run_once([], False, None, (1, 2), {'arg': 'val'})
72        self.god.check_playback()
73
74
75    def test_call_run_once_with_exception(self):
76        # setup
77        self.god.stub_function(self.test, 'drop_caches_between_iterations')
78        self.god.stub_function(self.test, 'run_once')
79        before_hook = self.god.create_mock_function('before_hook')
80        after_hook = self.god.create_mock_function('after_hook')
81        self.test.register_before_iteration_hook(before_hook)
82        self.test.register_after_iteration_hook(after_hook)
83        error = Exception('fail')
84
85        # tests the test._call_run_once implementation
86        self.test.drop_caches_between_iterations.expect_call()
87        before_hook.expect_call(self.test)
88        self.test.run_once.expect_call(1, 2, arg='val').and_raises(error)
89        after_hook.expect_call(self.test)
90        try:
91            self.test._call_run_once([], False, None, (1, 2), {'arg': 'val'})
92        except:
93            pass
94        self.god.check_playback()
95
96
97    def _setup_failed_test_calls(self, fail_count, error):
98        """
99        Set up failed test calls for use with call_run_once_with_retry.
100
101        @param fail_count: The amount of times to mock a failure.
102        @param error: The error to raise while failing.
103        """
104        self.god.stub_function(self.test.job, 'record')
105        self.god.stub_function(self.test, '_call_run_once')
106        # tests the test._call_run_once implementation
107        for run in xrange(0, fail_count):
108            self.test._call_run_once.expect_call([], False, None, (1, 2),
109                                                 {'arg': 'val'}).and_raises(
110                                                          error)
111            info_str = 'Run %s failed with %s' % (run, error)
112            # On the final run we do not emit this message.
113            if run != self.test.job.test_retry and isinstance(error,
114                                               common_lib_error.TestFailRetry):
115                self.test.job.record.expect_call('INFO', None, None, info_str)
116
117
118    def test_call_run_once_with_retry_exception(self):
119        """
120        Test call_run_once_with_retry duplicating a test that will always fail.
121        """
122        self.test.job.test_retry = 5
123        self.god.stub_function(self.test, 'drop_caches_between_iterations')
124        self.god.stub_function(self.test, 'run_once')
125        before_hook = self.god.create_mock_function('before_hook')
126        after_hook = self.god.create_mock_function('after_hook')
127        self.test.register_before_iteration_hook(before_hook)
128        self.test.register_after_iteration_hook(after_hook)
129        error = common_lib_error.TestFailRetry('fail')
130        self._setup_failed_test_calls(self.test.job.test_retry+1, error)
131        try:
132            self.test._call_run_once_with_retry([], False, None, (1, 2),
133                                                {'arg': 'val'})
134        except Exception as err:
135            if err != error:
136                raise
137        self.god.check_playback()
138
139
140    def test_call_run_once_with_retry_exception_unretryable(self):
141        """
142        Test call_run_once_with_retry duplicating a test that will always fail
143        with a non-retryable exception.
144        """
145        self.test.job.test_retry = 5
146        self.god.stub_function(self.test, 'drop_caches_between_iterations')
147        self.god.stub_function(self.test, 'run_once')
148        before_hook = self.god.create_mock_function('before_hook')
149        after_hook = self.god.create_mock_function('after_hook')
150        self.test.register_before_iteration_hook(before_hook)
151        self.test.register_after_iteration_hook(after_hook)
152        error = common_lib_error.TestFail('fail')
153        self._setup_failed_test_calls(1, error)
154        try:
155            self.test._call_run_once_with_retry([], False, None, (1, 2),
156                                                {'arg': 'val'})
157        except Exception as err:
158            if err != error:
159                raise
160        self.god.check_playback()
161
162
163    def test_call_run_once_with_retry_exception_and_pass(self):
164        """
165        Test call_run_once_with_retry duplicating a test that fails at first
166        and later passes.
167        """
168        # Stubbed out for the write_keyval call.
169        self.test.outputdir = '/tmp'
170        self.test.job._tap = None
171
172        num_to_fail = 2
173        self.test.job.test_retry = 5
174        self.god.stub_function(self.test, 'drop_caches_between_iterations')
175        self.god.stub_function(self.test, 'run_once')
176        before_hook = self.god.create_mock_function('before_hook')
177        after_hook = self.god.create_mock_function('after_hook')
178        self.god.stub_function(self.test, '_call_run_once')
179        self.test.register_before_iteration_hook(before_hook)
180        self.test.register_after_iteration_hook(after_hook)
181        self.god.stub_function(self.test.job, 'record')
182        # tests the test._call_run_once implementation
183        error = common_lib_error.TestFailRetry('fail')
184        self._setup_failed_test_calls(num_to_fail, error)
185        # Passing call
186        self.test._call_run_once.expect_call([], False, None, (1, 2),
187                                             {'arg': 'val'})
188        self.test._call_run_once_with_retry([], False, None, (1, 2),
189                                            {'arg': 'val'})
190        self.god.check_playback()
191
192
193    def _expect_call_run_once(self):
194        self.test._call_run_once.expect_call((), False, None, (), {})
195
196
197    def test_execute_test_length(self):
198        # test that test_length overrides iterations and works.
199        self.god.stub_function(self.test, '_call_run_once')
200
201        self._expect_call_run_once()
202        self._expect_call_run_once()
203        self._expect_call_run_once()
204        self.test.run_once_profiling.expect_call(None)
205        self.test.postprocess.expect_call()
206        self.test.process_failed_constraints.expect_call()
207
208        fake_time = iter(xrange(4)).next
209        self.test.execute(iterations=1, test_length=3, _get_time=fake_time)
210        self.god.check_playback()
211
212
213    def test_execute_iterations(self):
214        # test that iterations works.
215        self.god.stub_function(self.test, '_call_run_once')
216
217        iterations = 2
218        for _ in range(iterations):
219            self._expect_call_run_once()
220        self.test.run_once_profiling.expect_call(None)
221        self.test.postprocess.expect_call()
222        self.test.process_failed_constraints.expect_call()
223
224        self.test.execute(iterations=iterations)
225        self.god.check_playback()
226
227
228    def _mock_calls_for_execute_no_iterations(self):
229        self.test.run_once_profiling.expect_call(None)
230        self.test.postprocess.expect_call()
231        self.test.process_failed_constraints.expect_call()
232
233
234    def test_execute_iteration_zero(self):
235        # test that iterations=0 works.
236        self._mock_calls_for_execute_no_iterations()
237
238        self.test.execute(iterations=0)
239        self.god.check_playback()
240
241
242    def test_execute_profile_only(self):
243        # test that profile_only=True works.
244        self.god.stub_function(self.test, 'drop_caches_between_iterations')
245        self.test.drop_caches_between_iterations.expect_call()
246        self.test.run_once_profiling.expect_call(None)
247        self.test.drop_caches_between_iterations.expect_call()
248        self.test.run_once_profiling.expect_call(None)
249        self.test.postprocess.expect_call()
250        self.test.process_failed_constraints.expect_call()
251        self.test.execute(profile_only=True, iterations=2)
252        self.god.check_playback()
253
254
255    def test_execute_default_profile_only(self):
256        # test that profile_only=True works.
257        self.god.stub_function(self.test, 'drop_caches_between_iterations')
258        for _ in xrange(3):
259            self.test.drop_caches_between_iterations.expect_call()
260            self.test.run_once_profiling.expect_call(None)
261        self.test.postprocess.expect_call()
262        self.test.process_failed_constraints.expect_call()
263        self.test.job.default_profile_only = True
264        self.test.execute(iterations=3)
265        self.god.check_playback()
266
267
268    def test_execute_postprocess_profiled_false(self):
269        # test that postprocess_profiled_run=False works
270        self.god.stub_function(self.test, '_call_run_once')
271
272        self.test._call_run_once.expect_call((), False, False, (), {})
273        self.test.run_once_profiling.expect_call(False)
274        self.test.postprocess.expect_call()
275        self.test.process_failed_constraints.expect_call()
276
277        self.test.execute(postprocess_profiled_run=False, iterations=1)
278        self.god.check_playback()
279
280
281    def test_execute_postprocess_profiled_true(self):
282        # test that postprocess_profiled_run=True works
283        self.god.stub_function(self.test, '_call_run_once')
284
285        self.test._call_run_once.expect_call((), False, True, (), {})
286        self.test.run_once_profiling.expect_call(True)
287        self.test.postprocess.expect_call()
288        self.test.process_failed_constraints.expect_call()
289
290        self.test.execute(postprocess_profiled_run=True, iterations=1)
291        self.god.check_playback()
292
293
294if __name__ == '__main__':
295    unittest.main()
296