def test_kconfig_add(self): want_kconfig = kunit_config.Kconfig() want_kconfig.add_entry('NOT_REAL', 'y') tree = kunit_kernel.LinuxSourceTree('', kconfig_add=['CONFIG_NOT_REAL=y']) self.assertTrue(want_kconfig.is_subset_of(tree._kconfig), msg=tree._kconfig)
def main(argv, linux=None): parser = argparse.ArgumentParser( description='Helps writing and running KUnit tests.') subparser = parser.add_subparsers(dest='subcommand') run_parser = subparser.add_parser('run', help='Runs KUnit tests.') run_parser.add_argument('--raw_output', help='don\'t format output from kernel', action='store_true') run_parser.add_argument( '--timeout', help='maximum number of seconds to allow for all tests ' 'to run. This does not include time taken to build the ' 'tests.', type=int, default=300, metavar='timeout') run_parser.add_argument( '--jobs', help='As in the make command, "Specifies the number of ' 'jobs (commands) to run simultaneously."', type=int, default=8, metavar='jobs') run_parser.add_argument( '--build_dir', help='As in the make command, it specifies the build ' 'directory.', type=str, default=None, metavar='build_dir') run_parser.add_argument('--defconfig', help='Uses a default kunitconfig.', action='store_true') cli_args = parser.parse_args(argv) if cli_args.subcommand == 'run': if cli_args.defconfig: create_default_kunitconfig() if not linux: linux = kunit_kernel.LinuxSourceTree() request = KunitRequest(cli_args.raw_output, cli_args.timeout, cli_args.jobs, cli_args.build_dir, cli_args.defconfig) result = run_tests(linux, request) if result.status != KunitStatus.SUCCESS: sys.exit(1) else: parser.print_help()
def test_build_reconfig_no_config(self): with tempfile.TemporaryDirectory('') as build_dir: with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y') tree = kunit_kernel.LinuxSourceTree(build_dir) mock_build_config = mock.patch.object(tree, 'build_config').start() # Should generate the .config self.assertTrue(tree.build_reconfig(build_dir, make_options=[])) mock_build_config.assert_called_once_with(build_dir, [])
def test_multiple_kunitconfig_invalid(self): with tempfile.TemporaryDirectory('') as dir: other = os.path.join(dir, 'otherkunitconfig') with open(os.path.join(dir, '.kunitconfig'), 'w') as f: f.write('CONFIG_KUNIT=y') with open(other, 'w') as f: f.write('CONFIG_KUNIT=m') with self.assertRaisesRegex(kunit_kernel.ConfigError, '(?s)Multiple values.*CONFIG_KUNIT'): kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir, other])
def test_build_reconfig_no_config(self): with tempfile.TemporaryDirectory('') as build_dir: with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y') tree = kunit_kernel.LinuxSourceTree(build_dir) # Stub out the source tree operations, so we don't have # the defaults for any given architecture get in the # way. tree._ops = kunit_kernel.LinuxSourceTreeOperations('none', None) mock_build_config = mock.patch.object(tree, 'build_config').start() # Should generate the .config self.assertTrue(tree.build_reconfig(build_dir, make_options=[])) mock_build_config.assert_called_once_with(build_dir, [])
def tree_from_args(cli_args: argparse.Namespace) -> kunit_kernel.LinuxSourceTree: """Returns a LinuxSourceTree based on the user's arguments.""" # Allow users to specify multiple arguments in one string, e.g. '-smp 8' qemu_args: List[str] = [] if cli_args.qemu_args: for arg in cli_args.qemu_args: qemu_args.extend(shlex.split(arg)) return kunit_kernel.LinuxSourceTree(cli_args.build_dir, kunitconfig_paths=cli_args.kunitconfig, kconfig_add=cli_args.kconfig_add, arch=cli_args.arch, cross_compile=cli_args.cross_compile, qemu_config_path=cli_args.qemu_config, extra_qemu_args=qemu_args)
def test_run_kernel_hits_exception(self): def fake_start(unused_args, unused_build_dir): return subprocess.Popen(['echo "hi\nbye"'], shell=True, text=True, stdout=subprocess.PIPE) with tempfile.TemporaryDirectory('') as build_dir: tree = kunit_kernel.LinuxSourceTree(build_dir, load_config=False) mock.patch.object(tree._ops, 'start', side_effect=fake_start).start() with self.assertRaises(ValueError): for line in tree.run_kernel(build_dir=build_dir): self.assertEqual(line, 'hi\n') raise ValueError('uh oh, did not read all output') with open(kunit_kernel.get_outfile_path(build_dir), 'rt') as outfile: self.assertEqual(outfile.read(), 'hi\nbye\n', msg='Missing some output')
def test_build_reconfig_existing_config(self): with tempfile.TemporaryDirectory('') as build_dir: # Existing .config is a superset, should not touch it with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y') with open(kunit_kernel.get_old_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y') with open(kunit_kernel.get_kconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y') tree = kunit_kernel.LinuxSourceTree(build_dir) mock_build_config = mock.patch.object(tree, 'build_config').start() self.assertTrue(tree.build_reconfig(build_dir, make_options=[])) self.assertEqual(mock_build_config.call_count, 0)
def test_build_reconfig_add_config_line(self): tempConfig = tempfile.NamedTemporaryFile(delete=False, mode="w+") kconfig = kunit_config.Kconfig() operations = TestLinuxSourceTreeOperationsAddLine(tempConfig.name) with mock.patch.object(kunit_kernel, 'KCONFIG_PATH', tempConfig.name): tree = kunit_kernel.LinuxSourceTree(kconfig_provider = TestConfigProvider(kconfig), linux_build_operations = operations) tempConfig.write(str('CONFIG_TEST=n\nCONFIG_MMU=y\n')) tempConfig.seek(0) returnValue = tree.build_reconfig() self.assertEquals(returnValue.status, kunit_kernel.ConfigStatus.SUCCESS, returnValue.info)
def test_build_reconfig_remove_option(self): with tempfile.TemporaryDirectory('') as build_dir: # We removed CONFIG_KUNIT_TEST=y from our .kunitconfig... with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y') with open(kunit_kernel.get_old_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y') with open(kunit_kernel.get_kconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y') tree = kunit_kernel.LinuxSourceTree(build_dir) mock_build_config = mock.patch.object(tree, 'build_config').start() # ... so we should trigger a call to build_config() self.assertTrue(tree.build_reconfig(build_dir, make_options=[])) mock_build_config.assert_called_once_with(build_dir, [])
def test_multiple_kunitconfig(self): want_kconfig = kunit_config.Kconfig() want_kconfig.add_entry('KUNIT', 'y') want_kconfig.add_entry('KUNIT_TEST', 'm') with tempfile.TemporaryDirectory('') as dir: other = os.path.join(dir, 'otherkunitconfig') with open(os.path.join(dir, '.kunitconfig'), 'w') as f: f.write('CONFIG_KUNIT=y') with open(other, 'w') as f: f.write('CONFIG_KUNIT_TEST=m') pass tree = kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir, other]) self.assertTrue(want_kconfig.is_subset_of(tree._kconfig), msg=tree._kconfig)
def test_build_reconfig_existing_config(self): with tempfile.TemporaryDirectory('') as build_dir: # Existing .config is a superset, should not touch it with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y') with open(kunit_kernel.get_old_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y') with open(kunit_kernel.get_kconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y') tree = kunit_kernel.LinuxSourceTree(build_dir) # Stub out the source tree operations, so we don't have # the defaults for any given architecture get in the # way. tree._ops = kunit_kernel.LinuxSourceTreeOperations('none', None) mock_build_config = mock.patch.object(tree, 'build_config').start() self.assertTrue(tree.build_reconfig(build_dir, make_options=[])) self.assertEqual(mock_build_config.call_count, 0)
def test_build_reconfig_remove_option(self): with tempfile.TemporaryDirectory('') as build_dir: # We removed CONFIG_KUNIT_TEST=y from our .kunitconfig... with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y') with open(kunit_kernel.get_old_kunitconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y') with open(kunit_kernel.get_kconfig_path(build_dir), 'w') as f: f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y') tree = kunit_kernel.LinuxSourceTree(build_dir) # Stub out the source tree operations, so we don't have # the defaults for any given architecture get in the # way. tree._ops = kunit_kernel.LinuxSourceTreeOperations('none', None) mock_build_config = mock.patch.object(tree, 'build_config').start() # ... so we should trigger a call to build_config() self.assertTrue(tree.build_reconfig(build_dir, make_options=[])) mock_build_config.assert_called_once_with(build_dir, [])
def test_valid_kunitconfig(self): with tempfile.NamedTemporaryFile('wt') as kunitconfig: tree = kunit_kernel.LinuxSourceTree( '', kunitconfig_path=kunitconfig.name)
def test_invalid_kunitconfig(self): with self.assertRaisesRegex(kunit_kernel.ConfigError, 'nonexistent.* does not exist'): kunit_kernel.LinuxSourceTree('', kunitconfig_path='/nonexistent_file')
def test_invalid_arch(self): with self.assertRaisesRegex(kunit_kernel.ConfigError, 'not a valid arch, options are.*x86_64'): kunit_kernel.LinuxSourceTree('', arch='invalid')
def test_dir_kunitconfig(self): with tempfile.TemporaryDirectory('') as dir: with open(os.path.join(dir, '.kunitconfig'), 'w') as f: pass tree = kunit_kernel.LinuxSourceTree('', kunitconfig_path=dir)
import kunit_config import kunit_kernel import kunit_parser parser = argparse.ArgumentParser(description='Runs KUnit tests.') parser.add_argument('--raw_output', help='don\'t format output from kernel', action='store_true') parser.add_argument('--timeout', help='maximum number of seconds to allow for ' 'all tests to run. This does not include time taken to ' 'build the tests.', type=int, default=300, metavar='timeout') cli_args = parser.parse_args() linux = kunit_kernel.LinuxSourceTree() config_start = time.time() success = linux.build_reconfig() config_end = time.time() if not success: quit() kunit_parser.print_with_timestamp('Building KUnit Kernel ...') build_start = time.time() success = linux.build_um_kernel() build_end = time.time() if not success: quit()
def main(argv, linux=None): parser = argparse.ArgumentParser( description='Helps writing and running KUnit tests.') subparser = parser.add_subparsers(dest='subcommand') # The 'run' command will config, build, exec, and parse in one go. run_parser = subparser.add_parser('run', help='Runs KUnit tests.') add_common_opts(run_parser) add_build_opts(run_parser) add_exec_opts(run_parser) add_parse_opts(run_parser) config_parser = subparser.add_parser( 'config', help='Ensures that .config contains all of ' 'the options in .kunitconfig') add_common_opts(config_parser) build_parser = subparser.add_parser( 'build', help='Builds a kernel with KUnit tests') add_common_opts(build_parser) add_build_opts(build_parser) exec_parser = subparser.add_parser('exec', help='Run a kernel with KUnit tests') add_common_opts(exec_parser) add_exec_opts(exec_parser) add_parse_opts(exec_parser) # The 'parse' option is special, as it doesn't need the kernel source # (therefore there is no need for a build_dir, hence no add_common_opts) # and the '--file' argument is not relevant to 'run', so isn't in # add_parse_opts() parse_parser = subparser.add_parser( 'parse', help='Parses KUnit results from a file, ' 'and parses formatted results.') add_parse_opts(parse_parser) parse_parser.add_argument('file', help='Specifies the file to read results from.', type=str, nargs='?', metavar='input_file') cli_args = parser.parse_args(argv) if get_kernel_root_path(): os.chdir(get_kernel_root_path()) if cli_args.subcommand == 'run': if not os.path.exists(cli_args.build_dir): os.mkdir(cli_args.build_dir) if not linux: linux = kunit_kernel.LinuxSourceTree( cli_args.build_dir, kunitconfig_path=cli_args.kunitconfig, arch=cli_args.arch, cross_compile=cli_args.cross_compile, qemu_config_path=cli_args.qemu_config) request = KunitRequest(cli_args.raw_output, cli_args.timeout, cli_args.jobs, cli_args.build_dir, cli_args.alltests, cli_args.filter_glob, cli_args.json, cli_args.make_options) result = run_tests(linux, request) if result.status != KunitStatus.SUCCESS: sys.exit(1) elif cli_args.subcommand == 'config': if cli_args.build_dir and (not os.path.exists(cli_args.build_dir)): os.mkdir(cli_args.build_dir) if not linux: linux = kunit_kernel.LinuxSourceTree( cli_args.build_dir, kunitconfig_path=cli_args.kunitconfig, arch=cli_args.arch, cross_compile=cli_args.cross_compile, qemu_config_path=cli_args.qemu_config) request = KunitConfigRequest(cli_args.build_dir, cli_args.make_options) result = config_tests(linux, request) kunit_parser.print_with_timestamp( ('Elapsed time: %.3fs\n') % (result.elapsed_time)) if result.status != KunitStatus.SUCCESS: sys.exit(1) elif cli_args.subcommand == 'build': if not linux: linux = kunit_kernel.LinuxSourceTree( cli_args.build_dir, kunitconfig_path=cli_args.kunitconfig, arch=cli_args.arch, cross_compile=cli_args.cross_compile, qemu_config_path=cli_args.qemu_config) request = KunitBuildRequest(cli_args.jobs, cli_args.build_dir, cli_args.alltests, cli_args.make_options) result = build_tests(linux, request) kunit_parser.print_with_timestamp( ('Elapsed time: %.3fs\n') % (result.elapsed_time)) if result.status != KunitStatus.SUCCESS: sys.exit(1) elif cli_args.subcommand == 'exec': if not linux: linux = kunit_kernel.LinuxSourceTree( cli_args.build_dir, kunitconfig_path=cli_args.kunitconfig, arch=cli_args.arch, cross_compile=cli_args.cross_compile, qemu_config_path=cli_args.qemu_config) exec_request = KunitExecRequest(cli_args.timeout, cli_args.build_dir, cli_args.alltests, cli_args.filter_glob) exec_result = exec_tests(linux, exec_request) parse_request = KunitParseRequest(cli_args.raw_output, exec_result.result, cli_args.build_dir, cli_args.json) result = parse_tests(parse_request) kunit_parser.print_with_timestamp( ('Elapsed time: %.3fs\n') % (exec_result.elapsed_time)) if result.status != KunitStatus.SUCCESS: sys.exit(1) elif cli_args.subcommand == 'parse': if cli_args.file == None: kunit_output = sys.stdin else: with open(cli_args.file, 'r') as f: kunit_output = f.read().splitlines() request = KunitParseRequest(cli_args.raw_output, kunit_output, None, cli_args.json) result = parse_tests(request) if result.status != KunitStatus.SUCCESS: sys.exit(1) else: parser.print_help()
def test_kconfig_add(self): tree = kunit_kernel.LinuxSourceTree('', kconfig_add=['CONFIG_NOT_REAL=y']) self.assertIn(kunit_config.KconfigEntry('NOT_REAL', 'y'), tree._kconfig.entries())
'new', help='Prints out boilerplate for writing new tests.') new_parser.add_argument('--path', help='Path of source file to be tested.', type=str, required=True) new_parser.add_argument('--namespace_prefix', help='Namespace of the code to be tested.', type=str) new_parser.add_argument( '--print_test_only', help='Skip Kconfig and Makefile while printing sample ' 'test.', action='store_true') cli_args = parser.parse_args(argv) if cli_args.subcommand == 'new': print_test_skeletons(cli_args) elif cli_args.subcommand == 'run': request = KunitRequest(cli_args.raw_output, cli_args.timeout, cli_args.jobs, cli_args.external_config) result = run_tests(linux, request) if result.status != KunitStatus.SUCCESS: sys.exit(1) else: parser.print_help() if __name__ == '__main__': main(sys.argv[1:], kunit_kernel.LinuxSourceTree())