zephyr/scripts/west_commands/tests/test_bossac.py
Jamie McCrae ec7044437e treewide: Disable automatic argparse argument shortening
Disables allowing the python argparse library from automatically
shortening command line arguments, this prevents issues whereby
a new command is added and code that wrongly uses the shortened
command of an existing argument which is the same as the new
command being added will silently change script behaviour.

Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
2023-01-26 20:12:36 +09:00

551 lines
16 KiB
Python

# Copyright (c) 2018 Foundries.io
# Copyright (c) 2019 Nordic Semiconductor ASA.
# Copyright (c) 2020-2021 Gerson Fernando Budke <nandojve@gmail.com>
#
# SPDX-License-Identifier: Apache-2.0
import argparse
import os
import platform
from unittest.mock import patch, call
import pytest
from runners.bossac import BossacBinaryRunner
from conftest import RC_KERNEL_BIN
if platform.system() != 'Linux':
pytest.skip("skipping Linux-only bossac tests", allow_module_level=True)
TEST_BOSSAC_PORT = 'test-bossac-serial'
TEST_BOSSAC_SPEED = '1200'
TEST_OFFSET = 1234
TEST_FLASH_ADDRESS = 5678
TEST_BOARD_NAME = "my_board"
EXPECTED_COMMANDS = [
['stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '115200',
'ospeed', '115200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'],
['bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN],
]
EXPECTED_COMMANDS_WITH_SPEED = [
['stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', TEST_BOSSAC_SPEED,
'ospeed', TEST_BOSSAC_SPEED, 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'],
['bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN],
]
EXPECTED_COMMANDS_WITH_OFFSET = [
['stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '115200',
'ospeed', '115200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'],
['bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN, '-o', str(TEST_OFFSET)],
]
EXPECTED_COMMANDS_WITH_FLASH_ADDRESS = [
[
'stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '115200',
'ospeed', '115200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'
],
[
'bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN, '-o', str(TEST_FLASH_ADDRESS),
],
]
EXPECTED_COMMANDS_WITH_EXTENDED = [
[
'stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '1200',
'ospeed', '1200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'
],
[
'bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN, '-o', str(TEST_FLASH_ADDRESS),
],
]
# SAM-BA ROM without offset
# No code partition Kconfig
# No zephyr,code-partition (defined on DT)
DOTCONFIG_STD = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA ROM/FLASH with offset
DOTCONFIG_COND1 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA ROM/FLASH without offset
# No code partition Kconfig
DOTCONFIG_COND2 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA Extended Arduino with offset
DOTCONFIG_COND3 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_ARDUINO=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA Extended Adafruit with offset
DOTCONFIG_COND4 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_ADAFRUIT_UF2=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA omit offset
DOTCONFIG_COND5 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x0
'''
# SAM-BA Legacy Mode
DOTCONFIG_COND6 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_LEGACY=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
def adjust_runner_config(runner_config, tmpdir, dotconfig):
# Adjust a RunnerConfig object, 'runner_config', by
# replacing its build directory with 'tmpdir' after writing
# the contents of 'dotconfig' to tmpdir/zephyr/.config.
zephyr = tmpdir / 'zephyr'
zephyr.mkdir()
with open(zephyr / '.config', 'w') as f:
f.write(dotconfig)
return runner_config._replace(build_dir=os.fspath(tmpdir))
def require_patch(program):
assert program in ['bossac', 'stty']
os_path_isfile = os.path.isfile
def os_path_isfile_patch(filename):
if filename == RC_KERNEL_BIN:
return True
return os_path_isfile(filename)
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=None)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_init(cc, req, get_cod_par, sup, runner_config, tmpdir):
"""
Test commands using a runner created by constructor.
Requirements:
Any SDK
Configuration:
ROM bootloader
CONFIG_USE_DT_CODE_PARTITION=n
without zephyr,code-partition
Input:
none
Output:
no --offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_STD)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=None)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create(cc, req, get_cod_par, sup, runner_config, tmpdir):
"""
Test commands using a runner created from command line parameters.
Requirements:
Any SDK
Configuration:
ROM bootloader
CONFIG_USE_DT_CODE_PARTITION=n
without zephyr,code-partition
Input:
--bossac-port
Output:
no --offset
"""
args = ['--bossac-port', str(TEST_BOSSAC_PORT)]
parser = argparse.ArgumentParser(allow_abbrev=False)
BossacBinaryRunner.add_parser(parser)
arg_namespace = parser.parse_args(args)
runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_STD)
runner = BossacBinaryRunner.create(runner_config, arg_namespace)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=None)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_speed(cc, req, get_cod_par, sup, runner_config, tmpdir):
"""
Test commands using a runner created from command line parameters.
Requirements:
Any SDK
Configuration:
ROM bootloader
CONFIG_USE_DT_CODE_PARTITION=n
without zephyr,code-partition
Input:
--bossac-port
--speed
Output:
no --offset
"""
args = ['--bossac-port', str(TEST_BOSSAC_PORT),
'--speed', str(TEST_BOSSAC_SPEED)]
parser = argparse.ArgumentParser(allow_abbrev=False)
BossacBinaryRunner.add_parser(parser)
arg_namespace = parser.parse_args(args)
runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_STD)
runner = BossacBinaryRunner.create(runner_config, arg_namespace)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS_WITH_SPEED]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=True)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_flash_address(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test command with offset parameter
Requirements:
SDK >= 0.12.0
Configuration:
Any bootloader
CONFIG_USE_DT_CODE_PARTITION=y
with zephyr,code-partition
Input:
--bossac-port
Output:
--offset
"""
args = [
'--bossac-port',
str(TEST_BOSSAC_PORT),
]
parser = argparse.ArgumentParser(allow_abbrev=False)
BossacBinaryRunner.add_parser(parser)
arg_namespace = parser.parse_args(args)
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND1)
runner = BossacBinaryRunner.create(runner_config, arg_namespace)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [
call(x) for x in EXPECTED_COMMANDS_WITH_FLASH_ADDRESS
]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_omit_address(cc, req, bcfg_ini, sup,
runner_config, tmpdir):
"""
Test command that will omit offset because CONFIG_FLASH_LOAD_OFFSET is 0.
This case is valid for ROM bootloaders that define image start at 0 and
define flash partitions, to use the storage capabilities, for instance.
Requirements:
Any SDK
Configuration:
ROM bootloader
CONFIG_USE_DT_CODE_PARTITION=y
with zephyr,code-partition
Input:
--bossac-port
Output:
no --offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND5)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=True)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_arduino(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA extended protocol with Arduino variation
Requirements:
SDK >= 0.12.0
Configuration:
Extended bootloader
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_ARDUINO=y
with zephyr,code-partition
Input:
--bossac-port
Output:
--offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND3)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS_WITH_EXTENDED]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=True)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_adafruit(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA extended protocol with Adafruit UF2 variation
Requirements:
SDK >= 0.12.0
Configuration:
Extended bootloader
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_ADAFRUIT_UF2=y
with zephyr,code-partition
Input:
--bossac-port
Output:
--offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND4)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS_WITH_EXTENDED]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=True)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_legacy(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA legacy protocol
Requirements:
Any SDK
Configuration:
Extended bootloader
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_LEGACY=y
with zephyr,code-partition
Input:
--bossac-port
Output:
no --offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND6)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_oldsdk(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test old SDK and ask user to upgrade
Requirements:
SDK <= 0.12.0
Configuration:
Any bootloader
CONFIG_USE_DT_CODE_PARTITION=y
with zephyr,code-partition
Input:
Output:
Abort
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND1)
runner = BossacBinaryRunner(runner_config)
with pytest.raises(RuntimeError) as rinfo:
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert str(rinfo.value) == "This version of BOSSA does not support the" \
" --offset flag. Please upgrade to a newer" \
" Zephyr SDK version >= 0.12.0."
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=None)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_error_missing_dt_info(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA offset wrong configuration. No chosen code partition.
Requirements:
Any SDK
Configuration:
Any bootloader
CONFIG_USE_DT_CODE_PARTITION=y
with zephyr,code-partition (missing)
Input:
Output:
Abort
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND1)
runner = BossacBinaryRunner(runner_config)
with pytest.raises(RuntimeError) as rinfo:
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert str(rinfo.value) == "The device tree zephyr,code-partition" \
" chosen node must be defined."
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_error_missing_kconfig(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA offset wrong configuration. No CONFIG_USE_DT_CODE_PARTITION
Kconfig definition.
Requirements:
Any SDK
Configuration:
Any bootloader
CONFIG_USE_DT_CODE_PARTITION=y (missing)
with zephyr,code-partition
Input:
Output:
Abort
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND2)
runner = BossacBinaryRunner(runner_config)
with pytest.raises(RuntimeError) as rinfo:
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert str(rinfo.value) == \
"There is no CONFIG_USE_DT_CODE_PARTITION Kconfig defined at " \
+ TEST_BOARD_NAME + "_defconfig file.\n This means that" \
" zephyr,code-partition device tree node should not be defined." \
" Check Zephyr SAM-BA documentation."