scripts: twister: add copying of bsim exe

To make possible to build bsim tests by Twister, it is necessary to
copy executables to BabbleSim bin directory.

Signed-off-by: Piotr Golyzniak <metody159@gmail.com>
This commit is contained in:
Piotr Golyzniak 2023-12-17 23:41:07 +01:00 committed by Carles Cufí
commit 8831aa60eb
6 changed files with 97 additions and 3 deletions

View file

@ -419,7 +419,7 @@ harness: <string>
Twister to be able to evaluate if a test passes criteria. For example, a
keyboard harness is set on tests that require keyboard interaction to reach
verdict on whether a test has passed or failed, however, Twister lack this
harness implementation at the momemnt.
harness implementation at the moment.
Supported harnesses:
@ -445,6 +445,14 @@ harness: <string>
- net
- bluetooth
Harness ``bsim`` is implemented in limited way - it helps only to copy the
final executable (``zephyr.exe``) from build directory to BabbleSim's
``bin`` directory (``${BSIM_OUT_PATH}/bin``). This action is useful to allow
BabbleSim's tests to directly run after. By default, the executable file
name is (with dots and slashes replaced by underscores):
``bs_<platform_name>_<test_path>_<test_scenario_name>``.
This name can be overridden with the ``bsim_exe_name`` option in
``harness_config`` section.
platform_key: <list of platform attributes>
Often a test needs to only be built and run once to qualify as passing.
@ -553,6 +561,11 @@ harness_config: <harness configuration options>
robot_test_path: <robot file path> (default empty)
Specify a path to a file containing a Robot Framework test suite to be run.
bsim_exe_name: <string>
If provided, the executable filename when copying to BabbleSim's bin
directory, will be ``bs_<platform_name>_<bsim_exe_name>`` instead of the
default based on the test path and scenario name.
The following is an example yaml file with a few harness_config options.
.. code-block:: yaml

View file

@ -12,6 +12,7 @@ import xml.etree.ElementTree as ET
import logging
import threading
import time
import shutil
from twisterlib.error import ConfigurationError
from twisterlib.environment import ZEPHYR_BASE, PYTEST_PLUGIN_INSTALLED
@ -83,6 +84,8 @@ class Harness:
if self.record:
self.record_pattern = re.compile(self.record.get("regex", ""))
def build(self):
pass
def get_testcase_name(self):
"""
@ -651,6 +654,40 @@ class Ztest(Test):
pass
class Bsim(Harness):
def build(self):
"""
Copying the application executable to BabbleSim's bin directory enables
running multidevice bsim tests after twister has built them.
"""
if self.instance is None:
return
original_exe_path: str = os.path.join(self.instance.build_dir, 'zephyr', 'zephyr.exe')
if not os.path.exists(original_exe_path):
logger.warning('Cannot copy bsim exe - cannot find original executable.')
return
bsim_out_path: str = os.getenv('BSIM_OUT_PATH', '')
if not bsim_out_path:
logger.warning('Cannot copy bsim exe - BSIM_OUT_PATH not provided.')
return
new_exe_name: str = self.instance.testsuite.harness_config.get('bsim_exe_name', '')
if new_exe_name:
new_exe_name = f'bs_{self.instance.platform.name}_{new_exe_name}'
else:
new_exe_name = self.instance.name
new_exe_name = new_exe_name.replace(os.path.sep, '_').replace('.', '_')
new_exe_name = f'bs_{new_exe_name}'
new_exe_path: str = os.path.join(bsim_out_path, 'bin', new_exe_name)
logger.debug(f'Copying executable from {original_exe_path} to {new_exe_path}')
shutil.copy(original_exe_path, new_exe_path)
class HarnessImporter:
@staticmethod

View file

@ -1052,7 +1052,17 @@ class ProjectBuilder(FilterBuilder):
return self.run_cmake(args,filter_stages)
def build(self):
return self.run_build(['--build', self.build_dir])
harness = HarnessImporter.get_harness(self.instance.testsuite.harness.capitalize())
build_result = self.run_build(['--build', self.build_dir])
try:
harness.instance = self.instance
harness.build()
except ConfigurationError as error:
self.instance.status = "error"
self.instance.reason = str(error)
logger.error(self.instance.reason)
return
return build_result
def run(self):

View file

@ -123,6 +123,9 @@ mapping:
"regex":
type: str
required: true
"bsim_exe_name":
type: str
required: false
"min_ram":
type: int
required: false
@ -346,6 +349,9 @@ mapping:
"regex":
type: str
required: true
"bsim_exe_name":
type: str
required: false
"min_ram":
type: int
required: false

View file

@ -14,7 +14,7 @@ import pytest
ZEPHYR_BASE = os.getenv("ZEPHYR_BASE")
sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister"))
from twisterlib.harness import Gtest
from twisterlib.harness import Gtest, Bsim
from twisterlib.testinstance import TestInstance
GTEST_START_STATE = " RUN "
@ -250,3 +250,30 @@ def test_gtest_repeated_run(gtest):
),
],
)
def test_bsim_build(monkeypatch, tmp_path):
mocked_instance = mock.Mock()
build_dir = tmp_path / 'build_dir'
os.makedirs(build_dir)
mocked_instance.build_dir = str(build_dir)
mocked_instance.name = 'platform_name/test/dummy.test'
mocked_instance.testsuite.harness_config = {}
harness = Bsim()
harness.instance = mocked_instance
monkeypatch.setenv('BSIM_OUT_PATH', str(tmp_path))
os.makedirs(os.path.join(tmp_path, 'bin'), exist_ok=True)
zephyr_exe_path = os.path.join(build_dir, 'zephyr', 'zephyr.exe')
os.makedirs(os.path.dirname(zephyr_exe_path), exist_ok=True)
with open(zephyr_exe_path, 'w') as file:
file.write('TEST_EXE')
harness.build()
new_exe_path = os.path.join(tmp_path, 'bin', 'bs_platform_name_test_dummy_test')
assert os.path.exists(new_exe_path)
with open(new_exe_path, 'r') as file:
exe_content = file.read()
assert 'TEST_EXE' in exe_content

View file

@ -2071,6 +2071,7 @@ def test_projectbuilder_cmake():
def test_projectbuilder_build(mocked_jobserver):
instance_mock = mock.Mock()
instance_mock.testsuite.harness = 'test'
env_mock = mock.Mock()
pb = ProjectBuilder(instance_mock, env_mock, mocked_jobserver)