blob: c73fb4abbcbfcb81b10513020d8d871d6a668ec6 [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 *
Tom Rini50ad0192023-12-09 14:52:46 -050011# pylint: disable=E0611
Simon Glass1d5006c2022-10-29 19:47:05 -060012from tests import fs_helper
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090013
Marek Vasut60b83672025-03-17 04:12:50 +010014supported_fs_basic = ['fat16', 'fat32', 'exfat', 'ext4', 'fs_generic']
15supported_fs_ext = ['fat12', 'fat16', 'fat32', 'exfat', 'fs_generic']
Christian Taedcke570dc362023-11-15 13:44:24 +010016supported_fs_fat = ['fat12', 'fat16']
Marek Vasut60b83672025-03-17 04:12:50 +010017supported_fs_mkdir = ['fat12', 'fat16', 'fat32', 'exfat', 'fs_generic']
18supported_fs_unlink = ['fat12', 'fat16', 'fat32', 'exfat', 'fs_generic']
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +010019supported_fs_symlink = ['ext4']
Gabriel Dalimonte4b93d6e2025-02-17 13:26:44 -050020supported_fs_rename = ['fat12', 'fat16', 'fat32']
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
Gabriel Dalimonte4b93d6e2025-02-17 13:26:44 -050058 global supported_fs_rename
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090059
60 def intersect(listA, listB):
61 return [x for x in listA if x in listB]
62
63 supported_fs = config.getoption('fs_type')
64 if supported_fs:
Simon Glasse9f4d872018-12-27 08:11:13 -070065 print('*** FS TYPE modified: %s' % supported_fs)
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090066 supported_fs_basic = intersect(supported_fs, supported_fs_basic)
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +090067 supported_fs_ext = intersect(supported_fs, supported_fs_ext)
Christian Taedcke570dc362023-11-15 13:44:24 +010068 supported_fs_fat = intersect(supported_fs, supported_fs_fat)
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +090069 supported_fs_mkdir = intersect(supported_fs, supported_fs_mkdir)
Akashi, Takahirod49e7992018-09-11 16:06:03 +090070 supported_fs_unlink = intersect(supported_fs, supported_fs_unlink)
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +010071 supported_fs_symlink = intersect(supported_fs, supported_fs_symlink)
Gabriel Dalimonte4b93d6e2025-02-17 13:26:44 -050072 supported_fs_rename = intersect(supported_fs, supported_fs_rename)
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090073
74def pytest_generate_tests(metafunc):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +090075 """Parametrize fixtures, fs_obj_xxx
76
77 Each fixture will be parametrized with a corresponding support_fs_xxx
78 list.
79
80 Args:
81 metafunc: Pytest test function.
82
83 Returns:
84 Nothing.
85 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +090086 if 'fs_obj_basic' in metafunc.fixturenames:
87 metafunc.parametrize('fs_obj_basic', supported_fs_basic,
88 indirect=True, scope='module')
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +090089 if 'fs_obj_ext' in metafunc.fixturenames:
90 metafunc.parametrize('fs_obj_ext', supported_fs_ext,
91 indirect=True, scope='module')
Christian Taedcke570dc362023-11-15 13:44:24 +010092 if 'fs_obj_fat' in metafunc.fixturenames:
93 metafunc.parametrize('fs_obj_fat', supported_fs_fat,
94 indirect=True, scope='module')
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +090095 if 'fs_obj_mkdir' in metafunc.fixturenames:
96 metafunc.parametrize('fs_obj_mkdir', supported_fs_mkdir,
97 indirect=True, scope='module')
Akashi, Takahirod49e7992018-09-11 16:06:03 +090098 if 'fs_obj_unlink' in metafunc.fixturenames:
99 metafunc.parametrize('fs_obj_unlink', supported_fs_unlink,
100 indirect=True, scope='module')
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100101 if 'fs_obj_symlink' in metafunc.fixturenames:
102 metafunc.parametrize('fs_obj_symlink', supported_fs_symlink,
103 indirect=True, scope='module')
Gabriel Dalimonte4b93d6e2025-02-17 13:26:44 -0500104 if 'fs_obj_rename' in metafunc.fixturenames:
105 metafunc.parametrize('fs_obj_rename', supported_fs_rename,
106 indirect=True, scope='module')
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900107
108#
109# Helper functions
110#
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100111def fstype_to_prefix(fs_type):
112 """Convert a file system type to an U-Boot command prefix
113
114 Args:
115 fs_type: File system type.
116
117 Return:
118 A corresponding command prefix for file system type.
119 """
Marek Vasut60b83672025-03-17 04:12:50 +0100120 if fs_type == 'fs_generic' or fs_type == 'exfat':
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100121 return ''
122 elif re.match('fat', fs_type):
123 return 'fat'
124 else:
125 return fs_type
126
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900127def fstype_to_ubname(fs_type):
Michal Simek50fa1182023-05-17 09:17:16 +0200128 """Convert a file system type to an U-Boot specific string
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900129
130 A generated string can be used as part of file system related commands
131 or a config name in u-boot. Currently fat16 and fat32 are handled
132 specifically.
133
134 Args:
135 fs_type: File system type.
136
137 Return:
138 A corresponding string for file system type.
139 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900140 if re.match('fat', fs_type):
141 return 'fat'
142 else:
143 return fs_type
144
145def check_ubconfig(config, fs_type):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900146 """Check whether a file system is enabled in u-boot configuration.
147
148 This function is assumed to be called in a fixture function so that
149 the whole test cases will be skipped if a given file system is not
150 enabled.
151
152 Args:
153 fs_type: File system type.
154
155 Return:
156 Nothing.
157 """
Marek Vasut60b83672025-03-17 04:12:50 +0100158 if fs_type == 'exfat' and not config.buildconfig.get('config_fs_%s' % fs_type, None):
159 pytest.skip('.config feature "FS_%s" not enabled' % fs_type.upper())
160 if fs_type != 'exfat' and not config.buildconfig.get('config_cmd_%s' % fs_type, None):
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900161 pytest.skip('.config feature "CMD_%s" not enabled' % fs_type.upper())
Marek Vasut60b83672025-03-17 04:12:50 +0100162 if fs_type == 'fs_generic' or fs_type == 'exfat':
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100163 return
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900164 if not config.buildconfig.get('config_%s_write' % fs_type, None):
165 pytest.skip('.config feature "%s_WRITE" not enabled'
166 % fs_type.upper())
167
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900168# from test/py/conftest.py
169def tool_is_in_path(tool):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900170 """Check whether a given command is available on host.
171
172 Args:
173 tool: Command name.
174
175 Return:
176 True if available, False if not.
177 """
Simon Glasse9f4d872018-12-27 08:11:13 -0700178 for path in os.environ['PATH'].split(os.pathsep):
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900179 fn = os.path.join(path, tool)
180 if os.path.isfile(fn) and os.access(fn, os.X_OK):
181 return True
182 return False
183
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900184#
185# Fixture for basic fs test
186# derived from test/fs/fs-test.sh
187#
Tom Rini1b91cee2021-01-28 14:39:56 -0500188@pytest.fixture()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900189def fs_obj_basic(request, u_boot_config):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900190 """Set up a file system to be used in basic fs test.
191
192 Args:
193 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200194 u_boot_config: U-Boot configuration.
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900195
196 Return:
197 A fixture for basic fs test, i.e. a triplet of file system type,
198 volume file name and a list of MD5 hashes.
199 """
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900200 fs_type = request.param
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100201 fs_cmd_prefix = fstype_to_prefix(fs_type)
Marek Vasut60b83672025-03-17 04:12:50 +0100202 fs_cmd_write = 'save' if fs_type == 'fs_generic' or fs_type == 'exfat' else 'write'
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900203 fs_img = ''
204
205 fs_ubtype = fstype_to_ubname(fs_type)
206 check_ubconfig(u_boot_config, fs_ubtype)
207
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700208 scratch_dir = u_boot_config.persistent_data_dir + '/scratch'
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900209
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700210 small_file = scratch_dir + '/' + SMALL_FILE
211 big_file = scratch_dir + '/' + BIG_FILE
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900212
213 try:
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700214 check_call('mkdir -p %s' % scratch_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200215 except CalledProcessError as err:
216 pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err))
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200217 call('rm -f %s' % fs_img, shell=True)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300218 return
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200219
220 try:
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900221 # Create a subdirectory.
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700222 check_call('mkdir %s/SUBDIR' % scratch_dir, shell=True)
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900223
224 # Create big file in this image.
225 # Note that we work only on the start 1MB, couple MBs in the 2GB range
226 # and the last 1 MB of the huge 2.5GB file.
227 # So, just put random values only in those areas.
228 check_call('dd if=/dev/urandom of=%s bs=1M count=1'
229 % big_file, shell=True)
230 check_call('dd if=/dev/urandom of=%s bs=1M count=2 seek=2047'
231 % big_file, shell=True)
232 check_call('dd if=/dev/urandom of=%s bs=1M count=1 seek=2499'
233 % big_file, shell=True)
234
235 # Create a small file in this image.
236 check_call('dd if=/dev/urandom of=%s bs=1M count=1'
237 % small_file, shell=True)
238
239 # Delete the small file copies which possibly are written as part of a
240 # previous test.
241 # check_call('rm -f "%s.w"' % MB1, shell=True)
242 # check_call('rm -f "%s.w2"' % MB1, shell=True)
243
244 # Generate the md5sums of reads that we will test against small file
245 out = check_output(
246 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400247 % small_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900248 md5val = [ out.split()[0] ]
249
250 # Generate the md5sums of reads that we will test against big file
251 # One from beginning of file.
252 out = check_output(
253 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400254 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900255 md5val.append(out.split()[0])
256
257 # One from end of file.
258 out = check_output(
259 'dd if=%s bs=1M skip=2499 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400260 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900261 md5val.append(out.split()[0])
262
263 # One from the last 1MB chunk of 2GB
264 out = check_output(
265 'dd if=%s bs=1M skip=2047 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400266 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900267 md5val.append(out.split()[0])
268
269 # One from the start 1MB chunk from 2GB
270 out = check_output(
271 'dd if=%s bs=1M skip=2048 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400272 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900273 md5val.append(out.split()[0])
274
275 # One 1MB chunk crossing the 2GB boundary
276 out = check_output(
277 'dd if=%s bs=512K skip=4095 count=2 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400278 % big_file, shell=True).decode()
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900279 md5val.append(out.split()[0])
280
Richard Weinberger41eca322024-11-21 15:32:07 -0700281 try:
282 # 3GiB volume
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700283 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0xc0000000, '3GB', scratch_dir)
Richard Weinberger41eca322024-11-21 15:32:07 -0700284 except CalledProcessError as err:
285 pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err))
286 return
287
Heinrich Schuchardtbc856172020-04-20 20:48:40 +0200288 except CalledProcessError as err:
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200289 pytest.skip('Setup failed for filesystem: ' + fs_type + '. {}'.format(err))
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900290 return
291 else:
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100292 yield [fs_ubtype, fs_cmd_prefix, fs_cmd_write, fs_img, md5val]
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900293 finally:
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700294 call('rm -rf %s' % scratch_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200295 call('rm -f %s' % fs_img, shell=True)
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900296
297#
298# Fixture for extended fs test
299#
Tom Rini1b91cee2021-01-28 14:39:56 -0500300@pytest.fixture()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900301def fs_obj_ext(request, u_boot_config):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900302 """Set up a file system to be used in extended fs test.
303
304 Args:
305 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200306 u_boot_config: U-Boot configuration.
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900307
308 Return:
309 A fixture for extended fs test, i.e. a triplet of file system type,
310 volume file name and a list of MD5 hashes.
311 """
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900312 fs_type = request.param
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100313 fs_cmd_prefix = fstype_to_prefix(fs_type)
Marek Vasut60b83672025-03-17 04:12:50 +0100314 fs_cmd_write = 'save' if fs_type == 'fs_generic' or fs_type == 'exfat' else 'write'
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900315 fs_img = ''
316
317 fs_ubtype = fstype_to_ubname(fs_type)
318 check_ubconfig(u_boot_config, fs_ubtype)
319
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700320 scratch_dir = u_boot_config.persistent_data_dir + '/scratch'
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900321
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700322 min_file = scratch_dir + '/' + MIN_FILE
323 tmp_file = scratch_dir + '/tmpfile'
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900324
325 try:
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700326 check_call('mkdir -p %s' % scratch_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200327 except CalledProcessError as err:
328 pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err))
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200329 call('rm -f %s' % fs_img, shell=True)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300330 return
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200331
332 try:
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900333 # Create a test directory
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700334 check_call('mkdir %s/dir1' % scratch_dir, shell=True)
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900335
336 # Create a small file and calculate md5
337 check_call('dd if=/dev/urandom of=%s bs=1K count=20'
338 % min_file, shell=True)
339 out = check_output(
340 'dd if=%s bs=1K 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400341 % min_file, shell=True).decode()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900342 md5val = [ out.split()[0] ]
343
344 # Calculate md5sum of Test Case 4
345 check_call('dd if=%s of=%s bs=1K count=20'
346 % (min_file, tmp_file), shell=True)
347 check_call('dd if=%s of=%s bs=1K seek=5 count=20'
348 % (min_file, tmp_file), shell=True)
349 out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400350 % tmp_file, shell=True).decode()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900351 md5val.append(out.split()[0])
352
353 # Calculate md5sum of Test Case 5
354 check_call('dd if=%s of=%s bs=1K count=20'
355 % (min_file, tmp_file), shell=True)
356 check_call('dd if=%s of=%s bs=1K seek=5 count=5'
357 % (min_file, tmp_file), shell=True)
358 out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400359 % tmp_file, shell=True).decode()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900360 md5val.append(out.split()[0])
361
362 # Calculate md5sum of Test Case 7
363 check_call('dd if=%s of=%s bs=1K count=20'
364 % (min_file, tmp_file), shell=True)
365 check_call('dd if=%s of=%s bs=1K seek=20 count=20'
366 % (min_file, tmp_file), shell=True)
367 out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400368 % tmp_file, shell=True).decode()
AKASHI Takahirodde5d3f2018-09-11 15:59:20 +0900369 md5val.append(out.split()[0])
370
371 check_call('rm %s' % tmp_file, shell=True)
Richard Weinberger41eca322024-11-21 15:32:07 -0700372
373 try:
374 # 128MiB volume
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700375 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB', scratch_dir)
Richard Weinberger41eca322024-11-21 15:32:07 -0700376 except CalledProcessError as err:
377 pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err))
378 return
379
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900380 except CalledProcessError:
381 pytest.skip('Setup failed for filesystem: ' + fs_type)
382 return
383 else:
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100384 yield [fs_ubtype, fs_cmd_prefix, fs_cmd_write, fs_img, md5val]
AKASHI Takahiro615af9a2018-09-11 15:59:19 +0900385 finally:
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700386 call('rm -rf %s' % scratch_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200387 call('rm -f %s' % fs_img, shell=True)
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900388
389#
390# Fixture for mkdir test
391#
Tom Rini1b91cee2021-01-28 14:39:56 -0500392@pytest.fixture()
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900393def fs_obj_mkdir(request, u_boot_config):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900394 """Set up a file system to be used in mkdir test.
395
396 Args:
397 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200398 u_boot_config: U-Boot configuration.
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900399
400 Return:
401 A fixture for mkdir test, i.e. a duplet of file system type and
402 volume file name.
403 """
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900404 fs_type = request.param
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100405 fs_cmd_prefix = fstype_to_prefix(fs_type)
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900406 fs_img = ''
407
408 fs_ubtype = fstype_to_ubname(fs_type)
409 check_ubconfig(u_boot_config, fs_ubtype)
410
411 try:
412 # 128MiB volume
Richard Weinberger41eca322024-11-21 15:32:07 -0700413 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB', None)
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900414 except:
415 pytest.skip('Setup failed for filesystem: ' + fs_type)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200416 return
AKASHI Takahiro1e90c2c2018-09-11 15:59:21 +0900417 else:
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100418 yield [fs_ubtype, fs_cmd_prefix, fs_img]
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200419 call('rm -f %s' % fs_img, shell=True)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900420
421#
422# Fixture for unlink test
423#
Tom Rini1b91cee2021-01-28 14:39:56 -0500424@pytest.fixture()
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900425def fs_obj_unlink(request, u_boot_config):
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900426 """Set up a file system to be used in unlink test.
427
428 Args:
429 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200430 u_boot_config: U-Boot configuration.
Akashi Takahirobcdd1f22018-09-27 16:07:23 +0900431
432 Return:
433 A fixture for unlink test, i.e. a duplet of file system type and
434 volume file name.
435 """
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900436 fs_type = request.param
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100437 fs_cmd_prefix = fstype_to_prefix(fs_type)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900438 fs_img = ''
439
440 fs_ubtype = fstype_to_ubname(fs_type)
441 check_ubconfig(u_boot_config, fs_ubtype)
442
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700443 scratch_dir = u_boot_config.persistent_data_dir + '/scratch'
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900444
445 try:
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700446 check_call('mkdir -p %s' % scratch_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200447 except CalledProcessError as err:
448 pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err))
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200449 call('rm -f %s' % fs_img, shell=True)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300450 return
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200451
452 try:
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900453 # Test Case 1 & 3
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700454 check_call('mkdir %s/dir1' % scratch_dir, shell=True)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900455 check_call('dd if=/dev/urandom of=%s/dir1/file1 bs=1K count=1'
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700456 % scratch_dir, shell=True)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900457 check_call('dd if=/dev/urandom of=%s/dir1/file2 bs=1K count=1'
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700458 % scratch_dir, shell=True)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900459
460 # Test Case 2
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700461 check_call('mkdir %s/dir2' % scratch_dir, shell=True)
Tom Rini7f24c192019-10-24 11:59:20 -0400462 for i in range(0, 20):
463 check_call('mkdir %s/dir2/0123456789abcdef%02x'
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700464 % (scratch_dir, i), shell=True)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900465
466 # Test Case 4
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700467 check_call('mkdir %s/dir4' % scratch_dir, shell=True)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900468
469 # Test Case 5, 6 & 7
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700470 check_call('mkdir %s/dir5' % scratch_dir, shell=True)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900471 check_call('dd if=/dev/urandom of=%s/dir5/file1 bs=1K count=1'
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700472 % scratch_dir, shell=True)
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900473
Richard Weinberger41eca322024-11-21 15:32:07 -0700474 try:
475 # 128MiB volume
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700476 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB', scratch_dir)
Richard Weinberger41eca322024-11-21 15:32:07 -0700477 except CalledProcessError as err:
478 pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err))
479 return
480
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900481 except CalledProcessError:
482 pytest.skip('Setup failed for filesystem: ' + fs_type)
483 return
484 else:
Marek Vasut8d3fb2b2025-03-17 04:12:42 +0100485 yield [fs_ubtype, fs_cmd_prefix, fs_img]
Akashi, Takahirod49e7992018-09-11 16:06:03 +0900486 finally:
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700487 call('rm -rf %s' % scratch_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200488 call('rm -f %s' % fs_img, shell=True)
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100489
490#
491# Fixture for symlink fs test
492#
Tom Rini1b91cee2021-01-28 14:39:56 -0500493@pytest.fixture()
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100494def fs_obj_symlink(request, u_boot_config):
495 """Set up a file system to be used in symlink fs test.
496
497 Args:
498 request: Pytest request object.
Michal Simek50fa1182023-05-17 09:17:16 +0200499 u_boot_config: U-Boot configuration.
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100500
501 Return:
502 A fixture for basic fs test, i.e. a triplet of file system type,
503 volume file name and a list of MD5 hashes.
504 """
505 fs_type = request.param
506 fs_img = ''
507
508 fs_ubtype = fstype_to_ubname(fs_type)
509 check_ubconfig(u_boot_config, fs_ubtype)
510
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700511 scratch_dir = u_boot_config.persistent_data_dir + '/scratch'
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100512
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700513 small_file = scratch_dir + '/' + SMALL_FILE
514 medium_file = scratch_dir + '/' + MEDIUM_FILE
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100515
516 try:
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700517 check_call('mkdir -p %s' % scratch_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200518 except CalledProcessError as err:
519 pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err))
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200520 call('rm -f %s' % fs_img, shell=True)
Alper Nebi Yasak46132c22021-05-20 22:09:46 +0300521 return
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200522
523 try:
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100524 # Create a subdirectory.
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700525 check_call('mkdir %s/SUBDIR' % scratch_dir, shell=True)
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100526
527 # Create a small file in this image.
528 check_call('dd if=/dev/urandom of=%s bs=1M count=1'
529 % small_file, shell=True)
530
531 # Create a medium file in this image.
532 check_call('dd if=/dev/urandom of=%s bs=10M count=1'
533 % medium_file, shell=True)
534
535 # Generate the md5sums of reads that we will test against small file
536 out = check_output(
537 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400538 % small_file, shell=True).decode()
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100539 md5val = [out.split()[0]]
540 out = check_output(
541 'dd if=%s bs=10M skip=0 count=1 2> /dev/null | md5sum'
Tom Rini784e27d2019-10-24 11:59:24 -0400542 % medium_file, shell=True).decode()
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100543 md5val.extend([out.split()[0]])
544
Richard Weinberger41eca322024-11-21 15:32:07 -0700545 try:
546 # 1GiB volume
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700547 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x40000000, '1GB', scratch_dir)
Richard Weinberger41eca322024-11-21 15:32:07 -0700548 except CalledProcessError as err:
549 pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err))
550 return
551
Jean-Jacques Hiblot8aea8a62019-02-13 12:15:27 +0100552 except CalledProcessError:
553 pytest.skip('Setup failed for filesystem: ' + fs_type)
554 return
555 else:
556 yield [fs_ubtype, fs_img, md5val]
557 finally:
Richard Weinbergerba878ce2024-11-21 15:32:08 -0700558 call('rm -rf %s' % scratch_dir, shell=True)
Andy Shevchenkoe70ed8c2021-02-11 16:40:12 +0200559 call('rm -f %s' % fs_img, shell=True)
Christian Taedcke570dc362023-11-15 13:44:24 +0100560
561#
Gabriel Dalimonte4b93d6e2025-02-17 13:26:44 -0500562# Fixture for rename test
563#
564@pytest.fixture()
565def fs_obj_rename(request, u_boot_config):
566 """Set up a file system to be used in rename tests.
567
568 Args:
569 request: Pytest request object.
570 u_boot_config: U-Boot configuration.
571
572 Return:
573 A fixture for rename tests, i.e. a triplet of file system type,
574 volume file name, and dictionary of test identifier and md5val.
575 """
576 def new_rand_file(path):
577 check_call('dd if=/dev/urandom of=%s bs=1K count=1' % path, shell=True)
578
579 def file_hash(path):
580 out = check_output(
581 'dd if=%s bs=1K skip=0 count=1 2> /dev/null | md5sum' % path,
582 shell=True
583 )
584 return out.decode().split()[0]
585
586 fs_type = request.param
587 fs_img = ''
588
589 fs_ubtype = fstype_to_ubname(fs_type)
590 check_ubconfig(u_boot_config, fs_ubtype)
591
592 mount_dir = u_boot_config.persistent_data_dir + '/scratch'
593
594 try:
595 check_call('mkdir -p %s' % mount_dir, shell=True)
596 except CalledProcessError as err:
597 pytest.skip('Preparing mount folder failed for filesystem: ' + fs_type + '. {}'.format(err))
598 call('rm -f %s' % fs_img, shell=True)
599 return
600
601 try:
602 md5val = {}
603 # Test Case 1
604 check_call('mkdir %s/test1' % mount_dir, shell=True)
605 new_rand_file('%s/test1/file1' % mount_dir)
606 md5val['test1'] = file_hash('%s/test1/file1' % mount_dir)
607
608 # Test Case 2
609 check_call('mkdir %s/test2' % mount_dir, shell=True)
610 new_rand_file('%s/test2/file1' % mount_dir)
611 new_rand_file('%s/test2/file_exist' % mount_dir)
612 md5val['test2'] = file_hash('%s/test2/file1' % mount_dir)
613
614 # Test Case 3
615 check_call('mkdir -p %s/test3/dir1' % mount_dir, shell=True)
616 new_rand_file('%s/test3/dir1/file1' % mount_dir)
617 md5val['test3'] = file_hash('%s/test3/dir1/file1' % mount_dir)
618
619 # Test Case 4
620 check_call('mkdir -p %s/test4/dir1' % mount_dir, shell=True)
621 check_call('mkdir -p %s/test4/dir2/dir1' % mount_dir, shell=True)
622 new_rand_file('%s/test4/dir1/file1' % mount_dir)
623 md5val['test4'] = file_hash('%s/test4/dir1/file1' % mount_dir)
624
625 # Test Case 5
626 check_call('mkdir -p %s/test5/dir1' % mount_dir, shell=True)
627 new_rand_file('%s/test5/file2' % mount_dir)
628 md5val['test5'] = file_hash('%s/test5/file2' % mount_dir)
629
630 # Test Case 6
631 check_call('mkdir -p %s/test6/dir2/existing' % mount_dir, shell=True)
632 new_rand_file('%s/test6/existing' % mount_dir)
633 md5val['test6'] = file_hash('%s/test6/existing' % mount_dir)
634
635 # Test Case 7
636 check_call('mkdir -p %s/test7/dir1' % mount_dir, shell=True)
637 check_call('mkdir -p %s/test7/dir2/dir1' % mount_dir, shell=True)
638 new_rand_file('%s/test7/dir2/dir1/file1' % mount_dir)
639 md5val['test7'] = file_hash('%s/test7/dir2/dir1/file1' % mount_dir)
640
641 # Test Case 8
642 check_call('mkdir -p %s/test8/dir1' % mount_dir, shell=True)
643 new_rand_file('%s/test8/dir1/file1' % mount_dir)
644 md5val['test8'] = file_hash('%s/test8/dir1/file1' % mount_dir)
645
646 # Test Case 9
647 check_call('mkdir -p %s/test9/dir1/nested/inner' % mount_dir, shell=True)
648 new_rand_file('%s/test9/dir1/nested/inner/file1' % mount_dir)
649
650 # Test Case 10
651 check_call('mkdir -p %s/test10' % mount_dir, shell=True)
652 new_rand_file('%s/test10/file1' % mount_dir)
653 md5val['test10'] = file_hash('%s/test10/file1' % mount_dir)
654
655 # Test Case 11
656 check_call('mkdir -p %s/test11/dir1' % mount_dir, shell=True)
657 new_rand_file('%s/test11/dir1/file1' % mount_dir)
658 md5val['test11'] = file_hash('%s/test11/dir1/file1' % mount_dir)
659
660 try:
661 # 128MiB volume
662 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, 0x8000000, '128MB', mount_dir)
663 except CalledProcessError as err:
664 pytest.skip('Creating failed for filesystem: ' + fs_type + '. {}'.format(err))
665 return
666
667 except CalledProcessError:
668 pytest.skip('Setup failed for filesystem: ' + fs_type)
669 return
670 else:
671 yield [fs_ubtype, fs_img, md5val]
672 finally:
673 call('rm -rf %s' % mount_dir, shell=True)
674 call('rm -f %s' % fs_img, shell=True)
675
676#
Christian Taedcke570dc362023-11-15 13:44:24 +0100677# Fixture for fat test
678#
679@pytest.fixture()
680def fs_obj_fat(request, u_boot_config):
681 """Set up a file system to be used in fat test.
682
683 Args:
684 request: Pytest request object.
685 u_boot_config: U-Boot configuration.
686
687 Return:
688 A fixture for fat test, i.e. a duplet of file system type and
689 volume file name.
690 """
691
692 # the maximum size of a FAT12 filesystem resulting in 4084 clusters
693 MAX_FAT12_SIZE = 261695 * 1024
694
695 # the minimum size of a FAT16 filesystem that can be created with
696 # mkfs.vfat resulting in 4087 clusters
697 MIN_FAT16_SIZE = 8208 * 1024
698
699 fs_type = request.param
700 fs_img = ''
701
702 fs_ubtype = fstype_to_ubname(fs_type)
703 check_ubconfig(u_boot_config, fs_ubtype)
704
705 fs_size = MAX_FAT12_SIZE if fs_type == 'fat12' else MIN_FAT16_SIZE
706
707 try:
708 # the volume size depends on the filesystem
Richard Weinberger41eca322024-11-21 15:32:07 -0700709 fs_img = fs_helper.mk_fs(u_boot_config, fs_type, fs_size, f'{fs_size}', None, 1024)
Christian Taedcke570dc362023-11-15 13:44:24 +0100710 except:
711 pytest.skip('Setup failed for filesystem: ' + fs_type)
712 return
713 else:
714 yield [fs_ubtype, fs_img]
715 call('rm -f %s' % fs_img, shell=True)