Skip to content
Permalink
Browse files

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 <marti.bolivar@nordicsemi.no>
  • Loading branch information...
mbolivar authored and carlescufi committed Jun 2, 2019
1 parent c07267a commit c24e044c6e21082a74c638997f2ccfce3bf6d307
@@ -64,6 +64,7 @@ def create(cls, cfg, args):
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 @@ def do_run(self, command, **kwargs):
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),
@@ -35,8 +35,6 @@ def do_add_parser(cls, parser):
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 @@ def bmp_flash(self, command, **kwargs):
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 @@ def bmp_attach(self, command, **kwargs):
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 @@ def bmp_debug(self, command, **kwargs):
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)
@@ -50,6 +50,8 @@ def do_run(self, command, **kwargs):
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']
@@ -90,6 +90,7 @@ def find_device(self):
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
@@ -78,6 +78,7 @@ def create(cls, cfg, args):
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,
@@ -36,6 +36,8 @@ def create(cls, cfg, args):
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',
@@ -61,6 +61,7 @@ def create(cls, cfg, args):
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 @@ def do_run(self, command, **kwargs):
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 @@ def do_debug(self, **kwargs):
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']
@@ -61,7 +61,7 @@ def flash(self, **kwargs):
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 @@ def debug_debugserver(self, command, **kwargs):
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 @@ def debug_debugserver(self, command, **kwargs):
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)
@@ -87,6 +87,8 @@ def get_board_snr_from_user(self):
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()
@@ -55,6 +55,7 @@ def create(cls, cfg, args):
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 @@ def do_debug(self, **kwargs):
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)

@@ -86,6 +86,7 @@ def create(cls, cfg, args):
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 @@ def do_debug(self, **kwargs):
'-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):
@@ -108,6 +108,7 @@ def port_args(self):
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 @@ def debug_debugserver(self, command, **kwargs):
'-ex', 'monitor reset',
'-ex', 'load']

self.require(client_cmd[0])
self.print_gdbserver_message()
self.run_server_and_client(server_cmd, client_cmd)
@@ -36,5 +36,5 @@ def create(cls, cfg, args):

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)
@@ -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]]
@@ -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]

0 comments on commit c24e044

Please sign in to comment.
You can’t perform that action at this time.