From c24e044c6e21082a74c638997f2ccfce3bf6d307 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Sun, 2 Jun 2019 16:18:39 -0600 Subject: [PATCH] scripts: runners: check for required programs Add self.require() checks before running commands. Increase test coverage, including for this feature, while we are here. Signed-off-by: Marti Bolivar --- scripts/west_commands/runners/arc.py | 3 +- .../west_commands/runners/blackmagicprobe.py | 9 +- scripts/west_commands/runners/bossac.py | 2 + scripts/west_commands/runners/dfu.py | 1 + scripts/west_commands/runners/esp32.py | 1 + scripts/west_commands/runners/hifive1.py | 2 + scripts/west_commands/runners/intel_s1000.py | 5 + scripts/west_commands/runners/nios2.py | 4 +- scripts/west_commands/runners/nrfjprog.py | 2 + scripts/west_commands/runners/nsim.py | 3 +- scripts/west_commands/runners/openocd.py | 4 +- scripts/west_commands/runners/pyocd.py | 2 + scripts/west_commands/runners/xtensa.py | 2 +- .../tests/test_blackmagicprobe.py | 70 ++++++++++ scripts/west_commands/tests/test_bossac.py | 44 ++++++ scripts/west_commands/tests/test_dfu_util.py | 131 ++++++++++++++++++ scripts/west_commands/tests/test_nrfjprog.py | 12 +- scripts/west_commands/tests/test_pyocd.py | 32 ++++- 18 files changed, 309 insertions(+), 20 deletions(-) create mode 100644 scripts/west_commands/tests/test_blackmagicprobe.py create mode 100644 scripts/west_commands/tests/test_bossac.py create mode 100644 scripts/west_commands/tests/test_dfu_util.py diff --git a/scripts/west_commands/runners/arc.py b/scripts/west_commands/runners/arc.py index 5d5c867587..9309c5f802 100644 --- a/scripts/west_commands/runners/arc.py +++ b/scripts/west_commands/runners/arc.py @@ -64,6 +64,7 @@ class EmStarterKitBinaryRunner(ZephyrBinaryRunner): gdb_port=args.gdb_port) def do_run(self, command, **kwargs): + self.require(self.openocd_cmd[0]) kwargs['openocd-cfg'] = path.join(self.cfg.board_dir, 'support', 'openocd.cfg') @@ -73,8 +74,8 @@ class EmStarterKitBinaryRunner(ZephyrBinaryRunner): self.debugserver(**kwargs) def flash_debug(self, command, **kwargs): + self.require(self.gdb_cmd[0]) config = kwargs['openocd-cfg'] - server_cmd = (self.openocd_cmd + ['-f', config] + ['-c', 'tcl_port {}'.format(self.tcl_port), diff --git a/scripts/west_commands/runners/blackmagicprobe.py b/scripts/west_commands/runners/blackmagicprobe.py index 7b34060a55..4ffb86d043 100644 --- a/scripts/west_commands/runners/blackmagicprobe.py +++ b/scripts/west_commands/runners/blackmagicprobe.py @@ -35,8 +35,6 @@ class BlackMagicProbeRunner(ZephyrBinaryRunner): help='GDB serial port') def bmp_flash(self, command, **kwargs): - if self.gdb is None: - raise ValueError('Cannot flash; gdb is missing') if self.elf_file is None: raise ValueError('Cannot debug; elf file is missing') command = (self.gdb + @@ -51,8 +49,6 @@ class BlackMagicProbeRunner(ZephyrBinaryRunner): self.check_call(command) def bmp_attach(self, command, **kwargs): - if self.gdb is None: - raise ValueError('Cannot attach; gdb is missing') if self.elf_file is None: command = (self.gdb + ['-ex', "set confirm off", @@ -71,8 +67,6 @@ class BlackMagicProbeRunner(ZephyrBinaryRunner): self.check_call(command) def bmp_debug(self, command, **kwargs): - if self.gdb is None: - raise ValueError('Cannot debug; gdb is missing') if self.elf_file is None: raise ValueError('Cannot debug; elf file is missing') command = (self.gdb + @@ -85,6 +79,9 @@ class BlackMagicProbeRunner(ZephyrBinaryRunner): self.check_call(command) def do_run(self, command, **kwargs): + if self.gdb is None: + raise ValueError('Cannot execute; gdb not specified') + self.require(self.gdb[0]) if command == 'flash': self.bmp_flash(command, **kwargs) diff --git a/scripts/west_commands/runners/bossac.py b/scripts/west_commands/runners/bossac.py index 50bfd7b679..033f42e09c 100644 --- a/scripts/west_commands/runners/bossac.py +++ b/scripts/west_commands/runners/bossac.py @@ -50,6 +50,8 @@ class BossacBinaryRunner(ZephyrBinaryRunner): msg = 'CAUTION: No flash tool for your host system found!' raise NotImplementedError(msg) + self.require('stty') + self.require(self.bossac) cmd_stty = ['stty', '-F', self.port, 'raw', 'ispeed', '1200', 'ospeed', '1200', 'cs8', '-cstopb', 'ignpar', 'eol', '255', 'eof', '255'] diff --git a/scripts/west_commands/runners/dfu.py b/scripts/west_commands/runners/dfu.py index 1796963102..8b172738b5 100644 --- a/scripts/west_commands/runners/dfu.py +++ b/scripts/west_commands/runners/dfu.py @@ -90,6 +90,7 @@ class DfuUtilBinaryRunner(ZephyrBinaryRunner): return self.list_pattern in output def do_run(self, command, **kwargs): + self.require(self.cmd[0]) reset = False if not self.find_device(): reset = True diff --git a/scripts/west_commands/runners/esp32.py b/scripts/west_commands/runners/esp32.py index fca284c571..31bdf89c11 100644 --- a/scripts/west_commands/runners/esp32.py +++ b/scripts/west_commands/runners/esp32.py @@ -78,6 +78,7 @@ class Esp32BinaryRunner(ZephyrBinaryRunner): partition_table_bin=args.esp_flash_partition_table) def do_run(self, command, **kwargs): + self.require(self.espidf) bin_name = path.splitext(self.elf)[0] + path.extsep + 'bin' cmd_convert = [self.espidf, '--chip', 'esp32', 'elf2image', self.elf] cmd_flash = [self.espidf, '--chip', 'esp32', '--port', self.device, diff --git a/scripts/west_commands/runners/hifive1.py b/scripts/west_commands/runners/hifive1.py index 0976c57131..4eb95114d9 100644 --- a/scripts/west_commands/runners/hifive1.py +++ b/scripts/west_commands/runners/hifive1.py @@ -36,6 +36,8 @@ class HiFive1BinaryRunner(ZephyrBinaryRunner): return HiFive1BinaryRunner(cfg) def do_run(self, command, **kwargs): + self.require(self.cfg.openocd) + self.require(self.cfg.gdb) openocd_cmd = ([self.cfg.openocd, '-f', self.openocd_config]) gdb_cmd = ([self.cfg.gdb, self.cfg.elf_file, '--batch', '-ex', 'set remotetimeout 240', diff --git a/scripts/west_commands/runners/intel_s1000.py b/scripts/west_commands/runners/intel_s1000.py index 938df41963..d64c82b7c0 100644 --- a/scripts/west_commands/runners/intel_s1000.py +++ b/scripts/west_commands/runners/intel_s1000.py @@ -61,6 +61,7 @@ class IntelS1000BinaryRunner(ZephyrBinaryRunner): gdb_port=args.gdb_port) def do_run(self, command, **kwargs): + self.require(self.xt_ocd_dir) kwargs['ocd-topology'] = path.join(self.board_dir, 'support', self.ocd_topology) kwargs['ocd-jtag-instr'] = path.join(self.board_dir, 'support', @@ -76,6 +77,9 @@ class IntelS1000BinaryRunner(ZephyrBinaryRunner): self.do_debug(**kwargs) def flash(self, **kwargs): + if self.gdb_cmd is None: + raise ValueError('Cannot debug; no gdb specified') + self.require(self.gdb_cmd) topology_file = kwargs['ocd-topology'] jtag_instr_file = kwargs['ocd-jtag-instr'] gdb_flash_file = kwargs['gdb-flash-file'] @@ -113,6 +117,7 @@ class IntelS1000BinaryRunner(ZephyrBinaryRunner): raise ValueError('Cannot debug; elf is missing') if self.gdb_cmd is None: raise ValueError('Cannot debug; no gdb specified') + self.require(self.gdb_cmd) topology_file = kwargs['ocd-topology'] jtag_instr_file = kwargs['ocd-jtag-instr'] diff --git a/scripts/west_commands/runners/nios2.py b/scripts/west_commands/runners/nios2.py index f6242d29d5..b3a006e947 100644 --- a/scripts/west_commands/runners/nios2.py +++ b/scripts/west_commands/runners/nios2.py @@ -61,7 +61,7 @@ class Nios2BinaryRunner(ZephyrBinaryRunner): cmd = [self.quartus_py, '--sof', self.cpu_sof, '--kernel', self.hex_name] - + self.require(cmd[0]) self.check_call(cmd) def print_gdbserver_message(self, gdb_port): @@ -80,6 +80,7 @@ class Nios2BinaryRunner(ZephyrBinaryRunner): server_cmd = (['nios2-gdb-server', '--tcpport', str(gdb_port), '--stop', '--reset-target']) + self.require(server_cmd[0]) if command == 'debugserver': self.print_gdbserver_message(gdb_port) @@ -94,6 +95,7 @@ class Nios2BinaryRunner(ZephyrBinaryRunner): self.tui_arg + [self.elf_name, '-ex', 'target remote :{}'.format(gdb_port)]) + self.require(gdb_cmd[0]) self.print_gdbserver_message(gdb_port) self.run_server_and_client(server_cmd, gdb_cmd) diff --git a/scripts/west_commands/runners/nrfjprog.py b/scripts/west_commands/runners/nrfjprog.py index d67162a297..4d7c468047 100644 --- a/scripts/west_commands/runners/nrfjprog.py +++ b/scripts/west_commands/runners/nrfjprog.py @@ -87,6 +87,8 @@ class NrfJprogBinaryRunner(ZephyrBinaryRunner): return snrs[value - 1] def do_run(self, command, **kwargs): + self.require('nrfjprog') + commands = [] if self.snr is None: board_snr = self.get_board_snr_from_user() diff --git a/scripts/west_commands/runners/nsim.py b/scripts/west_commands/runners/nsim.py index 97cb5c0f9b..813f1dc19a 100644 --- a/scripts/west_commands/runners/nsim.py +++ b/scripts/west_commands/runners/nsim.py @@ -55,6 +55,7 @@ class NsimBinaryRunner(ZephyrBinaryRunner): props=args.props) def do_run(self, command, **kwargs): + self.require(self.nsim_cmd[0]) kwargs['nsim-cfg'] = path.join(self.cfg.board_dir, 'support', self.props) @@ -77,10 +78,10 @@ class NsimBinaryRunner(ZephyrBinaryRunner): server_cmd = (self.nsim_cmd + ['-gdb', '-port={}'.format(self.gdb_port), '-propsfile', config]) - gdb_cmd = (self.gdb_cmd + ['-ex', 'target remote :{}'.format(self.gdb_port), '-ex', 'load', self.cfg.elf_file]) + self.require(gdb_cmd[0]) self.run_server_and_client(server_cmd, gdb_cmd) diff --git a/scripts/west_commands/runners/openocd.py b/scripts/west_commands/runners/openocd.py index 176cedb3a8..c861161bf0 100644 --- a/scripts/west_commands/runners/openocd.py +++ b/scripts/west_commands/runners/openocd.py @@ -86,6 +86,7 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner): gdb_port=args.gdb_port) def do_run(self, command, **kwargs): + self.require(self.openocd_cmd[0]) if command == 'flash': self.do_flash(**kwargs) elif command == 'debug': @@ -135,11 +136,10 @@ class OpenOcdBinaryRunner(ZephyrBinaryRunner): '-c', 'init', '-c', 'targets', '-c', 'halt']) - gdb_cmd = (self.gdb_cmd + self.tui_arg + ['-ex', 'target remote :{}'.format(self.gdb_port), self.elf_name]) - + self.require(gdb_cmd[0]) self.run_server_and_client(server_cmd, gdb_cmd) def do_debugserver(self, **kwargs): diff --git a/scripts/west_commands/runners/pyocd.py b/scripts/west_commands/runners/pyocd.py index 134a4982f3..77e8a663a9 100644 --- a/scripts/west_commands/runners/pyocd.py +++ b/scripts/west_commands/runners/pyocd.py @@ -108,6 +108,7 @@ class PyOcdBinaryRunner(ZephyrBinaryRunner): return ['-p', str(self.gdb_port)] def do_run(self, command, **kwargs): + self.require(self.pyocd) if command == 'flash': self.flash(**kwargs) else: @@ -166,5 +167,6 @@ class PyOcdBinaryRunner(ZephyrBinaryRunner): '-ex', 'monitor reset', '-ex', 'load'] + self.require(client_cmd[0]) self.print_gdbserver_message() self.run_server_and_client(server_cmd, client_cmd) diff --git a/scripts/west_commands/runners/xtensa.py b/scripts/west_commands/runners/xtensa.py index 244c8c2e18..86a6e9db77 100644 --- a/scripts/west_commands/runners/xtensa.py +++ b/scripts/west_commands/runners/xtensa.py @@ -36,5 +36,5 @@ class XtensaBinaryRunner(ZephyrBinaryRunner): def do_run(self, command, **kwargs): gdb_cmd = [self.cfg.gdb, self.cfg.elf_file] - + self.require(gdb_cmd[0]) self.check_call(gdb_cmd) diff --git a/scripts/west_commands/tests/test_blackmagicprobe.py b/scripts/west_commands/tests/test_blackmagicprobe.py new file mode 100644 index 0000000000..be729bee2c --- /dev/null +++ b/scripts/west_commands/tests/test_blackmagicprobe.py @@ -0,0 +1,70 @@ +# Copyright (c) 2018 Foundries.io +# Copyright (c) 2019 Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +from unittest.mock import patch, call + +import pytest + +from runners.blackmagicprobe import BlackMagicProbeRunner +from conftest import RC_KERNEL_ELF, RC_GDB + +TEST_GDB_SERIAL = 'test-gdb-serial' + +# Expected subprocesses to be run for each command. Using the +# runner_config fixture (and always specifying gdb-serial) means we +# don't get 100% coverage, but it's a starting out point. +EXPECTED_COMMANDS = { + 'attach': + ([RC_GDB, + '-ex', "set confirm off", + '-ex', "target extended-remote {}".format(TEST_GDB_SERIAL), + '-ex', "monitor swdp_scan", + '-ex', "attach 1", + '-ex', "file {}".format(RC_KERNEL_ELF)],), + 'debug': + ([RC_GDB, + '-ex', "set confirm off", + '-ex', "target extended-remote {}".format(TEST_GDB_SERIAL), + '-ex', "monitor swdp_scan", + '-ex', "attach 1", + '-ex', "file {}".format(RC_KERNEL_ELF), + '-ex', "load {}".format(RC_KERNEL_ELF)],), + 'flash': + ([RC_GDB, + '-ex', "set confirm off", + '-ex', "target extended-remote {}".format(TEST_GDB_SERIAL), + '-ex', "monitor swdp_scan", + '-ex', "attach 1", + '-ex', "load {}".format(RC_KERNEL_ELF), + '-ex', "kill", + '-ex', "quit", + '-silent'],), +} + +def require_patch(program): + assert program == RC_GDB + +@pytest.mark.parametrize('command', EXPECTED_COMMANDS) +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +@patch('runners.core.ZephyrBinaryRunner.check_call') +def test_blackmagicprobe_init(cc, req, command, runner_config): + '''Test commands using a runner created by constructor.''' + runner = BlackMagicProbeRunner(runner_config, TEST_GDB_SERIAL) + runner.run(command) + assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS[command]] + +@pytest.mark.parametrize('command', EXPECTED_COMMANDS) +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +@patch('runners.core.ZephyrBinaryRunner.check_call') +def test_blackmagicprobe_create(cc, req, command, runner_config): + '''Test commands using a runner created from command line parameters.''' + args = ['--gdb-serial', TEST_GDB_SERIAL] + parser = argparse.ArgumentParser() + BlackMagicProbeRunner.add_parser(parser) + arg_namespace = parser.parse_args(args) + runner = BlackMagicProbeRunner.create(runner_config, arg_namespace) + runner.run(command) + assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS[command]] diff --git a/scripts/west_commands/tests/test_bossac.py b/scripts/west_commands/tests/test_bossac.py new file mode 100644 index 0000000000..f2121cad6e --- /dev/null +++ b/scripts/west_commands/tests/test_bossac.py @@ -0,0 +1,44 @@ +# Copyright (c) 2018 Foundries.io +# Copyright (c) 2019 Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +from unittest.mock import patch, call + +from runners.bossac import BossacBinaryRunner +from conftest import RC_KERNEL_BIN + +TEST_BOSSAC_PORT = 'test-bossac-serial' +TEST_OFFSET = 1234 +EXPECTED_COMMANDS = [ + ['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', + '-o', str(TEST_OFFSET), '-b', RC_KERNEL_BIN], +] + +def require_patch(program): + assert program in ['bossac', 'stty'] + +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +@patch('runners.core.ZephyrBinaryRunner.check_call') +def test_bossac_init(cc, req, runner_config): + '''Test commands using a runner created by constructor.''' + runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT, + offset=TEST_OFFSET) + runner.run('flash') + assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS] + +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +@patch('runners.core.ZephyrBinaryRunner.check_call') +def test_bossac_create(cc, req, runner_config): + '''Test commands using a runner created from command line parameters.''' + args = ['--bossac-port', str(TEST_BOSSAC_PORT), + '--offset', str(TEST_OFFSET)] + parser = argparse.ArgumentParser() + BossacBinaryRunner.add_parser(parser) + arg_namespace = parser.parse_args(args) + runner = BossacBinaryRunner.create(runner_config, arg_namespace) + runner.run('flash') + assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS] diff --git a/scripts/west_commands/tests/test_dfu_util.py b/scripts/west_commands/tests/test_dfu_util.py new file mode 100644 index 0000000000..b73918613b --- /dev/null +++ b/scripts/west_commands/tests/test_dfu_util.py @@ -0,0 +1,131 @@ +# Copyright (c) 2018 Foundries.io +# Copyright (c) 2019 Nordic Semiconductor ASA. +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +from unittest.mock import patch, call + +import pytest + +from runners.dfu import DfuUtilBinaryRunner, DfuSeConfig +from conftest import RC_KERNEL_BIN + +DFU_UTIL = 'dfu-util' +TEST_EXE = 'test-dfu-util' +TEST_PID = '0000:9999' +TEST_PID_RES = '-d,{}'.format(TEST_PID) +TEST_ALT_INT = '1' +TEST_ALT_STR = 'alt-name' +TEST_BIN_NAME = 'test-img.bin' +TEST_DFUSE_ADDR = 2 +TEST_DFUSE_OPTS = 'test-dfuse-opt' +TEST_DCFG_OPT = DfuSeConfig(address=TEST_DFUSE_ADDR, options='test-dfuse-opt') +TEST_DCFG_OPT_RES = '{}:{}'.format(hex(TEST_DFUSE_ADDR), TEST_DFUSE_OPTS) +TEST_DCFG_NOPT = DfuSeConfig(address=TEST_DFUSE_ADDR, options='') +TEST_DCFG_NOPT_RES = '{}:'.format(hex(TEST_DFUSE_ADDR)) +# A map from a test case to the expected dfu-util call. +# Test cases are (alt, exe, img, dfuse) tuples. +EXPECTED_COMMAND = { + (DFU_UTIL, TEST_ALT_INT, None, RC_KERNEL_BIN): + [DFU_UTIL, TEST_PID_RES, '-a', TEST_ALT_INT, '-D', RC_KERNEL_BIN], + + (DFU_UTIL, TEST_ALT_STR, None, RC_KERNEL_BIN): + [DFU_UTIL, TEST_PID_RES, '-a', TEST_ALT_STR, '-D', RC_KERNEL_BIN], + + (TEST_EXE, TEST_ALT_INT, None, RC_KERNEL_BIN): + [TEST_EXE, TEST_PID_RES, '-a', TEST_ALT_INT, '-D', RC_KERNEL_BIN], + + (DFU_UTIL, TEST_ALT_INT, None, TEST_BIN_NAME): + [DFU_UTIL, TEST_PID_RES, '-a', TEST_ALT_INT, '-D', TEST_BIN_NAME], + + (DFU_UTIL, TEST_ALT_INT, TEST_DCFG_OPT, RC_KERNEL_BIN): + [DFU_UTIL, TEST_PID_RES, '-s', TEST_DCFG_OPT_RES, '-a', TEST_ALT_INT, + '-D', RC_KERNEL_BIN], + + (DFU_UTIL, TEST_ALT_INT, TEST_DCFG_NOPT, RC_KERNEL_BIN): + [DFU_UTIL, TEST_PID_RES, '-s', TEST_DCFG_NOPT_RES, '-a', TEST_ALT_INT, + '-D', RC_KERNEL_BIN], +} + +def find_device_patch(): + return True + +def require_patch(program): + assert program in [DFU_UTIL, TEST_EXE] + +def id_fn(tc): + return 'exe={},alt={},dfuse_config={},img={}'.format(*tc) + +@pytest.mark.parametrize('tc', [ + # (exe, alt, dfuse_config, img) + (DFU_UTIL, TEST_ALT_INT, None, RC_KERNEL_BIN), + (DFU_UTIL, TEST_ALT_STR, None, RC_KERNEL_BIN), + (TEST_EXE, TEST_ALT_INT, None, RC_KERNEL_BIN), + (DFU_UTIL, TEST_ALT_INT, None, TEST_BIN_NAME), + (DFU_UTIL, TEST_ALT_INT, TEST_DCFG_OPT, RC_KERNEL_BIN), + (DFU_UTIL, TEST_ALT_INT, TEST_DCFG_NOPT, RC_KERNEL_BIN), +], ids=id_fn) +@patch('runners.dfu.DfuUtilBinaryRunner.find_device', + side_effect=find_device_patch) +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +@patch('runners.core.ZephyrBinaryRunner.check_call') +def test_dfu_util_init(cc, req, find_device, tc, runner_config): + '''Test commands using a runner created by constructor.''' + exe, alt, dfuse_config, img = tc + runner = DfuUtilBinaryRunner(runner_config, TEST_PID, alt, img, exe=exe, + dfuse_config=dfuse_config) + runner.run('flash') + assert find_device.called + assert req.called_with(exe) + assert cc.call_args_list == [call(EXPECTED_COMMAND[tc])] + +def get_flash_address_patch(args, bcfg): + return TEST_DFUSE_ADDR + +@pytest.mark.parametrize('tc', [ + # arg spec: (exe, alt, dfuse, modifiers, img) + (None, TEST_ALT_INT, False, None, None), + (None, TEST_ALT_STR, False, None, None), + (TEST_EXE, TEST_ALT_INT, False, None, None), + (None, TEST_ALT_INT, False, None, TEST_BIN_NAME), + (None, TEST_ALT_INT, True, TEST_DFUSE_OPTS, None), + (None, TEST_ALT_INT, True, None, None), + +], ids=id_fn) +@patch('runners.core.BuildConfiguration._init',) +@patch('runners.dfu.DfuUtilBinaryRunner.find_device', + side_effect=find_device_patch) +@patch('runners.core.ZephyrBinaryRunner.get_flash_address', + side_effect=get_flash_address_patch) +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +@patch('runners.core.ZephyrBinaryRunner.check_call') +def test_dfu_util_create(cc, req, gfa, find_device, bcfg, tc, runner_config): + '''Test commands using a runner created from command line parameters.''' + exe, alt, dfuse, modifiers, img = tc + args = ['--pid', TEST_PID, '--alt', alt] + if img: + args.extend(['--img', img]) + if dfuse: + args.append('--dfuse') + if modifiers: + args.extend(['--dfuse-modifiers', modifiers]) + else: + args.extend(['--dfuse-modifiers', '']) + if exe: + args.extend(['--dfu-util', exe]) + + parser = argparse.ArgumentParser() + DfuUtilBinaryRunner.add_parser(parser) + arg_namespace = parser.parse_args(args) + runner = DfuUtilBinaryRunner.create(runner_config, arg_namespace) + runner.run('flash') + + if dfuse: + cfg = DfuSeConfig(address=TEST_DFUSE_ADDR, options=modifiers or '') + else: + cfg = None + map_tc = (exe or DFU_UTIL, alt, cfg, img or RC_KERNEL_BIN) + assert find_device.called + assert req.called_with(exe) + assert cc.call_args_list == [call(EXPECTED_COMMAND[map_tc])] diff --git a/scripts/west_commands/tests/test_nrfjprog.py b/scripts/west_commands/tests/test_nrfjprog.py index fbdab9ccea..9238313c0c 100644 --- a/scripts/west_commands/tests/test_nrfjprog.py +++ b/scripts/west_commands/tests/test_nrfjprog.py @@ -186,6 +186,10 @@ 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: @@ -197,16 +201,18 @@ def id_fn(test_case): @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, test_case, runner_config): +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) runner.run('flash') + assert req.called assert cc.call_args_list == [call(x) for x in expected_commands(*test_case)] if snr is None: @@ -216,10 +222,11 @@ def test_nrfjprog_init(cc, get_snr, test_case, runner_config): @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, test_case, runner_config): +def test_nrfjprog_create(cc, get_snr, req, test_case, runner_config): family, softreset, snr, erase = test_case args = ['--nrf-family', family] @@ -236,6 +243,7 @@ def test_nrfjprog_create(cc, get_snr, test_case, runner_config): 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: diff --git a/scripts/west_commands/tests/test_pyocd.py b/scripts/west_commands/tests/test_pyocd.py index a7c3962a95..86547fd62d 100644 --- a/scripts/west_commands/tests/test_pyocd.py +++ b/scripts/west_commands/tests/test_pyocd.py @@ -136,6 +136,14 @@ def pyocd(runner_config, tmpdir): return _factory +# +# Helpers +# + +def require_patch(program): + assert program in ['pyocd', TEST_PYOCD, RC_GDB] + + # # Test cases for runners created by constructor. # @@ -145,8 +153,10 @@ def pyocd(runner_config, tmpdir): (TEST_DEF_KWARGS, FLASH_DEF_EXPECTED_CALL) ]) @patch('runners.pyocd.PyOcdBinaryRunner.check_call') -def test_flash(cc, pyocd_args, expected, pyocd): +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +def test_flash(require, cc, pyocd_args, expected, pyocd): pyocd(pyocd_args).run('flash') + assert require.called cc.assert_called_once_with(expected) @@ -155,8 +165,10 @@ def test_flash(cc, pyocd_args, expected, pyocd): (TEST_DEF_KWARGS, (DEBUG_DEF_EXPECTED_SERVER, DEBUG_DEF_EXPECTED_CLIENT)) ]) @patch('runners.pyocd.PyOcdBinaryRunner.run_server_and_client') -def test_debug(rsc, pyocd_args, expectedv, pyocd): +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +def test_debug(require, rsc, pyocd_args, expectedv, pyocd): pyocd(pyocd_args).run('debug') + assert require.called rsc.assert_called_once_with(*expectedv) @@ -165,8 +177,10 @@ def test_debug(rsc, pyocd_args, expectedv, pyocd): (TEST_DEF_KWARGS, DEBUGSERVER_DEF_EXPECTED_CALL) ]) @patch('runners.pyocd.PyOcdBinaryRunner.check_call') -def test_debugserver(cc, pyocd_args, expected, pyocd): +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +def test_debugserver(require, cc, pyocd_args, expected, pyocd): pyocd(pyocd_args).run('debugserver') + assert require.called cc.assert_called_once_with(expected) @@ -183,10 +197,12 @@ def test_debugserver(cc, pyocd_args, expected, pyocd): ]) @patch('runners.pyocd.BuildConfiguration') @patch('runners.pyocd.PyOcdBinaryRunner.check_call') -def test_flash_args(cc, bc, pyocd_args, flash_addr, expected, pyocd): +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +def test_flash_args(require, cc, bc, pyocd_args, flash_addr, expected, pyocd): with patch.object(PyOcdBinaryRunner, 'get_flash_address', return_value=flash_addr): pyocd(pyocd_args).run('flash') + assert require.called bc.assert_called_once_with(RC_BUILD_DIR) cc.assert_called_once_with(expected) @@ -197,8 +213,10 @@ def test_flash_args(cc, bc, pyocd_args, flash_addr, expected, pyocd): ]) @patch('runners.pyocd.BuildConfiguration') @patch('runners.pyocd.PyOcdBinaryRunner.run_server_and_client') -def test_debug_args(rsc, bc, pyocd_args, expectedv, pyocd): +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +def test_debug_args(require, rsc, bc, pyocd_args, expectedv, pyocd): pyocd(pyocd_args).run('debug') + assert require.called bc.assert_called_once_with(RC_BUILD_DIR) rsc.assert_called_once_with(*expectedv) @@ -209,7 +227,9 @@ def test_debug_args(rsc, bc, pyocd_args, expectedv, pyocd): ]) @patch('runners.pyocd.BuildConfiguration') @patch('runners.pyocd.PyOcdBinaryRunner.check_call') -def test_debugserver_args(cc, bc, pyocd_args, expected, pyocd): +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +def test_debugserver_args(require, cc, bc, pyocd_args, expected, pyocd): pyocd(pyocd_args).run('debugserver') + assert require.called bc.assert_called_once_with(RC_BUILD_DIR) cc.assert_called_once_with(expected)