nRF54H can only be flashed using nrfutil now, so some workaround present in the nrf_common module are no longer needed, e.g. UICR erasing. Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
614 lines
26 KiB
Python
614 lines
26 KiB
Python
# Copyright (c) 2018 Foundries.io
|
|
# Copyright (c) 2020 Nordic Semiconductor ASA
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
import argparse
|
|
import functools
|
|
import io
|
|
import os
|
|
from pathlib import Path
|
|
import shlex
|
|
import shutil
|
|
import typing
|
|
from unittest.mock import patch, call
|
|
|
|
import pytest
|
|
|
|
from runners.nrfjprog import NrfJprogBinaryRunner
|
|
from runners.nrfutil import NrfUtilBinaryRunner
|
|
from conftest import RC_KERNEL_HEX
|
|
|
|
|
|
#
|
|
# Test values
|
|
#
|
|
|
|
TEST_DEF_SNR = 'test-default-serial-number' # for mocking user input
|
|
TEST_OVR_SNR = 'test-override-serial-number'
|
|
|
|
TEST_TOOL_OPT = '--ip 192.168.1.10'
|
|
TEST_TOOL_OPT_L = shlex.split(TEST_TOOL_OPT)
|
|
|
|
# nRF53 flashing is special in that we have different results
|
|
# depending on the input hex file. For that reason, we test it with
|
|
# real hex files.
|
|
TEST_DIR = Path(__file__).parent / 'nrf'
|
|
NRF5340_APP_ONLY_HEX = os.fspath(TEST_DIR / 'nrf5340_app_only.hex')
|
|
NRF5340_NET_ONLY_HEX = os.fspath(TEST_DIR / 'nrf5340_net_only.hex')
|
|
NRF5340_APP_AND_NET_HEX = os.fspath(TEST_DIR / 'nrf5340_app_and_net.hex')
|
|
|
|
CLASS_MAP = {'nrfjprog': NrfJprogBinaryRunner, 'nrfutil': NrfUtilBinaryRunner}
|
|
|
|
#
|
|
# A dictionary mapping test cases to expected results.
|
|
#
|
|
# The keys are TC objects.
|
|
#
|
|
# The values are usually tool commands we expect to be executed for
|
|
# each test case. Verification is done by mocking the check_call()
|
|
# ZephyrBinaryRunner method which is used to run the commands.
|
|
#
|
|
# Values can also be callables which take a tmpdir and return the
|
|
# expected commands. This is needed for nRF53 testing.
|
|
#
|
|
|
|
class TC(typing.NamedTuple): # 'TestCase'
|
|
# NRF51, NRF52, etc.
|
|
family: str
|
|
|
|
# 'APP', 'NET', 'APP+NET', or None.
|
|
coprocessor: typing.Optional[str]
|
|
|
|
# Run a recover command first if True
|
|
recover: bool
|
|
|
|
# Use --reset instead of --pinreset if True
|
|
softreset: bool
|
|
|
|
# --snr TEST_OVR_SNR if True, --snr TEST_DEF_SNR if False
|
|
snr: bool
|
|
|
|
# --chiperase if True,
|
|
# --sectorerase if False (or --sectoranduicrerase on nRF52)
|
|
erase: bool
|
|
|
|
# --tool-opt TEST_TOOL_OPT if True
|
|
tool_opt: bool
|
|
|
|
EXPECTED_MAP = {'nrfjprog': 0, 'nrfutil': 1}
|
|
EXPECTED_RESULTS = {
|
|
|
|
# -------------------------------------------------------------------------
|
|
# NRF51
|
|
#
|
|
# family CP recov soft snr erase tool_opt
|
|
TC('NRF51_FAMILY', None, False, False, False, False, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF51',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF51_FAMILY', None, False, False, False, True, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF51',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF51_FAMILY', None, False, False, True, False, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF51',
|
|
'--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF51_FAMILY', None, False, True, False, False, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF51',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF51_FAMILY', None, True, False, False, False, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF51', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF51',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF51_FAMILY', None, True, True, True, True, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF51', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF51',
|
|
'--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF51_FAMILY', None, True, True, True, True, True):
|
|
((['nrfjprog', '--recover', '-f', 'NRF51', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF51',
|
|
'--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
# -------------------------------------------------------------------------
|
|
# NRF52
|
|
#
|
|
# family CP recov soft snr erase tool_opt
|
|
TC('NRF52_FAMILY', None, False, False, False, False, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase',
|
|
'--verify', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF52_FAMILY', None, False, False, False, True, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF52',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF52_FAMILY', None, False, False, True, False, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase',
|
|
'--verify', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF52_FAMILY', None, False, True, False, False, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase',
|
|
'--verify', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF52_FAMILY', None, True, False, False, False, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase',
|
|
'--verify', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF52_FAMILY', None, True, True, True, True, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF52',
|
|
'--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF52_FAMILY', None, True, True, True, True, True):
|
|
((['nrfjprog', '--recover', '-f', 'NRF52', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF52',
|
|
'--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
# -------------------------------------------------------------------------
|
|
# NRF53 APP only
|
|
#
|
|
# family CP recov soft snr erase tool_opt
|
|
TC('NRF53_FAMILY', 'APP', False, False, False, False, False):
|
|
((['nrfjprog', '--program', NRF5340_APP_ONLY_HEX, '--sectorerase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP', False, False, False, True, False):
|
|
((['nrfjprog', '--program', NRF5340_APP_ONLY_HEX, '--chiperase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP', False, False, True, False, False):
|
|
((['nrfjprog', '--program', NRF5340_APP_ONLY_HEX, '--sectorerase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP', False, True, False, False, False):
|
|
((['nrfjprog', '--program', NRF5340_APP_ONLY_HEX, '--sectorerase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP', True, False, False, False, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', NRF5340_APP_ONLY_HEX, '--sectorerase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP', True, True, True, True, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
|
'--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', NRF5340_APP_ONLY_HEX, '--chiperase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
# -------------------------------------------------------------------------
|
|
# NRF53 NET only
|
|
#
|
|
# family CP recov soft snr erase tool_opt
|
|
TC('NRF53_FAMILY', 'NET', False, False, False, False, False):
|
|
((['nrfjprog', '--program', NRF5340_NET_ONLY_HEX, '--sectorerase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'NET', False, False, False, True, False):
|
|
((['nrfjprog', '--program', NRF5340_NET_ONLY_HEX, '--chiperase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'NET', False, False, True, False, False):
|
|
((['nrfjprog', '--program', NRF5340_NET_ONLY_HEX, '--sectorerase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'NET', False, True, False, False, False):
|
|
((['nrfjprog', '--program', NRF5340_NET_ONLY_HEX, '--sectorerase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'NET', True, False, False, False, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', NRF5340_NET_ONLY_HEX, '--sectorerase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'NET', True, True, True, True, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
|
'--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', NRF5340_NET_ONLY_HEX, '--chiperase',
|
|
'--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
# -------------------------------------------------------------------------
|
|
# NRF53 APP+NET
|
|
#
|
|
# family CP recov soft snr erase tool_opt
|
|
TC('NRF53_FAMILY', 'APP+NET', False, False, False, False, False):
|
|
((lambda tmpdir, infile: \
|
|
(['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
|
'--sectorerase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
|
'--sectorerase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR])),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP+NET', False, False, False, True, False):
|
|
((lambda tmpdir, infile: \
|
|
(['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
|
'--chiperase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
|
'--chiperase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR])),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP+NET', False, False, True, False, False):
|
|
((lambda tmpdir, infile: \
|
|
(['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
|
'--sectorerase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_NETWORK', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
|
'--sectorerase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_APPLICATION', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR])),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP+NET', False, True, False, False, False):
|
|
((lambda tmpdir, infile: \
|
|
(['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
|
'--sectorerase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
|
'--sectorerase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_DEF_SNR])),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP+NET', True, False, False, False, False):
|
|
((lambda tmpdir, infile: \
|
|
(['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
|
'--sectorerase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
|
'--sectorerase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR])),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP+NET', True, True, True, True, False):
|
|
((lambda tmpdir, infile: \
|
|
(['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
|
'--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
|
'--chiperase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_NETWORK', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
|
'--chiperase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_APPLICATION', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR])),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF53_FAMILY', 'APP+NET', True, True, True, True, True):
|
|
((lambda tmpdir, infile: \
|
|
(['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
|
'--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
|
'--chiperase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_NETWORK', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog',
|
|
'--program',
|
|
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
|
'--chiperase', '--verify', '-f', 'NRF53',
|
|
'--coprocessor', 'CP_APPLICATION', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L)),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
# NRF91
|
|
#
|
|
# family CP recov soft snr erase tool_opt
|
|
TC('NRF91_FAMILY', None, False, False, False, False, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF91',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF91_FAMILY', None, False, False, False, True, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF91',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF91_FAMILY', None, False, False, True, False, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF91',
|
|
'--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF91_FAMILY', None, False, True, False, False, False):
|
|
((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF91',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF91_FAMILY', None, True, False, False, False, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF91', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF91',
|
|
'--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
|
(TEST_DEF_SNR, None)),
|
|
|
|
TC('NRF91_FAMILY', None, True, True, True, True, False):
|
|
((['nrfjprog', '--recover', '-f', 'NRF91', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF91',
|
|
'--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
|
(TEST_OVR_SNR, None)),
|
|
|
|
TC('NRF91_FAMILY', None, True, True, True, True, True):
|
|
((['nrfjprog', '--recover', '-f', 'NRF91', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF91',
|
|
'--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L,
|
|
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L),
|
|
(TEST_OVR_SNR, None)),
|
|
}
|
|
|
|
#
|
|
# Monkey-patches
|
|
#
|
|
|
|
def get_board_snr_patch(glob):
|
|
return TEST_DEF_SNR
|
|
|
|
def require_patch(cur_tool, program):
|
|
assert cur_tool == program
|
|
|
|
os_path_isfile = os.path.isfile
|
|
|
|
def os_path_isfile_patch(filename):
|
|
if filename == RC_KERNEL_HEX:
|
|
return True
|
|
return os_path_isfile(filename)
|
|
|
|
#
|
|
# Test functions.
|
|
#
|
|
# These are white box tests that rely on the above monkey-patches.
|
|
#
|
|
|
|
def id_fn(test_case):
|
|
if test_case.coprocessor is None:
|
|
cp = ''
|
|
else:
|
|
cp = f'-{test_case.coprocessor}'
|
|
s = 'soft_reset' if test_case.softreset else 'pin_reset'
|
|
sn = 'default_snr' if test_case.snr else 'override_snr'
|
|
e = 'chip_erase' if test_case.erase else 'sector[anduicr]_erase'
|
|
r = 'recover' if test_case.recover else 'no_recover'
|
|
t = 'tool_opt' if test_case.tool_opt else 'no_tool_opt'
|
|
|
|
return f'{test_case.family[:5]}{cp}-{s}-{sn}-{e}-{r}-{t}'
|
|
|
|
def fix_up_runner_config(test_case, runner_config, tmpdir):
|
|
# Helper that adjusts the common runner_config fixture for our
|
|
# nRF-specific tests.
|
|
|
|
to_replace = {}
|
|
|
|
# Provide a skeletal zephyr/.config file to use as the runner's
|
|
# BuildConfiguration.
|
|
zephyr = tmpdir / 'zephyr'
|
|
zephyr.mkdir()
|
|
dotconfig = os.fspath(zephyr / '.config')
|
|
with open(dotconfig, 'w') as f:
|
|
f.write(f'''
|
|
CONFIG_SOC_SERIES_{test_case.family[:5]}X=y
|
|
''')
|
|
to_replace['build_dir'] = tmpdir
|
|
|
|
if test_case.family != 'NRF53_FAMILY':
|
|
return runner_config._replace(**to_replace)
|
|
|
|
if test_case.coprocessor == 'APP':
|
|
to_replace['hex_file'] = NRF5340_APP_ONLY_HEX
|
|
elif test_case.coprocessor == 'NET':
|
|
to_replace['hex_file'] = NRF5340_NET_ONLY_HEX
|
|
elif test_case.coprocessor == 'APP+NET':
|
|
# Since the runner is going to generate files next to its input
|
|
# file, we need to stash a copy in a tmpdir it can use.
|
|
outfile = tmpdir / Path(NRF5340_APP_AND_NET_HEX).name
|
|
shutil.copyfile(NRF5340_APP_AND_NET_HEX, outfile)
|
|
to_replace['hex_file'] = os.fspath(outfile)
|
|
else:
|
|
assert False, f'bad test case {test_case}'
|
|
|
|
return runner_config._replace(**to_replace)
|
|
|
|
def check_expected(tool, test_case, check_fn, get_snr, tmpdir, runner_config):
|
|
|
|
expected = EXPECTED_RESULTS[test_case][EXPECTED_MAP[tool]]
|
|
if tool == 'nrfutil':
|
|
assert len(check_fn.call_args_list) == 1
|
|
assert len(check_fn.call_args_list[0].args) == 1
|
|
# Extract filename
|
|
nrfutil_args = check_fn.call_args_list[0].args[0]
|
|
tmpfile = nrfutil_args[nrfutil_args.index('--batch-path') + 1]
|
|
cmds = (['nrfutil', '--json', 'device', 'x-execute-batch', '--batch-path',
|
|
tmpfile, '--serial-number', expected[0]],)
|
|
call_args = [call(nrfutil_args)]
|
|
else:
|
|
cmds = expected
|
|
call_args = check_fn.call_args_list
|
|
|
|
if callable(cmds):
|
|
assert (call_args ==
|
|
[call(x) for x in cmds(tmpdir, runner_config.hex_file)])
|
|
else:
|
|
assert call_args == [call(x) for x in cmds]
|
|
|
|
if not test_case.snr:
|
|
get_snr.assert_called_once_with('*')
|
|
else:
|
|
get_snr.assert_not_called()
|
|
|
|
@pytest.mark.parametrize('tool', ["nrfjprog","nrfutil"])
|
|
@pytest.mark.parametrize('test_case', EXPECTED_RESULTS.keys(), ids=id_fn)
|
|
@patch('runners.core.ZephyrBinaryRunner.require')
|
|
@patch('runners.nrfjprog.NrfBinaryRunner.get_board_snr',
|
|
side_effect=get_board_snr_patch)
|
|
@patch('runners.nrfutil.subprocess.Popen')
|
|
@patch('runners.nrfjprog.NrfBinaryRunner.check_call')
|
|
def test_init(check_call, popen, get_snr, require, tool, test_case,
|
|
runner_config, tmpdir):
|
|
popen.return_value.__enter__.return_value.stdout = io.BytesIO(b'')
|
|
|
|
require.side_effect = functools.partial(require_patch, tool)
|
|
runner_config = fix_up_runner_config(test_case, runner_config, tmpdir)
|
|
snr = TEST_OVR_SNR if test_case.snr else None
|
|
tool_opt = TEST_TOOL_OPT_L if test_case.tool_opt else []
|
|
cls = CLASS_MAP[tool]
|
|
runner = cls(runner_config,
|
|
test_case.family,
|
|
test_case.softreset,
|
|
snr,
|
|
erase=test_case.erase,
|
|
tool_opt=tool_opt,
|
|
recover=test_case.recover)
|
|
|
|
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
|
|
runner.run('flash')
|
|
assert require.called
|
|
|
|
CHECK_FN_MAP = {'nrfjprog': check_call, 'nrfutil': popen}
|
|
check_expected(tool, test_case, CHECK_FN_MAP[tool], get_snr, tmpdir,
|
|
runner_config)
|
|
|
|
@pytest.mark.parametrize('tool', ["nrfjprog","nrfutil"])
|
|
@pytest.mark.parametrize('test_case', EXPECTED_RESULTS.keys(), ids=id_fn)
|
|
@patch('runners.core.ZephyrBinaryRunner.require')
|
|
@patch('runners.nrfjprog.NrfBinaryRunner.get_board_snr',
|
|
side_effect=get_board_snr_patch)
|
|
@patch('runners.nrfutil.subprocess.Popen')
|
|
@patch('runners.nrfjprog.NrfBinaryRunner.check_call')
|
|
def test_create(check_call, popen, get_snr, require, tool, test_case,
|
|
runner_config, tmpdir):
|
|
popen.return_value.__enter__.return_value.stdout = io.BytesIO(b'')
|
|
|
|
require.side_effect = functools.partial(require_patch, tool)
|
|
runner_config = fix_up_runner_config(test_case, runner_config, tmpdir)
|
|
|
|
args = []
|
|
if test_case.softreset:
|
|
args.append('--softreset')
|
|
if test_case.snr:
|
|
args.extend(['--dev-id', TEST_OVR_SNR])
|
|
if test_case.erase:
|
|
args.append('--erase')
|
|
if test_case.recover:
|
|
args.append('--recover')
|
|
if test_case.tool_opt:
|
|
args.extend(['--tool-opt', TEST_TOOL_OPT])
|
|
|
|
parser = argparse.ArgumentParser(allow_abbrev=False)
|
|
cls = CLASS_MAP[tool]
|
|
cls.add_parser(parser)
|
|
arg_namespace = parser.parse_args(args)
|
|
runner = cls.create(runner_config, arg_namespace)
|
|
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
|
|
runner.run('flash')
|
|
|
|
assert require.called
|
|
|
|
CHECK_FN_MAP = {'nrfjprog': check_call, 'nrfutil': popen}
|
|
check_expected(tool, test_case, CHECK_FN_MAP[tool], get_snr, tmpdir,
|
|
runner_config)
|