test_fatfsparse.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. #!/usr/bin/env python
  2. # SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. # SPDX-License-Identifier: Apache-2.0
  4. import os
  5. import shutil
  6. import sys
  7. import unittest
  8. from subprocess import STDOUT, run
  9. from test_utils import compare_folders, fill_sector, generate_local_folder_structure, generate_test_dir_2
  10. sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
  11. import fatfsgen # noqa E402 # pylint: disable=C0413
  12. from fatfs_utils.entry import Entry # noqa E402 # pylint: disable=C0413
  13. class FatFSGen(unittest.TestCase):
  14. def setUp(self) -> None:
  15. os.makedirs('output_data')
  16. generate_test_dir_2()
  17. def tearDown(self) -> None:
  18. shutil.rmtree('output_data', ignore_errors=True)
  19. shutil.rmtree('Espressif', ignore_errors=True)
  20. shutil.rmtree('testf', ignore_errors=True)
  21. shutil.rmtree('testf_wl', ignore_errors=True)
  22. if os.path.exists('fatfs_image.img'):
  23. os.remove('fatfs_image.img')
  24. @staticmethod
  25. def test_gen_parse() -> None:
  26. run([
  27. 'python',
  28. f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}',
  29. 'output_data/tst_str'
  30. ], stderr=STDOUT)
  31. run(['python', '../fatfsgen.py', 'output_data/tst_str'], stderr=STDOUT)
  32. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  33. assert set(os.listdir('Espressif')) == {'TEST', 'TESTFILE'}
  34. with open('Espressif/TESTFILE', 'rb') as in_:
  35. assert in_.read() == b'ahoj\n'
  36. assert set(os.listdir('Espressif/TEST')) == {'TEST', 'TESTFIL2'}
  37. with open('Espressif/TEST/TESTFIL2', 'rb') as in_:
  38. assert in_.read() == b'thisistest\n'
  39. assert set(os.listdir('Espressif/TEST/TEST')) == {'LASTFILE.TXT'}
  40. with open('Espressif/TEST/TEST/LASTFILE.TXT', 'rb') as in_:
  41. assert in_.read() == b'deeptest\n'
  42. @staticmethod
  43. def test_file_chaining() -> None:
  44. fatfs = fatfsgen.FATFS()
  45. fatfs.create_file('WRITEF', extension='TXT')
  46. fatfs.write_content(path_from_root=['WRITEF.TXT'], content=4096 * b'a' + b'a')
  47. fatfs.write_filesystem('fatfs_image.img')
  48. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  49. with open('Espressif/WRITEF.TXT', 'rb') as in_:
  50. assert in_.read() == 4097 * b'a'
  51. @staticmethod
  52. def test_full_two_sectors_folder() -> None:
  53. fatfs = fatfsgen.FATFS(size=2 * 1024 * 1024)
  54. fatfs.create_directory('TESTFOLD')
  55. for i in range((2 * 4096) // 32):
  56. fatfs.create_file(f'A{str(i).upper()}', path_from_root=['TESTFOLD'])
  57. fatfs.write_content(path_from_root=['TESTFOLD', 'A253'], content=b'later')
  58. fatfs.write_content(path_from_root=['TESTFOLD', 'A255'], content=b'last')
  59. fatfs.write_filesystem('fatfs_image.img')
  60. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  61. assert set(os.listdir('Espressif')) == {'TESTFOLD'}
  62. assert set(os.listdir('Espressif/TESTFOLD')) == {f'A{str(i).upper()}' for i in range(256)}
  63. with open('Espressif/TESTFOLD/A253', 'rb') as in_:
  64. assert in_.read() == b'later'
  65. with open('Espressif/TESTFOLD/A255', 'rb') as in_:
  66. assert in_.read() == b'last'
  67. @staticmethod
  68. def test_empty_fat16() -> None:
  69. fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024)
  70. fatfs.write_filesystem('fatfs_image.img')
  71. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  72. @staticmethod
  73. def test_chaining_fat16() -> None:
  74. fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024)
  75. fatfs.create_file('WRITEF', extension='TXT')
  76. fatfs.write_content(path_from_root=['WRITEF.TXT'], content=4096 * b'a' + b'a')
  77. fatfs.write_filesystem('fatfs_image.img')
  78. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  79. with open('Espressif/WRITEF.TXT', 'rb') as in_:
  80. assert in_.read() == 4097 * b'a'
  81. @staticmethod
  82. def test_full_sector_folder_fat16() -> None:
  83. fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024)
  84. fatfs.create_directory('TESTFOLD')
  85. fill_sector(fatfs)
  86. fatfs.write_content(path_from_root=['TESTFOLD', 'A0'], content=b'first')
  87. fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later')
  88. fatfs.write_filesystem('fatfs_image.img')
  89. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  90. assert set(os.listdir('Espressif')) == {'TESTFOLD'}
  91. assert set(os.listdir('Espressif/TESTFOLD')) == {f'A{str(i).upper()}' for i in range(128)}
  92. with open('Espressif/TESTFOLD/A0', 'rb') as in_:
  93. assert in_.read() == b'first'
  94. with open('Espressif/TESTFOLD/A126', 'rb') as in_:
  95. assert in_.read() == b'later'
  96. @staticmethod
  97. def file_(x: str, content_: str = 'hey this is a test') -> dict:
  98. return {
  99. 'type': 'file',
  100. 'name': x,
  101. 'content': content_
  102. }
  103. def test_e2e_file(self) -> None:
  104. struct_: dict = {
  105. 'type': 'folder',
  106. 'name': 'testf',
  107. 'content': [self.file_('NEWF')]
  108. }
  109. generate_local_folder_structure(struct_, path_='.')
  110. run([
  111. 'python',
  112. f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}',
  113. 'testf'
  114. ], stderr=STDOUT)
  115. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  116. assert compare_folders('testf', 'Espressif')
  117. shutil.rmtree('Espressif', ignore_errors=True)
  118. run([
  119. 'python',
  120. f'{os.path.join(os.path.dirname(__file__), "..", "wl_fatfsgen.py")}',
  121. 'testf'
  122. ], stderr=STDOUT)
  123. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  124. assert compare_folders('testf', 'Espressif')
  125. def test_e2e_deeper(self) -> None:
  126. folder_ = {
  127. 'type': 'folder',
  128. 'name': 'XYZ',
  129. 'content': [
  130. self.file_('NEWFLE'),
  131. self.file_('NEW.TXT'),
  132. self.file_('NEWE.TXT'),
  133. self.file_('NEW4.TXT'),
  134. self.file_('NEW5.TXT'),
  135. ]
  136. }
  137. struct_: dict = {
  138. 'type': 'folder',
  139. 'name': 'testf',
  140. 'content': [
  141. self.file_('MY_NEW'),
  142. folder_
  143. ]
  144. }
  145. generate_local_folder_structure(struct_, path_='.')
  146. run([
  147. 'python',
  148. f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}',
  149. 'testf'
  150. ], stderr=STDOUT)
  151. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  152. assert compare_folders('testf', 'Espressif')
  153. shutil.rmtree('Espressif', ignore_errors=True)
  154. run([
  155. 'python',
  156. f'{os.path.join(os.path.dirname(__file__), "..", "wl_fatfsgen.py")}',
  157. 'testf'
  158. ], stderr=STDOUT)
  159. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  160. assert compare_folders('testf', 'Espressif')
  161. def test_e2e_deeper_large(self) -> None:
  162. folder_ = {
  163. 'type': 'folder',
  164. 'name': 'XYZ',
  165. 'content': [
  166. self.file_('NEWFLE', content_=4097 * 'a'),
  167. self.file_('NEW.TXT', content_=2 * 4097 * 'a'),
  168. self.file_('NEWE.TXT'),
  169. self.file_('NEW4.TXT'),
  170. self.file_('NEW5.TXT'),
  171. ]
  172. }
  173. folder2_ = {
  174. 'type': 'folder',
  175. 'name': 'XYZ3',
  176. 'content': [
  177. self.file_('NEWFLE', content_=4097 * 'a'),
  178. self.file_('NEW.TXT', content_=2 * 4097 * 'a'),
  179. self.file_('NEWE.TXT'),
  180. self.file_('NEW4.TXT'),
  181. self.file_('NEW5.TXT'),
  182. ]
  183. }
  184. folder3_ = {
  185. 'type': 'folder',
  186. 'name': 'XYZ2',
  187. 'content': [self.file_(f'A{i}') for i in range(50)]
  188. }
  189. struct_: dict = {
  190. 'type': 'folder',
  191. 'name': 'testf',
  192. 'content': [
  193. self.file_('MY_NEW'),
  194. folder_,
  195. folder2_,
  196. folder3_
  197. ]
  198. }
  199. generate_local_folder_structure(struct_, path_='.')
  200. run([
  201. 'python',
  202. f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}',
  203. 'testf'
  204. ], stderr=STDOUT)
  205. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  206. assert compare_folders('testf', 'Espressif')
  207. shutil.rmtree('Espressif', ignore_errors=True)
  208. run([
  209. 'python',
  210. f'{os.path.join(os.path.dirname(__file__), "..", "wl_fatfsgen.py")}',
  211. 'testf'
  212. ], stderr=STDOUT)
  213. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  214. assert compare_folders('testf', 'Espressif')
  215. def test_e2e_very_deep(self) -> None:
  216. folder_ = {
  217. 'type': 'folder',
  218. 'name': 'XYZ',
  219. 'content': [
  220. self.file_('NEWFLE', content_=4097 * 'a'),
  221. self.file_('NEW.TXT', content_=2 * 4097 * 'a'),
  222. self.file_('NEWE.TXT'),
  223. self.file_('NEW4.TXT'),
  224. self.file_('NEW5.TXT'),
  225. ]
  226. }
  227. folder2_ = {
  228. 'type': 'folder',
  229. 'name': 'XYZ3',
  230. 'content': [
  231. self.file_('NEWFLE', content_=4097 * 'a'),
  232. self.file_('NEW.TXT', content_=2 * 4097 * 'a'),
  233. self.file_('NEWE.TXT'),
  234. self.file_('NEW4.TXT'),
  235. self.file_('NEW5.TXT'),
  236. folder_,
  237. ]
  238. }
  239. folder3_ = {
  240. 'type': 'folder',
  241. 'name': 'XYZ2',
  242. 'content': [self.file_(f'A{i}') for i in range(50)] + [folder2_]
  243. }
  244. struct_: dict = {
  245. 'type': 'folder',
  246. 'name': 'testf',
  247. 'content': [
  248. self.file_('MY_NEW'),
  249. folder_,
  250. folder2_,
  251. folder3_
  252. ]
  253. }
  254. generate_local_folder_structure(struct_, path_='.')
  255. run([
  256. 'python',
  257. f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}',
  258. 'testf'
  259. ], stderr=STDOUT)
  260. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  261. assert compare_folders('testf', 'Espressif')
  262. def test_e2e_very_deep_long(self) -> None:
  263. folder_ = {
  264. 'type': 'folder',
  265. 'name': 'veryveryverylong111',
  266. 'content': [
  267. self.file_('myndewveryverylongfile1.txt', content_=4097 * 'a'),
  268. self.file_('mynewveryverylongfile22.txt', content_=2 * 4097 * 'a'),
  269. self.file_('mynewveryverylongfile333.txt' * 8),
  270. self.file_('mynewveryverylongfile4444.txt' * 8),
  271. self.file_('mynewveryverylongfile5555.txt'),
  272. self.file_('SHORT.TXT'),
  273. ]
  274. }
  275. struct_: dict = {
  276. 'type': 'folder',
  277. 'name': 'testf',
  278. 'content': [
  279. self.file_('mynewveryverylongfile.txt' * 5),
  280. folder_,
  281. ]
  282. }
  283. generate_local_folder_structure(struct_, path_='.')
  284. run([
  285. 'python',
  286. f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}',
  287. 'testf', '--long_name_support'
  288. ], stderr=STDOUT)
  289. run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT)
  290. assert compare_folders('testf', 'Espressif')
  291. def test_parse_long_name(self) -> None:
  292. self.assertEqual(
  293. Entry.parse_entry_long(
  294. b'\x01t\x00h\x00i\x00s\x00_\x00\x0f\x00\xfbi\x00s\x00_\x00l\x00o\x00n\x00\x00\x00g\x00_\x00', 251),
  295. {
  296. 'order': 1,
  297. 'name1': b't\x00h\x00i\x00s\x00_\x00',
  298. 'name2': b'i\x00s\x00_\x00l\x00o\x00n\x00',
  299. 'name3': b'g\x00_\x00',
  300. 'is_last': False
  301. }
  302. )
  303. self.assertEqual(
  304. Entry.parse_entry_long(
  305. b'\x01t\x00h\x00i\x00s\x00_\x00\x0f\x00\xfbi\x00s\x00_\x00l\x00o\x00n\x00\x00\x00g\x00_\x00', 252
  306. ),
  307. {}
  308. )
  309. self.assertEqual(
  310. Entry.parse_entry_long(
  311. b'\x01t\x00h\x00i\x00s\x00_\x00\x0f\x01\xfbi\x00s\x00_\x00l\x00o\x00n\x00\x00\x00g\x00_\x00', 251
  312. ),
  313. {}
  314. )
  315. if __name__ == '__main__':
  316. unittest.main()