1# Copyright (c) 2018 Foundries.io 2# Copyright (c) 2020 Nordic Semiconductor ASA 3# 4# SPDX-License-Identifier: Apache-2.0 5 6import argparse 7import functools 8import io 9import os 10import shlex 11import typing 12from unittest.mock import patch, call 13 14import pytest 15 16from runners.nrfjprog import NrfJprogBinaryRunner 17from runners.nrfutil import NrfUtilBinaryRunner 18from conftest import RC_KERNEL_HEX 19 20 21# 22# Test values 23# 24 25TEST_DEF_SNR = 'test-default-serial-number' # for mocking user input 26TEST_OVR_SNR = 'test-override-serial-number' 27 28TEST_TOOL_OPT = '--ip 192.168.1.10' 29TEST_TOOL_OPT_L = shlex.split(TEST_TOOL_OPT) 30 31CLASS_MAP = {'nrfjprog': NrfJprogBinaryRunner, 'nrfutil': NrfUtilBinaryRunner} 32 33# 34# A dictionary mapping test cases to expected results. 35# 36# The keys are TC objects. 37# 38# The values are usually tool commands we expect to be executed for 39# each test case. Verification is done by mocking the check_call() 40# ZephyrBinaryRunner method which is used to run the commands. 41# 42# Values can also be callables which take a tmpdir and return the 43# expected commands. This is needed for nRF53 testing. 44# 45 46class TC(typing.NamedTuple): # 'TestCase' 47 # NRF51, NRF52, etc. 48 family: str 49 50 # 'APP', 'NET', 'APP+NET', or None. 51 coprocessor: typing.Optional[str] 52 53 # Run a recover command first if True 54 recover: bool 55 56 # Use --reset instead of --pinreset if True 57 softreset: bool 58 59 # Use --pinreset instead of --reset if True 60 pinreset: bool 61 62 # --snr TEST_OVR_SNR if True, --snr TEST_DEF_SNR if False 63 snr: bool 64 65 # --chiperase if True, 66 # --sectorerase if False (or --sectoranduicrerase on nRF52) 67 erase: bool 68 69 # --tool-opt TEST_TOOL_OPT if True 70 tool_opt: bool 71 72EXPECTED_MAP = {'nrfjprog': 0, 'nrfutil': 1} 73EXPECTED_RESULTS = { 74 75 # ------------------------------------------------------------------------- 76 # NRF51 77 # 78 # family CP recov soft pin snr erase tool_opt 79 TC('nrf51', None, False, False, False, False, False, False): 80 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF51', 81 '--snr', TEST_DEF_SNR], 82 ['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]), 83 (TEST_DEF_SNR, None)), 84 85 TC('nrf51', None, False, False, False, False, True, False): 86 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF51', 87 '--snr', TEST_DEF_SNR], 88 ['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]), 89 (TEST_DEF_SNR, None)), 90 91 TC('nrf51', None, False, False, True, True, False, False): 92 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF51', 93 '--snr', TEST_OVR_SNR], 94 ['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]), 95 (TEST_OVR_SNR, None)), 96 97 TC('nrf51', None, False, True, False, False, False, False): 98 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF51', 99 '--snr', TEST_DEF_SNR], 100 ['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]), 101 (TEST_DEF_SNR, None)), 102 103 TC('nrf51', None, True, False, True, False, False, False): 104 ((['nrfjprog', '--recover', '-f', 'NRF51', '--snr', TEST_DEF_SNR], 105 ['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF51', 106 '--snr', TEST_DEF_SNR], 107 ['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]), 108 (TEST_DEF_SNR, None)), 109 110 TC('nrf51', None, True, True, False, True, True, False): 111 ((['nrfjprog', '--recover', '-f', 'NRF51', '--snr', TEST_OVR_SNR], 112 ['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF51', 113 '--snr', TEST_OVR_SNR], 114 ['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]), 115 (TEST_OVR_SNR, None)), 116 117 TC('nrf51', None, True, True, False, True, True, True): 118 ((['nrfjprog', '--recover', '-f', 'NRF51', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L, 119 ['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF51', 120 '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L, 121 ['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L), 122 (TEST_OVR_SNR, None)), 123 124 # ------------------------------------------------------------------------- 125 # NRF52 126 # 127 # family CP recov soft pin snr erase tool_opt 128 TC('nrf52', None, False, False, False, False, False, False): 129 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase', 130 '--verify', '-f', 'NRF52', '--snr', TEST_DEF_SNR], 131 ['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]), 132 (TEST_DEF_SNR, None)), 133 134 TC('nrf52', None, False, False, True, False, True, False): 135 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF52', 136 '--snr', TEST_DEF_SNR], 137 ['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR], 138 ['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]), 139 (TEST_DEF_SNR, None)), 140 141 TC('nrf52', None, False, False, False, True, False, False): 142 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase', 143 '--verify', '-f', 'NRF52', '--snr', TEST_OVR_SNR], 144 ['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]), 145 (TEST_OVR_SNR, None)), 146 147 TC('nrf52', None, False, True, False, False, False, False): 148 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase', 149 '--verify', '-f', 'NRF52', '--snr', TEST_DEF_SNR], 150 ['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]), 151 (TEST_DEF_SNR, None)), 152 153 TC('nrf52', None, True, False, True, False, False, False): 154 ((['nrfjprog', '--recover', '-f', 'NRF52', '--snr', TEST_DEF_SNR], 155 ['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase', 156 '--verify', '-f', 'NRF52', '--snr', TEST_DEF_SNR], 157 ['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR], 158 ['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]), 159 (TEST_DEF_SNR, None)), 160 161 TC('nrf52', None, True, True, False, True, True, False): 162 ((['nrfjprog', '--recover', '-f', 'NRF52', '--snr', TEST_OVR_SNR], 163 ['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF52', 164 '--snr', TEST_OVR_SNR], 165 ['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]), 166 (TEST_OVR_SNR, None)), 167 168 TC('nrf52', None, True, True, False, True, True, True): 169 ((['nrfjprog', '--recover', '-f', 'NRF52', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L, 170 ['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF52', 171 '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L, 172 ['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L), 173 (TEST_OVR_SNR, None)), 174 175 # ------------------------------------------------------------------------- 176 # NRF53 APP 177 # 178 # family CP recov soft pin snr erase tool_opt 179 TC('nrf53', 'APP', False, False, False, False, False, False): 180 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', 181 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR], 182 ['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]), 183 (TEST_DEF_SNR, None)), 184 185 TC('nrf53', 'APP', False, False, True, False, True, False): 186 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', 187 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR], 188 ['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]), 189 (TEST_DEF_SNR, None)), 190 191 TC('nrf53', 'APP', False, False, False, True, False, False): 192 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', 193 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_OVR_SNR], 194 ['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]), 195 (TEST_OVR_SNR, None)), 196 197 TC('nrf53', 'APP', False, True, False, False, False, False): 198 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', 199 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR], 200 ['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]), 201 (TEST_DEF_SNR, None)), 202 203 TC('nrf53', 'APP', True, False, True, False, False, False): 204 ((['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', 205 '--snr', TEST_DEF_SNR], 206 ['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_DEF_SNR], 207 ['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', 208 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_DEF_SNR], 209 ['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]), 210 (TEST_DEF_SNR, None)), 211 212 TC('nrf53', 'APP', True, True, False, True, True, False): 213 ((['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', 214 '--snr', TEST_OVR_SNR], 215 ['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_OVR_SNR], 216 ['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', 217 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_APPLICATION', '--snr', TEST_OVR_SNR], 218 ['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]), 219 (TEST_OVR_SNR, None)), 220 221 # ------------------------------------------------------------------------- 222 # NRF53 NET 223 # 224 # family CP recov soft pin snr erase tool_opt 225 TC('nrf53', 'NET', False, False, False, False, False, False): 226 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', 227 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR], 228 ['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]), 229 (TEST_DEF_SNR, None)), 230 231 TC('nrf53', 'NET', False, False, True, False, True, False): 232 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', 233 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR], 234 ['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]), 235 (TEST_DEF_SNR, None)), 236 237 TC('nrf53', 'NET', False, False, False, True, False, False): 238 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', 239 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_OVR_SNR], 240 ['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]), 241 (TEST_OVR_SNR, None)), 242 243 TC('nrf53', 'NET', False, True, False, False, False, False): 244 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', 245 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR], 246 ['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]), 247 (TEST_DEF_SNR, None)), 248 249 TC('nrf53', 'NET', True, False, True, False, False, False): 250 ((['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', 251 '--snr', TEST_DEF_SNR], 252 ['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_DEF_SNR], 253 ['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', 254 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_DEF_SNR], 255 ['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]), 256 (TEST_DEF_SNR, None)), 257 258 TC('nrf53', 'NET', True, True, False, True, True, False): 259 ((['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', 260 '--snr', TEST_OVR_SNR], 261 ['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_OVR_SNR], 262 ['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', 263 '--verify', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK', '--snr', TEST_OVR_SNR], 264 ['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]), 265 (TEST_OVR_SNR, None)), 266 267 # ------------------------------------------------------------------------- 268 # NRF91 269 # 270 # family CP recov soft pin snr erase tool_opt 271 TC('nrf91', None, False, False, False, False, False, False): 272 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF91', 273 '--snr', TEST_DEF_SNR], 274 ['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]), 275 (TEST_DEF_SNR, None)), 276 277 TC('nrf91', None, False, False, True, False, True, False): 278 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF91', 279 '--snr', TEST_DEF_SNR], 280 ['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]), 281 (TEST_DEF_SNR, None)), 282 283 TC('nrf91', None, False, False, False, True, False, False): 284 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF91', 285 '--snr', TEST_OVR_SNR], 286 ['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]), 287 (TEST_OVR_SNR, None)), 288 289 TC('nrf91', None, False, True, False, False, False, False): 290 ((['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF91', 291 '--snr', TEST_DEF_SNR], 292 ['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]), 293 (TEST_DEF_SNR, None)), 294 295 TC('nrf91', None, True, False, True, False, False, False): 296 ((['nrfjprog', '--recover', '-f', 'NRF91', '--snr', TEST_DEF_SNR], 297 ['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '--verify', '-f', 'NRF91', 298 '--snr', TEST_DEF_SNR], 299 ['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]), 300 (TEST_DEF_SNR, None)), 301 302 TC('nrf91', None, True, True, False, True, True, False): 303 ((['nrfjprog', '--recover', '-f', 'NRF91', '--snr', TEST_OVR_SNR], 304 ['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF91', 305 '--snr', TEST_OVR_SNR], 306 ['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]), 307 (TEST_OVR_SNR, None)), 308 309 TC('nrf91', None, True, True, False, True, True, True): 310 ((['nrfjprog', '--recover', '-f', 'NRF91', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L, 311 ['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '--verify', '-f', 'NRF91', 312 '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L, 313 ['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_OVR_SNR] + TEST_TOOL_OPT_L), 314 (TEST_OVR_SNR, None)), 315} 316 317# 318# Monkey-patches 319# 320 321def get_board_snr_patch(glob): 322 return TEST_DEF_SNR 323 324def require_patch(cur_tool, program): 325 assert cur_tool == program 326 327os_path_isfile = os.path.isfile 328 329def os_path_isfile_patch(filename): 330 if filename == RC_KERNEL_HEX: 331 return True 332 return os_path_isfile(filename) 333 334# 335# Test functions. 336# 337# These are white box tests that rely on the above monkey-patches. 338# 339 340def id_fn(test_case): 341 if test_case.coprocessor is None: 342 cp = '' 343 else: 344 cp = f'-{test_case.coprocessor}' 345 s = 'soft_reset' if test_case.softreset else 'no_soft_reset' 346 p = 'pin_reset' if test_case.pinreset else 'no_pin_reset' 347 sn = 'default_snr' if test_case.snr else 'override_snr' 348 e = 'chip_erase' if test_case.erase else 'sector[anduicr]_erase' 349 r = 'recover' if test_case.recover else 'no_recover' 350 t = 'tool_opt' if test_case.tool_opt else 'no_tool_opt' 351 352 return f'{test_case.family[:5]}{cp}-{s}-{p}-{sn}-{e}-{r}-{t}' 353 354def fix_up_runner_config(test_case, runner_config, tmpdir): 355 # Helper that adjusts the common runner_config fixture for our 356 # nRF-specific tests. 357 358 to_replace = {} 359 360 # Provide a skeletal zephyr/.config file to use as the runner's 361 # BuildConfiguration. 362 zephyr = tmpdir / 'zephyr' 363 zephyr.mkdir() 364 dotconfig = os.fspath(zephyr / '.config') 365 with open(dotconfig, 'w') as f: 366 f.write(f''' 367CONFIG_SOC_SERIES_{test_case.family.upper()}X=y 368''') 369 if test_case.family == 'nrf53': 370 f.write(f''' 371CONFIG_SOC_NRF5340_CPU{test_case.coprocessor}=y 372''') 373 374 to_replace['build_dir'] = tmpdir 375 376 return runner_config._replace(**to_replace) 377 378def check_expected(tool, test_case, check_fn, get_snr, tmpdir, runner_config): 379 380 expected = EXPECTED_RESULTS[test_case][EXPECTED_MAP[tool]] 381 if tool == 'nrfutil': 382 # Skip the preparation calls for now 383 assert len(check_fn.call_args_list) >= 1 384 xi = len(check_fn.call_args_list) - 1 385 assert len(check_fn.call_args_list[xi].args) == 1 386 # Extract filename 387 nrfutil_args = check_fn.call_args_list[xi].args[0] 388 tmpfile = nrfutil_args[nrfutil_args.index('--batch-path') + 1] 389 cmds = (['nrfutil', '--json', 'device', 'x-execute-batch', '--batch-path', 390 tmpfile, '--serial-number', expected[0]],) 391 call_args = [call(nrfutil_args)] 392 else: 393 cmds = expected 394 call_args = check_fn.call_args_list 395 396 if callable(cmds): 397 assert (call_args == 398 [call(x) for x in cmds(tmpdir, runner_config.hex_file)]) 399 else: 400 assert call_args == [call(x) for x in cmds] 401 402 if not test_case.snr: 403 get_snr.assert_called_once_with('*') 404 else: 405 get_snr.assert_not_called() 406 407@pytest.mark.parametrize('tool', ["nrfjprog","nrfutil"]) 408@pytest.mark.parametrize('test_case', EXPECTED_RESULTS.keys(), ids=id_fn) 409@patch('runners.core.ZephyrBinaryRunner.require') 410@patch('runners.nrfjprog.NrfBinaryRunner.get_board_snr', 411 side_effect=get_board_snr_patch) 412@patch('runners.nrfutil.subprocess.Popen') 413@patch('runners.nrfjprog.NrfBinaryRunner.check_call') 414def test_init(check_call, popen, get_snr, require, tool, test_case, 415 runner_config, tmpdir): 416 popen.return_value.__enter__.return_value.stdout = io.BytesIO(b'') 417 popen.return_value.__enter__.return_value.returncode = 0 418 419 require.side_effect = functools.partial(require_patch, tool) 420 runner_config = fix_up_runner_config(test_case, runner_config, tmpdir) 421 snr = TEST_OVR_SNR if test_case.snr else None 422 tool_opt = TEST_TOOL_OPT_L if test_case.tool_opt else [] 423 cls = CLASS_MAP[tool] 424 runner = cls(runner_config, 425 test_case.family, 426 test_case.softreset, 427 test_case.pinreset, 428 snr, 429 erase=test_case.erase, 430 tool_opt=tool_opt, 431 recover=test_case.recover) 432 433 with patch('os.path.isfile', side_effect=os_path_isfile_patch): 434 runner.run('flash') 435 assert require.called 436 437 CHECK_FN_MAP = {'nrfjprog': check_call, 'nrfutil': popen} 438 check_expected(tool, test_case, CHECK_FN_MAP[tool], get_snr, tmpdir, 439 runner_config) 440 441@pytest.mark.parametrize('tool', ["nrfjprog","nrfutil"]) 442@pytest.mark.parametrize('test_case', EXPECTED_RESULTS.keys(), ids=id_fn) 443@patch('runners.core.ZephyrBinaryRunner.require') 444@patch('runners.nrfjprog.NrfBinaryRunner.get_board_snr', 445 side_effect=get_board_snr_patch) 446@patch('runners.nrfutil.subprocess.Popen') 447@patch('runners.nrfjprog.NrfBinaryRunner.check_call') 448def test_create(check_call, popen, get_snr, require, tool, test_case, 449 runner_config, tmpdir): 450 popen.return_value.__enter__.return_value.stdout = io.BytesIO(b'') 451 popen.return_value.__enter__.return_value.returncode = 0 452 453 require.side_effect = functools.partial(require_patch, tool) 454 runner_config = fix_up_runner_config(test_case, runner_config, tmpdir) 455 456 args = [] 457 if test_case.softreset: 458 args.append('--softreset') 459 if test_case.pinreset: 460 args.append('--pinreset') 461 if test_case.snr: 462 args.extend(['--dev-id', TEST_OVR_SNR]) 463 if test_case.erase: 464 args.append('--erase') 465 if test_case.recover: 466 args.append('--recover') 467 if test_case.tool_opt: 468 args.extend(['--tool-opt', TEST_TOOL_OPT]) 469 470 parser = argparse.ArgumentParser(allow_abbrev=False) 471 cls = CLASS_MAP[tool] 472 cls.add_parser(parser) 473 arg_namespace = parser.parse_args(args) 474 runner = cls.create(runner_config, arg_namespace) 475 with patch('os.path.isfile', side_effect=os_path_isfile_patch): 476 runner.run('flash') 477 478 assert require.called 479 480 CHECK_FN_MAP = {'nrfjprog': check_call, 'nrfutil': popen} 481 check_expected(tool, test_case, CHECK_FN_MAP[tool], get_snr, tmpdir, 482 runner_config) 483