mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-09 18:25:37 +00:00
I've had some requests to be able to use code in the runners package without having west installed. It turns out to be pretty easy to make this happen, as west is currently only used for west.log and some trivial helper methods: - To replace west log, use the standard logging module - Add an appropriate handler for each runner's logger in run_common.py which delegates to west.log, to keep output working as expected. Signed-off-by: Marti Bolivar <marti.bolivar@nordicsemi.no>
254 lines
9.7 KiB
Python
254 lines
9.7 KiB
Python
# Copyright (c) 2018 Foundries.io
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
import argparse
|
|
from unittest.mock import patch, call
|
|
|
|
import pytest
|
|
|
|
from runners.nrfjprog import NrfJprogBinaryRunner
|
|
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'
|
|
|
|
#
|
|
# Expected results.
|
|
#
|
|
# This dictionary maps different configurations to the commands we expect to be
|
|
# executed for them. Verification is done by mocking the check_call() method,
|
|
# which is used to run the commands.
|
|
#
|
|
# The key naming scheme is <F><SR><SN><E>, where:
|
|
#
|
|
# - F: family, 1 for 'NRF51' or 2 for 'NRF52'
|
|
# - SR: soft reset, Y for yes, N for pin reset
|
|
# - SNR: serial number override, Y for yes, N for 'use default'
|
|
# - E: full chip erase, Y for yes, N for sector / sector and UICR only
|
|
#
|
|
|
|
EXPECTED_COMMANDS = {
|
|
# NRF51:
|
|
'1NNN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
|
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
|
|
|
'1NNY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF51', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_DEF_SNR], # noqa: E501
|
|
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
|
|
|
'1NYN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
|
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
|
|
|
'1NYY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF51', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_OVR_SNR], # noqa: E501
|
|
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
|
|
|
'1YNN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
|
|
|
'1YNY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF51', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_DEF_SNR], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
|
|
|
'1YYN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
|
|
|
'1YYY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF51', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_OVR_SNR], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
|
|
|
# NRF52:
|
|
'2NNN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_DEF_SNR, '--sectoranduicrerase'], # noqa: E501
|
|
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
|
|
|
'2NNY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_DEF_SNR], # noqa: E501
|
|
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
|
|
|
'2NYN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_OVR_SNR, '--sectoranduicrerase'], # noqa: E501
|
|
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
|
|
|
'2NYY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_OVR_SNR], # noqa: E501
|
|
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
|
|
|
'2YNN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_DEF_SNR, '--sectoranduicrerase'], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
|
|
|
'2YNY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_DEF_SNR], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
|
|
|
'2YYN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_OVR_SNR, '--sectoranduicrerase'], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
|
|
|
'2YYY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_OVR_SNR], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
|
|
|
# NRF91:
|
|
'9NNN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
|
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
|
|
|
'9NNY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF91', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_DEF_SNR], # noqa: E501
|
|
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
|
|
|
'9NYN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
|
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
|
|
|
'9NYY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF91', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_OVR_SNR], # noqa: E501
|
|
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
|
|
|
'9YNN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
|
|
|
'9YNY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF91', '--snr', TEST_DEF_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_DEF_SNR], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
|
|
|
'9YYN':
|
|
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
|
|
|
'9YYY':
|
|
(['nrfjprog', '--eraseall', '-f', 'NRF91', '--snr', TEST_OVR_SNR],
|
|
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_OVR_SNR], # noqa: E501
|
|
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
|
|
|
}
|
|
|
|
|
|
def expected_commands(family, softreset, snr, erase):
|
|
'''Expected NrfJprogBinaryRunner results given parameters.
|
|
|
|
Returns a factory function which expects the following arguments:
|
|
|
|
- family: string, 'NRF51', 'NRF52' or 'NRF91'
|
|
- softreset: boolean, controls whether soft reset is performed
|
|
- snr: string serial number of board, or None
|
|
- erase: boolean, whether to do a full chip erase or not
|
|
'''
|
|
expected_key = '{}{}{}{}'.format(
|
|
'1' if family == 'NRF51' else '2' if family == 'NRF52' else '9',
|
|
'Y' if softreset else 'N',
|
|
'Y' if snr else 'N',
|
|
'Y' if erase else 'N')
|
|
|
|
return EXPECTED_COMMANDS[expected_key]
|
|
|
|
|
|
#
|
|
# Test cases
|
|
#
|
|
|
|
TEST_CASES = [(f, sr, snr, e)
|
|
for f in ('NRF51', 'NRF52', 'NRF91')
|
|
for sr in (False, True)
|
|
for snr in (TEST_OVR_SNR, None)
|
|
for e in (False, True)]
|
|
|
|
|
|
def get_board_snr_patch():
|
|
return TEST_DEF_SNR
|
|
|
|
|
|
def require_patch(program):
|
|
assert program == 'nrfjprog'
|
|
|
|
|
|
def id_fn(test_case):
|
|
ret = ''
|
|
for x in test_case:
|
|
if x in ('NRF51', 'NRF52'):
|
|
ret += x[-1:]
|
|
else:
|
|
ret += 'Y' if x else 'N'
|
|
return ret
|
|
|
|
|
|
@pytest.mark.parametrize('test_case', TEST_CASES, ids=id_fn)
|
|
@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
|
|
@patch('runners.nrfjprog.NrfJprogBinaryRunner.get_board_snr_from_user',
|
|
side_effect=get_board_snr_patch)
|
|
@patch('runners.nrfjprog.NrfJprogBinaryRunner.check_call')
|
|
def test_nrfjprog_init(cc, get_snr, req, test_case, runner_config):
|
|
family, softreset, snr, erase = test_case
|
|
|
|
runner = NrfJprogBinaryRunner(runner_config, family, softreset, snr,
|
|
erase=erase)
|
|
if snr is None:
|
|
with pytest.raises(ValueError) as e:
|
|
runner.run('flash')
|
|
assert 'snr must not be None' in str(e)
|
|
else:
|
|
runner.run('flash')
|
|
assert req.called
|
|
assert cc.call_args_list == [call(x) for x in
|
|
expected_commands(*test_case)]
|
|
get_snr.assert_not_called()
|
|
|
|
|
|
@pytest.mark.parametrize('test_case', TEST_CASES, ids=id_fn)
|
|
@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
|
|
@patch('runners.nrfjprog.NrfJprogBinaryRunner.get_board_snr_from_user',
|
|
side_effect=get_board_snr_patch)
|
|
@patch('runners.nrfjprog.NrfJprogBinaryRunner.check_call')
|
|
def test_nrfjprog_create(cc, get_snr, req, test_case, runner_config):
|
|
family, softreset, snr, erase = test_case
|
|
|
|
args = ['--nrf-family', family]
|
|
if softreset:
|
|
args.append('--softreset')
|
|
if snr is not None:
|
|
args.extend(['--snr', snr])
|
|
if erase:
|
|
args.append('--erase')
|
|
|
|
parser = argparse.ArgumentParser()
|
|
NrfJprogBinaryRunner.add_parser(parser)
|
|
arg_namespace = parser.parse_args(args)
|
|
runner = NrfJprogBinaryRunner.create(runner_config, arg_namespace)
|
|
runner.run('flash')
|
|
|
|
assert req.called
|
|
assert cc.call_args_list == [call(x) for x in
|
|
expected_commands(*test_case)]
|
|
if snr is None:
|
|
get_snr.assert_called_once_with()
|
|
else:
|
|
get_snr.assert_not_called()
|