test_dfu_util.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. # Copyright (c) 2018 Foundries.io
  2. # Copyright (c) 2019 Nordic Semiconductor ASA.
  3. #
  4. # SPDX-License-Identifier: Apache-2.0
  5. import argparse
  6. import os
  7. from unittest.mock import patch, call
  8. import pytest
  9. from runners.dfu import DfuUtilBinaryRunner, DfuSeConfig
  10. from conftest import RC_KERNEL_BIN
  11. DFU_UTIL = 'dfu-util'
  12. TEST_EXE = 'test-dfu-util'
  13. TEST_PID = '0000:9999'
  14. TEST_PID_RES = '-d,{}'.format(TEST_PID)
  15. TEST_ALT_INT = '1'
  16. TEST_ALT_STR = 'alt-name'
  17. TEST_BIN_NAME = 'test-img.bin'
  18. TEST_DFUSE_ADDR = 2
  19. TEST_DFUSE_OPTS = 'test-dfuse-opt'
  20. TEST_DCFG_OPT = DfuSeConfig(address=TEST_DFUSE_ADDR, options='test-dfuse-opt')
  21. TEST_DCFG_OPT_RES = '{}:{}'.format(hex(TEST_DFUSE_ADDR), TEST_DFUSE_OPTS)
  22. TEST_DCFG_NOPT = DfuSeConfig(address=TEST_DFUSE_ADDR, options='')
  23. TEST_DCFG_NOPT_RES = '{}:'.format(hex(TEST_DFUSE_ADDR))
  24. # A map from a test case to the expected dfu-util call.
  25. # Test cases are (alt, exe, img, dfuse) tuples.
  26. EXPECTED_COMMAND = {
  27. (DFU_UTIL, TEST_ALT_INT, None, RC_KERNEL_BIN):
  28. [DFU_UTIL, TEST_PID_RES, '-a', TEST_ALT_INT, '-D', RC_KERNEL_BIN],
  29. (DFU_UTIL, TEST_ALT_STR, None, RC_KERNEL_BIN):
  30. [DFU_UTIL, TEST_PID_RES, '-a', TEST_ALT_STR, '-D', RC_KERNEL_BIN],
  31. (TEST_EXE, TEST_ALT_INT, None, RC_KERNEL_BIN):
  32. [TEST_EXE, TEST_PID_RES, '-a', TEST_ALT_INT, '-D', RC_KERNEL_BIN],
  33. (DFU_UTIL, TEST_ALT_INT, None, TEST_BIN_NAME):
  34. [DFU_UTIL, TEST_PID_RES, '-a', TEST_ALT_INT, '-D', TEST_BIN_NAME],
  35. (DFU_UTIL, TEST_ALT_INT, TEST_DCFG_OPT, RC_KERNEL_BIN):
  36. [DFU_UTIL, TEST_PID_RES, '-s', TEST_DCFG_OPT_RES, '-a', TEST_ALT_INT,
  37. '-D', RC_KERNEL_BIN],
  38. (DFU_UTIL, TEST_ALT_INT, TEST_DCFG_NOPT, RC_KERNEL_BIN):
  39. [DFU_UTIL, TEST_PID_RES, '-s', TEST_DCFG_NOPT_RES, '-a', TEST_ALT_INT,
  40. '-D', RC_KERNEL_BIN],
  41. }
  42. def find_device_patch():
  43. return True
  44. def require_patch(program):
  45. assert program in [DFU_UTIL, TEST_EXE]
  46. os_path_isfile = os.path.isfile
  47. def os_path_isfile_patch(filename):
  48. if filename == RC_KERNEL_BIN:
  49. return True
  50. return os_path_isfile(filename)
  51. def id_fn(tc):
  52. return 'exe={},alt={},dfuse_config={},img={}'.format(*tc)
  53. @pytest.mark.parametrize('tc', [
  54. # (exe, alt, dfuse_config, img)
  55. (DFU_UTIL, TEST_ALT_INT, None, RC_KERNEL_BIN),
  56. (DFU_UTIL, TEST_ALT_STR, None, RC_KERNEL_BIN),
  57. (TEST_EXE, TEST_ALT_INT, None, RC_KERNEL_BIN),
  58. (DFU_UTIL, TEST_ALT_INT, None, TEST_BIN_NAME),
  59. (DFU_UTIL, TEST_ALT_INT, TEST_DCFG_OPT, RC_KERNEL_BIN),
  60. (DFU_UTIL, TEST_ALT_INT, TEST_DCFG_NOPT, RC_KERNEL_BIN),
  61. ], ids=id_fn)
  62. @patch('runners.dfu.DfuUtilBinaryRunner.find_device',
  63. side_effect=find_device_patch)
  64. @patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
  65. @patch('runners.core.ZephyrBinaryRunner.check_call')
  66. def test_dfu_util_init(cc, req, find_device, tc, runner_config):
  67. '''Test commands using a runner created by constructor.'''
  68. exe, alt, dfuse_config, img = tc
  69. runner = DfuUtilBinaryRunner(runner_config, TEST_PID, alt, img, exe=exe,
  70. dfuse_config=dfuse_config)
  71. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  72. runner.run('flash')
  73. assert find_device.called
  74. assert req.called_with(exe)
  75. assert cc.call_args_list == [call(EXPECTED_COMMAND[tc])]
  76. def get_flash_address_patch(args, bcfg):
  77. return TEST_DFUSE_ADDR
  78. @pytest.mark.parametrize('tc', [
  79. # arg spec: (exe, alt, dfuse, modifiers, img)
  80. (None, TEST_ALT_INT, False, None, None),
  81. (None, TEST_ALT_STR, False, None, None),
  82. (TEST_EXE, TEST_ALT_INT, False, None, None),
  83. (None, TEST_ALT_INT, False, None, TEST_BIN_NAME),
  84. (None, TEST_ALT_INT, True, TEST_DFUSE_OPTS, None),
  85. (None, TEST_ALT_INT, True, None, None),
  86. ], ids=id_fn)
  87. @patch('runners.dfu.DfuUtilBinaryRunner.find_device',
  88. side_effect=find_device_patch)
  89. @patch('runners.core.ZephyrBinaryRunner.get_flash_address',
  90. side_effect=get_flash_address_patch)
  91. @patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
  92. @patch('runners.core.ZephyrBinaryRunner.check_call')
  93. def test_dfu_util_create(cc, req, gfa, find_device, tc, runner_config, tmpdir):
  94. '''Test commands using a runner created from command line parameters.'''
  95. exe, alt, dfuse, modifiers, img = tc
  96. args = ['--pid', TEST_PID, '--alt', alt]
  97. if img:
  98. args.extend(['--img', img])
  99. if dfuse:
  100. args.append('--dfuse')
  101. if modifiers:
  102. args.extend(['--dfuse-modifiers', modifiers])
  103. else:
  104. args.extend(['--dfuse-modifiers', ''])
  105. if exe:
  106. args.extend(['--dfu-util', exe])
  107. (tmpdir / 'zephyr').mkdir()
  108. with open(os.fspath(tmpdir / 'zephyr' / '.config'), 'w') as f:
  109. f.write('\n')
  110. runner_config = runner_config._replace(build_dir=os.fspath(tmpdir))
  111. parser = argparse.ArgumentParser()
  112. DfuUtilBinaryRunner.add_parser(parser)
  113. arg_namespace = parser.parse_args(args)
  114. runner = DfuUtilBinaryRunner.create(runner_config, arg_namespace)
  115. with patch('os.path.isfile', side_effect=os_path_isfile_patch):
  116. runner.run('flash')
  117. if dfuse:
  118. cfg = DfuSeConfig(address=TEST_DFUSE_ADDR, options=modifiers or '')
  119. else:
  120. cfg = None
  121. map_tc = (exe or DFU_UTIL, alt, cfg, img or RC_KERNEL_BIN)
  122. assert find_device.called
  123. assert req.called_with(exe)
  124. assert cc.call_args_list == [call(EXPECTED_COMMAND[map_tc])]