linux-stable/tools/testing/kunit/kunit_tool_test.py
Linus Torvalds 53e5504bdb linux-kselftest-kunit-5.9-rc1
This Kunit update for Linux 5.9-rc1 consists of:
 
 - Adds a generic kunit_resource API extending it to support
   resources that are passed in to kunit in addition kunit
   allocated resources. In addition, KUnit resources are now
   refcounted to avoid passed in resources being released while
   in use by kunit.
 
 - Add support for named resources.
 
 - Important bug fixes from Brendan Higgins and Will Chen
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEPZKym/RZuOCGeA/kCwJExA0NQxwFAl8pyI4ACgkQCwJExA0N
 QxwQmQ//YXvS1IMt4yLQ7iTrhSK2CavzPi/zX+1bgXj7RfEPrdolF12tcHf7b/Ef
 UwhG/PTEE6VkBWFuprleGk0fvVW9h13K+2RkN6wkx8rmTMunMhqmMIRj4neGQWQH
 LV9bYcc5HBH36jbSnJYMFDJdsATq3mmPMeknzkJf/qZgWxczBLo3pUHPNRuhZWq7
 MaRUutpo1f3oSroxhcY8gouRjjPq+yUCip9EeQfdZc/LV9tqjwhjfo+zRKAY3jGf
 0KL00wv4NMTNBSgLkxXFrTcyP28Y84MZB+wE3ikyE5a5wzzvMXuEtZhJk9a9q2ZJ
 tZI+ICCjnTa+E3pN93F2w7cwyrQysxNH1tpK0qv1hGXLRuxOGCJ993AeUtIWjnyV
 CYh/OGK9o92pRuTmoJnMNk9em1WF45YTtvhzpadPiBGb84nbxYSAlrDmm/4xC89p
 7PPpkkVxFReMiu1fIyXOV++y33YFMDtoWe/Qn3pLBRpDDs/XWdK0eT4dVWx1/ttl
 BdtbAxXafApVI5lGk1qPoGC1MO9XvaAidQP6PULD/rhw2Ww6rtlvwGVPffx/omkn
 zgzPTxH1rBehzKPcEaorQqqR6yGXxb4v+gJi1Tg8qRE51Lw619dfyZlJO7axp2h6
 7RO3BOVrIkwLP9XT2NPlL6t+RqbQXezGoZjigLmBRlCSvs1lbLs=
 =kIIk
 -----END PGP SIGNATURE-----

Merge tag 'linux-kselftest-kunit-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull kunit updates from Shuah Khan:

 - Add a generic kunit_resource API extending it to support resources
   that are passed in to kunit in addition kunit allocated resources. In
   addition, KUnit resources are now refcounted to avoid passed in
   resources being released while in use by kunit.

 - Add support for named resources.

 - Important bug fixes from Brendan Higgins and Will Chen

* tag 'linux-kselftest-kunit-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  kunit: tool: fix improper treatment of file location
  kunit: tool: fix broken default args in unit tests
  kunit: capture stderr on all make subprocess calls
  Documentation: kunit: Remove references to --defconfig
  kunit: add support for named resources
  kunit: generalize kunit_resource API beyond allocated resources
2020-08-05 10:07:39 -07:00

352 lines
13 KiB
Python
Executable file

#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0
#
# A collection of tests for tools/testing/kunit/kunit.py
#
# Copyright (C) 2019, Google LLC.
# Author: Brendan Higgins <brendanhiggins@google.com>
import unittest
from unittest import mock
import tempfile, shutil # Handling test_tmpdir
import os
import kunit_config
import kunit_parser
import kunit_kernel
import kunit
test_tmpdir = ''
def setUpModule():
global test_tmpdir
test_tmpdir = tempfile.mkdtemp()
def tearDownModule():
shutil.rmtree(test_tmpdir)
def get_absolute_path(path):
return os.path.join(os.path.dirname(__file__), path)
class KconfigTest(unittest.TestCase):
def test_is_subset_of(self):
kconfig0 = kunit_config.Kconfig()
self.assertTrue(kconfig0.is_subset_of(kconfig0))
kconfig1 = kunit_config.Kconfig()
kconfig1.add_entry(kunit_config.KconfigEntry('TEST', 'y'))
self.assertTrue(kconfig1.is_subset_of(kconfig1))
self.assertTrue(kconfig0.is_subset_of(kconfig1))
self.assertFalse(kconfig1.is_subset_of(kconfig0))
def test_read_from_file(self):
kconfig = kunit_config.Kconfig()
kconfig_path = get_absolute_path(
'test_data/test_read_from_file.kconfig')
kconfig.read_from_file(kconfig_path)
expected_kconfig = kunit_config.Kconfig()
expected_kconfig.add_entry(
kunit_config.KconfigEntry('UML', 'y'))
expected_kconfig.add_entry(
kunit_config.KconfigEntry('MMU', 'y'))
expected_kconfig.add_entry(
kunit_config.KconfigEntry('TEST', 'y'))
expected_kconfig.add_entry(
kunit_config.KconfigEntry('EXAMPLE_TEST', 'y'))
expected_kconfig.add_entry(
kunit_config.KconfigEntry('MK8', 'n'))
self.assertEqual(kconfig.entries(), expected_kconfig.entries())
def test_write_to_file(self):
kconfig_path = os.path.join(test_tmpdir, '.config')
expected_kconfig = kunit_config.Kconfig()
expected_kconfig.add_entry(
kunit_config.KconfigEntry('UML', 'y'))
expected_kconfig.add_entry(
kunit_config.KconfigEntry('MMU', 'y'))
expected_kconfig.add_entry(
kunit_config.KconfigEntry('TEST', 'y'))
expected_kconfig.add_entry(
kunit_config.KconfigEntry('EXAMPLE_TEST', 'y'))
expected_kconfig.add_entry(
kunit_config.KconfigEntry('MK8', 'n'))
expected_kconfig.write_to_file(kconfig_path)
actual_kconfig = kunit_config.Kconfig()
actual_kconfig.read_from_file(kconfig_path)
self.assertEqual(actual_kconfig.entries(),
expected_kconfig.entries())
class KUnitParserTest(unittest.TestCase):
def assertContains(self, needle, haystack):
for line in haystack:
if needle in line:
return
raise AssertionError('"' +
str(needle) + '" not found in "' + str(haystack) + '"!')
def test_output_isolated_correctly(self):
log_path = get_absolute_path(
'test_data/test_output_isolated_correctly.log')
file = open(log_path)
result = kunit_parser.isolate_kunit_output(file.readlines())
self.assertContains('TAP version 14\n', result)
self.assertContains(' # Subtest: example', result)
self.assertContains(' 1..2', result)
self.assertContains(' ok 1 - example_simple_test', result)
self.assertContains(' ok 2 - example_mock_test', result)
self.assertContains('ok 1 - example', result)
file.close()
def test_output_with_prefix_isolated_correctly(self):
log_path = get_absolute_path(
'test_data/test_pound_sign.log')
with open(log_path) as file:
result = kunit_parser.isolate_kunit_output(file.readlines())
self.assertContains('TAP version 14\n', result)
self.assertContains(' # Subtest: kunit-resource-test', result)
self.assertContains(' 1..5', result)
self.assertContains(' ok 1 - kunit_resource_test_init_resources', result)
self.assertContains(' ok 2 - kunit_resource_test_alloc_resource', result)
self.assertContains(' ok 3 - kunit_resource_test_destroy_resource', result)
self.assertContains(' foo bar #', result)
self.assertContains(' ok 4 - kunit_resource_test_cleanup_resources', result)
self.assertContains(' ok 5 - kunit_resource_test_proper_free_ordering', result)
self.assertContains('ok 1 - kunit-resource-test', result)
self.assertContains(' foo bar # non-kunit output', result)
self.assertContains(' # Subtest: kunit-try-catch-test', result)
self.assertContains(' 1..2', result)
self.assertContains(' ok 1 - kunit_test_try_catch_successful_try_no_catch',
result)
self.assertContains(' ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch',
result)
self.assertContains('ok 2 - kunit-try-catch-test', result)
self.assertContains(' # Subtest: string-stream-test', result)
self.assertContains(' 1..3', result)
self.assertContains(' ok 1 - string_stream_test_empty_on_creation', result)
self.assertContains(' ok 2 - string_stream_test_not_empty_after_add', result)
self.assertContains(' ok 3 - string_stream_test_get_string', result)
self.assertContains('ok 3 - string-stream-test', result)
def test_parse_successful_test_log(self):
all_passed_log = get_absolute_path(
'test_data/test_is_test_passed-all_passed.log')
file = open(all_passed_log)
result = kunit_parser.parse_run_tests(file.readlines())
self.assertEqual(
kunit_parser.TestStatus.SUCCESS,
result.status)
file.close()
def test_parse_failed_test_log(self):
failed_log = get_absolute_path(
'test_data/test_is_test_passed-failure.log')
file = open(failed_log)
result = kunit_parser.parse_run_tests(file.readlines())
self.assertEqual(
kunit_parser.TestStatus.FAILURE,
result.status)
file.close()
def test_no_tests(self):
empty_log = get_absolute_path(
'test_data/test_is_test_passed-no_tests_run.log')
file = open(empty_log)
result = kunit_parser.parse_run_tests(
kunit_parser.isolate_kunit_output(file.readlines()))
self.assertEqual(0, len(result.suites))
self.assertEqual(
kunit_parser.TestStatus.NO_TESTS,
result.status)
file.close()
def test_no_kunit_output(self):
crash_log = get_absolute_path(
'test_data/test_insufficient_memory.log')
file = open(crash_log)
print_mock = mock.patch('builtins.print').start()
result = kunit_parser.parse_run_tests(
kunit_parser.isolate_kunit_output(file.readlines()))
print_mock.assert_any_call(StrContains("no kunit output detected"))
print_mock.stop()
file.close()
def test_crashed_test(self):
crashed_log = get_absolute_path(
'test_data/test_is_test_passed-crash.log')
file = open(crashed_log)
result = kunit_parser.parse_run_tests(file.readlines())
self.assertEqual(
kunit_parser.TestStatus.TEST_CRASHED,
result.status)
file.close()
def test_ignores_prefix_printk_time(self):
prefix_log = get_absolute_path(
'test_data/test_config_printk_time.log')
with open(prefix_log) as file:
result = kunit_parser.parse_run_tests(file.readlines())
self.assertEqual('kunit-resource-test', result.suites[0].name)
def test_ignores_multiple_prefixes(self):
prefix_log = get_absolute_path(
'test_data/test_multiple_prefixes.log')
with open(prefix_log) as file:
result = kunit_parser.parse_run_tests(file.readlines())
self.assertEqual('kunit-resource-test', result.suites[0].name)
def test_prefix_mixed_kernel_output(self):
mixed_prefix_log = get_absolute_path(
'test_data/test_interrupted_tap_output.log')
with open(mixed_prefix_log) as file:
result = kunit_parser.parse_run_tests(file.readlines())
self.assertEqual('kunit-resource-test', result.suites[0].name)
def test_prefix_poundsign(self):
pound_log = get_absolute_path('test_data/test_pound_sign.log')
with open(pound_log) as file:
result = kunit_parser.parse_run_tests(file.readlines())
self.assertEqual('kunit-resource-test', result.suites[0].name)
def test_kernel_panic_end(self):
panic_log = get_absolute_path('test_data/test_kernel_panic_interrupt.log')
with open(panic_log) as file:
result = kunit_parser.parse_run_tests(file.readlines())
self.assertEqual('kunit-resource-test', result.suites[0].name)
def test_pound_no_prefix(self):
pound_log = get_absolute_path('test_data/test_pound_no_prefix.log')
with open(pound_log) as file:
result = kunit_parser.parse_run_tests(file.readlines())
self.assertEqual('kunit-resource-test', result.suites[0].name)
class StrContains(str):
def __eq__(self, other):
return self in other
class KUnitMainTest(unittest.TestCase):
def setUp(self):
path = get_absolute_path('test_data/test_is_test_passed-all_passed.log')
file = open(path)
all_passed_log = file.readlines()
self.print_patch = mock.patch('builtins.print')
self.print_mock = self.print_patch.start()
self.linux_source_mock = mock.Mock()
self.linux_source_mock.build_reconfig = mock.Mock(return_value=True)
self.linux_source_mock.build_um_kernel = mock.Mock(return_value=True)
self.linux_source_mock.run_kernel = mock.Mock(return_value=all_passed_log)
def tearDown(self):
self.print_patch.stop()
pass
def test_config_passes_args_pass(self):
kunit.main(['config', '--build_dir=.kunit'], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 1
assert self.linux_source_mock.run_kernel.call_count == 0
def test_build_passes_args_pass(self):
kunit.main(['build'], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 0
self.linux_source_mock.build_um_kernel.assert_called_once_with(False, 8, '.kunit', None)
assert self.linux_source_mock.run_kernel.call_count == 0
def test_exec_passes_args_pass(self):
kunit.main(['exec'], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 0
assert self.linux_source_mock.run_kernel.call_count == 1
self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='.kunit', timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_run_passes_args_pass(self):
kunit.main(['run'], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 1
assert self.linux_source_mock.run_kernel.call_count == 1
self.linux_source_mock.run_kernel.assert_called_once_with(
build_dir='.kunit', timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_exec_passes_args_fail(self):
self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
with self.assertRaises(SystemExit) as e:
kunit.main(['exec'], self.linux_source_mock)
assert type(e.exception) == SystemExit
assert e.exception.code == 1
def test_run_passes_args_fail(self):
self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
with self.assertRaises(SystemExit) as e:
kunit.main(['run'], self.linux_source_mock)
assert type(e.exception) == SystemExit
assert e.exception.code == 1
assert self.linux_source_mock.build_reconfig.call_count == 1
assert self.linux_source_mock.run_kernel.call_count == 1
self.print_mock.assert_any_call(StrContains(' 0 tests run'))
def test_exec_raw_output(self):
self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
kunit.main(['exec', '--raw_output'], self.linux_source_mock)
assert self.linux_source_mock.run_kernel.call_count == 1
for kall in self.print_mock.call_args_list:
assert kall != mock.call(StrContains('Testing complete.'))
assert kall != mock.call(StrContains(' 0 tests run'))
def test_run_raw_output(self):
self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
kunit.main(['run', '--raw_output'], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 1
assert self.linux_source_mock.run_kernel.call_count == 1
for kall in self.print_mock.call_args_list:
assert kall != mock.call(StrContains('Testing complete.'))
assert kall != mock.call(StrContains(' 0 tests run'))
def test_exec_timeout(self):
timeout = 3453
kunit.main(['exec', '--timeout', str(timeout)], self.linux_source_mock)
self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='.kunit', timeout=timeout)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_run_timeout(self):
timeout = 3453
kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 1
self.linux_source_mock.run_kernel.assert_called_once_with(
build_dir='.kunit', timeout=timeout)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_run_builddir(self):
build_dir = '.kunit'
kunit.main(['run', '--build_dir=.kunit'], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 1
self.linux_source_mock.run_kernel.assert_called_once_with(
build_dir=build_dir, timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_config_builddir(self):
build_dir = '.kunit'
kunit.main(['config', '--build_dir', build_dir], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 1
def test_build_builddir(self):
build_dir = '.kunit'
kunit.main(['build', '--build_dir', build_dir], self.linux_source_mock)
self.linux_source_mock.build_um_kernel.assert_called_once_with(False, 8, build_dir, None)
def test_exec_builddir(self):
build_dir = '.kunit'
kunit.main(['exec', '--build_dir', build_dir], self.linux_source_mock)
self.linux_source_mock.run_kernel.assert_called_once_with(build_dir=build_dir, timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
if __name__ == '__main__':
unittest.main()