From a7d6ca2bd947e02cb2ed81e9778e75ba7fcf7db8 Mon Sep 17 00:00:00 2001 From: Al Semjonovs Date: Thu, 22 Sep 2022 08:46:44 -0600 Subject: [PATCH] west: west twister integration Add twister command to west. Signed-off-by: Al Semjonovs --- scripts/west-commands.yml | 5 ++ scripts/west_commands/tests/test_twister.py | 53 +++++++++++++++++ scripts/west_commands/twister_cmd.py | 64 +++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 scripts/west_commands/tests/test_twister.py create mode 100644 scripts/west_commands/twister_cmd.py diff --git a/scripts/west-commands.yml b/scripts/west-commands.yml index a9d9d3bf641..5f63b44225c 100644 --- a/scripts/west-commands.yml +++ b/scripts/west-commands.yml @@ -15,6 +15,11 @@ west-commands: - name: build class: Build help: compile a Zephyr application + - file: scripts/west_commands/twister_cmd.py + commands: + - name: twister + class: Twister + help: west twister wrapper - file: scripts/west_commands/sign.py commands: - name: sign diff --git a/scripts/west_commands/tests/test_twister.py b/scripts/west_commands/tests/test_twister.py new file mode 100644 index 00000000000..c884b8e851e --- /dev/null +++ b/scripts/west_commands/tests/test_twister.py @@ -0,0 +1,53 @@ +# Copyright (c) 2023 Google Inc +# +# SPDX-License-Identifier: Apache-2.0 + +from argparse import Namespace + +from twister_cmd import Twister +import pytest +import argparse + +TEST_CASES = [ + { + "r": [], + "c": False, + "test_only": False, + }, + { + "r": ["-c", "-T tests/ztest/base"], + "c": True, + "T": [" tests/ztest/base"], + "test_only": False, + }, + { + "r": ["--test-only"], + "c": False, + "test_only": True, + }, +] + +ARGS = Namespace( + help=None, + zephyr_base=None, + verbose=0, + command="twister", +) + + +@pytest.mark.parametrize("test_case", TEST_CASES) +def test_parse_remainder(test_case): + twister = Twister() + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, + allow_abbrev=False + ) + sub_p = parser.add_subparsers() + + twister.parser = twister.do_add_parser(sub_p) + options = twister._parse_arguments(args=test_case["r"], options=None) + + assert options.clobber_output == test_case["c"] + assert options.test_only == test_case["test_only"] + if "T" in test_case: + assert options.testsuite_root == test_case["T"] diff --git a/scripts/west_commands/twister_cmd.py b/scripts/west_commands/twister_cmd.py new file mode 100644 index 00000000000..b6b599416d8 --- /dev/null +++ b/scripts/west_commands/twister_cmd.py @@ -0,0 +1,64 @@ +# Copyright (c) 2023 Google +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import os +import sys + +from west import log +from west.commands import WestCommand + +from zephyr_ext_common import ZEPHYR_SCRIPTS + +# Resolve path to twister libs and add imports +twister_path = ZEPHYR_SCRIPTS +os.environ["ZEPHYR_BASE"] = str(twister_path.parent) + +sys.path.insert(0, str(twister_path)) +sys.path.insert(0, str(twister_path / "pylib" / "twister")) + +from twisterlib.environment import add_parse_arguments, parse_arguments +from twisterlib.twister_main import main + +TWISTER_DESCRIPTION = """\ +Convenience wrapper for twister. The below options are shared with the twister +script and have the same effects as if you ran twister directly. Refer to the +twister documentation for more information. +""" + + +class Twister(WestCommand): + def __init__(self): + super(Twister, self).__init__( + "twister", + # Keep this in sync with the string in west-commands.yml. + "west twister wrapper", + TWISTER_DESCRIPTION, + accepts_unknown_args=True, + ) + + def do_add_parser(self, parser_adder): + parser = parser_adder.add_parser( + self.name, + help=self.help, + formatter_class=argparse.RawDescriptionHelpFormatter, + description=self.description, + allow_abbrev=False + ) + + parser = add_parse_arguments(parser) + + return parser + + def do_run(self, args, remainder): + log.dbg( + "args: {} remainder: {}".format(args, remainder), level=log.VERBOSE_EXTREME + ) + + options = self._parse_arguments(args=remainder, options=args) + main(options) + + def _parse_arguments(self, args, options): + """Helper function for testing purposes""" + return parse_arguments(self.parser, args, options)