Skip to content
Merged
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
3 changes: 2 additions & 1 deletion .github/workflows/twister_tests_blackbox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ jobs:
west init -l . || true
# we do not depend on any hals, tools or bootloader, save some time and space...
west config manifest.group-filter -- -hal,-tools,-bootloader
west config manifest.group-filter -- -hal,-tools,-bootloader,-babblesim
west config manifest.project-filter -- -nrf_hw_models
west config --global update.narrow true
west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /github/cache/zephyrproject)
west forall -c 'git reset --hard HEAD'
Expand Down
19 changes: 19 additions & 0 deletions doc/develop/test/twister.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,25 @@ using an external J-Link probe. The ``probe_id`` keyword overrides the
runner: jlink
serial: null

Using Single Board For Multiple Variants
++++++++++++++++++++++++++++++++++++++++

The ``platform`` attribute can be a list of names or a string
with names separated by spaces. This allows to run tests for
different platform variants on the same physical board, without
re-configuring the hardware map file for each variant. For example:

.. code-block:: yaml

- connected: true
id: '001234567890'
platform:
- nrf5340dk/nrf5340/cpuapp
- nrf5340dk/nrf5340/cpuapp/ns
product: J-Link
runner: nrfjprog
serial: /dev/ttyACM1

Quarantine
++++++++++

Expand Down
36 changes: 26 additions & 10 deletions scripts/pylib/twister/twisterlib/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import threading
import time

from contextlib import contextmanager
from pathlib import Path
from queue import Queue, Empty
from twisterlib.environment import ZEPHYR_BASE, strip_ansi_sequences
Expand Down Expand Up @@ -458,6 +459,17 @@ def monitor_serial(self, ser, halt_event, harness):

log_out_fp.close()

@staticmethod
@contextmanager
def acquire_dut_locks(duts):
try:
for d in duts:
d.lock.acquire()
yield
finally:
for d in duts:
d.lock.release()

def device_is_available(self, instance):
device = instance.platform.name
fixture = instance.testsuite.harness_config.get("fixture")
Expand All @@ -475,15 +487,16 @@ def device_is_available(self, instance):

# Select an available DUT with less failures
for d in sorted(duts_found, key=lambda _dut: _dut.failures):
d.lock.acquire()
avail = False
if d.available:
d.available = 0
d.counter_increment()
avail = True
logger.debug(f"Retain DUT:{d.platform}, Id:{d.id}, "
f"counter:{d.counter}, failures:{d.failures}")
d.lock.release()
duts_shared_hw = [_d for _d in self.duts if _d.id == d.id] # get all DUTs with the same id
with self.acquire_dut_locks(duts_shared_hw):
avail = False
if d.available:
for _d in duts_shared_hw:
_d.available = 0
d.counter_increment()
avail = True
logger.debug(f"Retain DUT:{d.platform}, Id:{d.id}, "
f"counter:{d.counter}, failures:{d.failures}")
if avail:
return d

Expand All @@ -494,7 +507,10 @@ def make_dut_available(self, dut):
dut.failures_increment()
logger.debug(f"Release DUT:{dut.platform}, Id:{dut.id}, "
f"counter:{dut.counter}, failures:{dut.failures}")
dut.available = 1
duts_shared_hw = [_d for _d in self.duts if _d.id == dut.id] # get all DUTs with the same id
with self.acquire_dut_locks(duts_shared_hw):
for _d in duts_shared_hw:
_d.available = 1

@staticmethod
def run_custom_script(script, timeout):
Expand Down
49 changes: 28 additions & 21 deletions scripts/pylib/twister/twisterlib/hardwaremap.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,13 @@ def load(self, map_file):
flash_before = dut.get('flash_before')
if flash_before is None:
flash_before = self.options.flash_before and (not (flash_with_test or serial_pty))
platform = dut.get('platform')
platform = dut.get('platform')
if isinstance(platform, str):
platforms = platform.split()
elif isinstance(platform, list):
platforms = platform
else:
raise ValueError(f"Invalid platform value: {platform}")
id = dut.get('id')
runner = dut.get('runner')
runner_params = dut.get('runner_params')
Expand All @@ -268,28 +274,29 @@ def load(self, map_file):
baud = dut.get('baud', None)
product = dut.get('product')
fixtures = dut.get('fixtures', [])
connected= dut.get('connected') and ((serial or serial_pty) is not None)
connected = dut.get('connected') and ((serial or serial_pty) is not None)
if not connected:
continue
new_dut = DUT(platform=platform,
product=product,
runner=runner,
runner_params=runner_params,
id=id,
serial_pty=serial_pty,
serial=serial,
serial_baud=baud,
connected=connected,
pre_script=pre_script,
flash_before=flash_before,
post_script=post_script,
post_flash_script=post_flash_script,
script_param=script_param,
flash_timeout=flash_timeout,
flash_with_test=flash_with_test)
new_dut.fixtures = fixtures
new_dut.counter = 0
self.duts.append(new_dut)
for plat in platforms:
new_dut = DUT(platform=plat,
product=product,
runner=runner,
runner_params=runner_params,
id=id,
serial_pty=serial_pty,
serial=serial,
serial_baud=baud,
connected=connected,
pre_script=pre_script,
flash_before=flash_before,
post_script=post_script,
post_flash_script=post_flash_script,
script_param=script_param,
flash_timeout=flash_timeout,
flash_with_test=flash_with_test)
new_dut.fixtures = fixtures
new_dut.counter = 0
self.duts.append(new_dut)

def scan(self, persistent=False):
from serial.tools import list_ports
Expand Down
2 changes: 1 addition & 1 deletion scripts/schemas/twister/hwmap-schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ sequence:
type: str
required: false
"platform":
type: str
type: any
required: true
"probe_id":
type: str
Expand Down
1 change: 1 addition & 0 deletions scripts/tests/twister/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,7 @@ def mock_serial(*args, **kwargs):
dut = DUT()
dut.available = 0
dut.failures = 0
handler.duts = [dut]

hardware_baud = 14400
flash_timeout = 60
Expand Down
4 changes: 2 additions & 2 deletions scripts/tests/twister_blackbox/test_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import sys
import json

from conftest import TEST_DATA, ZEPHYR_BASE, testsuite_filename_mock, clear_log_in_test

Check failure on line 16 in scripts/tests/twister_blackbox/test_coverage.py

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

E0611

scripts/tests/twister_blackbox/test_coverage.py:16 No name 'TEST_DATA' in module 'conftest' (no-name-in-module)

Check failure on line 16 in scripts/tests/twister_blackbox/test_coverage.py

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

E0611

scripts/tests/twister_blackbox/test_coverage.py:16 No name 'testsuite_filename_mock' in module 'conftest' (no-name-in-module)

Check failure on line 16 in scripts/tests/twister_blackbox/test_coverage.py

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

E0611

scripts/tests/twister_blackbox/test_coverage.py:16 No name 'clear_log_in_test' in module 'conftest' (no-name-in-module)
from twisterlib.testplan import TestPlan


Expand Down Expand Up @@ -46,7 +46,7 @@
'coverage.log', 'coverage.json',
'coverage'
],
r'{"files": \[], "gcovr/format_version": ".*"}'
r'{"files": \[\], "gcovr/format_version": ".*"}'
),
]
TESTDATA_4 = [
Expand Down Expand Up @@ -243,7 +243,7 @@
with open(path, "r") as json_file:
json_content = json.load(json_file)
pattern = re.compile(expected_content)
assert pattern.match(json.dumps(json_content))
assert pattern.match(json.dumps(json_content, sort_keys=True))
if os.path.exists(base_dir):
os.rmdir(base_dir)

Expand Down
Loading