blob: fca54488374ff54cdc53640e8e1976535367864a [file] [log] [blame]
AKASHI Takahiro615af9a2018-09-11 15:59:19 +09001# SPDX-License-Identifier: GPL-2.0+
2# Copyright (c) 2018, Linaro Limited
3# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
4
5import os
6import os.path
7import pytest
8import re
9from subprocess import call, check_call, check_output, CalledProcessError
10from fstest_defs import *
Alper Nebi Yasak7ff17f22021-06-04 22:04:46 +030011import u_boot_utils as util
Tom Rini50ad0192023-12-09 14:52:46 -050012# pylint: disable=E0611
Simon Glass1d5006c2022-10-29 19:47:05 -060013from tests import fs_helper
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090014
15supported_fs_basic = ['fat16', 'fat32', 'ext4']
Christian Taedckea1fd7352023-11-15 13:44:22 +010016supported_fs_ext = ['fat12', 'fat16', 'fat32']
Christian Taedcke570dc362023-11-15 13:44:24 +010017supported_fs_fat = ['fat12', 'fat16']
Christian Taedckea1fd7352023-11-15 13:44:22 +010018supported_fs_mkdir = ['fat12', 'fat16', 'fat32']
19supported_fs_unlink = ['fat12', 'fat16', 'fat32']
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +010020supported_fs_symlink = ['ext4']
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090021
22#
23# Filesystem test specific setup
24#
25def pytest_addoption(parser):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +090026 """Enable --fs-type option.
27
28 See pytest_configure() about how it works.
29
30 Args:
31 parser: Pytest command-line parser.
32
33 Returns:
34 Nothing.
35 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090036 parser.addoption('--fs-type', action='append', default=None,
37 help='Targeting Filesystem Types')
38
39def pytest_configure(config):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +090040 """Restrict a file system(s) to be tested.
41
42 A file system explicitly named with --fs-type option is selected
43 if it belongs to a default supported_fs_xxx list.
44 Multiple options can be specified.
45
46 Args:
47 config: Pytest configuration.
48
49 Returns:
50 Nothing.
51 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090052 global supported_fs_basic
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +090053 global supported_fs_ext
Christian Taedcke570dc362023-11-15 13:44:24 +010054 global supported_fs_fat
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +090055 global supported_fs_mkdir
Akashi, Takahirod49e7992018-09-11 16:06:03 +090056 global supported_fs_unlink
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +010057 global supported_fs_symlink
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090058
59 def intersect(listA, listB):
60 return [x for x in listA if x in listB]
61
62 supported_fs = config.getoption('fs_type')
63 if supported_fs:
Simon Glasse9f4d872018-12-27 08:11:13 -070064 print('*** FS TYPE modified: %s' % supported_fs)
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090065 supported_fs_basic = intersect(supported_fs, supported_fs_basic)
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +090066 supported_fs_ext = intersect(supported_fs, supported_fs_ext)
Christian Taedcke570dc362023-11-15 13:44:24 +010067 supported_fs_fat = intersect(supported_fs, supported_fs_fat)
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +090068 supported_fs_mkdir = intersect(supported_fs, supported_fs_mkdir)
Akashi, Takahirod49e7992018-09-11 16:06:03 +090069 supported_fs_unlink = intersect(supported_fs, supported_fs_unlink)
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +010070 supported_fs_symlink = intersect(supported_fs, supported_fs_symlink)
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090071
72def pytest_generate_tests(metafunc):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +090073 """Parametrize fixtures, fs_obj_xxx
74
75 Each fixture will be parametrized with a corresponding support_fs_xxx
76 list.
77
78 Args:
79 metafunc: Pytest test function.
80
81 Returns:
82 Nothing.
83 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090084 if 'fs_obj_basic' in metafunc.fixturenames:
85 metafunc.parametrize('fs_obj_basic', supported_fs_basic,
86 indirect=True, scope='module')
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +090087 if 'fs_obj_ext' in metafunc.fixturenames:
88 metafunc.parametrize('fs_obj_ext', supported_fs_ext,
89 indirect=True, scope='module')
Christian Taedcke570dc362023-11-15 13:44:24 +010090 if 'fs_obj_fat' in metafunc.fixturenames:
91 metafunc.parametrize('fs_obj_fat', supported_fs_fat,
92 indirect=True, scope='module')
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +090093 if 'fs_obj_mkdir' in metafunc.fixturenames:
94 metafunc.parametrize('fs_obj_mkdir', supported_fs_mkdir,
95 indirect=True, scope='module')
Akashi, Takahirod49e7992018-09-11 16:06:03 +090096 if 'fs_obj_unlink' in metafunc.fixturenames:
97 metafunc.parametrize('fs_obj_unlink', supported_fs_unlink,
98 indirect=True, scope='module')
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +010099 if 'fs_obj_symlink' in metafunc.fixturenames:
100 metafunc.parametrize('fs_obj_symlink', supported_fs_symlink,
101 indirect=True, scope='module')
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900102
103#
104# Helper functions
105#
106def fstype_to_ubname(fs_type):
Michal Simek50fa1182023-05-17 09:17:16 +0200107 """Convert a file system type to an U-Boot specific string
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900108
109 A generated string can be used as part of file system related commands
110 or a config name in u-boot. Currently fat16 and fat32 are handled
111 specifically.
112
113 Args:
114 fs_type: File system type.
115
116 Return:
117 A corresponding string for file system type.
118 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900119 if re.match('fat', fs_type):
120 return 'fat'
121 else:
122 return fs_type
123
124def check_ubconfig(config, fs_type):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900125 """Check whether a file system is enabled in u-boot configuration.
126
127 This function is assumed to be called in a fixture function so that
128 the whole test cases will be skipped if a given file system is not
129 enabled.
130
131 Args:
132 fs_type: File system type.
133
134 Return:
135 Nothing.
136 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900137 if not config.buildconfig.get('config_cmd_%s' % fs_type, None):
138 pytest.skip('.config feature "CMD_%s" not enabled' % fs_type.upper())
139 if not config.buildconfig.get('config_%s_write' % fs_type, None):
140 pytest.skip('.config feature "%s_WRITE" not enabled'
141 % fs_type.upper())
142
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900143# from test/py/conftest.py
144def tool_is_in_path(tool):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900145 """Check whether a given command is available on host.
146
147 Args:
148 tool: Command name.
149
150 Return:
151 True if available, False if not.
152 """
Simon Glasse9f4d872018-12-27 08:11:13 -0700153 for path in os.environ['PATH'].split(os.pathsep):
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900154 fn = os.path.join(path, tool)
155 if os.path.isfile(fn) and os.access(fn, os.X_OK):
156 return True
157 return False
158
159fuse_mounted = False
160
161def mount_fs(fs_type, device, mount_point):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900162 """Mount a volume.
163
164 Args:
165 fs_type: File system type.
166 device: Volume's file name.
167 mount_point: Mount point.
168
169 Return:
170 Nothing.
171 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900172 global fuse_mounted
173
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900174 try:
Alper Nebi Yasak7ff17f22021-06-04 22:04:46 +0300175 check_call('guestmount --pid-file guestmount.pid -a %s -m /dev/sda %s'
Alper Nebi Yasak3dec7a52021-06-04 22:04:45 +0300176 % (device, mount_point), shell=True)
177 fuse_mounted = True
178 return
179 except CalledProcessError:
180 fuse_mounted = False
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900181
Alper Nebi Yasak3dec7a52021-06-04 22:04:45 +0300182 mount_opt = 'loop,rw'
183 if re.match('fat', fs_type):
184 mount_opt += ',umask=0000'
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900185
Alper Nebi Yasak3dec7a52021-06-04 22:04:45 +0300186 check_call('sudo mount -o %s %s %s'
187 % (mount_opt, device, mount_point), shell=True)
188
189 # may not be effective for some file systems
190 check_call('sudo chmod a+rw %s' % mount_point, shell=True)
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900191
Akashi Takahiro89101f82018-09-27 16:07:22 +0900192def umount_fs(mount_point):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900193 """Unmount a volume.
194
195 Args:
196 mount_point: Mount point.
197
198 Return:
199 Nothing.
200 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900201 if fuse_mounted:
202 call('sync')
203 call('guestunmount %s' % mount_point, shell=True)
Alper Nebi Yasak7ff17f22021-06-04 22:04:46 +0300204
205 try:
206 with open("guestmount.pid", "r") as pidfile:
207 pid = int(pidfile.read())
208 util.waitpid(pid, kill=True)
209 os.remove("guestmount.pid")
210
211 except FileNotFoundError:
212 pass
213
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900214 else:
215 call('sudo umount %s' % mount_point, shell=True)
216
217#
218# Fixture for basic fs test
219# derived from test/fs/fs-test.sh
220#
Tom Rini1b91cee2021-01-28 14:39:56 -0500221@pytest.fixture()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900222def fs_obj_basic(request, u_boot_config):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900223 """Set up a file system to be used in basic fs test.
224
225 Args:
226 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200227 u_boot_config: U-Boot configuration.
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900228
229 Return:
230 A fixture for basic fs test, i.e. a triplet of file system type,
231 volume file name and a list of MD5 hashes.
232 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900233 fs_type = request.param
234 fs_img = ''
235
236 fs_ubtype = fstype_to_ubname(fs_type)
237 check_ubconfig(u_boot_config, fs_ubtype)
238
239 mount_dir = u_boot_config.persistent_data_dir + '/mnt'
240
241 small_file = mount_dir + '/' + SMALL_FILE
242 big_file = mount_dir + '/' + BIG_FILE
243
244 try:
245
246 # 3GiB volume
Simon Glass1d5006c2022-10-29 19:47:05 -0600247 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0xc0000000, '3GB')
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200248 except CalledProcessError as err:
249 pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err))
250 return
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900251
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200252 try:
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900253 check_call('mkdir -p %s' % mount_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200254 except CalledProcessError as err:
255 pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err))
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200256 call('rm -f %s' % fs_img, shell=True)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300257 return
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200258
259 try:
260 # Mount the image so we can populate it.
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900261 mount_fs(fs_type, fs_img, mount_dir)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300262 except CalledProcessError as err:
263 pytest.skip('Mounting to folder failed for filesystem: ' + fs_type + '. {}'.format(err))
264 call('rmdir %s' % mount_dir, shell=True)
265 call('rm -f %s' % fs_img, shell=True)
266 return
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900267
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300268 try:
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900269 # Create a subdirectory.
270 check_call('mkdir %s/SUBDIR' % mount_dir, shell=True)
271
272 # Create big file in this image.
273 # Note that we work only on the start 1MB, couple MBs in the 2GB range
274 # and the last 1 MB of the huge 2.5GB file.
275 # So, just put random values only in those areas.
276 check_call('dd if=/dev/urandom of=%s bs=1M count=1'
277 % big_file, shell=True)
278 check_call('dd if=/dev/urandom of=%s bs=1M count=2 seek=2047'
279 % big_file, shell=True)
280 check_call('dd if=/dev/urandom of=%s bs=1M count=1 seek=2499'
281 % big_file, shell=True)
282
283 # Create a small file in this image.
284 check_call('dd if=/dev/urandom of=%s bs=1M count=1'
285 % small_file, shell=True)
286
287 # Delete the small file copies which possibly are written as part of a
288 # previous test.
289 # check_call('rm -f "%s.w"' % MB1, shell=True)
290 # check_call('rm -f "%s.w2"' % MB1, shell=True)
291
292 # Generate the md5sums of reads that we will test against small file
293 out = check_output(
294 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400295 % small_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900296 md5val = [ out.split()[0] ]
297
298 # Generate the md5sums of reads that we will test against big file
299 # One from beginning of file.
300 out = check_output(
301 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400302 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900303 md5val.append(out.split()[0])
304
305 # One from end of file.
306 out = check_output(
307 'dd if=%s bs=1M skip=2499 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400308 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900309 md5val.append(out.split()[0])
310
311 # One from the last 1MB chunk of 2GB
312 out = check_output(
313 'dd if=%s bs=1M skip=2047 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400314 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900315 md5val.append(out.split()[0])
316
317 # One from the start 1MB chunk from 2GB
318 out = check_output(
319 'dd if=%s bs=1M skip=2048 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400320 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900321 md5val.append(out.split()[0])
322
323 # One 1MB chunk crossing the 2GB boundary
324 out = check_output(
325 'dd if=%s bs=512K skip=4095 count=2 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400326 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900327 md5val.append(out.split()[0])
328
Heinrich Schuchardtbc856172020-04-20 20:48:40 +0200329 except CalledProcessError as err:
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200330 pytest.skip('Setup failed for filesystem: ' + fs_type + '. {}'.format(err))
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300331 umount_fs(mount_dir)
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900332 return
333 else:
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300334 umount_fs(mount_dir)
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900335 yield [fs_ubtype, fs_img, md5val]
336 finally:
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900337 call('rmdir %s' % mount_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200338 call('rm -f %s' % fs_img, shell=True)
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900339
340#
341# Fixture for extended fs test
342#
Tom Rini1b91cee2021-01-28 14:39:56 -0500343@pytest.fixture()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900344def fs_obj_ext(request, u_boot_config):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900345 """Set up a file system to be used in extended fs test.
346
347 Args:
348 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200349 u_boot_config: U-Boot configuration.
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900350
351 Return:
352 A fixture for extended fs test, i.e. a triplet of file system type,
353 volume file name and a list of MD5 hashes.
354 """
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900355 fs_type = request.param
356 fs_img = ''
357
358 fs_ubtype = fstype_to_ubname(fs_type)
359 check_ubconfig(u_boot_config, fs_ubtype)
360
361 mount_dir = u_boot_config.persistent_data_dir + '/mnt'
362
363 min_file = mount_dir + '/' + MIN_FILE
364 tmp_file = mount_dir + '/tmpfile'
365
366 try:
367
368 # 128MiB volume
Simon Glass1d5006c2022-10-29 19:47:05 -0600369 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200370 except CalledProcessError as err:
371 pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err))
372 return
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900373
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200374 try:
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900375 check_call('mkdir -p %s' % mount_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200376 except CalledProcessError as err:
377 pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err))
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200378 call('rm -f %s' % fs_img, shell=True)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300379 return
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200380
381 try:
382 # Mount the image so we can populate it.
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900383 mount_fs(fs_type, fs_img, mount_dir)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300384 except CalledProcessError as err:
385 pytest.skip('Mounting to folder failed for filesystem: ' + fs_type + '. {}'.format(err))
386 call('rmdir %s' % mount_dir, shell=True)
387 call('rm -f %s' % fs_img, shell=True)
388 return
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900389
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300390 try:
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900391 # Create a test directory
392 check_call('mkdir %s/dir1' % mount_dir, shell=True)
393
394 # Create a small file and calculate md5
395 check_call('dd if=/dev/urandom of=%s bs=1K count=20'
396 % min_file, shell=True)
397 out = check_output(
398 'dd if=%s bs=1K 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400399 % min_file, shell=True).decode()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900400 md5val = [ out.split()[0] ]
401
402 # Calculate md5sum of Test Case 4
403 check_call('dd if=%s of=%s bs=1K count=20'
404 % (min_file, tmp_file), shell=True)
405 check_call('dd if=%s of=%s bs=1K seek=5 count=20'
406 % (min_file, tmp_file), shell=True)
407 out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400408 % tmp_file, shell=True).decode()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900409 md5val.append(out.split()[0])
410
411 # Calculate md5sum of Test Case 5
412 check_call('dd if=%s of=%s bs=1K count=20'
413 % (min_file, tmp_file), shell=True)
414 check_call('dd if=%s of=%s bs=1K seek=5 count=5'
415 % (min_file, tmp_file), shell=True)
416 out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400417 % tmp_file, shell=True).decode()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900418 md5val.append(out.split()[0])
419
420 # Calculate md5sum of Test Case 7
421 check_call('dd if=%s of=%s bs=1K count=20'
422 % (min_file, tmp_file), shell=True)
423 check_call('dd if=%s of=%s bs=1K seek=20 count=20'
424 % (min_file, tmp_file), shell=True)
425 out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400426 % tmp_file, shell=True).decode()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900427 md5val.append(out.split()[0])
428
429 check_call('rm %s' % tmp_file, shell=True)
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900430 except CalledProcessError:
431 pytest.skip('Setup failed for filesystem: ' + fs_type)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300432 umount_fs(mount_dir)
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900433 return
434 else:
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300435 umount_fs(mount_dir)
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900436 yield [fs_ubtype, fs_img, md5val]
437 finally:
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900438 call('rmdir %s' % mount_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200439 call('rm -f %s' % fs_img, shell=True)
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900440
441#
442# Fixture for mkdir test
443#
Tom Rini1b91cee2021-01-28 14:39:56 -0500444@pytest.fixture()
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900445def fs_obj_mkdir(request, u_boot_config):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900446 """Set up a file system to be used in mkdir test.
447
448 Args:
449 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200450 u_boot_config: U-Boot configuration.
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900451
452 Return:
453 A fixture for mkdir test, i.e. a duplet of file system type and
454 volume file name.
455 """
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900456 fs_type = request.param
457 fs_img = ''
458
459 fs_ubtype = fstype_to_ubname(fs_type)
460 check_ubconfig(u_boot_config, fs_ubtype)
461
462 try:
463 # 128MiB volume
Simon Glass1d5006c2022-10-29 19:47:05 -0600464 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900465 except:
466 pytest.skip('Setup failed for filesystem: ' + fs_type)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200467 return
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900468 else:
469 yield [fs_ubtype, fs_img]
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200470 call('rm -f %s' % fs_img, shell=True)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900471
472#
473# Fixture for unlink test
474#
Tom Rini1b91cee2021-01-28 14:39:56 -0500475@pytest.fixture()
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900476def fs_obj_unlink(request, u_boot_config):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900477 """Set up a file system to be used in unlink test.
478
479 Args:
480 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200481 u_boot_config: U-Boot configuration.
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900482
483 Return:
484 A fixture for unlink test, i.e. a duplet of file system type and
485 volume file name.
486 """
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900487 fs_type = request.param
488 fs_img = ''
489
490 fs_ubtype = fstype_to_ubname(fs_type)
491 check_ubconfig(u_boot_config, fs_ubtype)
492
493 mount_dir = u_boot_config.persistent_data_dir + '/mnt'
494
495 try:
496
497 # 128MiB volume
Simon Glass1d5006c2022-10-29 19:47:05 -0600498 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200499 except CalledProcessError as err:
500 pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err))
501 return
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900502
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200503 try:
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900504 check_call('mkdir -p %s' % mount_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200505 except CalledProcessError as err:
506 pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err))
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200507 call('rm -f %s' % fs_img, shell=True)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300508 return
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200509
510 try:
511 # Mount the image so we can populate it.
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900512 mount_fs(fs_type, fs_img, mount_dir)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300513 except CalledProcessError as err:
514 pytest.skip('Mounting to folder failed for filesystem: ' + fs_type + '. {}'.format(err))
515 call('rmdir %s' % mount_dir, shell=True)
516 call('rm -f %s' % fs_img, shell=True)
517 return
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900518
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300519 try:
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900520 # Test Case 1 & 3
521 check_call('mkdir %s/dir1' % mount_dir, shell=True)
522 check_call('dd if=/dev/urandom of=%s/dir1/file1 bs=1K count=1'
523 % mount_dir, shell=True)
524 check_call('dd if=/dev/urandom of=%s/dir1/file2 bs=1K count=1'
525 % mount_dir, shell=True)
526
527 # Test Case 2
528 check_call('mkdir %s/dir2' % mount_dir, shell=True)
Tom Rini7f24c192019-10-24 11:59:20 -0400529 for i in range(0, 20):
530 check_call('mkdir %s/dir2/0123456789abcdef%02x'
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900531 % (mount_dir, i), shell=True)
532
533 # Test Case 4
534 check_call('mkdir %s/dir4' % mount_dir, shell=True)
535
536 # Test Case 5, 6 & 7
537 check_call('mkdir %s/dir5' % mount_dir, shell=True)
538 check_call('dd if=/dev/urandom of=%s/dir5/file1 bs=1K count=1'
539 % mount_dir, shell=True)
540
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900541 except CalledProcessError:
542 pytest.skip('Setup failed for filesystem: ' + fs_type)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300543 umount_fs(mount_dir)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900544 return
545 else:
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300546 umount_fs(mount_dir)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900547 yield [fs_ubtype, fs_img]
548 finally:
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900549 call('rmdir %s' % mount_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200550 call('rm -f %s' % fs_img, shell=True)
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100551
552#
553# Fixture for symlink fs test
554#
Tom Rini1b91cee2021-01-28 14:39:56 -0500555@pytest.fixture()
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100556def fs_obj_symlink(request, u_boot_config):
557 """Set up a file system to be used in symlink fs test.
558
559 Args:
560 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200561 u_boot_config: U-Boot configuration.
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100562
563 Return:
564 A fixture for basic fs test, i.e. a triplet of file system type,
565 volume file name and a list of MD5 hashes.
566 """
567 fs_type = request.param
568 fs_img = ''
569
570 fs_ubtype = fstype_to_ubname(fs_type)
571 check_ubconfig(u_boot_config, fs_ubtype)
572
573 mount_dir = u_boot_config.persistent_data_dir + '/mnt'
574
575 small_file = mount_dir + '/' + SMALL_FILE
576 medium_file = mount_dir + '/' + MEDIUM_FILE
577
578 try:
579
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200580 # 1GiB volume
Simon Glass1d5006c2022-10-29 19:47:05 -0600581 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x40000000, '1GB')
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200582 except CalledProcessError as err:
583 pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err))
584 return
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100585
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200586 try:
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100587 check_call('mkdir -p %s' % mount_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200588 except CalledProcessError as err:
589 pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err))
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200590 call('rm -f %s' % fs_img, shell=True)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300591 return
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200592
593 try:
594 # Mount the image so we can populate it.
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100595 mount_fs(fs_type, fs_img, mount_dir)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300596 except CalledProcessError as err:
597 pytest.skip('Mounting to folder failed for filesystem: ' + fs_type + '. {}'.format(err))
598 call('rmdir %s' % mount_dir, shell=True)
599 call('rm -f %s' % fs_img, shell=True)
600 return
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100601
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300602 try:
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100603 # Create a subdirectory.
604 check_call('mkdir %s/SUBDIR' % mount_dir, shell=True)
605
606 # Create a small file in this image.
607 check_call('dd if=/dev/urandom of=%s bs=1M count=1'
608 % small_file, shell=True)
609
610 # Create a medium file in this image.
611 check_call('dd if=/dev/urandom of=%s bs=10M count=1'
612 % medium_file, shell=True)
613
614 # Generate the md5sums of reads that we will test against small file
615 out = check_output(
616 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400617 % small_file, shell=True).decode()
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100618 md5val = [out.split()[0]]
619 out = check_output(
620 'dd if=%s bs=10M skip=0 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400621 % medium_file, shell=True).decode()
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100622 md5val.extend([out.split()[0]])
623
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100624 except CalledProcessError:
625 pytest.skip('Setup failed for filesystem: ' + fs_type)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300626 umount_fs(mount_dir)
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100627 return
628 else:
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300629 umount_fs(mount_dir)
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100630 yield [fs_ubtype, fs_img, md5val]
631 finally:
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100632 call('rmdir %s' % mount_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200633 call('rm -f %s' % fs_img, shell=True)
Christian Taedcke570dc362023-11-15 13:44:24 +0100634
635#
636# Fixture for fat test
637#
638@pytest.fixture()
639def fs_obj_fat(request, u_boot_config):
640 """Set up a file system to be used in fat test.
641
642 Args:
643 request: Pytest request object.
644 u_boot_config: U-Boot configuration.
645
646 Return:
647 A fixture for fat test, i.e. a duplet of file system type and
648 volume file name.
649 """
650
651 # the maximum size of a FAT12 filesystem resulting in 4084 clusters
652 MAX_FAT12_SIZE = 261695 * 1024
653
654 # the minimum size of a FAT16 filesystem that can be created with
655 # mkfs.vfat resulting in 4087 clusters
656 MIN_FAT16_SIZE = 8208 * 1024
657
658 fs_type = request.param
659 fs_img = ''
660
661 fs_ubtype = fstype_to_ubname(fs_type)
662 check_ubconfig(u_boot_config, fs_ubtype)
663
664 fs_size = MAX_FAT12_SIZE if fs_type == 'fat12' else MIN_FAT16_SIZE
665
666 try:
667 # the volume size depends on the filesystem
668 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, fs_size, f'{fs_size}', 1024)
669 except:
670 pytest.skip('Setup failed for filesystem: ' + fs_type)
671 return
672 else:
673 yield [fs_ubtype, fs_img]
674 call('rm -f %s' % fs_img, shell=True)