test_mkdfu.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright 2020-2021 Espressif Systems (Shanghai) CO LTD
  5. #
  6. # Licensed under the Apache License, Version 2.0 (the "License");
  7. # you may not use this file except in compliance with the License.
  8. # You may obtain a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. from __future__ import unicode_literals
  18. import collections
  19. import filecmp
  20. import json
  21. import os
  22. import shutil
  23. import sys
  24. import tempfile
  25. import time
  26. import unittest
  27. import pexpect
  28. current_dir = os.path.dirname(os.path.realpath(__file__))
  29. mkdfu_path = os.path.join(current_dir, '..', 'mkdfu.py')
  30. class TestMkDFU(unittest.TestCase):
  31. def common_test(self, json_input=None, file_args=[], output_to_compare=None, part_size=None):
  32. '''
  33. - json_input - input JSON file compatible with mkdfu.py - used when not None
  34. - file_args - list of (address, path_to_file) tuples
  35. - output_to_compare - path to the file containing the expected output - tested when not None
  36. - part_size - partition size - used when not None
  37. '''
  38. with tempfile.NamedTemporaryFile(delete=False) as f_out:
  39. self.addCleanup(os.unlink, f_out.name)
  40. args = [mkdfu_path, 'write',
  41. '-o', f_out.name,
  42. '--pid', '2']
  43. if part_size:
  44. args += ['--part-size', str(part_size)]
  45. if json_input:
  46. args += ['--json', json_input]
  47. for addr, f_path in file_args:
  48. args += [str(addr), f_path]
  49. p = pexpect.spawn(sys.executable, args, timeout=10, encoding='utf-8')
  50. self.addCleanup(p.terminate, force=True)
  51. for addr, f_path in sorted(file_args, key=lambda e: e[0]):
  52. p.expect_exact('Adding {} at {}'.format(f_path, hex(addr)))
  53. p.expect_exact('"{}" has been written. You may proceed with DFU flashing.'.format(f_out.name))
  54. # Need to wait for the process to end because the output file is closed when mkdfu exits.
  55. # Do non-blocking wait instead of the blocking p.wait():
  56. for _ in range(10):
  57. if not p.isalive():
  58. break
  59. time.sleep(0.5)
  60. else:
  61. p.terminate()
  62. if output_to_compare:
  63. self.assertTrue(filecmp.cmp(f_out.name, os.path.join(current_dir, output_to_compare)), 'Output files are different')
  64. class TestHelloWorldExample(TestMkDFU):
  65. '''
  66. tests with images prepared in the "1" subdirectory
  67. '''
  68. def test_with_json(self):
  69. with tempfile.NamedTemporaryFile(mode='w', dir=os.path.join(current_dir, '1'), delete=False) as f:
  70. self.addCleanup(os.unlink, f.name)
  71. bins = [('0x1000', '1.bin'), ('0x8000', '2.bin'), ('0x10000', '3.bin')]
  72. json.dump({'flash_files': collections.OrderedDict(bins)}, f)
  73. self.common_test(json_input=f.name, output_to_compare='1/dfu.bin')
  74. def test_without_json(self):
  75. self.common_test(file_args=[(0x1000, '1/1.bin'),
  76. (0x8000, '1/2.bin'),
  77. (0x10000, '1/3.bin')],
  78. output_to_compare='1/dfu.bin')
  79. def test_filenames(self):
  80. temp_dir = tempfile.mkdtemp(prefix='very_long_directory_name' * 8)
  81. self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True)
  82. with tempfile.NamedTemporaryFile(prefix='ľščťžýáíéěř\u0420\u043e\u0441\u0441\u0438\u044f',
  83. dir=temp_dir,
  84. delete=False) as f:
  85. bootloader = f.name
  86. shutil.copyfile(os.path.join(current_dir, '1', '1.bin'), bootloader)
  87. self.common_test(file_args=[(0x1000, bootloader),
  88. (0x8000, os.path.join(current_dir, '1', '2.bin')),
  89. (0x10000, os.path.join(current_dir, '1', '3.bin'))])
  90. class TestSplit(TestMkDFU):
  91. '''
  92. tests with images prepared in the "2" subdirectory
  93. "2/dfu.bin" was prepared with:
  94. mkdfu.py write --part-size 5 --pid 2 -o 2/dfu.bin 0 bin
  95. where the content of "bin" is b"\xce" * 10
  96. '''
  97. def test_split(self):
  98. temp_dir = tempfile.mkdtemp(dir=current_dir)
  99. self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True)
  100. with open(os.path.join(temp_dir, 'bin'), 'wb') as f:
  101. self.addCleanup(os.unlink, f.name)
  102. f.write(b'\xce' * 10)
  103. self.common_test(file_args=[(0, f.name)],
  104. part_size=5,
  105. output_to_compare='2/dfu.bin')
  106. if __name__ == '__main__':
  107. unittest.main()