Skip to content

Commit

Permalink
twister: pytest: Bluetooth: multi harness boards test against DuT
Browse files Browse the repository at this point in the history
Add one harness_devices pytest fixture,
Which will build and flash different harness apps into multi harness boards,
then init all harness devices as dut for tests.
Add tests for central_ht and peripehral_ht apps with this feature.

Signed-off-by: Jingsai Lu <[email protected]>
  • Loading branch information
JingsaiLu committed Jan 8, 2025
1 parent bc42004 commit d8aed94
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 8 deletions.
25 changes: 25 additions & 0 deletions samples/bluetooth/central_ht/pytest/test_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (c) 2025 NXP
#
# SPDX-License-Identifier: Apache-2.0

import logging

logger = logging.getLogger(__name__)


def test_os_boot(dut, harness_devices):
dut.readlines_until('Booting Zephyr OS build', timeout=5)
harness_devices[0].readlines_until('Booting Zephyr OS build', timeout=5)


def test_bluetooth_boot(dut, harness_devices):
dut.readlines_until('Scanning successfully started', timeout=5)
harness_devices[0].readlines_until('Advertising successfully started', timeout=5)


def test_bluetooth_connection(dut, harness_devices):
dut.readlines_until('Connected', timeout=5)


def test_match_temp_value_over_ble(dut, harness_devices):
dut.readlines_until(r'Temperature \d{1,2}C', timeout=5)
7 changes: 5 additions & 2 deletions samples/bluetooth/central_ht/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ tests:
- qemu_cortex_m3
sample.bluetooth.central_ht.nxp:
# Disabling monolithic since CI environment doesn't use blobs
build_only: true
harness: bluetooth
harness: pytest
platform_allow:
- rd_rw612_bga
- frdm_rw612
- frdm_mcxw71/mcxw716c
extra_configs:
- CONFIG_NXP_MONOLITHIC_NBU=n
harness_config:
pytest_dut_scope: session
pytest_args: ['--harness_apps=zephyr/samples/bluetooth/peripheral_ht']
26 changes: 26 additions & 0 deletions samples/bluetooth/peripheral_ht/pytest/test_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (c) 2025 NXP
#
# SPDX-License-Identifier: Apache-2.0

import logging

logger = logging.getLogger(__name__)


def test_os_boot(dut, harness_devices):
dut.readlines_until('Booting Zephyr OS build', timeout=5)
harness_devices[0].readlines_until('Booting Zephyr OS build', timeout=5)


def test_bluetooth_boot(dut, harness_devices):
dut.readlines_until('Advertising successfully started', timeout=5)
harness_devices[0].readlines_until('Scanning successfully started', timeout=5)


def test_bluetooth_connection(dut, harness_devices):
harness_devices[0].readlines_until('Connected', timeout=5)


def test_match_temp_value_over_ble(dut, harness_devices):
dut.readlines_until('Indication success', timeout=5)
harness_devices[0].readlines_until(r'Temperature \d{1,2}C', timeout=5)
7 changes: 5 additions & 2 deletions samples/bluetooth/peripheral_ht/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ tests:
- mimxrt1020_evk
sample.bluetooth.peripheral_ht.nxp:
# Disabling monolithic since CI environment doesn't use blobs
build_only: true
harness: bluetooth
harness: pytest
platform_allow:
- rd_rw612_bga
- frdm_rw612
- frdm_mcxw71/mcxw716c
extra_configs:
- CONFIG_NXP_MONOLITHIC_NBU=n
harness_config:
pytest_dut_scope: session
pytest_args: ['--harness_apps=zephyr/samples/bluetooth/central_ht']
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
#
# SPDX-License-Identifier: Apache-2.0

import os
import sys
import copy
import logging
import time
import subprocess
from pathlib import Path
from typing import Generator, Type

import pytest
import time

from twister_harness.device.device_adapter import DeviceAdapter
from twister_harness.device.factory import DeviceFactory
Expand All @@ -16,6 +20,11 @@
from twister_harness.helpers.mcumgr import MCUmgr
from twister_harness.helpers.utils import find_in_config

from twister_harness.helpers.domains_helper import ZEPHYR_BASE
sys.path.insert(0, os.path.join(ZEPHYR_BASE, 'scripts')) # import zephyr_module in environment.py
sys.path.insert(0, os.path.join(ZEPHYR_BASE, 'scripts', 'pylib', 'twister'))
from twisterlib.hardwaremap import HardwareMap

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -92,3 +101,70 @@ 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 harness_devices(request, twister_harness_config):
"""Return harness_device list object."""

class TwisterOptionsWrapper:

device_flash_timeout: float = 60.0 # [s]
device_flash_with_test: bool = True
flash_before: bool = False

harness_device_yml = request.config.getoption('--harness_device_map')
harness_apps = request.config.getoption('--harness_apps')
logger.info(f'harness_device_yml:{harness_device_yml}')
logger.info(f'harness_apps:{harness_apps}')

harness_app_list = harness_apps.split(' ')
logger.info(f'harness_app:{harness_app_list}')

# reuse twister HardwareMap class to load harness device config yaml
options = TwisterOptionsWrapper()
harness_device_hwm = HardwareMap(options)
harness_device_hwm.load(harness_device_yml)
logger.info(f'harness_device_hwm[0]:{harness_device_hwm.duts[0]}')

if not harness_device_hwm.duts or (len(harness_app_list) != len(harness_device_hwm.duts)):
pytest.skip("Skipping all tests due to wrong harness setting.")

# reuse most dut config for harness_device, only build and flash different app into them
dut_device_config: DeviceConfig = twister_harness_config.devices[0]
logger.info(f'dut_device_config:{dut_device_config}')

harness_devices = []
for index, harness_hw in enumerate(harness_device_hwm.duts):
harness_app = harness_app_list[index]
# split harness_app into appname, extra_config
harness_app = harness_app.split('-')
appname, extra_config = harness_app[0], harness_app[1:]
extra_config = ['-' + config for config in extra_config]
# build harness_app image for harness device
build_dir = f'./harness_{harness_hw.platform}_{os.path.basename(appname)}'
cmd = ['west', 'build', appname, '-b', harness_hw.platform, '--build-dir', build_dir] + extra_config
logger.info(' '.join(cmd))
logger.info(os.getcwd())
subprocess.call(cmd)

# update the specific configuration for harness_hw
harness_device_config = copy.deepcopy(dut_device_config)
harness_device_config.id = harness_hw.id
harness_device_config.serial = harness_hw.serial
harness_device_config.build_dir = Path(build_dir)
logger.info(f'harness_device_config:{harness_device_config}')

# init harness device as DuT
device_class: Type[DeviceAdapter] = DeviceFactory.get_device(harness_device_config.type)
device_object = device_class(harness_device_config)
device_object.initialize_log_files(request.node.name)
harness_devices.append(device_object)

try:
for device_object in harness_devices:
device_object.launch()
yield harness_devices
finally: # to make sure we close all running processes execution
for device_object in harness_devices:
device_object.close()
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ def pytest_addoption(parser: pytest.Parser):
'--extra-test-args',
help='Additional args passed to the test binary'
)
twister_harness_group.addoption(
'--harness_apps', default=None,
help='harness zephyr sample app for interaction with DuT.')
twister_harness_group.addoption(
'--harness_device_map', default=None,
help='harness devices info for interaction with DuT.')


def pytest_configure(config: pytest.Config):
Expand Down
4 changes: 2 additions & 2 deletions scripts/pylib/twister/twisterlib/hardwaremap.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ class HardwareMap:
]
}

def __init__(self, env=None):
def __init__(self, options=None):
self.detected = []
self.duts = []
self.options = env.options
self.options = options

def discover(self):

Expand Down
2 changes: 1 addition & 1 deletion scripts/pylib/twister/twisterlib/twister_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def main(options: argparse.Namespace, default_options: argparse.Namespace):
env = TwisterEnv(options, default_options)
env.discover()

hwm = HardwareMap(env)
hwm = HardwareMap(env.options)
ret = hwm.discover()
if ret == 0:
return 0
Expand Down

0 comments on commit d8aed94

Please sign in to comment.