conftest.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. # SPDX-License-Identifier: GPL-2.0+
  2. # Copyright (c) 2018, Linaro Limited
  3. # Author: Takahiro Akashi <takahiro.akashi@linaro.org>
  4. import os
  5. import os.path
  6. import pytest
  7. import re
  8. from subprocess import call, check_call, check_output, CalledProcessError
  9. from fstest_defs import *
  10. supported_fs_basic = ['fat16', 'fat32', 'ext4']
  11. supported_fs_ext = ['fat16', 'fat32']
  12. #
  13. # Filesystem test specific setup
  14. #
  15. def pytest_addoption(parser):
  16. parser.addoption('--fs-type', action='append', default=None,
  17. help='Targeting Filesystem Types')
  18. def pytest_configure(config):
  19. global supported_fs_basic
  20. global supported_fs_ext
  21. def intersect(listA, listB):
  22. return [x for x in listA if x in listB]
  23. supported_fs = config.getoption('fs_type')
  24. if supported_fs:
  25. print("*** FS TYPE modified: %s" % supported_fs)
  26. supported_fs_basic = intersect(supported_fs, supported_fs_basic)
  27. supported_fs_ext = intersect(supported_fs, supported_fs_ext)
  28. def pytest_generate_tests(metafunc):
  29. if 'fs_obj_basic' in metafunc.fixturenames:
  30. metafunc.parametrize('fs_obj_basic', supported_fs_basic,
  31. indirect=True, scope='module')
  32. if 'fs_obj_ext' in metafunc.fixturenames:
  33. metafunc.parametrize('fs_obj_ext', supported_fs_ext,
  34. indirect=True, scope='module')
  35. #
  36. # Helper functions
  37. #
  38. def fstype_to_ubname(fs_type):
  39. if re.match('fat', fs_type):
  40. return 'fat'
  41. else:
  42. return fs_type
  43. def check_ubconfig(config, fs_type):
  44. if not config.buildconfig.get('config_cmd_%s' % fs_type, None):
  45. pytest.skip('.config feature "CMD_%s" not enabled' % fs_type.upper())
  46. if not config.buildconfig.get('config_%s_write' % fs_type, None):
  47. pytest.skip('.config feature "%s_WRITE" not enabled'
  48. % fs_type.upper())
  49. def mk_fs(config, fs_type, size, id):
  50. fs_img = '%s.%s.img' % (id, fs_type)
  51. fs_img = config.persistent_data_dir + '/' + fs_img
  52. if fs_type == 'fat16':
  53. mkfs_opt = '-F 16'
  54. elif fs_type == 'fat32':
  55. mkfs_opt = '-F 32'
  56. else:
  57. mkfs_opt = ''
  58. if re.match('fat', fs_type):
  59. fs_lnxtype = 'vfat'
  60. else:
  61. fs_lnxtype = fs_type
  62. count = (size + 1048576 - 1) / 1048576
  63. try:
  64. check_call('rm -f %s' % fs_img, shell=True)
  65. check_call('dd if=/dev/zero of=%s bs=1M count=%d'
  66. % (fs_img, count), shell=True)
  67. check_call('mkfs.%s %s %s'
  68. % (fs_lnxtype, mkfs_opt, fs_img), shell=True)
  69. return fs_img
  70. except CalledProcessError:
  71. call('rm -f %s' % fs_img, shell=True)
  72. raise
  73. # from test/py/conftest.py
  74. def tool_is_in_path(tool):
  75. for path in os.environ["PATH"].split(os.pathsep):
  76. fn = os.path.join(path, tool)
  77. if os.path.isfile(fn) and os.access(fn, os.X_OK):
  78. return True
  79. return False
  80. fuse_mounted = False
  81. def mount_fs(fs_type, device, mount_point):
  82. global fuse_mounted
  83. fuse_mounted = False
  84. try:
  85. if tool_is_in_path('guestmount'):
  86. fuse_mounted = True
  87. check_call('guestmount -a %s -m /dev/sda %s'
  88. % (device, mount_point), shell=True)
  89. else:
  90. mount_opt = "loop,rw"
  91. if re.match('fat', fs_type):
  92. mount_opt += ",umask=0000"
  93. check_call('sudo mount -o %s %s %s'
  94. % (mount_opt, device, mount_point), shell=True)
  95. # may not be effective for some file systems
  96. check_call('sudo chmod a+rw %s' % mount_point, shell=True)
  97. except CalledProcessError:
  98. raise
  99. def umount_fs(fs_type, mount_point):
  100. if fuse_mounted:
  101. call('sync')
  102. call('guestunmount %s' % mount_point, shell=True)
  103. else:
  104. call('sudo umount %s' % mount_point, shell=True)
  105. #
  106. # Fixture for basic fs test
  107. # derived from test/fs/fs-test.sh
  108. #
  109. # NOTE: yield_fixture was deprecated since pytest-3.0
  110. @pytest.yield_fixture()
  111. def fs_obj_basic(request, u_boot_config):
  112. fs_type = request.param
  113. fs_img = ''
  114. fs_ubtype = fstype_to_ubname(fs_type)
  115. check_ubconfig(u_boot_config, fs_ubtype)
  116. mount_dir = u_boot_config.persistent_data_dir + '/mnt'
  117. small_file = mount_dir + '/' + SMALL_FILE
  118. big_file = mount_dir + '/' + BIG_FILE
  119. try:
  120. # 3GiB volume
  121. fs_img = mk_fs(u_boot_config, fs_type, 0xc0000000, '3GB')
  122. # Mount the image so we can populate it.
  123. check_call('mkdir -p %s' % mount_dir, shell=True)
  124. mount_fs(fs_type, fs_img, mount_dir)
  125. # Create a subdirectory.
  126. check_call('mkdir %s/SUBDIR' % mount_dir, shell=True)
  127. # Create big file in this image.
  128. # Note that we work only on the start 1MB, couple MBs in the 2GB range
  129. # and the last 1 MB of the huge 2.5GB file.
  130. # So, just put random values only in those areas.
  131. check_call('dd if=/dev/urandom of=%s bs=1M count=1'
  132. % big_file, shell=True)
  133. check_call('dd if=/dev/urandom of=%s bs=1M count=2 seek=2047'
  134. % big_file, shell=True)
  135. check_call('dd if=/dev/urandom of=%s bs=1M count=1 seek=2499'
  136. % big_file, shell=True)
  137. # Create a small file in this image.
  138. check_call('dd if=/dev/urandom of=%s bs=1M count=1'
  139. % small_file, shell=True)
  140. # Delete the small file copies which possibly are written as part of a
  141. # previous test.
  142. # check_call('rm -f "%s.w"' % MB1, shell=True)
  143. # check_call('rm -f "%s.w2"' % MB1, shell=True)
  144. # Generate the md5sums of reads that we will test against small file
  145. out = check_output(
  146. 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
  147. % small_file, shell=True)
  148. md5val = [ out.split()[0] ]
  149. # Generate the md5sums of reads that we will test against big file
  150. # One from beginning of file.
  151. out = check_output(
  152. 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
  153. % big_file, shell=True)
  154. md5val.append(out.split()[0])
  155. # One from end of file.
  156. out = check_output(
  157. 'dd if=%s bs=1M skip=2499 count=1 2> /dev/null | md5sum'
  158. % big_file, shell=True)
  159. md5val.append(out.split()[0])
  160. # One from the last 1MB chunk of 2GB
  161. out = check_output(
  162. 'dd if=%s bs=1M skip=2047 count=1 2> /dev/null | md5sum'
  163. % big_file, shell=True)
  164. md5val.append(out.split()[0])
  165. # One from the start 1MB chunk from 2GB
  166. out = check_output(
  167. 'dd if=%s bs=1M skip=2048 count=1 2> /dev/null | md5sum'
  168. % big_file, shell=True)
  169. md5val.append(out.split()[0])
  170. # One 1MB chunk crossing the 2GB boundary
  171. out = check_output(
  172. 'dd if=%s bs=512K skip=4095 count=2 2> /dev/null | md5sum'
  173. % big_file, shell=True)
  174. md5val.append(out.split()[0])
  175. umount_fs(fs_type, mount_dir)
  176. except CalledProcessError:
  177. pytest.skip('Setup failed for filesystem: ' + fs_type)
  178. return
  179. else:
  180. yield [fs_ubtype, fs_img, md5val]
  181. finally:
  182. umount_fs(fs_type, mount_dir)
  183. call('rmdir %s' % mount_dir, shell=True)
  184. if fs_img:
  185. call('rm -f %s' % fs_img, shell=True)
  186. #
  187. # Fixture for extended fs test
  188. #
  189. # NOTE: yield_fixture was deprecated since pytest-3.0
  190. @pytest.yield_fixture()
  191. def fs_obj_ext(request, u_boot_config):
  192. fs_type = request.param
  193. fs_img = ''
  194. fs_ubtype = fstype_to_ubname(fs_type)
  195. check_ubconfig(u_boot_config, fs_ubtype)
  196. mount_dir = u_boot_config.persistent_data_dir + '/mnt'
  197. min_file = mount_dir + '/' + MIN_FILE
  198. tmp_file = mount_dir + '/tmpfile'
  199. try:
  200. # 128MiB volume
  201. fs_img = mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
  202. # Mount the image so we can populate it.
  203. check_call('mkdir -p %s' % mount_dir, shell=True)
  204. mount_fs(fs_type, fs_img, mount_dir)
  205. # Create a test directory
  206. check_call('mkdir %s/dir1' % mount_dir, shell=True)
  207. # Create a small file and calculate md5
  208. check_call('dd if=/dev/urandom of=%s bs=1K count=20'
  209. % min_file, shell=True)
  210. out = check_output(
  211. 'dd if=%s bs=1K 2> /dev/null | md5sum'
  212. % min_file, shell=True)
  213. md5val = [ out.split()[0] ]
  214. # Calculate md5sum of Test Case 4
  215. check_call('dd if=%s of=%s bs=1K count=20'
  216. % (min_file, tmp_file), shell=True)
  217. check_call('dd if=%s of=%s bs=1K seek=5 count=20'
  218. % (min_file, tmp_file), shell=True)
  219. out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
  220. % tmp_file, shell=True)
  221. md5val.append(out.split()[0])
  222. # Calculate md5sum of Test Case 5
  223. check_call('dd if=%s of=%s bs=1K count=20'
  224. % (min_file, tmp_file), shell=True)
  225. check_call('dd if=%s of=%s bs=1K seek=5 count=5'
  226. % (min_file, tmp_file), shell=True)
  227. out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
  228. % tmp_file, shell=True)
  229. md5val.append(out.split()[0])
  230. # Calculate md5sum of Test Case 7
  231. check_call('dd if=%s of=%s bs=1K count=20'
  232. % (min_file, tmp_file), shell=True)
  233. check_call('dd if=%s of=%s bs=1K seek=20 count=20'
  234. % (min_file, tmp_file), shell=True)
  235. out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
  236. % tmp_file, shell=True)
  237. md5val.append(out.split()[0])
  238. check_call('rm %s' % tmp_file, shell=True)
  239. umount_fs(fs_type, mount_dir)
  240. except CalledProcessError:
  241. pytest.skip('Setup failed for filesystem: ' + fs_type)
  242. return
  243. else:
  244. yield [fs_ubtype, fs_img, md5val]
  245. finally:
  246. umount_fs(fs_type, mount_dir)
  247. call('rmdir %s' % mount_dir, shell=True)
  248. if fs_img:
  249. call('rm -f %s' % fs_img, shell=True)