1#!/usr/bin/env python3 2# Copyright (c) 2023 Intel Corporation 3# 4# SPDX-License-Identifier: Apache-2.0 5""" 6Blackbox tests for twister's command line functions 7""" 8import importlib 9from unittest import mock 10import os 11import pytest 12import sys 13 14# pylint: disable=no-name-in-module 15from conftest import ZEPHYR_BASE, testsuite_filename_mock, clear_log_in_test 16from twisterlib.testplan import TestPlan 17 18sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/twister/twisterlib")) 19 20@mock.patch.object(TestPlan, 'TESTSUITE_FILENAME', testsuite_filename_mock) 21class TestHardwaremap: 22 TESTDATA_1 = [ 23 ( 24 [ 25 'ARM', 26 'SEGGER', 27 'MBED' 28 ], 29 [ 30 'DAPLink CMSIS-DAP', 31 'MBED CMSIS-DAP' 32 ], 33 [1234, 'abcd'], 34 'pyocd' 35 ), 36 ( 37 [ 38 'STMicroelectronics', 39 'Atmel Corp.' 40 ], 41 [ 42 'J-Link', 43 'J-Link OB' 44 ], 45 [1234, 'abcd'], 46 'jlink' 47 ), 48 ( 49 [ 50 'Silicon Labs', 51 'NXP Semiconductors', 52 'Microchip Technology Inc.' 53 ], 54 [ 55 'STM32 STLink', 56 '^XDS110.*', 57 'STLINK-V3' 58 ], 59 [1234, 'abcd'], 60 'openocd' 61 ), 62 ( 63 [ 64 'FTDI', 65 'Digilent', 66 'Microsoft' 67 ], 68 [ 69 'TTL232R-3V3', 70 'MCP2200 USB Serial Port Emulator' 71 ], 72 [1234, 'abcd'], 73 'dediprog' 74 ) 75 ] 76 TESTDATA_2 = [ 77 ( 78 'FTDI', 79 'DAPLink CMSIS-DAP', 80 1234, 81 'pyocd' 82 ) 83 ] 84 TESTDATA_3 = [ 85 ( 86 'Texas Instruments', 87 'DAPLink CMSIS-DAP', 88 'abcd', 'las' 89 ), 90 ( 91 'Texas Instruments', 92 'DAPLink CMSIS-DAP', 93 'abcd', 'dse0' 94 ) 95 ] 96 97 @classmethod 98 def setup_class(cls): 99 apath = os.path.join(ZEPHYR_BASE, 'scripts', 'twister') 100 cls.loader = importlib.machinery.SourceFileLoader('__main__', apath) 101 cls.spec = importlib.util.spec_from_loader(cls.loader.name, cls.loader) 102 cls.twister_module = importlib.util.module_from_spec(cls.spec) 103 104 @classmethod 105 def teardown_class(cls): 106 pass 107 108 @pytest.mark.parametrize( 109 ('manufacturer', 'product', 'serial', 'runner'), 110 TESTDATA_1, 111 ) 112 def test_generate(self, capfd, out_path, manufacturer, product, serial, runner): 113 file_name = "test-map.yaml" 114 path = os.path.join(ZEPHYR_BASE, file_name) 115 args = ['--outdir', out_path, '--generate-hardware-map', file_name] 116 117 if os.path.exists(path): 118 os.remove(path) 119 120 def mocked_comports(): 121 return [ 122 mock.Mock(device='/dev/ttyUSB23', 123 manufacturer=id_man, 124 product=id_pro, 125 serial_number=id_serial 126 ) 127 ] 128 129 for id_man in manufacturer: 130 for id_pro in product: 131 for id_serial in serial: 132 with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ 133 mock.patch('serial.tools.list_ports.comports', 134 side_effect=mocked_comports), \ 135 pytest.raises(SystemExit) as sys_exit: 136 self.loader.exec_module(self.twister_module) 137 138 out, err = capfd.readouterr() 139 sys.stdout.write(out) 140 sys.stderr.write(err) 141 142 assert os.path.exists(path) 143 144 expected_data = '- connected: true\n' \ 145 f' id: {id_serial}\n' \ 146 ' platform: unknown\n' \ 147 f' product: {id_pro}\n' \ 148 f' runner: {runner}\n' \ 149 ' serial: /dev/ttyUSB23\n' 150 151 load_data = open(path).read() 152 assert load_data == expected_data 153 154 if os.path.exists(path): 155 os.remove(path) 156 157 assert str(sys_exit.value) == '0' 158 clear_log_in_test() 159 160 @pytest.mark.parametrize( 161 ('manufacturer', 'product', 'serial', 'runner'), 162 TESTDATA_2, 163 ) 164 def test_few_generate(self, capfd, out_path, manufacturer, product, serial, runner): 165 file_name = "test-map.yaml" 166 path = os.path.join(ZEPHYR_BASE, file_name) 167 args = ['--outdir', out_path, '--generate-hardware-map', file_name] 168 169 if os.path.exists(path): 170 os.remove(path) 171 172 def mocked_comports(): 173 return [ 174 mock.Mock(device='/dev/ttyUSB23', 175 manufacturer=manufacturer, 176 product=product, 177 serial_number=serial 178 ), 179 mock.Mock(device='/dev/ttyUSB24', 180 manufacturer=manufacturer, 181 product=product, 182 serial_number=serial + 1 183 ), 184 mock.Mock(device='/dev/ttyUSB24', 185 manufacturer=manufacturer, 186 product=product, 187 serial_number=serial + 2 188 ), 189 mock.Mock(device='/dev/ttyUSB25', 190 manufacturer=manufacturer, 191 product=product, 192 serial_number=serial + 3 193 ) 194 ] 195 196 with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ 197 mock.patch('serial.tools.list_ports.comports', 198 side_effect=mocked_comports), \ 199 pytest.raises(SystemExit) as sys_exit: 200 self.loader.exec_module(self.twister_module) 201 202 out, err = capfd.readouterr() 203 sys.stdout.write(out) 204 sys.stderr.write(err) 205 206 assert os.path.exists(path) 207 208 expected_data = '- connected: true\n' \ 209 f' id: {serial}\n' \ 210 ' platform: unknown\n' \ 211 f' product: {product}\n' \ 212 f' runner: {runner}\n' \ 213 ' serial: /dev/ttyUSB23\n' \ 214 '- connected: true\n' \ 215 f' id: {serial + 1}\n' \ 216 ' platform: unknown\n' \ 217 f' product: {product}\n' \ 218 f' runner: {runner}\n' \ 219 ' serial: /dev/ttyUSB24\n' \ 220 '- connected: true\n' \ 221 f' id: {serial + 2}\n' \ 222 ' platform: unknown\n' \ 223 f' product: {product}\n' \ 224 f' runner: {runner}\n' \ 225 ' serial: /dev/ttyUSB24\n' \ 226 '- connected: true\n' \ 227 f' id: {serial + 3}\n' \ 228 ' platform: unknown\n' \ 229 f' product: {product}\n' \ 230 f' runner: {runner}\n' \ 231 ' serial: /dev/ttyUSB25\n' 232 233 load_data = open(path).read() 234 assert load_data == expected_data 235 236 if os.path.exists(path): 237 os.remove(path) 238 239 assert str(sys_exit.value) == '0' 240 241 @pytest.mark.parametrize( 242 ('manufacturer', 'product', 'serial', 'location'), 243 TESTDATA_3, 244 ) 245 def test_texas_exeption(self, capfd, out_path, manufacturer, product, serial, location): 246 file_name = "test-map.yaml" 247 path = os.path.join(ZEPHYR_BASE, file_name) 248 args = ['--outdir', out_path, '--generate-hardware-map', file_name] 249 250 if os.path.exists(path): 251 os.remove(path) 252 253 def mocked_comports(): 254 return [ 255 mock.Mock(device='/dev/ttyUSB23', 256 manufacturer=manufacturer, 257 product=product, 258 serial_number=serial, 259 location=location 260 ) 261 ] 262 263 with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ 264 mock.patch('serial.tools.list_ports.comports', 265 side_effect=mocked_comports), \ 266 pytest.raises(SystemExit) as sys_exit: 267 self.loader.exec_module(self.twister_module) 268 269 out, err = capfd.readouterr() 270 sys.stdout.write(out) 271 sys.stderr.write(err) 272 273 assert os.path.exists(path) 274 275 expected_data = '- connected: true\n' \ 276 f' id: {serial}\n' \ 277 ' platform: unknown\n' \ 278 f' product: {product}\n' \ 279 ' runner: pyocd\n' \ 280 ' serial: /dev/ttyUSB23\n' 281 expected_data2 = '[]\n' 282 283 load_data = open(path).read() 284 if location.endswith('0'): 285 assert load_data == expected_data 286 else: 287 assert load_data == expected_data2 288 if os.path.exists(path): 289 os.remove(path) 290 291 assert str(sys_exit.value) == '0' 292