mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
kunit: add bash completion
Currently, kunit.py has many subcommands and options, making it difficult to remember them without checking the help message. Add --list-cmds and --list-opts to kunit.py to get available commands and options, use those outputs in kunit-completion.sh to show completion. This implementation is similar to perf and tools/perf/perf-completion.sh. Example output: $ source tools/testing/kunit/kunit-completion.sh $ ./tools/testing/kunit/kunit.py [TAB][TAB] build config exec parse run $ ./tools/testing/kunit/kunit.py run --k[TAB][TAB] --kconfig_add --kernel_args --kunitconfig Link: https://lore.kernel.org/r/20260117-kunit-completion-v2-1-cabd127d0801@gmail.com Reviewed-by: David Gow <davidgow@google.com> Signed-off-by: Ryota Sakamoto <sakamo.ryota@gmail.com> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
This commit is contained in:
parent
f126d68819
commit
db0c35ca36
4 changed files with 94 additions and 0 deletions
|
|
@ -335,3 +335,12 @@ command line arguments:
|
|||
|
||||
- ``--list_tests_attr``: If set, lists all tests that will be run and all of their
|
||||
attributes.
|
||||
|
||||
Command-line completion
|
||||
==============================
|
||||
|
||||
The kunit_tool comes with a bash completion script:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
source tools/testing/kunit/kunit-completion.sh
|
||||
|
|
|
|||
34
tools/testing/kunit/kunit-completion.sh
Normal file
34
tools/testing/kunit/kunit-completion.sh
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
# bash completion support for KUnit
|
||||
|
||||
_kunit_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
|
||||
_kunit()
|
||||
{
|
||||
local cur prev words cword
|
||||
_init_completion || return
|
||||
|
||||
local script="${_kunit_dir}/kunit.py"
|
||||
|
||||
if [[ $cword -eq 1 && "$cur" != -* ]]; then
|
||||
local cmds=$(${script} --list-cmds 2>/dev/null)
|
||||
COMPREPLY=($(compgen -W "${cmds}" -- "$cur"))
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$cur" == -* ]]; then
|
||||
if [[ -n "${words[1]}" && "${words[1]}" != -* ]]; then
|
||||
local opts=$(${script} ${words[1]} --list-opts 2>/dev/null)
|
||||
COMPREPLY=($(compgen -W "${opts}" -- "$cur"))
|
||||
return 0
|
||||
else
|
||||
local opts=$(${script} --list-opts 2>/dev/null)
|
||||
COMPREPLY=($(compgen -W "${opts}" -- "$cur"))
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
complete -o default -F _kunit kunit.py
|
||||
complete -o default -F _kunit kunit
|
||||
complete -o default -F _kunit ./tools/testing/kunit/kunit.py
|
||||
|
|
@ -328,6 +328,17 @@ def get_default_build_dir() -> str:
|
|||
return os.path.join(os.environ['KBUILD_OUTPUT'], '.kunit')
|
||||
return '.kunit'
|
||||
|
||||
def add_completion_opts(parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument('--list-opts',
|
||||
help=argparse.SUPPRESS,
|
||||
action='store_true')
|
||||
|
||||
def add_root_opts(parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument('--list-cmds',
|
||||
help=argparse.SUPPRESS,
|
||||
action='store_true')
|
||||
add_completion_opts(parser)
|
||||
|
||||
def add_common_opts(parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument('--build_dir',
|
||||
help='As in the make command, it specifies the build '
|
||||
|
|
@ -379,6 +390,8 @@ def add_common_opts(parser: argparse.ArgumentParser) -> None:
|
|||
help='Additional QEMU arguments, e.g. "-smp 8"',
|
||||
action='append', metavar='')
|
||||
|
||||
add_completion_opts(parser)
|
||||
|
||||
def add_build_opts(parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument('--jobs',
|
||||
help='As in the make command, "Specifies the number of '
|
||||
|
|
@ -574,6 +587,7 @@ subcommand_handlers_map = {
|
|||
def main(argv: Sequence[str]) -> None:
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Helps writing and running KUnit tests.')
|
||||
add_root_opts(parser)
|
||||
subparser = parser.add_subparsers(dest='subcommand')
|
||||
|
||||
# The 'run' command will config, build, exec, and parse in one go.
|
||||
|
|
@ -608,12 +622,28 @@ def main(argv: Sequence[str]) -> None:
|
|||
parse_parser.add_argument('file',
|
||||
help='Specifies the file to read results from.',
|
||||
type=str, nargs='?', metavar='input_file')
|
||||
add_completion_opts(parse_parser)
|
||||
|
||||
cli_args = parser.parse_args(massage_argv(argv))
|
||||
|
||||
if get_kernel_root_path():
|
||||
os.chdir(get_kernel_root_path())
|
||||
|
||||
if cli_args.list_cmds:
|
||||
print(" ".join(subparser.choices.keys()))
|
||||
return
|
||||
|
||||
if cli_args.list_opts:
|
||||
target_parser = subparser.choices.get(cli_args.subcommand)
|
||||
if not target_parser:
|
||||
target_parser = parser
|
||||
|
||||
# Accessing private attribute _option_string_actions to get
|
||||
# the list of options. This is not a public API, but argparse
|
||||
# does not provide a way to inspect options programmatically.
|
||||
print(' '.join(target_parser._option_string_actions.keys()))
|
||||
return
|
||||
|
||||
subcomand_handler = subcommand_handlers_map.get(cli_args.subcommand, None)
|
||||
|
||||
if subcomand_handler is None:
|
||||
|
|
|
|||
|
|
@ -11,11 +11,13 @@ from unittest import mock
|
|||
|
||||
import tempfile, shutil # Handling test_tmpdir
|
||||
|
||||
import io
|
||||
import itertools
|
||||
import json
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Iterable
|
||||
|
||||
import kunit_config
|
||||
|
|
@ -886,5 +888,24 @@ class KUnitMainTest(unittest.TestCase):
|
|||
mock.call(args=None, build_dir='.kunit', filter_glob='suite2.test1', filter='', filter_action=None, timeout=300),
|
||||
])
|
||||
|
||||
@mock.patch.object(sys, 'stdout', new_callable=io.StringIO)
|
||||
def test_list_cmds(self, mock_stdout):
|
||||
kunit.main(['--list-cmds'])
|
||||
output = mock_stdout.getvalue()
|
||||
output_cmds = sorted(output.split())
|
||||
expected_cmds = sorted(['build', 'config', 'exec', 'parse', 'run'])
|
||||
self.assertEqual(output_cmds, expected_cmds)
|
||||
|
||||
@mock.patch.object(sys, 'stdout', new_callable=io.StringIO)
|
||||
def test_run_list_opts(self, mock_stdout):
|
||||
kunit.main(['run', '--list-opts'])
|
||||
output = mock_stdout.getvalue()
|
||||
output_cmds = set(output.split())
|
||||
self.assertIn('--help', output_cmds)
|
||||
self.assertIn('--kunitconfig', output_cmds)
|
||||
self.assertIn('--jobs', output_cmds)
|
||||
self.assertIn('--kernel_args', output_cmds)
|
||||
self.assertIn('--raw_output', output_cmds)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue