Add some logic in blackmagicprobe.py to guess the GDB serial port based on the OS instead of just trying the flag or /dev/ttyACM0. The new logic explicitly looks for the well known path for BMP on Linux (/dev/ttyBmpGdb), so that we can remove it from the board files that have it set explicitly right now. At the same time it still allows setting the port from the flag and also checks an environment variable, so that it can be used for systems with multiple probes. As a fallback, it looks for a valid serial port, picking the first one (the probe creates two, the GDB one is the first one), and raise an exception if nothing is found. Signed-off-by: Fabio Baltieri <fabio.baltieri@gmail.com>
202 lines
7.8 KiB
Python
202 lines
7.8 KiB
Python
# 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 os
|
|
|
|
import pytest
|
|
|
|
from runners import blackmagicprobe
|
|
from runners.blackmagicprobe import BlackMagicProbeRunner
|
|
from conftest import RC_KERNEL_ELF, RC_GDB
|
|
import serial.tools.list_ports
|
|
|
|
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'],),
|
|
}
|
|
|
|
EXPECTED_CONNECT_SRST_COMMAND = {
|
|
'attach': 'monitor connect_rst disable',
|
|
'debug': 'monitor connect_rst enable',
|
|
'flash': 'monitor connect_rst enable',
|
|
}
|
|
|
|
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]]
|
|
|
|
@pytest.mark.parametrize('command', EXPECTED_CONNECT_SRST_COMMAND)
|
|
@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
|
|
@patch('runners.core.ZephyrBinaryRunner.check_call')
|
|
def test_blackmagicprobe_connect_rst(cc, req, command, runner_config):
|
|
'''Test that commands list the correct connect_rst value when enabled.'''
|
|
args = ['--gdb-serial', TEST_GDB_SERIAL, '--connect-rst']
|
|
parser = argparse.ArgumentParser()
|
|
BlackMagicProbeRunner.add_parser(parser)
|
|
arg_namespace = parser.parse_args(args)
|
|
runner = BlackMagicProbeRunner.create(runner_config, arg_namespace)
|
|
runner.run(command)
|
|
expected = EXPECTED_CONNECT_SRST_COMMAND[command]
|
|
assert expected in cc.call_args_list[0][0][0]
|
|
|
|
@pytest.mark.parametrize('arg, env, expected', [
|
|
# Argument has priority
|
|
('/dev/XXX', None, '/dev/XXX'),
|
|
('/dev/XXX', '/dev/YYYY', '/dev/XXX'),
|
|
|
|
# Then BMP_GDB_SERIAL env variable
|
|
(None, '/dev/XXX', '/dev/XXX'),
|
|
])
|
|
def test_blackmagicprobe_gdb_serial_generic(arg, env, expected):
|
|
if env:
|
|
os.environ['BMP_GDB_SERIAL'] = env
|
|
else:
|
|
if 'BMP_GDB_SERIAL' in os.environ:
|
|
os.environ.pop('BMP_GDB_SERIAL')
|
|
|
|
ret = blackmagicprobe.blackmagicprobe_gdb_serial(arg)
|
|
assert expected == ret
|
|
|
|
@pytest.mark.parametrize('known_path, comports, globs, expected', [
|
|
(True, False, ['/dev/ttyACM0', '/dev/ttyACM1'],
|
|
blackmagicprobe.DEFAULT_LINUX_BMP_PATH),
|
|
(False, True, [], '/dev/ttyACM3'),
|
|
(False, False, ['/dev/ttyACM0', '/dev/ttyACM1'], '/dev/ttyACM0'),
|
|
(False, False, ['/dev/ttyACM1', '/dev/ttyACM0'], '/dev/ttyACM0'),
|
|
])
|
|
@patch('serial.tools.list_ports.comports')
|
|
@patch('os.path.exists')
|
|
@patch('glob.glob')
|
|
def test_blackmagicprobe_gdb_serial_linux(gg, ope, stlpc, known_path, comports,
|
|
globs, expected):
|
|
gg.return_value = globs
|
|
ope.return_value = known_path
|
|
if comports:
|
|
fake_comport1 = serial.tools.list_ports_common.ListPortInfo(
|
|
'/dev/ttyACM1')
|
|
fake_comport1.interface = 'something'
|
|
fake_comport2 = serial.tools.list_ports_common.ListPortInfo(
|
|
'/dev/ttyACM2')
|
|
fake_comport2.interface = None
|
|
fake_comport3 = serial.tools.list_ports_common.ListPortInfo(
|
|
'/dev/ttyACM3')
|
|
fake_comport3.interface = blackmagicprobe.BMP_GDB_INTERFACE
|
|
stlpc.return_value = [fake_comport1, fake_comport2, fake_comport3]
|
|
else:
|
|
stlpc.return_value = []
|
|
|
|
ret = blackmagicprobe.blackmagicprobe_gdb_serial_linux()
|
|
assert expected == ret
|
|
|
|
@pytest.mark.parametrize('comports, globs, expected', [
|
|
(True, [], '/dev/cu.usbmodem3'),
|
|
(False, ['/dev/cu.usbmodemAABBCC0', '/dev/cu.usbmodemAABBCC1'],
|
|
'/dev/cu.usbmodemAABBCC0'),
|
|
(False, ['/dev/cu.usbmodemAABBCC1', '/dev/cu.usbmodemAABBCC0'],
|
|
'/dev/cu.usbmodemAABBCC0'),
|
|
])
|
|
@patch('serial.tools.list_ports.comports')
|
|
@patch('glob.glob')
|
|
def test_blackmagicprobe_gdb_serial_darwin(gg, stlpc, comports, globs, expected):
|
|
gg.return_value = globs
|
|
if comports:
|
|
fake_comport1 = serial.tools.list_ports_common.ListPortInfo(
|
|
'/dev/cu.usbmodem1')
|
|
fake_comport1.description = 'unrelated'
|
|
fake_comport2 = serial.tools.list_ports_common.ListPortInfo(
|
|
'/dev/cu.usbmodem2')
|
|
fake_comport2.description = None
|
|
fake_comport3 = serial.tools.list_ports_common.ListPortInfo(
|
|
'/dev/cu.usbmodem3')
|
|
fake_comport3.description = f'{blackmagicprobe.BMP_GDB_PRODUCT} v1234'
|
|
fake_comport4 = serial.tools.list_ports_common.ListPortInfo(
|
|
'/dev/cu.usbmodem4')
|
|
fake_comport4.description = f'{blackmagicprobe.BMP_GDB_PRODUCT} v1234'
|
|
stlpc.return_value = [fake_comport1, fake_comport2,
|
|
fake_comport4, fake_comport3]
|
|
else:
|
|
stlpc.return_value = []
|
|
|
|
ret = blackmagicprobe.blackmagicprobe_gdb_serial_darwin()
|
|
assert expected == ret
|
|
|
|
@pytest.mark.parametrize('comports, expected', [
|
|
(True, 'COM4'),
|
|
(False, 'COM1'),
|
|
])
|
|
@patch('serial.tools.list_ports.comports')
|
|
def test_blackmagicprobe_gdb_serial_win32(stlpc, comports, expected):
|
|
if comports:
|
|
fake_comport1 = serial.tools.list_ports_common.ListPortInfo('COM2')
|
|
fake_comport1.vid = 123
|
|
fake_comport1.pid = 456
|
|
fake_comport2 = serial.tools.list_ports_common.ListPortInfo('COM3')
|
|
fake_comport2.vid = None
|
|
fake_comport2.pid = None
|
|
fake_comport3 = serial.tools.list_ports_common.ListPortInfo('COM4')
|
|
fake_comport3.vid = blackmagicprobe.BMP_GDB_VID
|
|
fake_comport3.pid = blackmagicprobe.BMP_GDB_PID
|
|
fake_comport4 = serial.tools.list_ports_common.ListPortInfo('COM5')
|
|
fake_comport4.vid = blackmagicprobe.BMP_GDB_VID
|
|
fake_comport4.pid = blackmagicprobe.BMP_GDB_PID
|
|
stlpc.return_value = [fake_comport1, fake_comport2,
|
|
fake_comport4, fake_comport3]
|
|
else:
|
|
stlpc.return_value = []
|
|
|
|
ret = blackmagicprobe.blackmagicprobe_gdb_serial_win32()
|
|
assert expected == ret
|