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