diff --git a/boards/common/renode_robot.board.cmake b/boards/common/renode_robot.board.cmake new file mode 100644 index 00000000000..3d42b3b8de1 --- /dev/null +++ b/boards/common/renode_robot.board.cmake @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_set_robot_runner_ifnset(renode-robot) + +# `--variable` is a renode-test argument, for setting a variable that can be later used in a .robot file: +# ELF: used in common.robot to set the `elf` variable in the default .resc script defined in board.cmake +# RESC: path to the .resc script, defined in board.cmake +# UART: default UART used by Robot in tests, defined in board.cmake +# KEYWORDS: path to common.robot, which contains common Robot keywords +# RESULTS_DIR: directory in which Robot artifacts will be generated after running a testsuite +board_runner_args(renode-robot "--renode-robot-arg=--variable=ELF:@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}") +board_runner_args(renode-robot "--renode-robot-arg=--variable=RESC:@${RENODE_SCRIPT}") +board_runner_args(renode-robot "--renode-robot-arg=--variable=UART:${RENODE_UART}") +board_runner_args(renode-robot "--renode-robot-arg=--variable=KEYWORDS:${ZEPHYR_BASE}/tests/robot/common.robot") +board_runner_args(renode-robot "--renode-robot-arg=--variable=RESULTS_DIR:${APPLICATION_BINARY_DIR}") + +board_finalize_runner_args(renode-robot) diff --git a/boards/microchip/m2gl025_miv/board.cmake b/boards/microchip/m2gl025_miv/board.cmake index 74cca86292d..b2d72a05eca 100644 --- a/boards/microchip/m2gl025_miv/board.cmake +++ b/boards/microchip/m2gl025_miv/board.cmake @@ -5,4 +5,6 @@ set(RENODE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/support/m2gl025_miv.resc) set(RENODE_UART sysbus.uart) set_ifndef(BOARD_SIM_RUNNER renode) +set_ifndef(BOARD_ROBOT_RUNNER renode-robot) include(${ZEPHYR_BASE}/boards/common/renode.board.cmake) +include(${ZEPHYR_BASE}/boards/common/renode_robot.board.cmake) diff --git a/boards/sifive/hifive1/board.cmake b/boards/sifive/hifive1/board.cmake index 29ec8b2e6ab..93a6487d6c8 100644 --- a/boards/sifive/hifive1/board.cmake +++ b/boards/sifive/hifive1/board.cmake @@ -30,4 +30,6 @@ elseif("${BOARD_REVISION}" STREQUAL "B") endif() set_ifndef(BOARD_SIM_RUNNER renode) +set_ifndef(BOARD_ROBOT_RUNNER renode-robot) include(${ZEPHYR_BASE}/boards/common/renode.board.cmake) +include(${ZEPHYR_BASE}/boards/common/renode_robot.board.cmake) diff --git a/cmake/flash/CMakeLists.txt b/cmake/flash/CMakeLists.txt index bdfa7fd5f87..9c2b18b6e89 100644 --- a/cmake/flash/CMakeLists.txt +++ b/cmake/flash/CMakeLists.txt @@ -101,6 +101,10 @@ function(create_runners_yaml) runners_yaml_append("\n# Default simulation runner if --runner is not given.") runners_yaml_append("sim-runner: ${BOARD_SIM_RUNNER}") endif() + if(DEFINED BOARD_ROBOT_RUNNER) + runners_yaml_append("\n# Default test runner if --runner is not given.") + runners_yaml_append("robot-runner: ${BOARD_ROBOT_RUNNER}") + endif() # Sets up common runner configuration values. runners_yaml_append_config() diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 6c0231676a2..d8ea799016a 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -705,7 +705,7 @@ endfunction() # This section provides glue between CMake and the Python code that # manages the runners. -set(TYPES "FLASH" "DEBUG" "SIM") +set(TYPES "FLASH" "DEBUG" "SIM" "ROBOT") function(_board_check_runner_type type) # private helper if (NOT "${type}" IN_LIST TYPES) message(FATAL_ERROR "invalid type ${type}; should be one of: ${TYPES}") @@ -724,7 +724,7 @@ endfunction() # # This would set the board's flash runner to "pyocd". # -# In general, "type" is FLASH, DEBUG or SIM and "runner" is +# In general, "type" is FLASH, DEBUG, SIM or ROBOT and "runner" is # the name of a runner. function(board_set_runner type runner) _board_check_runner_type(${type}) @@ -766,6 +766,11 @@ macro(board_set_debugger_ifnset runner) board_set_runner_ifnset(DEBUG ${runner}) endmacro() +# A convenience macro for board_set_runner_ifnset(ROBOT ${runner}). +macro(board_set_robot_runner_ifnset runner) + board_set_runner_ifnset(ROBOT ${runner}) +endmacro() + # A convenience macro for board_set_runner_ifnset(SIM ${runner}). macro(board_set_sim_runner_ifnset runner) board_set_runner_ifnset(SIM ${runner}) diff --git a/doc/develop/west/build-flash-debug.rst b/doc/develop/west/build-flash-debug.rst index 4456151aa06..75db9a8a90b 100644 --- a/doc/develop/west/build-flash-debug.rst +++ b/doc/develop/west/build-flash-debug.rst @@ -698,6 +698,44 @@ determined by the imported subclasses of ``ZephyrBinaryRunner``. runner implementations are in other submodules, such as ``runners.nrfjprog``, ``runners.openocd``, etc. +Running Robot Framework tests: ``west robot`` +********************************************* + +.. tip:: Run ``west robot -h`` for additional help. + +Basics +====== + +Currently the command supports only one runner which is using ``renode-test``, +(essentially a wrapper for running Robot tests in Renode), but can be +easily extended by adding other runners. + +From a Zephyr build directory, to run a Robot test suite:: + + west robot --runner=renode-robot --testsuite path/to/testsuite.robot + +This will run all tests from testsuite.robot and print output provided +by Robot Framework. + +To pass additional parameters to Renode use ``--renode-robot-args`` switch. +For example to show Renode logs in addition to Robot Framework's output: + + west robot --runner=renode-robot --testsuite path/to/testsuite.robot --renode-robot-arg="--show-log" + +Runner-Specific Overrides +========================= + +To view all of the available options for the Robot runners your board +supports, as well as their usage information, use ``--context`` (or +``-H``):: + + west robot --runner=renode-robot --context + + +To view all available options "renode-test" runner supports, use:: + + west robot --runner=renode-robot --renode-robot-help + Simulating a board with: ``west simulate`` ****************************************** diff --git a/scripts/west-commands.yml b/scripts/west-commands.yml index 54254c381fa..24bbddb9845 100644 --- a/scripts/west-commands.yml +++ b/scripts/west-commands.yml @@ -66,6 +66,11 @@ west-commands: - name: bindesc class: Bindesc help: work with Binary Descriptors + - file: scripts/west_commands/robot.py + commands: + - name: robot + class: Robot + help: run RobotFramework test suites - file: scripts/west_commands/simulate.py commands: - name: simulate diff --git a/scripts/west_commands/robot.py b/scripts/west_commands/robot.py new file mode 100644 index 00000000000..fb5325afe94 --- /dev/null +++ b/scripts/west_commands/robot.py @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 + +from west.commands import WestCommand +from run_common import add_parser_common, do_run_common + +EXPORT_DESCRIPTION = '''\ +Run RobotFramework test suites with a runner of choice. +''' + + +class Robot(WestCommand): + + def __init__(self): + super(Robot, self).__init__( + 'robot', + # Keep this in sync with the string in west-commands.yml. + 'run RobotFramework test suites', + EXPORT_DESCRIPTION, + accepts_unknown_args=True) + + self.runner_key = 'robot-runner' # in runners.yaml + + def do_add_parser(self, parser_adder): + return add_parser_common(self, parser_adder) + + def do_run(self, my_args, runner_args): + do_run_common(self, my_args, runner_args) diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py index 53df19d0550..0f08aa36659 100644 --- a/scripts/west_commands/runners/__init__.py +++ b/scripts/west_commands/runners/__init__.py @@ -49,6 +49,7 @@ _names = [ 'openocd', 'pyocd', 'renode', + 'renode-robot', 'qemu', 'silabs_commander', 'spi_burn', diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index 618cb4e1ee2..f411f56cad3 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -200,7 +200,7 @@ class MissingProgram(FileNotFoundError): super().__init__(errno.ENOENT, os.strerror(errno.ENOENT), program) -_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach', 'simulate'} +_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach', 'simulate', 'robot'} @dataclass class RunnerCaps: @@ -212,7 +212,7 @@ class RunnerCaps: Available capabilities: - commands: set of supported commands; default is {'flash', - 'debug', 'debugserver', 'attach', 'simulate'}. + 'debug', 'debugserver', 'attach', 'simulate', 'robot'}. - dev_id: whether the runner supports device identifiers, in the form of an -i, --dev-id option. This is useful when the user has multiple debuggers diff --git a/scripts/west_commands/runners/renode-robot.py b/scripts/west_commands/runners/renode-robot.py new file mode 100644 index 00000000000..3a5c87ad7d0 --- /dev/null +++ b/scripts/west_commands/runners/renode-robot.py @@ -0,0 +1,60 @@ +# Copyright (c) 2024 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 + +'''Runner stub for renode-test.''' + +import subprocess +from runners.core import ZephyrBinaryRunner, RunnerCaps + + +class RenodeRobotRunner(ZephyrBinaryRunner): + '''Place-holder for Renode runner customizations.''' + + def __init__(self, cfg, args): + super().__init__(cfg) + self.testsuite = args.testsuite + self.renode_robot_arg = args.renode_robot_arg + self.renode_robot_help = args.renode_robot_help + + @classmethod + def name(cls): + return 'renode-robot' + + @classmethod + def capabilities(cls): + return RunnerCaps(commands={'robot'}, hide_load_files=True) + + @classmethod + def do_add_parser(cls, parser): + parser.add_argument('--testsuite', + help='path to Robot test suite') + parser.add_argument('--renode-robot-arg', + metavar='ARG', + action='append', + help='additional argument passed to renode-test') + parser.add_argument('--renode-robot-help', + default=False, + action='store_true', + help='print all possible `renode-test` arguments') + + @classmethod + def do_create(cls, cfg, args): + return RenodeRobotRunner(cfg, args) + + def do_run(self, command, **kwargs): + self.run_test(**kwargs) + + def run_test(self, **kwargs): + cmd = ['renode-test'] + if self.renode_robot_help is True: + cmd.append('--help') + else: + if self.renode_robot_arg is not None: + for arg in self.renode_robot_arg: + cmd.append(arg) + if self.testsuite is not None: + cmd.append(self.testsuite) + else: + self.logger.error("No Robot testsuite passed to renode-test! Use the `--testsuite` argument to provide one.") + subprocess.run(cmd, check=True) diff --git a/scripts/west_commands/tests/test_imports.py b/scripts/west_commands/tests/test_imports.py index c842df0cd51..4675da61256 100644 --- a/scripts/west_commands/tests/test_imports.py +++ b/scripts/west_commands/tests/test_imports.py @@ -40,6 +40,7 @@ def test_runner_imports(): 'pyocd', 'qemu', 'renode', + 'renode-robot', 'silabs_commander', 'spi_burn', 'stm32cubeprogrammer',