Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions doc/develop/test/twister.rst
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,34 @@ filter: <expression>

Would match it.

required_images: <list of images>
A list of test scenarios that are required to be built for this test to run.
If the test does not have a ``CMakeLists.txt`` file or has set ``no_own_image``
to True, then the first image from this list will be used as the test
scenario image.
All required test scenarios must be available from the tree (given with ``-T`` option).
If a required test scenario is not available in tree or its build failed,
the test will be skipped.
If the required scenario is prefixed with a platform name, then it will be
built for that platform only.
The following is an example yaml with 2 required images.

.. code-block:: yaml

tests:
shared.app.example:
required_images:
- test.example.first
- native_sim:test.example.second
no_own_image: True

Not supported with options: ``--subset`` or ``--runtime-artifact-cleanup``.

no_own_image: <True|False> (default False)
If true, the test scenario will not be built. Instead, it
will use the first test scenario from ``required_images`` list.
Not supported on QEMU platforms.

required_snippets: <list of needed snippets>
:ref:`Snippets <snippets>` are supported in twister for test scenarios that
require them. As with normal applications, twister supports using the base
Expand Down
8 changes: 8 additions & 0 deletions samples/subsys/testsuite/shared_app/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(shared_app_with_own_image)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
5 changes: 5 additions & 0 deletions samples/subsys/testsuite/shared_app/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CONFIG_PRINTK=y
CONFIG_SHELL=y
CONFIG_LOG=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_KERNEL_SHELL=y
23 changes: 23 additions & 0 deletions samples/subsys/testsuite/shared_app/pytest/test_shared_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations

import logging
from pathlib import Path

from twister_harness import DeviceAdapter, Shell

logger = logging.getLogger(__name__)


def test_shell_is_ready(shell: Shell):
# wait_for_prompt is called from shell fixture, so if passed, shell is ready to use
assert True


def test_second_app_is_found(dut: DeviceAdapter, shell: Shell, required_images):
logger.info(f"Required images: {required_images}")
assert required_images
assert Path(required_images[0]).is_dir()
assert Path(Path(required_images[0]) / 'build.log').exists()
10 changes: 10 additions & 0 deletions samples/subsys/testsuite/shared_app/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

int main(void)
{
return 0;
}
36 changes: 36 additions & 0 deletions samples/subsys/testsuite/shared_app/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
common:
filter: CONFIG_SERIAL and dt_chosen_enabled("zephyr,shell-uart")
min_ram: 40
extra_configs:
- arch:posix:CONFIG_NATIVE_UART_0_ON_STDINOUT=y
integration_platforms:
- native_sim
tests:
sample.shared.build_only:
build_only: true
sample.shared.with_own_image.pytest:
required_images:
- sample.shared.build_only
harness: pytest
harness_config:
pytest_dut_scope: module
tags: pytest shared
sample.shared.no_own_image.pytest:
no_own_image: true
required_images:
- sample.shared.with_own_image.pytest
- sample.shared.build_only
harness: pytest
harness_config:
pytest_dut_scope: module
tags: pytest shared
sample.shared.no_own_image.helloworld:
no_own_image: true
required_images:
- sample.basic.helloworld
harness: console
harness_config:
type: one_line
regex:
- "Hello World! (.*)"
tags: shared
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,8 @@ def is_mcumgr_available() -> None:
@pytest.fixture()
def mcumgr(is_mcumgr_available: None, dut: DeviceAdapter) -> Generator[MCUmgr, None, None]:
yield MCUmgr.create_for_serial(dut.device_config.serial)


@pytest.fixture(scope='session')
def required_images(request):
return request.config.getoption('--required-image')
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ def pytest_addoption(parser: pytest.Parser):
'--twister-fixture', action='append', dest='fixtures', metavar='FIXTURE', default=[],
help='Twister fixture supported by this platform. May be given multiple times.'
)
twister_harness_group.addoption(
'--required-image', action='append', dest='required_images', default=[],
help='Paths to build_dir of required images. May be given multiple times.'
)


def pytest_configure(config: pytest.Config):
Expand Down
2 changes: 2 additions & 0 deletions scripts/pylib/twister/twisterlib/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class TwisterConfigParser:
"extra_conf_files": {"type": "list", "default": []},
"extra_overlay_confs" : {"type": "list", "default": []},
"extra_dtc_overlay_files": {"type": "list", "default": []},
"required_images": {"type": "list"},
"no_own_image": {"type": "bool", "default": False },
"required_snippets": {"type": "list"},
"build_only": {"type": "bool", "default": False},
"build_on_all": {"type": "bool", "default": False},
Expand Down
2 changes: 1 addition & 1 deletion scripts/pylib/twister/twisterlib/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def get_default_domain_build_dir(self):
domain_path = os.path.join(self.build_dir, "domains.yaml")
domains = Domains.from_file(domain_path)
logger.debug("Loaded sysbuild domain data from %s" % domain_path)
build_dir = domains.get_default_domain().build_dir
build_dir = os.path.join(self.build_dir, domains.get_default_domain().name)
else:
build_dir = self.build_dir
return build_dir
Expand Down
6 changes: 6 additions & 0 deletions scripts/pylib/twister/twisterlib/harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,12 @@ def generate_command(self):
else:
raise PytestHarnessException(f'Support for handler {handler.type_str} not implemented yet')

if self.instance.required_build_dirs:
# skip first image, it is used as main app when no_own_image is set
start_index = 1 if self.instance.no_own_image else 0
for req_image in self.instance.required_build_dirs[start_index:]:
command.append(f'--required-image={req_image}')

if handler.type_str != 'device':
for fixture in handler.options.fixture:
command.append(f'--twister-fixture={fixture}')
Expand Down
Loading
Loading