kunit: tool: more descriptive metavars/--help output

Before, our help output contained lines like
  --kconfig_add KCONFIG_ADD
  --qemu_config qemu_config
  --jobs jobs

They're not very helpful.

The former kind come from the automatic 'metavar' we get from argparse,
the uppercase version of the flag name.
The latter are where we manually specified metavar as the flag name.

After:
  --build_dir DIR
  --make_options X=Y
  --kunitconfig PATH
  --kconfig_add CONFIG_X=Y
  --arch ARCH
  --cross_compile PREFIX
  --qemu_config FILE
  --jobs N
  --timeout SECONDS
  --raw_output [{all,kunit}]
  --json [FILE]

This patch tries to make the code more clear by specifying the _type_ of
input we expect, e.g. --build_dir is a DIR, --qemu_config is a FILE.
I also switched it to uppercase since it looked more clearly like
placeholder text that way.

This patch also changes --raw_output to specify `choices` to make it
more clear what the options are, and this way argparse can validate it
for us, as shown by the added test case.

Signed-off-by: Daniel Latypov <dlatypov@google.com>
Reviewed-by: David Gow <davidgow@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
This commit is contained in:
Daniel Latypov 2022-02-26 13:23:25 -08:00 committed by Shuah Khan
parent d34f82d67d
commit baa3331503
2 changed files with 17 additions and 14 deletions

View file

@ -206,8 +206,6 @@ def parse_tests(request: KunitParseRequest, metadata: kunit_json.Metadata, input
pass pass
elif request.raw_output == 'kunit': elif request.raw_output == 'kunit':
output = kunit_parser.extract_tap_lines(output) output = kunit_parser.extract_tap_lines(output)
else:
print(f'Unknown --raw_output option "{request.raw_output}"', file=sys.stderr)
for line in output: for line in output:
print(line.rstrip()) print(line.rstrip())
@ -284,10 +282,10 @@ def add_common_opts(parser) -> None:
parser.add_argument('--build_dir', parser.add_argument('--build_dir',
help='As in the make command, it specifies the build ' help='As in the make command, it specifies the build '
'directory.', 'directory.',
type=str, default='.kunit', metavar='build_dir') type=str, default='.kunit', metavar='DIR')
parser.add_argument('--make_options', parser.add_argument('--make_options',
help='X=Y make option, can be repeated.', help='X=Y make option, can be repeated.',
action='append') action='append', metavar='X=Y')
parser.add_argument('--alltests', parser.add_argument('--alltests',
help='Run all KUnit tests through allyesconfig', help='Run all KUnit tests through allyesconfig',
action='store_true') action='store_true')
@ -295,11 +293,11 @@ def add_common_opts(parser) -> None:
help='Path to Kconfig fragment that enables KUnit tests.' help='Path to Kconfig fragment that enables KUnit tests.'
' If given a directory, (e.g. lib/kunit), "/.kunitconfig" ' ' If given a directory, (e.g. lib/kunit), "/.kunitconfig" '
'will get automatically appended.', 'will get automatically appended.',
metavar='kunitconfig') metavar='PATH')
parser.add_argument('--kconfig_add', parser.add_argument('--kconfig_add',
help='Additional Kconfig options to append to the ' help='Additional Kconfig options to append to the '
'.kunitconfig, e.g. CONFIG_KASAN=y. Can be repeated.', '.kunitconfig, e.g. CONFIG_KASAN=y. Can be repeated.',
action='append') action='append', metavar='CONFIG_X=Y')
parser.add_argument('--arch', parser.add_argument('--arch',
help=('Specifies the architecture to run tests under. ' help=('Specifies the architecture to run tests under. '
@ -307,7 +305,7 @@ def add_common_opts(parser) -> None:
'string passed to the ARCH make param, ' 'string passed to the ARCH make param, '
'e.g. i386, x86_64, arm, um, etc. Non-UML ' 'e.g. i386, x86_64, arm, um, etc. Non-UML '
'architectures run on QEMU.'), 'architectures run on QEMU.'),
type=str, default='um', metavar='arch') type=str, default='um', metavar='ARCH')
parser.add_argument('--cross_compile', parser.add_argument('--cross_compile',
help=('Sets make\'s CROSS_COMPILE variable; it should ' help=('Sets make\'s CROSS_COMPILE variable; it should '
@ -319,18 +317,18 @@ def add_common_opts(parser) -> None:
'if you have downloaded the microblaze toolchain ' 'if you have downloaded the microblaze toolchain '
'from the 0-day website to a directory in your ' 'from the 0-day website to a directory in your '
'home directory called `toolchains`).'), 'home directory called `toolchains`).'),
metavar='cross_compile') metavar='PREFIX')
parser.add_argument('--qemu_config', parser.add_argument('--qemu_config',
help=('Takes a path to a path to a file containing ' help=('Takes a path to a path to a file containing '
'a QemuArchParams object.'), 'a QemuArchParams object.'),
type=str, metavar='qemu_config') type=str, metavar='FILE')
def add_build_opts(parser) -> None: def add_build_opts(parser) -> None:
parser.add_argument('--jobs', parser.add_argument('--jobs',
help='As in the make command, "Specifies the number of ' help='As in the make command, "Specifies the number of '
'jobs (commands) to run simultaneously."', 'jobs (commands) to run simultaneously."',
type=int, default=get_default_jobs(), metavar='jobs') type=int, default=get_default_jobs(), metavar='N')
def add_exec_opts(parser) -> None: def add_exec_opts(parser) -> None:
parser.add_argument('--timeout', parser.add_argument('--timeout',
@ -339,7 +337,7 @@ def add_exec_opts(parser) -> None:
'tests.', 'tests.',
type=int, type=int,
default=300, default=300,
metavar='timeout') metavar='SECONDS')
parser.add_argument('filter_glob', parser.add_argument('filter_glob',
help='Filter which KUnit test suites/tests run at ' help='Filter which KUnit test suites/tests run at '
'boot-time, e.g. list* or list*.*del_test', 'boot-time, e.g. list* or list*.*del_test',
@ -349,7 +347,7 @@ def add_exec_opts(parser) -> None:
metavar='filter_glob') metavar='filter_glob')
parser.add_argument('--kernel_args', parser.add_argument('--kernel_args',
help='Kernel command-line parameters. Maybe be repeated', help='Kernel command-line parameters. Maybe be repeated',
action='append') action='append', metavar='')
parser.add_argument('--run_isolated', help='If set, boot the kernel for each ' parser.add_argument('--run_isolated', help='If set, boot the kernel for each '
'individual suite/test. This is can be useful for debugging ' 'individual suite/test. This is can be useful for debugging '
'a non-hermetic test, one that might pass/fail based on ' 'a non-hermetic test, one that might pass/fail based on '
@ -360,13 +358,13 @@ def add_exec_opts(parser) -> None:
def add_parse_opts(parser) -> None: def add_parse_opts(parser) -> None:
parser.add_argument('--raw_output', help='If set don\'t format output from kernel. ' parser.add_argument('--raw_output', help='If set don\'t format output from kernel. '
'If set to --raw_output=kunit, filters to just KUnit output.', 'If set to --raw_output=kunit, filters to just KUnit output.',
type=str, nargs='?', const='all', default=None) type=str, nargs='?', const='all', default=None, choices=['all', 'kunit'])
parser.add_argument('--json', parser.add_argument('--json',
nargs='?', nargs='?',
help='Stores test results in a JSON, and either ' help='Stores test results in a JSON, and either '
'prints to stdout or saves to file if a ' 'prints to stdout or saves to file if a '
'filename is specified', 'filename is specified',
type=str, const='stdout', default=None) type=str, const='stdout', default=None, metavar='FILE')
def main(argv, linux=None): def main(argv, linux=None):
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(

View file

@ -593,6 +593,11 @@ class KUnitMainTest(unittest.TestCase):
self.assertNotEqual(call, mock.call(StrContains('Testing complete.'))) self.assertNotEqual(call, mock.call(StrContains('Testing complete.')))
self.assertNotEqual(call, mock.call(StrContains(' 0 tests run'))) self.assertNotEqual(call, mock.call(StrContains(' 0 tests run')))
def test_run_raw_output_invalid(self):
self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
with self.assertRaises(SystemExit) as e:
kunit.main(['run', '--raw_output=invalid'], self.linux_source_mock)
def test_run_raw_output_does_not_take_positional_args(self): def test_run_raw_output_does_not_take_positional_args(self):
# --raw_output is a string flag, but we don't want it to consume # --raw_output is a string flag, but we don't want it to consume
# any positional arguments, only ones after an '=' # any positional arguments, only ones after an '='