0001
0002
0003
0004
0005
0006
0007
0008
0009 import unittest
0010 from unittest import mock
0011
0012 import tempfile, shutil
0013
0014 import itertools
0015 import json
0016 import os
0017 import signal
0018 import subprocess
0019 from typing import Iterable
0020
0021 import kunit_config
0022 import kunit_parser
0023 import kunit_kernel
0024 import kunit_json
0025 import kunit
0026
0027 test_tmpdir = ''
0028 abs_test_data_dir = ''
0029
0030 def setUpModule():
0031 global test_tmpdir, abs_test_data_dir
0032 test_tmpdir = tempfile.mkdtemp()
0033 abs_test_data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test_data'))
0034
0035 def tearDownModule():
0036 shutil.rmtree(test_tmpdir)
0037
0038 def test_data_path(path):
0039 return os.path.join(abs_test_data_dir, path)
0040
0041 class KconfigTest(unittest.TestCase):
0042
0043 def test_is_subset_of(self):
0044 kconfig0 = kunit_config.Kconfig()
0045 self.assertTrue(kconfig0.is_subset_of(kconfig0))
0046
0047 kconfig1 = kunit_config.Kconfig()
0048 kconfig1.add_entry('TEST', 'y')
0049 self.assertTrue(kconfig1.is_subset_of(kconfig1))
0050 self.assertTrue(kconfig0.is_subset_of(kconfig1))
0051 self.assertFalse(kconfig1.is_subset_of(kconfig0))
0052
0053 def test_read_from_file(self):
0054 kconfig_path = test_data_path('test_read_from_file.kconfig')
0055
0056 kconfig = kunit_config.parse_file(kconfig_path)
0057
0058 expected_kconfig = kunit_config.Kconfig()
0059 expected_kconfig.add_entry('UML', 'y')
0060 expected_kconfig.add_entry('MMU', 'y')
0061 expected_kconfig.add_entry('TEST', 'y')
0062 expected_kconfig.add_entry('EXAMPLE_TEST', 'y')
0063 expected_kconfig.add_entry('MK8', 'n')
0064
0065 self.assertEqual(kconfig, expected_kconfig)
0066
0067 def test_write_to_file(self):
0068 kconfig_path = os.path.join(test_tmpdir, '.config')
0069
0070 expected_kconfig = kunit_config.Kconfig()
0071 expected_kconfig.add_entry('UML', 'y')
0072 expected_kconfig.add_entry('MMU', 'y')
0073 expected_kconfig.add_entry('TEST', 'y')
0074 expected_kconfig.add_entry('EXAMPLE_TEST', 'y')
0075 expected_kconfig.add_entry('MK8', 'n')
0076
0077 expected_kconfig.write_to_file(kconfig_path)
0078
0079 actual_kconfig = kunit_config.parse_file(kconfig_path)
0080 self.assertEqual(actual_kconfig, expected_kconfig)
0081
0082 class KUnitParserTest(unittest.TestCase):
0083
0084 def assertContains(self, needle: str, haystack: kunit_parser.LineStream):
0085
0086 copy, backup = itertools.tee(haystack)
0087 for line in copy:
0088 if needle in line:
0089 return
0090 raise AssertionError(f'"{needle}" not found in {list(backup)}!')
0091
0092 def test_output_isolated_correctly(self):
0093 log_path = test_data_path('test_output_isolated_correctly.log')
0094 with open(log_path) as file:
0095 result = kunit_parser.extract_tap_lines(file.readlines())
0096 self.assertContains('TAP version 14', result)
0097 self.assertContains('# Subtest: example', result)
0098 self.assertContains('1..2', result)
0099 self.assertContains('ok 1 - example_simple_test', result)
0100 self.assertContains('ok 2 - example_mock_test', result)
0101 self.assertContains('ok 1 - example', result)
0102
0103 def test_output_with_prefix_isolated_correctly(self):
0104 log_path = test_data_path('test_pound_sign.log')
0105 with open(log_path) as file:
0106 result = kunit_parser.extract_tap_lines(file.readlines())
0107 self.assertContains('TAP version 14', result)
0108 self.assertContains('# Subtest: kunit-resource-test', result)
0109 self.assertContains('1..5', result)
0110 self.assertContains('ok 1 - kunit_resource_test_init_resources', result)
0111 self.assertContains('ok 2 - kunit_resource_test_alloc_resource', result)
0112 self.assertContains('ok 3 - kunit_resource_test_destroy_resource', result)
0113 self.assertContains('foo bar #', result)
0114 self.assertContains('ok 4 - kunit_resource_test_cleanup_resources', result)
0115 self.assertContains('ok 5 - kunit_resource_test_proper_free_ordering', result)
0116 self.assertContains('ok 1 - kunit-resource-test', result)
0117 self.assertContains('foo bar # non-kunit output', result)
0118 self.assertContains('# Subtest: kunit-try-catch-test', result)
0119 self.assertContains('1..2', result)
0120 self.assertContains('ok 1 - kunit_test_try_catch_successful_try_no_catch',
0121 result)
0122 self.assertContains('ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch',
0123 result)
0124 self.assertContains('ok 2 - kunit-try-catch-test', result)
0125 self.assertContains('# Subtest: string-stream-test', result)
0126 self.assertContains('1..3', result)
0127 self.assertContains('ok 1 - string_stream_test_empty_on_creation', result)
0128 self.assertContains('ok 2 - string_stream_test_not_empty_after_add', result)
0129 self.assertContains('ok 3 - string_stream_test_get_string', result)
0130 self.assertContains('ok 3 - string-stream-test', result)
0131
0132 def test_parse_successful_test_log(self):
0133 all_passed_log = test_data_path('test_is_test_passed-all_passed.log')
0134 with open(all_passed_log) as file:
0135 result = kunit_parser.parse_run_tests(file.readlines())
0136 self.assertEqual(
0137 kunit_parser.TestStatus.SUCCESS,
0138 result.status)
0139
0140 def test_parse_successful_nested_tests_log(self):
0141 all_passed_log = test_data_path('test_is_test_passed-all_passed_nested.log')
0142 with open(all_passed_log) as file:
0143 result = kunit_parser.parse_run_tests(file.readlines())
0144 self.assertEqual(
0145 kunit_parser.TestStatus.SUCCESS,
0146 result.status)
0147
0148 def test_kselftest_nested(self):
0149 kselftest_log = test_data_path('test_is_test_passed-kselftest.log')
0150 with open(kselftest_log) as file:
0151 result = kunit_parser.parse_run_tests(file.readlines())
0152 self.assertEqual(
0153 kunit_parser.TestStatus.SUCCESS,
0154 result.status)
0155
0156 def test_parse_failed_test_log(self):
0157 failed_log = test_data_path('test_is_test_passed-failure.log')
0158 with open(failed_log) as file:
0159 result = kunit_parser.parse_run_tests(file.readlines())
0160 self.assertEqual(
0161 kunit_parser.TestStatus.FAILURE,
0162 result.status)
0163
0164 def test_no_header(self):
0165 empty_log = test_data_path('test_is_test_passed-no_tests_run_no_header.log')
0166 with open(empty_log) as file:
0167 result = kunit_parser.parse_run_tests(
0168 kunit_parser.extract_tap_lines(file.readlines()))
0169 self.assertEqual(0, len(result.subtests))
0170 self.assertEqual(
0171 kunit_parser.TestStatus.FAILURE_TO_PARSE_TESTS,
0172 result.status)
0173
0174 def test_missing_test_plan(self):
0175 missing_plan_log = test_data_path('test_is_test_passed-'
0176 'missing_plan.log')
0177 with open(missing_plan_log) as file:
0178 result = kunit_parser.parse_run_tests(
0179 kunit_parser.extract_tap_lines(
0180 file.readlines()))
0181
0182 self.assertEqual(0, result.counts.errors)
0183
0184 self.assertEqual(10, result.counts.total())
0185 self.assertEqual(
0186 kunit_parser.TestStatus.SUCCESS,
0187 result.status)
0188
0189 def test_no_tests(self):
0190 header_log = test_data_path('test_is_test_passed-no_tests_run_with_header.log')
0191 with open(header_log) as file:
0192 result = kunit_parser.parse_run_tests(
0193 kunit_parser.extract_tap_lines(file.readlines()))
0194 self.assertEqual(0, len(result.subtests))
0195 self.assertEqual(
0196 kunit_parser.TestStatus.NO_TESTS,
0197 result.status)
0198
0199 def test_no_tests_no_plan(self):
0200 no_plan_log = test_data_path('test_is_test_passed-no_tests_no_plan.log')
0201 with open(no_plan_log) as file:
0202 result = kunit_parser.parse_run_tests(
0203 kunit_parser.extract_tap_lines(file.readlines()))
0204 self.assertEqual(0, len(result.subtests[0].subtests[0].subtests))
0205 self.assertEqual(
0206 kunit_parser.TestStatus.NO_TESTS,
0207 result.subtests[0].subtests[0].status)
0208 self.assertEqual(1, result.counts.errors)
0209
0210
0211 def test_no_kunit_output(self):
0212 crash_log = test_data_path('test_insufficient_memory.log')
0213 print_mock = mock.patch('kunit_printer.Printer.print').start()
0214 with open(crash_log) as file:
0215 result = kunit_parser.parse_run_tests(
0216 kunit_parser.extract_tap_lines(file.readlines()))
0217 print_mock.assert_any_call(StrContains('could not find any KTAP output!'))
0218 print_mock.stop()
0219 self.assertEqual(0, len(result.subtests))
0220
0221 def test_skipped_test(self):
0222 skipped_log = test_data_path('test_skip_tests.log')
0223 with open(skipped_log) as file:
0224 result = kunit_parser.parse_run_tests(file.readlines())
0225
0226
0227 self.assertEqual(
0228 kunit_parser.TestStatus.SUCCESS,
0229 result.status)
0230
0231 def test_skipped_all_tests(self):
0232 skipped_log = test_data_path('test_skip_all_tests.log')
0233 with open(skipped_log) as file:
0234 result = kunit_parser.parse_run_tests(file.readlines())
0235
0236 self.assertEqual(
0237 kunit_parser.TestStatus.SKIPPED,
0238 result.status)
0239
0240 def test_ignores_hyphen(self):
0241 hyphen_log = test_data_path('test_strip_hyphen.log')
0242 with open(hyphen_log) as file:
0243 result = kunit_parser.parse_run_tests(file.readlines())
0244
0245
0246 self.assertEqual(
0247 kunit_parser.TestStatus.SUCCESS,
0248 result.status)
0249 self.assertEqual(
0250 "sysctl_test",
0251 result.subtests[0].name)
0252 self.assertEqual(
0253 "example",
0254 result.subtests[1].name)
0255 file.close()
0256
0257
0258 def test_ignores_prefix_printk_time(self):
0259 prefix_log = test_data_path('test_config_printk_time.log')
0260 with open(prefix_log) as file:
0261 result = kunit_parser.parse_run_tests(file.readlines())
0262 self.assertEqual(
0263 kunit_parser.TestStatus.SUCCESS,
0264 result.status)
0265 self.assertEqual('kunit-resource-test', result.subtests[0].name)
0266
0267 def test_ignores_multiple_prefixes(self):
0268 prefix_log = test_data_path('test_multiple_prefixes.log')
0269 with open(prefix_log) as file:
0270 result = kunit_parser.parse_run_tests(file.readlines())
0271 self.assertEqual(
0272 kunit_parser.TestStatus.SUCCESS,
0273 result.status)
0274 self.assertEqual('kunit-resource-test', result.subtests[0].name)
0275
0276 def test_prefix_mixed_kernel_output(self):
0277 mixed_prefix_log = test_data_path('test_interrupted_tap_output.log')
0278 with open(mixed_prefix_log) as file:
0279 result = kunit_parser.parse_run_tests(file.readlines())
0280 self.assertEqual(
0281 kunit_parser.TestStatus.SUCCESS,
0282 result.status)
0283 self.assertEqual('kunit-resource-test', result.subtests[0].name)
0284
0285 def test_prefix_poundsign(self):
0286 pound_log = test_data_path('test_pound_sign.log')
0287 with open(pound_log) as file:
0288 result = kunit_parser.parse_run_tests(file.readlines())
0289 self.assertEqual(
0290 kunit_parser.TestStatus.SUCCESS,
0291 result.status)
0292 self.assertEqual('kunit-resource-test', result.subtests[0].name)
0293
0294 def test_kernel_panic_end(self):
0295 panic_log = test_data_path('test_kernel_panic_interrupt.log')
0296 with open(panic_log) as file:
0297 result = kunit_parser.parse_run_tests(file.readlines())
0298 self.assertEqual(
0299 kunit_parser.TestStatus.TEST_CRASHED,
0300 result.status)
0301 self.assertEqual('kunit-resource-test', result.subtests[0].name)
0302
0303 def test_pound_no_prefix(self):
0304 pound_log = test_data_path('test_pound_no_prefix.log')
0305 with open(pound_log) as file:
0306 result = kunit_parser.parse_run_tests(file.readlines())
0307 self.assertEqual(
0308 kunit_parser.TestStatus.SUCCESS,
0309 result.status)
0310 self.assertEqual('kunit-resource-test', result.subtests[0].name)
0311
0312 def line_stream_from_strs(strs: Iterable[str]) -> kunit_parser.LineStream:
0313 return kunit_parser.LineStream(enumerate(strs, start=1))
0314
0315 class LineStreamTest(unittest.TestCase):
0316
0317 def test_basic(self):
0318 stream = line_stream_from_strs(['hello', 'world'])
0319
0320 self.assertTrue(stream, msg='Should be more input')
0321 self.assertEqual(stream.line_number(), 1)
0322 self.assertEqual(stream.peek(), 'hello')
0323 self.assertEqual(stream.pop(), 'hello')
0324
0325 self.assertTrue(stream, msg='Should be more input')
0326 self.assertEqual(stream.line_number(), 2)
0327 self.assertEqual(stream.peek(), 'world')
0328 self.assertEqual(stream.pop(), 'world')
0329
0330 self.assertFalse(stream, msg='Should be no more input')
0331 with self.assertRaisesRegex(ValueError, 'LineStream: going past EOF'):
0332 stream.pop()
0333
0334 def test_is_lazy(self):
0335 called_times = 0
0336 def generator():
0337 nonlocal called_times
0338 for _ in range(1,5):
0339 called_times += 1
0340 yield called_times, str(called_times)
0341
0342 stream = kunit_parser.LineStream(generator())
0343 self.assertEqual(called_times, 0)
0344
0345 self.assertEqual(stream.pop(), '1')
0346 self.assertEqual(called_times, 1)
0347
0348 self.assertEqual(stream.pop(), '2')
0349 self.assertEqual(called_times, 2)
0350
0351 class LinuxSourceTreeTest(unittest.TestCase):
0352
0353 def setUp(self):
0354 mock.patch.object(signal, 'signal').start()
0355 self.addCleanup(mock.patch.stopall)
0356
0357 def test_invalid_kunitconfig(self):
0358 with self.assertRaisesRegex(kunit_kernel.ConfigError, 'nonexistent.* does not exist'):
0359 kunit_kernel.LinuxSourceTree('', kunitconfig_paths=['/nonexistent_file'])
0360
0361 def test_valid_kunitconfig(self):
0362 with tempfile.NamedTemporaryFile('wt') as kunitconfig:
0363 kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[kunitconfig.name])
0364
0365 def test_dir_kunitconfig(self):
0366 with tempfile.TemporaryDirectory('') as dir:
0367 with open(os.path.join(dir, '.kunitconfig'), 'w'):
0368 pass
0369 kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir])
0370
0371 def test_multiple_kunitconfig(self):
0372 want_kconfig = kunit_config.Kconfig()
0373 want_kconfig.add_entry('KUNIT', 'y')
0374 want_kconfig.add_entry('KUNIT_TEST', 'm')
0375
0376 with tempfile.TemporaryDirectory('') as dir:
0377 other = os.path.join(dir, 'otherkunitconfig')
0378 with open(os.path.join(dir, '.kunitconfig'), 'w') as f:
0379 f.write('CONFIG_KUNIT=y')
0380 with open(other, 'w') as f:
0381 f.write('CONFIG_KUNIT_TEST=m')
0382 pass
0383
0384 tree = kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir, other])
0385 self.assertTrue(want_kconfig.is_subset_of(tree._kconfig), msg=tree._kconfig)
0386
0387
0388 def test_multiple_kunitconfig_invalid(self):
0389 with tempfile.TemporaryDirectory('') as dir:
0390 other = os.path.join(dir, 'otherkunitconfig')
0391 with open(os.path.join(dir, '.kunitconfig'), 'w') as f:
0392 f.write('CONFIG_KUNIT=y')
0393 with open(other, 'w') as f:
0394 f.write('CONFIG_KUNIT=m')
0395
0396 with self.assertRaisesRegex(kunit_kernel.ConfigError, '(?s)Multiple values.*CONFIG_KUNIT'):
0397 kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir, other])
0398
0399
0400 def test_kconfig_add(self):
0401 want_kconfig = kunit_config.Kconfig()
0402 want_kconfig.add_entry('NOT_REAL', 'y')
0403
0404 tree = kunit_kernel.LinuxSourceTree('', kconfig_add=['CONFIG_NOT_REAL=y'])
0405 self.assertTrue(want_kconfig.is_subset_of(tree._kconfig), msg=tree._kconfig)
0406
0407 def test_invalid_arch(self):
0408 with self.assertRaisesRegex(kunit_kernel.ConfigError, 'not a valid arch, options are.*x86_64'):
0409 kunit_kernel.LinuxSourceTree('', arch='invalid')
0410
0411 def test_run_kernel_hits_exception(self):
0412 def fake_start(unused_args, unused_build_dir):
0413 return subprocess.Popen(['echo "hi\nbye"'], shell=True, text=True, stdout=subprocess.PIPE)
0414
0415 with tempfile.TemporaryDirectory('') as build_dir:
0416 tree = kunit_kernel.LinuxSourceTree(build_dir)
0417 mock.patch.object(tree._ops, 'start', side_effect=fake_start).start()
0418
0419 with self.assertRaises(ValueError):
0420 for line in tree.run_kernel(build_dir=build_dir):
0421 self.assertEqual(line, 'hi\n')
0422 raise ValueError('uh oh, did not read all output')
0423
0424 with open(kunit_kernel.get_outfile_path(build_dir), 'rt') as outfile:
0425 self.assertEqual(outfile.read(), 'hi\nbye\n', msg='Missing some output')
0426
0427 def test_build_reconfig_no_config(self):
0428 with tempfile.TemporaryDirectory('') as build_dir:
0429 with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f:
0430 f.write('CONFIG_KUNIT=y')
0431
0432 tree = kunit_kernel.LinuxSourceTree(build_dir)
0433
0434
0435
0436 tree._ops = kunit_kernel.LinuxSourceTreeOperations('none', None)
0437 mock_build_config = mock.patch.object(tree, 'build_config').start()
0438
0439
0440 self.assertTrue(tree.build_reconfig(build_dir, make_options=[]))
0441 mock_build_config.assert_called_once_with(build_dir, [])
0442
0443 def test_build_reconfig_existing_config(self):
0444 with tempfile.TemporaryDirectory('') as build_dir:
0445
0446 with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f:
0447 f.write('CONFIG_KUNIT=y')
0448 with open(kunit_kernel.get_old_kunitconfig_path(build_dir), 'w') as f:
0449 f.write('CONFIG_KUNIT=y')
0450 with open(kunit_kernel.get_kconfig_path(build_dir), 'w') as f:
0451 f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y')
0452
0453 tree = kunit_kernel.LinuxSourceTree(build_dir)
0454
0455
0456
0457 tree._ops = kunit_kernel.LinuxSourceTreeOperations('none', None)
0458 mock_build_config = mock.patch.object(tree, 'build_config').start()
0459
0460 self.assertTrue(tree.build_reconfig(build_dir, make_options=[]))
0461 self.assertEqual(mock_build_config.call_count, 0)
0462
0463 def test_build_reconfig_remove_option(self):
0464 with tempfile.TemporaryDirectory('') as build_dir:
0465
0466 with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f:
0467 f.write('CONFIG_KUNIT=y')
0468 with open(kunit_kernel.get_old_kunitconfig_path(build_dir), 'w') as f:
0469 f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y')
0470 with open(kunit_kernel.get_kconfig_path(build_dir), 'w') as f:
0471 f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y')
0472
0473 tree = kunit_kernel.LinuxSourceTree(build_dir)
0474
0475
0476
0477 tree._ops = kunit_kernel.LinuxSourceTreeOperations('none', None)
0478 mock_build_config = mock.patch.object(tree, 'build_config').start()
0479
0480
0481 self.assertTrue(tree.build_reconfig(build_dir, make_options=[]))
0482 mock_build_config.assert_called_once_with(build_dir, [])
0483
0484
0485
0486
0487 class KUnitJsonTest(unittest.TestCase):
0488
0489 def _json_for(self, log_file):
0490 with open(test_data_path(log_file)) as file:
0491 test_result = kunit_parser.parse_run_tests(file)
0492 json_obj = kunit_json.get_json_result(
0493 test=test_result,
0494 metadata=kunit_json.Metadata())
0495 return json.loads(json_obj)
0496
0497 def test_failed_test_json(self):
0498 result = self._json_for('test_is_test_passed-failure.log')
0499 self.assertEqual(
0500 {'name': 'example_simple_test', 'status': 'FAIL'},
0501 result["sub_groups"][1]["test_cases"][0])
0502
0503 def test_crashed_test_json(self):
0504 result = self._json_for('test_kernel_panic_interrupt.log')
0505 self.assertEqual(
0506 {'name': '', 'status': 'ERROR'},
0507 result["sub_groups"][2]["test_cases"][1])
0508
0509 def test_skipped_test_json(self):
0510 result = self._json_for('test_skip_tests.log')
0511 self.assertEqual(
0512 {'name': 'example_skip_test', 'status': 'SKIP'},
0513 result["sub_groups"][1]["test_cases"][1])
0514
0515 def test_no_tests_json(self):
0516 result = self._json_for('test_is_test_passed-no_tests_run_with_header.log')
0517 self.assertEqual(0, len(result['sub_groups']))
0518
0519 def test_nested_json(self):
0520 result = self._json_for('test_is_test_passed-all_passed_nested.log')
0521 self.assertEqual(
0522 {'name': 'example_simple_test', 'status': 'PASS'},
0523 result["sub_groups"][0]["sub_groups"][0]["test_cases"][0])
0524
0525 class StrContains(str):
0526 def __eq__(self, other):
0527 return self in other
0528
0529 class KUnitMainTest(unittest.TestCase):
0530 def setUp(self):
0531 path = test_data_path('test_is_test_passed-all_passed.log')
0532 with open(path) as file:
0533 all_passed_log = file.readlines()
0534
0535 self.print_mock = mock.patch('kunit_printer.Printer.print').start()
0536 self.addCleanup(mock.patch.stopall)
0537
0538 self.mock_linux_init = mock.patch.object(kunit_kernel, 'LinuxSourceTree').start()
0539 self.linux_source_mock = self.mock_linux_init.return_value
0540 self.linux_source_mock.build_reconfig.return_value = True
0541 self.linux_source_mock.build_kernel.return_value = True
0542 self.linux_source_mock.run_kernel.return_value = all_passed_log
0543
0544 def test_config_passes_args_pass(self):
0545 kunit.main(['config', '--build_dir=.kunit'])
0546 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0547 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 0)
0548
0549 def test_build_passes_args_pass(self):
0550 kunit.main(['build'])
0551 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0552 self.linux_source_mock.build_kernel.assert_called_once_with(False, kunit.get_default_jobs(), '.kunit', None)
0553 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 0)
0554
0555 def test_exec_passes_args_pass(self):
0556 kunit.main(['exec'])
0557 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 0)
0558 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1)
0559 self.linux_source_mock.run_kernel.assert_called_once_with(
0560 args=None, build_dir='.kunit', filter_glob='', timeout=300)
0561 self.print_mock.assert_any_call(StrContains('Testing complete.'))
0562
0563 def test_run_passes_args_pass(self):
0564 kunit.main(['run'])
0565 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0566 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1)
0567 self.linux_source_mock.run_kernel.assert_called_once_with(
0568 args=None, build_dir='.kunit', filter_glob='', timeout=300)
0569 self.print_mock.assert_any_call(StrContains('Testing complete.'))
0570
0571 def test_exec_passes_args_fail(self):
0572 self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
0573 with self.assertRaises(SystemExit) as e:
0574 kunit.main(['exec'])
0575 self.assertEqual(e.exception.code, 1)
0576
0577 def test_run_passes_args_fail(self):
0578 self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
0579 with self.assertRaises(SystemExit) as e:
0580 kunit.main(['run'])
0581 self.assertEqual(e.exception.code, 1)
0582 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0583 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1)
0584 self.print_mock.assert_any_call(StrContains('could not find any KTAP output!'))
0585
0586 def test_exec_no_tests(self):
0587 self.linux_source_mock.run_kernel = mock.Mock(return_value=['TAP version 14', '1..0'])
0588 with self.assertRaises(SystemExit) as e:
0589 kunit.main(['run'])
0590 self.assertEqual(e.exception.code, 1)
0591 self.linux_source_mock.run_kernel.assert_called_once_with(
0592 args=None, build_dir='.kunit', filter_glob='', timeout=300)
0593 self.print_mock.assert_any_call(StrContains(' 0 tests run!'))
0594
0595 def test_exec_raw_output(self):
0596 self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
0597 kunit.main(['exec', '--raw_output'])
0598 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1)
0599 for call in self.print_mock.call_args_list:
0600 self.assertNotEqual(call, mock.call(StrContains('Testing complete.')))
0601 self.assertNotEqual(call, mock.call(StrContains(' 0 tests run!')))
0602
0603 def test_run_raw_output(self):
0604 self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
0605 kunit.main(['run', '--raw_output'])
0606 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0607 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1)
0608 for call in self.print_mock.call_args_list:
0609 self.assertNotEqual(call, mock.call(StrContains('Testing complete.')))
0610 self.assertNotEqual(call, mock.call(StrContains(' 0 tests run!')))
0611
0612 def test_run_raw_output_kunit(self):
0613 self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
0614 kunit.main(['run', '--raw_output=kunit'])
0615 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0616 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1)
0617 for call in self.print_mock.call_args_list:
0618 self.assertNotEqual(call, mock.call(StrContains('Testing complete.')))
0619 self.assertNotEqual(call, mock.call(StrContains(' 0 tests run')))
0620
0621 def test_run_raw_output_invalid(self):
0622 self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
0623 with self.assertRaises(SystemExit) as e:
0624 kunit.main(['run', '--raw_output=invalid'])
0625 self.assertNotEqual(e.exception.code, 0)
0626
0627 def test_run_raw_output_does_not_take_positional_args(self):
0628
0629
0630 self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
0631 kunit.main(['run', '--raw_output', 'filter_glob'])
0632 self.linux_source_mock.run_kernel.assert_called_once_with(
0633 args=None, build_dir='.kunit', filter_glob='filter_glob', timeout=300)
0634
0635 def test_exec_timeout(self):
0636 timeout = 3453
0637 kunit.main(['exec', '--timeout', str(timeout)])
0638 self.linux_source_mock.run_kernel.assert_called_once_with(
0639 args=None, build_dir='.kunit', filter_glob='', timeout=timeout)
0640 self.print_mock.assert_any_call(StrContains('Testing complete.'))
0641
0642 def test_run_timeout(self):
0643 timeout = 3453
0644 kunit.main(['run', '--timeout', str(timeout)])
0645 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0646 self.linux_source_mock.run_kernel.assert_called_once_with(
0647 args=None, build_dir='.kunit', filter_glob='', timeout=timeout)
0648 self.print_mock.assert_any_call(StrContains('Testing complete.'))
0649
0650 def test_run_builddir(self):
0651 build_dir = '.kunit'
0652 kunit.main(['run', '--build_dir=.kunit'])
0653 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0654 self.linux_source_mock.run_kernel.assert_called_once_with(
0655 args=None, build_dir=build_dir, filter_glob='', timeout=300)
0656 self.print_mock.assert_any_call(StrContains('Testing complete.'))
0657
0658 def test_config_builddir(self):
0659 build_dir = '.kunit'
0660 kunit.main(['config', '--build_dir', build_dir])
0661 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0662
0663 def test_build_builddir(self):
0664 build_dir = '.kunit'
0665 jobs = kunit.get_default_jobs()
0666 kunit.main(['build', '--build_dir', build_dir])
0667 self.linux_source_mock.build_kernel.assert_called_once_with(False, jobs, build_dir, None)
0668
0669 def test_exec_builddir(self):
0670 build_dir = '.kunit'
0671 kunit.main(['exec', '--build_dir', build_dir])
0672 self.linux_source_mock.run_kernel.assert_called_once_with(
0673 args=None, build_dir=build_dir, filter_glob='', timeout=300)
0674 self.print_mock.assert_any_call(StrContains('Testing complete.'))
0675
0676 def test_run_kunitconfig(self):
0677 kunit.main(['run', '--kunitconfig=mykunitconfig'])
0678
0679 self.mock_linux_init.assert_called_once_with('.kunit',
0680 kunitconfig_paths=['mykunitconfig'],
0681 kconfig_add=None,
0682 arch='um',
0683 cross_compile=None,
0684 qemu_config_path=None,
0685 extra_qemu_args=[])
0686
0687 def test_config_kunitconfig(self):
0688 kunit.main(['config', '--kunitconfig=mykunitconfig'])
0689
0690 self.mock_linux_init.assert_called_once_with('.kunit',
0691 kunitconfig_paths=['mykunitconfig'],
0692 kconfig_add=None,
0693 arch='um',
0694 cross_compile=None,
0695 qemu_config_path=None,
0696 extra_qemu_args=[])
0697
0698 @mock.patch.object(kunit_kernel, 'LinuxSourceTree')
0699 def test_run_multiple_kunitconfig(self, mock_linux_init):
0700 mock_linux_init.return_value = self.linux_source_mock
0701 kunit.main(['run', '--kunitconfig=mykunitconfig', '--kunitconfig=other'])
0702
0703 mock_linux_init.assert_called_once_with('.kunit',
0704 kunitconfig_paths=['mykunitconfig', 'other'],
0705 kconfig_add=None,
0706 arch='um',
0707 cross_compile=None,
0708 qemu_config_path=None,
0709 extra_qemu_args=[])
0710
0711 def test_run_kconfig_add(self):
0712 kunit.main(['run', '--kconfig_add=CONFIG_KASAN=y', '--kconfig_add=CONFIG_KCSAN=y'])
0713
0714 self.mock_linux_init.assert_called_once_with('.kunit',
0715 kunitconfig_paths=None,
0716 kconfig_add=['CONFIG_KASAN=y', 'CONFIG_KCSAN=y'],
0717 arch='um',
0718 cross_compile=None,
0719 qemu_config_path=None,
0720 extra_qemu_args=[])
0721
0722 def test_run_qemu_args(self):
0723 kunit.main(['run', '--arch=x86_64', '--qemu_args', '-m 2048'])
0724
0725 self.mock_linux_init.assert_called_once_with('.kunit',
0726 kunitconfig_paths=None,
0727 kconfig_add=None,
0728 arch='x86_64',
0729 cross_compile=None,
0730 qemu_config_path=None,
0731 extra_qemu_args=['-m', '2048'])
0732
0733 def test_run_kernel_args(self):
0734 kunit.main(['run', '--kernel_args=a=1', '--kernel_args=b=2'])
0735 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1)
0736 self.linux_source_mock.run_kernel.assert_called_once_with(
0737 args=['a=1','b=2'], build_dir='.kunit', filter_glob='', timeout=300)
0738 self.print_mock.assert_any_call(StrContains('Testing complete.'))
0739
0740 def test_list_tests(self):
0741 want = ['suite.test1', 'suite.test2', 'suite2.test1']
0742 self.linux_source_mock.run_kernel.return_value = ['TAP version 14', 'init: random output'] + want
0743
0744 got = kunit._list_tests(self.linux_source_mock,
0745 kunit.KunitExecRequest(None, None, '.kunit', 300, False, 'suite*', None, 'suite'))
0746
0747 self.assertEqual(got, want)
0748
0749 self.linux_source_mock.run_kernel.assert_called_once_with(
0750 args=['kunit.action=list'], build_dir='.kunit', filter_glob='suite*', timeout=300)
0751
0752
0753 @mock.patch.object(kunit, '_list_tests')
0754 def test_run_isolated_by_suite(self, mock_tests):
0755 mock_tests.return_value = ['suite.test1', 'suite.test2', 'suite2.test1']
0756 kunit.main(['exec', '--run_isolated=suite', 'suite*.test*'])
0757
0758
0759 mock_tests.assert_called_once_with(mock.ANY,
0760 kunit.KunitExecRequest(None, None, '.kunit', 300, False, 'suite*.test*', None, 'suite'))
0761 self.linux_source_mock.run_kernel.assert_has_calls([
0762 mock.call(args=None, build_dir='.kunit', filter_glob='suite.test*', timeout=300),
0763 mock.call(args=None, build_dir='.kunit', filter_glob='suite2.test*', timeout=300),
0764 ])
0765
0766 @mock.patch.object(kunit, '_list_tests')
0767 def test_run_isolated_by_test(self, mock_tests):
0768 mock_tests.return_value = ['suite.test1', 'suite.test2', 'suite2.test1']
0769 kunit.main(['exec', '--run_isolated=test', 'suite*'])
0770
0771
0772 mock_tests.assert_called_once_with(mock.ANY,
0773 kunit.KunitExecRequest(None, None, '.kunit', 300, False, 'suite*', None, 'test'))
0774 self.linux_source_mock.run_kernel.assert_has_calls([
0775 mock.call(args=None, build_dir='.kunit', filter_glob='suite.test1', timeout=300),
0776 mock.call(args=None, build_dir='.kunit', filter_glob='suite.test2', timeout=300),
0777 mock.call(args=None, build_dir='.kunit', filter_glob='suite2.test1', timeout=300),
0778 ])
0779
0780
0781 if __name__ == '__main__':
0782 unittest.main()