1# Copyright (c) 2018 Foundries.io 2# Copyright (c) 2019 Nordic Semiconductor ASA. 3# 4# SPDX-License-Identifier: Apache-2.0 5 6import argparse 7from unittest.mock import patch, call 8import os 9 10import pytest 11 12from runners import blackmagicprobe 13from runners.blackmagicprobe import BlackMagicProbeRunner 14from conftest import RC_KERNEL_ELF, RC_GDB 15import serial.tools.list_ports 16 17TEST_GDB_SERIAL = 'test-gdb-serial' 18 19# Expected subprocesses to be run for each command. Using the 20# runner_config fixture (and always specifying gdb-serial) means we 21# don't get 100% coverage, but it's a starting out point. 22EXPECTED_COMMANDS = { 23 'attach': 24 ([RC_GDB, 25 '-ex', "set confirm off", 26 '-ex', "target extended-remote {}".format(TEST_GDB_SERIAL), 27 '-ex', "monitor swdp_scan", 28 '-ex', "attach 1", 29 '-ex', "file {}".format(RC_KERNEL_ELF)],), 30 'debug': 31 ([RC_GDB, 32 '-ex', "set confirm off", 33 '-ex', "target extended-remote {}".format(TEST_GDB_SERIAL), 34 '-ex', "monitor swdp_scan", 35 '-ex', "attach 1", 36 '-ex', "file {}".format(RC_KERNEL_ELF), 37 '-ex', "load {}".format(RC_KERNEL_ELF)],), 38 'flash': 39 ([RC_GDB, 40 '-ex', "set confirm off", 41 '-ex', "target extended-remote {}".format(TEST_GDB_SERIAL), 42 '-ex', "monitor swdp_scan", 43 '-ex', "attach 1", 44 '-ex', "load {}".format(RC_KERNEL_ELF), 45 '-ex', "kill", 46 '-ex', "quit", 47 '-silent'],), 48} 49 50EXPECTED_CONNECT_SRST_COMMAND = { 51 'attach': 'monitor connect_rst disable', 52 'debug': 'monitor connect_rst enable', 53 'flash': 'monitor connect_rst enable', 54} 55 56def require_patch(program): 57 assert program == RC_GDB 58 59@pytest.mark.parametrize('command', EXPECTED_COMMANDS) 60@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) 61@patch('runners.core.ZephyrBinaryRunner.check_call') 62def test_blackmagicprobe_init(cc, req, command, runner_config): 63 '''Test commands using a runner created by constructor.''' 64 runner = BlackMagicProbeRunner(runner_config, TEST_GDB_SERIAL) 65 runner.run(command) 66 assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS[command]] 67 68@pytest.mark.parametrize('command', EXPECTED_COMMANDS) 69@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) 70@patch('runners.core.ZephyrBinaryRunner.check_call') 71def test_blackmagicprobe_create(cc, req, command, runner_config): 72 '''Test commands using a runner created from command line parameters.''' 73 args = ['--gdb-serial', TEST_GDB_SERIAL] 74 parser = argparse.ArgumentParser(allow_abbrev=False) 75 BlackMagicProbeRunner.add_parser(parser) 76 arg_namespace = parser.parse_args(args) 77 runner = BlackMagicProbeRunner.create(runner_config, arg_namespace) 78 runner.run(command) 79 assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS[command]] 80 81@pytest.mark.parametrize('command', EXPECTED_CONNECT_SRST_COMMAND) 82@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) 83@patch('runners.core.ZephyrBinaryRunner.check_call') 84def test_blackmagicprobe_connect_rst(cc, req, command, runner_config): 85 '''Test that commands list the correct connect_rst value when enabled.''' 86 args = ['--gdb-serial', TEST_GDB_SERIAL, '--connect-rst'] 87 parser = argparse.ArgumentParser(allow_abbrev=False) 88 BlackMagicProbeRunner.add_parser(parser) 89 arg_namespace = parser.parse_args(args) 90 runner = BlackMagicProbeRunner.create(runner_config, arg_namespace) 91 runner.run(command) 92 expected = EXPECTED_CONNECT_SRST_COMMAND[command] 93 assert expected in cc.call_args_list[0][0][0] 94 95@pytest.mark.parametrize('arg, env, expected', [ 96 # Argument has priority 97 ('/dev/XXX', None, '/dev/XXX'), 98 ('/dev/XXX', '/dev/YYYY', '/dev/XXX'), 99 100 # Then BMP_GDB_SERIAL env variable 101 (None, '/dev/XXX', '/dev/XXX'), 102 ]) 103def test_blackmagicprobe_gdb_serial_generic(arg, env, expected): 104 if env: 105 os.environ['BMP_GDB_SERIAL'] = env 106 else: 107 if 'BMP_GDB_SERIAL' in os.environ: 108 os.environ.pop('BMP_GDB_SERIAL') 109 110 ret = blackmagicprobe.blackmagicprobe_gdb_serial(arg) 111 assert expected == ret 112 113@pytest.mark.parametrize('known_path, comports, globs, expected', [ 114 (True, False, ['/dev/ttyACM0', '/dev/ttyACM1'], 115 blackmagicprobe.DEFAULT_LINUX_BMP_PATH), 116 (False, True, [], '/dev/ttyACM3'), 117 (False, False, ['/dev/ttyACM0', '/dev/ttyACM1'], '/dev/ttyACM0'), 118 (False, False, ['/dev/ttyACM1', '/dev/ttyACM0'], '/dev/ttyACM0'), 119 ]) 120@patch('serial.tools.list_ports.comports') 121@patch('os.path.exists') 122@patch('glob.glob') 123def test_blackmagicprobe_gdb_serial_linux(gg, ope, stlpc, known_path, comports, 124 globs, expected): 125 gg.return_value = globs 126 ope.return_value = known_path 127 if comports: 128 fake_comport1 = serial.tools.list_ports_common.ListPortInfo( 129 '/dev/ttyACM1') 130 fake_comport1.interface = 'something' 131 fake_comport2 = serial.tools.list_ports_common.ListPortInfo( 132 '/dev/ttyACM2') 133 fake_comport2.interface = None 134 fake_comport3 = serial.tools.list_ports_common.ListPortInfo( 135 '/dev/ttyACM3') 136 fake_comport3.interface = blackmagicprobe.BMP_GDB_INTERFACE 137 stlpc.return_value = [fake_comport1, fake_comport2, fake_comport3] 138 else: 139 stlpc.return_value = [] 140 141 ret = blackmagicprobe.blackmagicprobe_gdb_serial_linux() 142 assert expected == ret 143 144@pytest.mark.parametrize('comports, globs, expected', [ 145 (True, [], '/dev/cu.usbmodem3'), 146 (False, ['/dev/cu.usbmodemAABBCC0', '/dev/cu.usbmodemAABBCC1'], 147 '/dev/cu.usbmodemAABBCC0'), 148 (False, ['/dev/cu.usbmodemAABBCC1', '/dev/cu.usbmodemAABBCC0'], 149 '/dev/cu.usbmodemAABBCC0'), 150 ]) 151@patch('serial.tools.list_ports.comports') 152@patch('glob.glob') 153def test_blackmagicprobe_gdb_serial_darwin(gg, stlpc, comports, globs, expected): 154 gg.return_value = globs 155 if comports: 156 fake_comport1 = serial.tools.list_ports_common.ListPortInfo( 157 '/dev/cu.usbmodem1') 158 fake_comport1.description = 'unrelated' 159 fake_comport2 = serial.tools.list_ports_common.ListPortInfo( 160 '/dev/cu.usbmodem2') 161 fake_comport2.description = None 162 fake_comport3 = serial.tools.list_ports_common.ListPortInfo( 163 '/dev/cu.usbmodem3') 164 fake_comport3.description = f'{blackmagicprobe.BMP_GDB_PRODUCT} v1234' 165 fake_comport4 = serial.tools.list_ports_common.ListPortInfo( 166 '/dev/cu.usbmodem4') 167 fake_comport4.description = f'{blackmagicprobe.BMP_GDB_PRODUCT} v1234' 168 stlpc.return_value = [fake_comport1, fake_comport2, 169 fake_comport4, fake_comport3] 170 else: 171 stlpc.return_value = [] 172 173 ret = blackmagicprobe.blackmagicprobe_gdb_serial_darwin() 174 assert expected == ret 175 176@pytest.mark.parametrize('comports, expected', [ 177 (True, 'COM4'), 178 (False, 'COM1'), 179 ]) 180@patch('serial.tools.list_ports.comports') 181def test_blackmagicprobe_gdb_serial_win32(stlpc, comports, expected): 182 if comports: 183 fake_comport1 = serial.tools.list_ports_common.ListPortInfo('COM2') 184 fake_comport1.vid = 123 185 fake_comport1.pid = 456 186 fake_comport2 = serial.tools.list_ports_common.ListPortInfo('COM3') 187 fake_comport2.vid = None 188 fake_comport2.pid = None 189 fake_comport3 = serial.tools.list_ports_common.ListPortInfo('COM4') 190 fake_comport3.vid = blackmagicprobe.BMP_GDB_VID 191 fake_comport3.pid = blackmagicprobe.BMP_GDB_PID 192 fake_comport4 = serial.tools.list_ports_common.ListPortInfo('COM5') 193 fake_comport4.vid = blackmagicprobe.BMP_GDB_VID 194 fake_comport4.pid = blackmagicprobe.BMP_GDB_PID 195 stlpc.return_value = [fake_comport1, fake_comport2, 196 fake_comport4, fake_comport3] 197 else: 198 stlpc.return_value = [] 199 200 ret = blackmagicprobe.blackmagicprobe_gdb_serial_win32() 201 assert expected == ret 202