blob: d701258e37ede2c96484b0d300919cfc969c0d9f [file] [log] [blame]
jadmanskia9894d02009-08-21 16:49:48 +00001#!/usr/bin/python
Aviv Keshet39164ca2013-03-27 15:08:33 -07002#pylint: disable-msg=C0111
mbligh234a84f2008-11-20 19:57:43 +00003"""Unit Tests for autotest.client.common_lib.test"""
4
5__author__ = 'gps@google.com (Gregory P. Smith)'
6
Keith Haddowd804bc82016-03-15 17:16:03 -07007import json
8import tempfile
mbligh234a84f2008-11-20 19:57:43 +00009import unittest
mbligh234a84f2008-11-20 19:57:43 +000010import common
Scott Zawalski91493c82013-01-25 16:15:20 -050011from autotest_lib.client.common_lib import test
mbligh234a84f2008-11-20 19:57:43 +000012from autotest_lib.client.common_lib.test_utils import mock
Aviv Keshet39164ca2013-03-27 15:08:33 -070013from autotest_lib.client.common_lib import error as common_lib_error
mbligh234a84f2008-11-20 19:57:43 +000014
mbligh4b835b82009-02-11 01:26:13 +000015class TestTestCase(unittest.TestCase):
mbligh234a84f2008-11-20 19:57:43 +000016 class _neutered_base_test(test.base_test):
17 """A child class of base_test to avoid calling the constructor."""
18 def __init__(self, *args, **kwargs):
mbligh4b835b82009-02-11 01:26:13 +000019 class MockJob(object):
20 pass
21 class MockProfilerManager(object):
22 def active(self):
23 return False
mblighc6bf6012009-10-02 00:02:15 +000024 def present(self):
25 return True
mbligh4b835b82009-02-11 01:26:13 +000026 self.job = MockJob()
showarda6082ef2009-10-12 20:25:44 +000027 self.job.default_profile_only = False
mbligh4b835b82009-02-11 01:26:13 +000028 self.job.profilers = MockProfilerManager()
Scott Zawalski91493c82013-01-25 16:15:20 -050029 self.job.test_retry = 0
jadmanskia93fbca2009-08-21 15:34:04 +000030 self._new_keyval = False
mbligh5e703a22009-06-15 22:00:12 +000031 self.iteration = 0
mbligh742ae422009-05-13 20:46:41 +000032 self.before_iteration_hooks = []
33 self.after_iteration_hooks = []
34
mbligh234a84f2008-11-20 19:57:43 +000035
36 def setUp(self):
37 self.god = mock.mock_god()
38 self.test = self._neutered_base_test()
mbligh234a84f2008-11-20 19:57:43 +000039
40
41 def tearDown(self):
42 self.god.unstub_all()
43
44
mbligh4b835b82009-02-11 01:26:13 +000045
mbligh4b835b82009-02-11 01:26:13 +000046class Test_base_test_execute(TestTestCase):
47 # Test the various behaviors of the base_test.execute() method.
48 def setUp(self):
49 TestTestCase.setUp(self)
mbligh4b835b82009-02-11 01:26:13 +000050 self.god.stub_function(self.test, 'run_once_profiling')
51 self.god.stub_function(self.test, 'postprocess')
mbligh32cb5b42009-05-01 23:05:09 +000052 self.god.stub_function(self.test, 'process_failed_constraints')
mbligh4b835b82009-02-11 01:26:13 +000053
mbligh4b835b82009-02-11 01:26:13 +000054
mbligh4395bbd2009-03-25 19:34:17 +000055 def test_call_run_once(self):
56 # setup
57 self.god.stub_function(self.test, 'drop_caches_between_iterations')
58 self.god.stub_function(self.test, 'run_once')
59 self.god.stub_function(self.test, 'postprocess_iteration')
mbligh7af09972009-04-17 22:17:08 +000060 self.god.stub_function(self.test, 'analyze_perf_constraints')
mbligh4395bbd2009-03-25 19:34:17 +000061 before_hook = self.god.create_mock_function('before_hook')
62 after_hook = self.god.create_mock_function('after_hook')
mbligh742ae422009-05-13 20:46:41 +000063 self.test.register_before_iteration_hook(before_hook)
64 self.test.register_after_iteration_hook(after_hook)
mbligh4395bbd2009-03-25 19:34:17 +000065
66 # tests the test._call_run_once implementation
67 self.test.drop_caches_between_iterations.expect_call()
showardd4ead172009-05-01 00:08:56 +000068 before_hook.expect_call(self.test)
mbligh4395bbd2009-03-25 19:34:17 +000069 self.test.run_once.expect_call(1, 2, arg='val')
mbligh4395bbd2009-03-25 19:34:17 +000070 self.test.postprocess_iteration.expect_call()
mbligh7af09972009-04-17 22:17:08 +000071 self.test.analyze_perf_constraints.expect_call([])
Eric Lidaf6ff02011-03-01 15:31:31 -080072 after_hook.expect_call(self.test)
jadmanskia93fbca2009-08-21 15:34:04 +000073 self.test._call_run_once([], False, None, (1, 2), {'arg': 'val'})
showardd4ead172009-05-01 00:08:56 +000074 self.god.check_playback()
mbligh4395bbd2009-03-25 19:34:17 +000075
76
Eric Lidaf6ff02011-03-01 15:31:31 -080077 def test_call_run_once_with_exception(self):
78 # setup
79 self.god.stub_function(self.test, 'drop_caches_between_iterations')
80 self.god.stub_function(self.test, 'run_once')
81 before_hook = self.god.create_mock_function('before_hook')
82 after_hook = self.god.create_mock_function('after_hook')
83 self.test.register_before_iteration_hook(before_hook)
84 self.test.register_after_iteration_hook(after_hook)
85 error = Exception('fail')
86
87 # tests the test._call_run_once implementation
88 self.test.drop_caches_between_iterations.expect_call()
89 before_hook.expect_call(self.test)
90 self.test.run_once.expect_call(1, 2, arg='val').and_raises(error)
91 after_hook.expect_call(self.test)
92 try:
93 self.test._call_run_once([], False, None, (1, 2), {'arg': 'val'})
94 except:
95 pass
96 self.god.check_playback()
97
98
Scott Zawalski91493c82013-01-25 16:15:20 -050099 def _setup_failed_test_calls(self, fail_count, error):
100 """
101 Set up failed test calls for use with call_run_once_with_retry.
102
103 @param fail_count: The amount of times to mock a failure.
104 @param error: The error to raise while failing.
105 """
106 self.god.stub_function(self.test.job, 'record')
107 self.god.stub_function(self.test, '_call_run_once')
108 # tests the test._call_run_once implementation
109 for run in xrange(0, fail_count):
110 self.test._call_run_once.expect_call([], False, None, (1, 2),
111 {'arg': 'val'}).and_raises(
112 error)
113 info_str = 'Run %s failed with %s' % (run, error)
114 # On the final run we do not emit this message.
Aviv Keshet39164ca2013-03-27 15:08:33 -0700115 if run != self.test.job.test_retry and isinstance(error,
116 common_lib_error.TestFailRetry):
Scott Zawalski91493c82013-01-25 16:15:20 -0500117 self.test.job.record.expect_call('INFO', None, None, info_str)
118
119
120 def test_call_run_once_with_retry_exception(self):
121 """
122 Test call_run_once_with_retry duplicating a test that will always fail.
123 """
124 self.test.job.test_retry = 5
125 self.god.stub_function(self.test, 'drop_caches_between_iterations')
126 self.god.stub_function(self.test, 'run_once')
127 before_hook = self.god.create_mock_function('before_hook')
128 after_hook = self.god.create_mock_function('after_hook')
129 self.test.register_before_iteration_hook(before_hook)
130 self.test.register_after_iteration_hook(after_hook)
Aviv Keshet39164ca2013-03-27 15:08:33 -0700131 error = common_lib_error.TestFailRetry('fail')
Scott Zawalski91493c82013-01-25 16:15:20 -0500132 self._setup_failed_test_calls(self.test.job.test_retry+1, error)
133 try:
134 self.test._call_run_once_with_retry([], False, None, (1, 2),
135 {'arg': 'val'})
136 except Exception as err:
137 if err != error:
138 raise
139 self.god.check_playback()
140
141
Aviv Keshet39164ca2013-03-27 15:08:33 -0700142 def test_call_run_once_with_retry_exception_unretryable(self):
143 """
144 Test call_run_once_with_retry duplicating a test that will always fail
145 with a non-retryable exception.
146 """
147 self.test.job.test_retry = 5
148 self.god.stub_function(self.test, 'drop_caches_between_iterations')
149 self.god.stub_function(self.test, 'run_once')
150 before_hook = self.god.create_mock_function('before_hook')
151 after_hook = self.god.create_mock_function('after_hook')
152 self.test.register_before_iteration_hook(before_hook)
153 self.test.register_after_iteration_hook(after_hook)
154 error = common_lib_error.TestFail('fail')
155 self._setup_failed_test_calls(1, error)
156 try:
157 self.test._call_run_once_with_retry([], False, None, (1, 2),
158 {'arg': 'val'})
159 except Exception as err:
160 if err != error:
161 raise
162 self.god.check_playback()
163
164
Scott Zawalski91493c82013-01-25 16:15:20 -0500165 def test_call_run_once_with_retry_exception_and_pass(self):
166 """
167 Test call_run_once_with_retry duplicating a test that fails at first
168 and later passes.
169 """
170 # Stubbed out for the write_keyval call.
171 self.test.outputdir = '/tmp'
172 self.test.job._tap = None
173
174 num_to_fail = 2
175 self.test.job.test_retry = 5
176 self.god.stub_function(self.test, 'drop_caches_between_iterations')
177 self.god.stub_function(self.test, 'run_once')
178 before_hook = self.god.create_mock_function('before_hook')
179 after_hook = self.god.create_mock_function('after_hook')
180 self.god.stub_function(self.test, '_call_run_once')
181 self.test.register_before_iteration_hook(before_hook)
182 self.test.register_after_iteration_hook(after_hook)
183 self.god.stub_function(self.test.job, 'record')
184 # tests the test._call_run_once implementation
Aviv Keshet39164ca2013-03-27 15:08:33 -0700185 error = common_lib_error.TestFailRetry('fail')
Scott Zawalski91493c82013-01-25 16:15:20 -0500186 self._setup_failed_test_calls(num_to_fail, error)
187 # Passing call
188 self.test._call_run_once.expect_call([], False, None, (1, 2),
189 {'arg': 'val'})
190 self.test._call_run_once_with_retry([], False, None, (1, 2),
191 {'arg': 'val'})
192 self.god.check_playback()
193
194
mbligh4395bbd2009-03-25 19:34:17 +0000195 def _expect_call_run_once(self):
jadmanskia93fbca2009-08-21 15:34:04 +0000196 self.test._call_run_once.expect_call((), False, None, (), {})
mbligh4395bbd2009-03-25 19:34:17 +0000197
198
mbligh4b835b82009-02-11 01:26:13 +0000199 def test_execute_test_length(self):
200 # test that test_length overrides iterations and works.
mbligh4395bbd2009-03-25 19:34:17 +0000201 self.god.stub_function(self.test, '_call_run_once')
202
203 self._expect_call_run_once()
204 self._expect_call_run_once()
205 self._expect_call_run_once()
mbligha49c5cb2009-02-26 01:01:09 +0000206 self.test.run_once_profiling.expect_call(None)
mbligh4b835b82009-02-11 01:26:13 +0000207 self.test.postprocess.expect_call()
mbligh32cb5b42009-05-01 23:05:09 +0000208 self.test.process_failed_constraints.expect_call()
mbligh4b835b82009-02-11 01:26:13 +0000209
210 fake_time = iter(xrange(4)).next
211 self.test.execute(iterations=1, test_length=3, _get_time=fake_time)
212 self.god.check_playback()
213
214
215 def test_execute_iterations(self):
216 # test that iterations works.
mbligh4395bbd2009-03-25 19:34:17 +0000217 self.god.stub_function(self.test, '_call_run_once')
218
mbligh4b835b82009-02-11 01:26:13 +0000219 iterations = 2
220 for _ in range(iterations):
mbligh4395bbd2009-03-25 19:34:17 +0000221 self._expect_call_run_once()
mbligha49c5cb2009-02-26 01:01:09 +0000222 self.test.run_once_profiling.expect_call(None)
mbligh4b835b82009-02-11 01:26:13 +0000223 self.test.postprocess.expect_call()
mbligh32cb5b42009-05-01 23:05:09 +0000224 self.test.process_failed_constraints.expect_call()
mbligh4b835b82009-02-11 01:26:13 +0000225
226 self.test.execute(iterations=iterations)
227 self.god.check_playback()
228
229
230 def _mock_calls_for_execute_no_iterations(self):
mbligha49c5cb2009-02-26 01:01:09 +0000231 self.test.run_once_profiling.expect_call(None)
mbligh4b835b82009-02-11 01:26:13 +0000232 self.test.postprocess.expect_call()
mbligh32cb5b42009-05-01 23:05:09 +0000233 self.test.process_failed_constraints.expect_call()
mbligh4b835b82009-02-11 01:26:13 +0000234
235
236 def test_execute_iteration_zero(self):
237 # test that iterations=0 works.
238 self._mock_calls_for_execute_no_iterations()
239
240 self.test.execute(iterations=0)
241 self.god.check_playback()
242
243
244 def test_execute_profile_only(self):
mblighc6bf6012009-10-02 00:02:15 +0000245 # test that profile_only=True works.
jadmanskia93fbca2009-08-21 15:34:04 +0000246 self.god.stub_function(self.test, 'drop_caches_between_iterations')
247 self.test.drop_caches_between_iterations.expect_call()
248 self.test.run_once_profiling.expect_call(None)
249 self.test.drop_caches_between_iterations.expect_call()
250 self.test.run_once_profiling.expect_call(None)
251 self.test.postprocess.expect_call()
252 self.test.process_failed_constraints.expect_call()
mbligh4b835b82009-02-11 01:26:13 +0000253 self.test.execute(profile_only=True, iterations=2)
254 self.god.check_playback()
255
256
showarda6082ef2009-10-12 20:25:44 +0000257 def test_execute_default_profile_only(self):
258 # test that profile_only=True works.
259 self.god.stub_function(self.test, 'drop_caches_between_iterations')
260 for _ in xrange(3):
261 self.test.drop_caches_between_iterations.expect_call()
262 self.test.run_once_profiling.expect_call(None)
263 self.test.postprocess.expect_call()
264 self.test.process_failed_constraints.expect_call()
265 self.test.job.default_profile_only = True
266 self.test.execute(iterations=3)
267 self.god.check_playback()
268
269
mbligha49c5cb2009-02-26 01:01:09 +0000270 def test_execute_postprocess_profiled_false(self):
271 # test that postprocess_profiled_run=False works
mbligh4395bbd2009-03-25 19:34:17 +0000272 self.god.stub_function(self.test, '_call_run_once')
273
jadmanskia93fbca2009-08-21 15:34:04 +0000274 self.test._call_run_once.expect_call((), False, False, (), {})
mbligha49c5cb2009-02-26 01:01:09 +0000275 self.test.run_once_profiling.expect_call(False)
276 self.test.postprocess.expect_call()
mbligh32cb5b42009-05-01 23:05:09 +0000277 self.test.process_failed_constraints.expect_call()
mbligha49c5cb2009-02-26 01:01:09 +0000278
279 self.test.execute(postprocess_profiled_run=False, iterations=1)
280 self.god.check_playback()
281
282
283 def test_execute_postprocess_profiled_true(self):
284 # test that postprocess_profiled_run=True works
mbligh4395bbd2009-03-25 19:34:17 +0000285 self.god.stub_function(self.test, '_call_run_once')
286
jadmanskia93fbca2009-08-21 15:34:04 +0000287 self.test._call_run_once.expect_call((), False, True, (), {})
mbligha49c5cb2009-02-26 01:01:09 +0000288 self.test.run_once_profiling.expect_call(True)
289 self.test.postprocess.expect_call()
mbligh32cb5b42009-05-01 23:05:09 +0000290 self.test.process_failed_constraints.expect_call()
mbligha49c5cb2009-02-26 01:01:09 +0000291
292 self.test.execute(postprocess_profiled_run=True, iterations=1)
293 self.god.check_playback()
294
295
Keith Haddowd804bc82016-03-15 17:16:03 -0700296 def test_output_single_perf_value(self):
297 self.test.resultsdir = tempfile.mkdtemp()
298
299 self.test.output_perf_value("Test", 1, units="ms", higher_is_better=True)
300
301 f = open(self.test.resultsdir + "/results-chart.json")
302 expected_result = {"Test": {"summary": {"units": "ms", "type": "scalar",
303 "value": 1, "improvement_direction": "up"}}}
304 self.assertDictEqual(expected_result, json.loads(f.read()))
305
306
307 def test_output_single_perf_value_twice(self):
308 self.test.resultsdir = tempfile.mkdtemp()
309
310 self.test.output_perf_value("Test", 1, units="ms", higher_is_better=True)
311 self.test.output_perf_value("Test", 2, units="ms", higher_is_better=True)
312
313 f = open(self.test.resultsdir + "/results-chart.json")
Keith Haddow4fc24652016-03-16 10:08:17 -0700314 expected_result = {"Test": {"summary": {"units": "ms",
315 "type": "list_of_scalar_values", "values": [1, 2],
316 "improvement_direction": "up"}}}
Keith Haddowd804bc82016-03-15 17:16:03 -0700317 self.assertDictEqual(expected_result, json.loads(f.read()))
318
319
320 def test_output_single_perf_value_three_times(self):
321 self.test.resultsdir = tempfile.mkdtemp()
322
Keith Haddow4fc24652016-03-16 10:08:17 -0700323 self.test.output_perf_value("Test", 1, units="ms",
324 higher_is_better=True)
Keith Haddowd804bc82016-03-15 17:16:03 -0700325 self.test.output_perf_value("Test", 2, units="ms", higher_is_better=True)
326 self.test.output_perf_value("Test", 3, units="ms", higher_is_better=True)
327
328 f = open(self.test.resultsdir + "/results-chart.json")
Keith Haddow4fc24652016-03-16 10:08:17 -0700329 expected_result = {"Test": {"summary": {"units": "ms",
330 "type": "list_of_scalar_values", "values": [1, 2, 3],
331 "improvement_direction": "up"}}}
Keith Haddowd804bc82016-03-15 17:16:03 -0700332 self.assertDictEqual(expected_result, json.loads(f.read()))
333
334
335 def test_output_list_perf_value(self):
336 self.test.resultsdir = tempfile.mkdtemp()
337
Keith Haddow4fc24652016-03-16 10:08:17 -0700338 self.test.output_perf_value("Test", [1, 2, 3], units="ms",
339 higher_is_better=False)
Keith Haddowd804bc82016-03-15 17:16:03 -0700340
341 f = open(self.test.resultsdir + "/results-chart.json")
Keith Haddow4fc24652016-03-16 10:08:17 -0700342 expected_result = {"Test": {"summary": {"units": "ms",
343 "type": "list_of_scalar_values", "values": [1, 2, 3],
344 "improvement_direction": "down"}}}
Keith Haddowd804bc82016-03-15 17:16:03 -0700345 self.assertDictEqual(expected_result, json.loads(f.read()))
346
347
348 def test_output_single_then_list_perf_value(self):
349 self.test.resultsdir = tempfile.mkdtemp()
Keith Haddow4fc24652016-03-16 10:08:17 -0700350 self.test.output_perf_value("Test", 1, units="ms",
351 higher_is_better=False)
352 self.test.output_perf_value("Test", [4, 3, 2], units="ms",
353 higher_is_better=False)
Keith Haddowd804bc82016-03-15 17:16:03 -0700354 f = open(self.test.resultsdir + "/results-chart.json")
Keith Haddow4fc24652016-03-16 10:08:17 -0700355 expected_result = {"Test": {"summary": {"units": "ms",
356 "type": "list_of_scalar_values",
357 "values": [1, 4, 3, 2],
358 "improvement_direction": "down"}}}
Keith Haddowd804bc82016-03-15 17:16:03 -0700359 self.assertDictEqual(expected_result, json.loads(f.read()))
360
361
362 def test_output_list_then_list_perf_value(self):
363 self.test.resultsdir = tempfile.mkdtemp()
Keith Haddow4fc24652016-03-16 10:08:17 -0700364 self.test.output_perf_value("Test", [1, 2, 3], units="ms",
365 higher_is_better=False)
366 self.test.output_perf_value("Test", [4, 3, 2], units="ms",
367 higher_is_better=False)
Keith Haddowd804bc82016-03-15 17:16:03 -0700368 f = open(self.test.resultsdir + "/results-chart.json")
Keith Haddow4fc24652016-03-16 10:08:17 -0700369 expected_result = {"Test": {"summary": {"units": "ms",
370 "type": "list_of_scalar_values",
371 "values": [1, 2, 3, 4, 3, 2],
372 "improvement_direction": "down"}}}
Keith Haddowd804bc82016-03-15 17:16:03 -0700373 self.assertDictEqual(expected_result, json.loads(f.read()))
374
375
Keith Haddow4fc24652016-03-16 10:08:17 -0700376 def test_output_single_perf_value_input_string(self):
377 self.test.resultsdir = tempfile.mkdtemp()
378
379 self.test.output_perf_value("Test", u'-0.34', units="ms",
380 higher_is_better=True)
381
382 f = open(self.test.resultsdir + "/results-chart.json")
383 expected_result = {"Test": {"summary": {"units": "ms", "type": "scalar",
384 "value": -0.34, "improvement_direction": "up"}}}
385 self.assertDictEqual(expected_result, json.loads(f.read()))
386
387
388 def test_output_single_perf_value_input_list_of_string(self):
389 self.test.resultsdir = tempfile.mkdtemp()
390
391 self.test.output_perf_value("Test", [0, u'-0.34', 1], units="ms",
392 higher_is_better=True)
393
394 f = open(self.test.resultsdir + "/results-chart.json")
395 expected_result = {"Test": {"summary": {"units": "ms",
396 "type": "list_of_scalar_values",
397 "values": [0, -0.34, 1],
398 "improvement_direction": "up"}}}
399 self.assertDictEqual(expected_result, json.loads(f.read()))
400
401
402
mbligh234a84f2008-11-20 19:57:43 +0000403if __name__ == '__main__':
404 unittest.main()