• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.4
2#
3#   Copyright 2016 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import mock
18import unittest
19
20from acts import asserts
21from acts import base_test
22from acts import signals
23from acts import test_runner
24
25MSG_EXPECTED_EXCEPTION = "This is an expected exception."
26MSG_EXPECTED_TEST_FAILURE = "This is an expected test failure."
27MSG_UNEXPECTED_EXCEPTION = "Unexpected exception!"
28
29MOCK_EXTRA = {"key": "value", "answer_to_everything": 42}
30
31def never_call():
32    raise Exception(MSG_UNEXPECTED_EXCEPTION)
33
34class SomeError(Exception):
35    """A custom exception class used for tests in this module."""
36
37class ActsBaseClassTest(unittest.TestCase):
38
39    def setUp(self):
40        self.mock_test_cls_configs = {
41            'reporter': mock.MagicMock(),
42            'log': mock.MagicMock(),
43            'log_path': '/tmp',
44            'cli_args': None,
45            'user_params': {}
46        }
47        self.mock_test_name = "test_something"
48
49    def test_current_test_case_name(self):
50        class MockBaseTest(base_test.BaseTestClass):
51            def test_func(self):
52                asserts.assert_true(self.current_test_name == "test_func", ("Got "
53                                 "unexpected test name %s."
54                                 ) % self.current_test_name)
55        bt_cls = MockBaseTest(self.mock_test_cls_configs)
56        bt_cls.run(test_names=["test_func"])
57        actual_record = bt_cls.results.passed[0]
58        self.assertEqual(actual_record.test_name, "test_func")
59        self.assertIsNone(actual_record.details)
60        self.assertIsNone(actual_record.extras)
61
62    def test_self_tests_list(self):
63        class MockBaseTest(base_test.BaseTestClass):
64            def __init__(self, controllers):
65                super(MockBaseTest, self).__init__(controllers)
66                self.tests = ("test_something",)
67            def test_something(self):
68                pass
69            def test_never(self):
70                # This should not execute it's not on default test list.
71                never_call()
72        bt_cls = MockBaseTest(self.mock_test_cls_configs)
73        bt_cls.run()
74        actual_record = bt_cls.results.passed[0]
75        self.assertEqual(actual_record.test_name, "test_something")
76
77    def test_self_tests_list_fail_by_convention(self):
78        class MockBaseTest(base_test.BaseTestClass):
79            def __init__(self, controllers):
80                super(MockBaseTest, self).__init__(controllers)
81                self.tests = ("not_a_test_something",)
82            def not_a_test_something(self):
83                pass
84            def test_never(self):
85                # This should not execute it's not on default test list.
86                never_call()
87        bt_cls = MockBaseTest(self.mock_test_cls_configs)
88        expected_msg = ("Test case name not_a_test_something does not follow "
89                        "naming convention test_\*, abort.")
90        with self.assertRaisesRegexp(test_runner.USERError,
91                                     expected_msg):
92            bt_cls.run()
93
94    def test_cli_test_selection_override_self_tests_list(self):
95        class MockBaseTest(base_test.BaseTestClass):
96            def __init__(self, controllers):
97                super(MockBaseTest, self).__init__(controllers)
98                self.tests = ("test_never",)
99            def test_something(self):
100                pass
101            def test_never(self):
102                # This should not execute it's not selected by cmd line input.
103                never_call()
104        bt_cls = MockBaseTest(self.mock_test_cls_configs)
105        bt_cls.run(test_names=["test_something"])
106        actual_record = bt_cls.results.passed[0]
107        self.assertEqual(actual_record.test_name, "test_something")
108
109    def test_cli_test_selection_fail_by_convention(self):
110        class MockBaseTest(base_test.BaseTestClass):
111            def __init__(self, controllers):
112                super(MockBaseTest, self).__init__(controllers)
113                self.tests = ("not_a_test_something",)
114            def not_a_test_something(self):
115                pass
116            def test_never(self):
117                # This should not execute it's not selected by cmd line input.
118                never_call()
119        bt_cls = MockBaseTest(self.mock_test_cls_configs)
120        expected_msg = ("Test case name not_a_test_something does not follow "
121                        "naming convention test_*, abort.")
122        with self.assertRaises(test_runner.USERError, msg=expected_msg):
123            bt_cls.run(test_names=["not_a_test_something"])
124
125    def test_default_execution_of_all_tests(self):
126        class MockBaseTest(base_test.BaseTestClass):
127            def test_something(self):
128                pass
129            def not_a_test(self):
130                # This should not execute its name doesn't follow test case
131                # naming convention.
132                never_call()
133        bt_cls = MockBaseTest(self.mock_test_cls_configs)
134        bt_cls.run(test_names=["test_something"])
135        actual_record = bt_cls.results.passed[0]
136        self.assertEqual(actual_record.test_name, "test_something")
137
138    def test_setup_class_fail_by_exception(self):
139        class MockBaseTest(base_test.BaseTestClass):
140            def setup_class(self):
141                raise Exception(MSG_EXPECTED_EXCEPTION)
142            def test_something(self):
143                # This should not execute because setup_class failed.
144                never_call()
145        bt_cls = MockBaseTest(self.mock_test_cls_configs)
146        bt_cls.run(test_names=["test_func"])
147        actual_record = bt_cls.results.failed[0]
148        self.assertEqual(actual_record.test_name, "")
149        expected_msg = "setup_class failed for MockBaseTest: %s" % (
150                       MSG_EXPECTED_EXCEPTION)
151        self.assertEqual(actual_record.details, expected_msg)
152        self.assertIsNone(actual_record.extras)
153        expected_summary = ("Executed 1, Failed 1, Passed 0, Requested 1, "
154                            "Skipped 0, Unknown 0")
155        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
156
157    def test_setup_test_fail_by_exception(self):
158        class MockBaseTest(base_test.BaseTestClass):
159            def setup_test(self):
160                raise Exception(MSG_EXPECTED_EXCEPTION)
161            def test_something(self):
162                # This should not execute because setup_test failed.
163                never_call()
164        bt_cls = MockBaseTest(self.mock_test_cls_configs)
165        bt_cls.run(test_names=["test_something"])
166        actual_record = bt_cls.results.unknown[0]
167        self.assertEqual(actual_record.test_name, self.mock_test_name)
168        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
169        self.assertIsNone(actual_record.extras)
170        expected_summary = ("Executed 1, Failed 0, Passed 0, Requested 1, "
171                            "Skipped 0, Unknown 1")
172        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
173
174    def test_setup_test_fail_by_test_signal(self):
175        class MockBaseTest(base_test.BaseTestClass):
176            def setup_test(self):
177                raise signals.TestFailure(MSG_EXPECTED_EXCEPTION)
178            def test_something(self):
179                # This should not execute because setup_test failed.
180                never_call()
181        bt_cls = MockBaseTest(self.mock_test_cls_configs)
182        bt_cls.run(test_names=["test_something"])
183        actual_record = bt_cls.results.failed[0]
184        self.assertEqual(actual_record.test_name, self.mock_test_name)
185        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
186        self.assertIsNone(actual_record.extras)
187        expected_summary = ("Executed 1, Failed 1, Passed 0, Requested 1, "
188                            "Skipped 0, Unknown 0")
189        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
190
191    def test_setup_test_fail_by_return_False(self):
192        class MockBaseTest(base_test.BaseTestClass):
193            def setup_test(self):
194                return False
195            def test_something(self):
196                # This should not execute because setup_test failed.
197                never_call()
198        bt_cls = MockBaseTest(self.mock_test_cls_configs)
199        bt_cls.run(test_names=["test_something"])
200        actual_record = bt_cls.results.failed[0]
201        expected_msg = "Setup for %s failed." % self.mock_test_name
202        self.assertEqual(actual_record.test_name, self.mock_test_name)
203        self.assertEqual(actual_record.details, expected_msg)
204        self.assertIsNone(actual_record.extras)
205        expected_summary = ("Executed 1, Failed 1, Passed 0, Requested 1, "
206                            "Skipped 0, Unknown 0")
207        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
208
209    def test_teardown_test_assert_fail(self):
210        class MockBaseTest(base_test.BaseTestClass):
211            def teardown_test(self):
212                asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
213            def test_something(self):
214                pass
215        bt_cls = MockBaseTest(self.mock_test_cls_configs)
216        bt_cls.run()
217        actual_record = bt_cls.results.failed[0]
218        self.assertEqual(actual_record.test_name, self.mock_test_name)
219        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
220        self.assertIsNone(actual_record.extras)
221        expected_summary = ("Executed 1, Failed 1, Passed 0, Requested 1, "
222                            "Skipped 0, Unknown 0")
223        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
224
225    def test_teardown_test_raise_exception(self):
226        class MockBaseTest(base_test.BaseTestClass):
227            def teardown_test(self):
228                raise Exception(MSG_EXPECTED_EXCEPTION)
229            def test_something(self):
230                pass
231        bt_cls = MockBaseTest(self.mock_test_cls_configs)
232        bt_cls.run()
233        actual_record = bt_cls.results.unknown[0]
234        self.assertEqual(actual_record.test_name, self.mock_test_name)
235        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
236        self.assertIsNone(actual_record.extras)
237        expected_summary = ("Executed 1, Failed 0, Passed 0, Requested 1, "
238                            "Skipped 0, Unknown 1")
239        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
240
241    def test_on_pass_raise_exception(self):
242        class MockBaseTest(base_test.BaseTestClass):
243            def on_pass(self, test_name, begin_time):
244                raise Exception(MSG_EXPECTED_EXCEPTION)
245            def test_something(self):
246                asserts.explicit_pass(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
247        bt_cls = MockBaseTest(self.mock_test_cls_configs)
248        bt_cls.run()
249        actual_record = bt_cls.results.unknown[0]
250        self.assertEqual(actual_record.test_name, self.mock_test_name)
251        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
252        self.assertEqual(actual_record.extras, MOCK_EXTRA)
253        self.assertEqual(actual_record.extra_errors,
254                         {'_on_pass': MSG_EXPECTED_EXCEPTION})
255        expected_summary = ("Executed 1, Failed 0, Passed 0, Requested 1, "
256                            "Skipped 0, Unknown 1")
257        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
258
259    def test_on_fail_raise_exception(self):
260        class MockBaseTest(base_test.BaseTestClass):
261            def on_fail(self, test_name, begin_time):
262                raise Exception(MSG_EXPECTED_EXCEPTION)
263            def test_something(self):
264                asserts.fail(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
265        bt_cls = MockBaseTest(self.mock_test_cls_configs)
266        bt_cls.run()
267        actual_record = bt_cls.results.unknown[0]
268        self.assertEqual(bt_cls.results.failed, [])
269        self.assertEqual(actual_record.test_name, self.mock_test_name)
270        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
271        self.assertEqual(actual_record.extras, MOCK_EXTRA)
272        self.assertEqual(actual_record.extra_errors,
273                         {'_on_fail': MSG_EXPECTED_EXCEPTION})
274        expected_summary = ("Executed 1, Failed 0, Passed 0, Requested 1, "
275                            "Skipped 0, Unknown 1")
276        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
277
278    def test_abort_class(self):
279        class MockBaseTest(base_test.BaseTestClass):
280            def test_1(self):
281                pass
282            def test_2(self):
283                asserts.abort_class(MSG_EXPECTED_EXCEPTION)
284                never_call()
285            def test_3(self):
286                never_call()
287        bt_cls = MockBaseTest(self.mock_test_cls_configs)
288        bt_cls.run(test_names=["test_1", "test_2", "test_3"])
289        self.assertEqual(bt_cls.results.passed[0].test_name,
290                         "test_1")
291        self.assertEqual(bt_cls.results.failed[0].details,
292                         MSG_EXPECTED_EXCEPTION)
293        self.assertEqual(bt_cls.results.summary_str(),
294                         ("Executed 2, Failed 1, Passed 1, Requested 3, "
295                          "Skipped 0, Unknown 0"))
296
297    def test_uncaught_exception(self):
298        class MockBaseTest(base_test.BaseTestClass):
299            def test_func(self):
300                raise Exception(MSG_EXPECTED_EXCEPTION)
301                never_call()
302        bt_cls = MockBaseTest(self.mock_test_cls_configs)
303        bt_cls.run(test_names=["test_func"])
304        actual_record = bt_cls.results.unknown[0]
305        self.assertEqual(actual_record.test_name, "test_func")
306        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
307        self.assertIsNone(actual_record.extras)
308
309    def test_fail(self):
310        class MockBaseTest(base_test.BaseTestClass):
311            def test_func(self):
312                asserts.fail(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
313                never_call()
314        bt_cls = MockBaseTest(self.mock_test_cls_configs)
315        bt_cls.run(test_names=["test_func"])
316        actual_record = bt_cls.results.failed[0]
317        self.assertEqual(actual_record.test_name, "test_func")
318        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
319        self.assertEqual(actual_record.extras, MOCK_EXTRA)
320
321    def test_assert_true(self):
322        class MockBaseTest(base_test.BaseTestClass):
323            def test_func(self):
324                asserts.assert_true(False, MSG_EXPECTED_EXCEPTION,
325                                 extras=MOCK_EXTRA)
326                never_call()
327        bt_cls = MockBaseTest(self.mock_test_cls_configs)
328        bt_cls.run(test_names=["test_func"])
329        actual_record = bt_cls.results.failed[0]
330        self.assertEqual(actual_record.test_name, "test_func")
331        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
332        self.assertEqual(actual_record.extras, MOCK_EXTRA)
333
334    def test_assert_equal_pass(self):
335        class MockBaseTest(base_test.BaseTestClass):
336            def test_func(self):
337                asserts.assert_equal(1, 1, extras=MOCK_EXTRA)
338        bt_cls = MockBaseTest(self.mock_test_cls_configs)
339        bt_cls.run()
340        actual_record = bt_cls.results.passed[0]
341        self.assertEqual(actual_record.test_name, "test_func")
342        self.assertIsNone(actual_record.details)
343        self.assertIsNone(actual_record.extras)
344
345    def test_assert_equal_fail(self):
346        class MockBaseTest(base_test.BaseTestClass):
347            def test_func(self):
348                asserts.assert_equal(1, 2, extras=MOCK_EXTRA)
349        bt_cls = MockBaseTest(self.mock_test_cls_configs)
350        bt_cls.run()
351        actual_record = bt_cls.results.failed[0]
352        self.assertEqual(actual_record.test_name, "test_func")
353        self.assertEqual(actual_record.details, "1 != 2")
354        self.assertEqual(actual_record.extras, MOCK_EXTRA)
355
356    def test_assert_equal_fail_with_msg(self):
357        class MockBaseTest(base_test.BaseTestClass):
358            def test_func(self):
359                asserts.assert_equal(1, 2, msg=MSG_EXPECTED_EXCEPTION,
360                                     extras=MOCK_EXTRA)
361        bt_cls = MockBaseTest(self.mock_test_cls_configs)
362        bt_cls.run()
363        actual_record = bt_cls.results.failed[0]
364        self.assertEqual(actual_record.test_name, "test_func")
365        expected_msg = "1 != 2 " + MSG_EXPECTED_EXCEPTION
366        self.assertEqual(actual_record.details, expected_msg)
367        self.assertEqual(actual_record.extras, MOCK_EXTRA)
368
369    def test_assert_raises_pass(self):
370        class MockBaseTest(base_test.BaseTestClass):
371            def test_func(self):
372                with asserts.assert_raises(SomeError, extras=MOCK_EXTRA):
373                    raise SomeError(MSG_EXPECTED_EXCEPTION)
374        bt_cls = MockBaseTest(self.mock_test_cls_configs)
375        bt_cls.run()
376        actual_record = bt_cls.results.passed[0]
377        self.assertEqual(actual_record.test_name, "test_func")
378        self.assertIsNone(actual_record.details)
379        self.assertIsNone(actual_record.extras)
380
381    def test_assert_raises_fail_with_noop(self):
382        class MockBaseTest(base_test.BaseTestClass):
383            def test_func(self):
384                with asserts.assert_raises(SomeError, extras=MOCK_EXTRA):
385                    pass
386        bt_cls = MockBaseTest(self.mock_test_cls_configs)
387        bt_cls.run()
388        actual_record = bt_cls.results.failed[0]
389        self.assertEqual(actual_record.test_name, "test_func")
390        self.assertEqual(actual_record.details, "SomeError not raised")
391        self.assertEqual(actual_record.extras, MOCK_EXTRA)
392
393    def test_assert_raises_fail_with_wrong_error(self):
394        class MockBaseTest(base_test.BaseTestClass):
395            def test_func(self):
396                with asserts.assert_raises(SomeError, extras=MOCK_EXTRA):
397                    raise AttributeError(MSG_UNEXPECTED_EXCEPTION)
398        bt_cls = MockBaseTest(self.mock_test_cls_configs)
399        bt_cls.run()
400        actual_record = bt_cls.results.unknown[0]
401        self.assertEqual(actual_record.test_name, "test_func")
402        self.assertEqual(actual_record.details, MSG_UNEXPECTED_EXCEPTION)
403        self.assertIsNone(actual_record.extras)
404
405    def test_assert_raises_regex_pass(self):
406        class MockBaseTest(base_test.BaseTestClass):
407            def test_func(self):
408                with asserts.assert_raises_regex(
409                        SomeError,
410                        expected_regex=MSG_EXPECTED_EXCEPTION,
411                        extras=MOCK_EXTRA):
412                    raise SomeError(MSG_EXPECTED_EXCEPTION)
413        bt_cls = MockBaseTest(self.mock_test_cls_configs)
414        bt_cls.run()
415        actual_record = bt_cls.results.passed[0]
416        self.assertEqual(actual_record.test_name, "test_func")
417        self.assertIsNone(actual_record.details)
418        self.assertIsNone(actual_record.extras)
419
420    def test_assert_raises_fail_with_noop(self):
421        class MockBaseTest(base_test.BaseTestClass):
422            def test_func(self):
423                with asserts.assert_raises_regex(
424                        SomeError,
425                        expected_regex=MSG_EXPECTED_EXCEPTION,
426                        extras=MOCK_EXTRA):
427                    pass
428        bt_cls = MockBaseTest(self.mock_test_cls_configs)
429        bt_cls.run()
430        actual_record = bt_cls.results.failed[0]
431        self.assertEqual(actual_record.test_name, "test_func")
432        self.assertEqual(actual_record.details, "SomeError not raised")
433        self.assertEqual(actual_record.extras, MOCK_EXTRA)
434
435    def test_assert_raises_fail_with_wrong_regex(self):
436        wrong_msg = "ha"
437        class MockBaseTest(base_test.BaseTestClass):
438            def test_func(self):
439                with asserts.assert_raises_regex(
440                        SomeError,
441                        expected_regex=MSG_EXPECTED_EXCEPTION,
442                        extras=MOCK_EXTRA):
443                    raise SomeError(wrong_msg)
444        bt_cls = MockBaseTest(self.mock_test_cls_configs)
445        bt_cls.run()
446        actual_record = bt_cls.results.failed[0]
447        self.assertEqual(actual_record.test_name, "test_func")
448        expected_details = ('"This is an expected exception." does not match '
449                            '"%s"') % wrong_msg
450        self.assertEqual(actual_record.details, expected_details)
451        self.assertEqual(actual_record.extras, MOCK_EXTRA)
452
453    def test_assert_raises_fail_with_wrong_error(self):
454        class MockBaseTest(base_test.BaseTestClass):
455            def test_func(self):
456                with asserts.assert_raises_regex(
457                        SomeError,
458                        expected_regex=MSG_EXPECTED_EXCEPTION,
459                        extras=MOCK_EXTRA):
460                    raise AttributeError(MSG_UNEXPECTED_EXCEPTION)
461        bt_cls = MockBaseTest(self.mock_test_cls_configs)
462        bt_cls.run()
463        actual_record = bt_cls.results.unknown[0]
464        self.assertEqual(actual_record.test_name, "test_func")
465        self.assertEqual(actual_record.details, MSG_UNEXPECTED_EXCEPTION)
466        self.assertIsNone(actual_record.extras)
467
468    def test_explicit_pass(self):
469        class MockBaseTest(base_test.BaseTestClass):
470            def test_func(self):
471                asserts.explicit_pass(MSG_EXPECTED_EXCEPTION,
472                                      extras=MOCK_EXTRA)
473                never_call()
474        bt_cls = MockBaseTest(self.mock_test_cls_configs)
475        bt_cls.run(test_names=["test_func"])
476        actual_record = bt_cls.results.passed[0]
477        self.assertEqual(actual_record.test_name, "test_func")
478        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
479        self.assertEqual(actual_record.extras, MOCK_EXTRA)
480
481    def test_implicit_pass(self):
482        class MockBaseTest(base_test.BaseTestClass):
483            def test_func(self):
484                pass
485        bt_cls = MockBaseTest(self.mock_test_cls_configs)
486        bt_cls.run(test_names=["test_func"])
487        actual_record = bt_cls.results.passed[0]
488        self.assertEqual(actual_record.test_name, "test_func")
489        self.assertIsNone(actual_record.details)
490        self.assertIsNone(actual_record.extras)
491
492    def test_skip(self):
493        class MockBaseTest(base_test.BaseTestClass):
494            def test_func(self):
495                asserts.skip(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
496                never_call()
497        bt_cls = MockBaseTest(self.mock_test_cls_configs)
498        bt_cls.run(test_names=["test_func"])
499        actual_record = bt_cls.results.skipped[0]
500        self.assertEqual(actual_record.test_name, "test_func")
501        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
502        self.assertEqual(actual_record.extras, MOCK_EXTRA)
503
504    def test_skip_if(self):
505        class MockBaseTest(base_test.BaseTestClass):
506            def test_func(self):
507                asserts.skip_if(False, MSG_UNEXPECTED_EXCEPTION)
508                asserts.skip_if(True, MSG_EXPECTED_EXCEPTION,
509                                extras=MOCK_EXTRA)
510                never_call()
511        bt_cls = MockBaseTest(self.mock_test_cls_configs)
512        bt_cls.run(test_names=["test_func"])
513        actual_record = bt_cls.results.skipped[0]
514        self.assertEqual(actual_record.test_name, "test_func")
515        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
516        self.assertEqual(actual_record.extras, MOCK_EXTRA)
517
518    def test_unpack_userparams_required(self):
519        """Missing a required param should raise an error."""
520        required = ["something"]
521        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
522        expected_msg = ("Missing required user param '%s' in test "
523                        "configuration.") % required[0]
524        with self.assertRaises(base_test.BaseTestError, msg=expected_msg):
525            bc.unpack_userparams(required)
526
527    def test_unpack_userparams_optional(self):
528        """Missing an optional param should not raise an error."""
529        opt = ["something"]
530        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
531        bc.unpack_userparams(opt_param_names=opt)
532
533    def test_unpack_userparams_basic(self):
534        """Required and optional params are unpacked properly."""
535        required = ["something"]
536        optional = ["something_else"]
537        configs = dict(self.mock_test_cls_configs)
538        configs["user_params"]["something"] = 42
539        configs["user_params"]["something_else"] = 53
540        bc = base_test.BaseTestClass(configs)
541        bc.unpack_userparams(req_param_names=required,
542                             opt_param_names=optional)
543        self.assertEqual(bc.something, 42)
544        self.assertEqual(bc.something_else, 53)
545
546    def test_unpack_userparams_default_overwrite(self):
547        default_arg_val = "haha"
548        actual_arg_val = "wawa"
549        arg_name = "arg1"
550        configs = dict(self.mock_test_cls_configs)
551        configs["user_params"][arg_name] = actual_arg_val
552        bc = base_test.BaseTestClass(configs)
553        bc.unpack_userparams(opt_param_names=[arg_name],
554                             arg1=default_arg_val)
555        self.assertEqual(bc.arg1, actual_arg_val)
556
557    def test_unpack_userparams_default_None(self):
558        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
559        bc.unpack_userparams(arg1="haha")
560        self.assertEqual(bc.arg1, "haha")
561
562    def test_generated_tests(self):
563        """Execute code paths for generated test cases.
564
565        Three test cases are generated, each of them produces a different
566        result: one pass, one fail, and one skip.
567
568        This test verifies that the exact three tests are executed and their
569        results are reported correctly.
570        """
571        static_arg = "haha"
572        static_kwarg = "meh"
573        itrs = ["pass", "fail", "skip"]
574        class MockBaseTest(base_test.BaseTestClass):
575            def name_gen(self, setting, arg, special_arg=None):
576                return "test_%s_%s" % (setting, arg)
577            def logic(self, setting, arg, special_arg=None):
578                asserts.assert_true(setting in itrs,
579                                 ("%s is not in acceptable settings range %s"
580                                 ) % (setting, itrs))
581                asserts.assert_true(arg == static_arg,
582                                 "Expected %s, got %s" % (static_arg, arg))
583                asserts.assert_true(arg == static_arg,
584                                 "Expected %s, got %s" % (static_kwarg,
585                                                          special_arg))
586                if setting == "pass":
587                    asserts.explicit_pass(MSG_EXPECTED_EXCEPTION,
588                                          extras=MOCK_EXTRA)
589                elif setting == "fail":
590                    asserts.fail(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
591                elif setting == "skip":
592                    asserts.skip(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
593            @signals.generated_test
594            def test_func(self):
595                self.run_generated_testcases(
596                    test_func=self.logic,
597                    settings=itrs,
598                    args=(static_arg,),
599                    name_func=self.name_gen
600                )
601        bt_cls = MockBaseTest(self.mock_test_cls_configs)
602        bt_cls.run(test_names=["test_func"])
603        self.assertEqual(len(bt_cls.results.requested), 3)
604        pass_record = bt_cls.results.passed[0]
605        self.assertEqual(pass_record.test_name, "test_pass_%s" % static_arg)
606        self.assertEqual(pass_record.details, MSG_EXPECTED_EXCEPTION)
607        self.assertEqual(pass_record.extras, MOCK_EXTRA)
608        skip_record = bt_cls.results.skipped[0]
609        self.assertEqual(skip_record.test_name, "test_skip_%s" % static_arg)
610        self.assertEqual(skip_record.details, MSG_EXPECTED_EXCEPTION)
611        self.assertEqual(skip_record.extras, MOCK_EXTRA)
612        fail_record = bt_cls.results.failed[0]
613        self.assertEqual(fail_record.test_name, "test_fail_%s" % static_arg)
614        self.assertEqual(fail_record.details, MSG_EXPECTED_EXCEPTION)
615        self.assertEqual(fail_record.extras, MOCK_EXTRA)
616
617if __name__ == "__main__":
618   unittest.main()