Skip to content

Commit 2266d1f

Browse files
MarekPietanordicjm
authored andcommitted
applications: nrf_desktop: Add pytest test for nRF54L15 DK
Change adds pytest test configuration for nRF54L15 DK. Using pytest is necessary to perform twister runtime tests of configurations that require MCUboot KMU keys provisioning. Jira: NCSDK-30872 Signed-off-by: Marek Pieta <[email protected]>
1 parent 2d39eb9 commit 2266d1f

File tree

2 files changed

+117
-5
lines changed

2 files changed

+117
-5
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#
2+
# Copyright (c) 2024 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
import os
8+
import logging
9+
import subprocess
10+
import re
11+
import shlex
12+
13+
from twister_harness import DeviceAdapter
14+
from twister_harness.helpers.utils import find_in_config
15+
16+
logger = logging.getLogger(__name__)
17+
18+
def run_command(command: list[str], timeout: int = 30):
19+
try:
20+
ret: subprocess.CompletedProcess = subprocess.run(command,
21+
text=True,
22+
stdout=subprocess.PIPE,
23+
stderr=subprocess.STDOUT,
24+
timeout=timeout)
25+
except subprocess.TimeoutExpired:
26+
logger.error(f"Timeout expired for command: {shlex.join(command)}")
27+
raise
28+
29+
if ret.returncode:
30+
logger.error(f"Command failed: {shlex.join(command)}")
31+
logger.error(ret.stdout)
32+
raise subprocess.CalledProcessError(ret.returncode, command)
33+
34+
35+
def _mcuboot_key_path(dut: DeviceAdapter):
36+
mcuboot_conf_path = os.path.join(str(dut.device_config.build_dir), "mcuboot", "zephyr",
37+
".config")
38+
return find_in_config(mcuboot_conf_path, "CONFIG_BOOT_SIGNATURE_KEY_FILE")
39+
40+
41+
def mcuboot_provision(dut: DeviceAdapter):
42+
soc = dut.device_config.platform.split("/")[1]
43+
key_path = _mcuboot_key_path(dut)
44+
command = ["west", "ncs-provision", "upload", "-s", soc, "-k", key_path]
45+
if dut.device_config.id:
46+
command.extend(["--dev-id", dut.device_config.id])
47+
48+
logger.info("KMU provisioning")
49+
run_command(command)
50+
51+
52+
def board_reset(dut: DeviceAdapter):
53+
command = ["nrfutil", "device", "reset"]
54+
if dut.device_config.id:
55+
command.extend(["--serial-number", dut.device_config.id])
56+
57+
logger.info("Resetting board")
58+
run_command(command)
59+
60+
61+
def logs_verify(dut: DeviceAdapter):
62+
# Expected logs are sourced from nRF Desktop `sample.yaml` file.
63+
expected_logs = [
64+
"app_event_manager: e:module_state_event module:main state:READY",
65+
"ble_state: Bluetooth initialized",
66+
"settings_loader: Settings loaded",
67+
"ble_bond: Selected Bluetooth LE peers",
68+
"(ble_adv: Advertising started)|(ble_scan: Scan started)",
69+
"dfu: Secondary image slot is clean"
70+
]
71+
error_log = "<err>"
72+
73+
expected_regexes = list(map(re.compile, expected_logs))
74+
75+
while True:
76+
line = dut.readline(timeout=120)
77+
78+
if line is None:
79+
break
80+
81+
assert error_log not in line
82+
83+
for r in expected_regexes:
84+
if r.search(line):
85+
expected_regexes.remove(r)
86+
87+
if len(expected_regexes) == 0:
88+
break
89+
90+
91+
# Expect to match all of the regexes
92+
assert len(expected_regexes) == 0
93+
94+
95+
def test_boot(dut: DeviceAdapter):
96+
# nRF Desktop and bootloader images are already programmed at this stage.
97+
mcuboot_provision(dut)
98+
99+
# Clear buffer to ensure proper state and then reset the board to start test.
100+
dut.clear_buffer()
101+
board_reset(dut)
102+
103+
logs_verify(dut)

applications/nrf_desktop/sample.yaml

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ sample:
66
common:
77
sysbuild: true
88
tags: ci_build sysbuild ci_applications_nrf_desktop
9-
harness: console
109
harness_config:
1110
type: multi_line
1211
ordered: false
@@ -18,13 +17,19 @@ common:
1817
- "(ble_adv: Advertising started)|(ble_scan: Scan started)"
1918
- "dfu: Secondary image slot is clean"
2019
tests:
20+
applications.nrf_desktop.zdebug.uart.kmu_provision:
21+
platform_allow:
22+
- nrf54l15dk/nrf54l15/cpuapp
23+
integration_platforms:
24+
- nrf54l15dk/nrf54l15/cpuapp
25+
timeout: 180
26+
harness: pytest
2127
applications.nrf_desktop.zdebug.uart:
2228
platform_allow:
2329
- nrf54h20dk/nrf54h20/cpuapp
24-
- nrf54l15dk/nrf54l15/cpuapp
2530
integration_platforms:
2631
- nrf54h20dk/nrf54h20/cpuapp
27-
- nrf54l15dk/nrf54l15/cpuapp
32+
harness: console
2833
applications.nrf_desktop.zdebug:
2934
build_only: true
3035
platform_allow: >
@@ -49,14 +54,16 @@ tests:
4954
integration_platforms:
5055
- nrf52840dk/nrf52840
5156
extra_args: FILE_SUFFIX=wwcb
52-
applications.nrf_desktop.zdebug_fast_pair.gmouse.uart:
57+
applications.nrf_desktop.zdebug_fast_pair.gmouse.uart.kmu_provision:
5358
platform_allow:
5459
- nrf54l15dk/nrf54l15/cpuapp
5560
integration_platforms:
5661
- nrf54l15dk/nrf54l15/cpuapp
5762
extra_args: FILE_SUFFIX=fast_pair
5863
FP_MODEL_ID=0x8E717D
5964
FP_ANTI_SPOOFING_KEY=dZxFzP7X9CcfLPC0apyRkmgsh3n2EbWo9NFNXfVuxAM=
65+
timeout: 180
66+
harness: pytest
6067
applications.nrf_desktop.zdebug_fast_pair.gmouse:
6168
build_only: true
6269
platform_allow: nrf52840dk/nrf52840 nrf52840gmouse/nrf52840
@@ -111,12 +118,14 @@ tests:
111118
integration_platforms:
112119
- nrf52840dk/nrf52840
113120
extra_args: FILE_SUFFIX=dongle
114-
applications.nrf_desktop.zdebug_keyboard.uart:
121+
applications.nrf_desktop.zdebug_keyboard.uart.kmu_provision:
115122
platform_allow:
116123
- nrf54l15dk/nrf54l15/cpuapp
117124
integration_platforms:
118125
- nrf54l15dk/nrf54l15/cpuapp
119126
extra_args: FILE_SUFFIX=keyboard
127+
timeout: 180
128+
harness: pytest
120129
applications.nrf_desktop.zdebug_keyboard:
121130
build_only: true
122131
platform_allow:

0 commit comments

Comments
 (0)