1# SPDX-License-Identifier:      GPL-2.0+
2# Copyright (c) 2018, Linaro Limited
3# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
4#
5# U-Boot File System:Exntented Test
6
7"""
8This test verifies extended write operation on file system.
9"""
10
11import os.path
12import pytest
13import re
14from subprocess import check_output
15from fstest_defs import *
16from fstest_helpers import assert_fs_integrity
17
18PLAIN_FILE='abcdefgh.txt'
19MANGLE_FILE='abcdefghi.txt'
20
21def str2fat(long_filename):
22    splitext = os.path.splitext(long_filename.upper())
23    name = splitext[0]
24    ext = splitext[1][1:]
25    if len(name) > 8:
26        name = '%s~1' % name[:6]
27    return '%-8s %s' % (name, ext)
28
29@pytest.mark.boardspec('sandbox')
30@pytest.mark.slow
31class TestFsExt(object):
32    def test_fs_ext1(self, u_boot_console, fs_obj_ext):
33        """
34        Test Case 1 - write a file with absolute path
35        """
36        fs_type,fs_img,md5val = fs_obj_ext
37        with u_boot_console.log.section('Test Case 1 - write with abs path'):
38            # Test Case 1a - Check if command successfully returned
39            output = u_boot_console.run_command_list([
40                'host bind 0 %s' % fs_img,
41                '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
42                '%swrite host 0:0 %x /dir1/%s.w1 $filesize'
43                    % (fs_type, ADDR, MIN_FILE)])
44            assert('20480 bytes written' in ''.join(output))
45
46            # Test Case 1b - Check md5 of file content
47            output = u_boot_console.run_command_list([
48                'mw.b %x 00 100' % ADDR,
49                '%sload host 0:0 %x /dir1/%s.w1' % (fs_type, ADDR, MIN_FILE),
50                'md5sum %x $filesize' % ADDR,
51                'setenv filesize'])
52            assert(md5val[0] in ''.join(output))
53            assert_fs_integrity(fs_type, fs_img)
54
55    def test_fs_ext2(self, u_boot_console, fs_obj_ext):
56        """
57        Test Case 2 - write to a file with relative path
58        """
59        fs_type,fs_img,md5val = fs_obj_ext
60        with u_boot_console.log.section('Test Case 2 - write with rel path'):
61            # Test Case 2a - Check if command successfully returned
62            output = u_boot_console.run_command_list([
63                'host bind 0 %s' % fs_img,
64                '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
65                '%swrite host 0:0 %x dir1/%s.w2 $filesize'
66                    % (fs_type, ADDR, MIN_FILE)])
67            assert('20480 bytes written' in ''.join(output))
68
69            # Test Case 2b - Check md5 of file content
70            output = u_boot_console.run_command_list([
71                'mw.b %x 00 100' % ADDR,
72                '%sload host 0:0 %x dir1/%s.w2' % (fs_type, ADDR, MIN_FILE),
73                'md5sum %x $filesize' % ADDR,
74                'setenv filesize'])
75            assert(md5val[0] in ''.join(output))
76            assert_fs_integrity(fs_type, fs_img)
77
78    def test_fs_ext3(self, u_boot_console, fs_obj_ext):
79        """
80        Test Case 3 - write to a file with invalid path
81        """
82        fs_type,fs_img,md5val = fs_obj_ext
83        with u_boot_console.log.section('Test Case 3 - write with invalid path'):
84            # Test Case 3 - Check if command expectedly failed
85            output = u_boot_console.run_command_list([
86                'host bind 0 %s' % fs_img,
87                '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
88                '%swrite host 0:0 %x /dir1/none/%s.w3 $filesize'
89                    % (fs_type, ADDR, MIN_FILE)])
90            assert('Unable to write file /dir1/none/' in ''.join(output))
91            assert_fs_integrity(fs_type, fs_img)
92
93    def test_fs_ext4(self, u_boot_console, fs_obj_ext):
94        """
95        Test Case 4 - write at non-zero offset, enlarging file size
96        """
97        fs_type,fs_img,md5val = fs_obj_ext
98        with u_boot_console.log.section('Test Case 4 - write at non-zero offset, enlarging file size'):
99            # Test Case 4a - Check if command successfully returned
100            output = u_boot_console.run_command_list([
101                'host bind 0 %s' % fs_img,
102                '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
103                '%swrite host 0:0 %x /dir1/%s.w4 $filesize'
104                    % (fs_type, ADDR, MIN_FILE)])
105            output = u_boot_console.run_command(
106                '%swrite host 0:0 %x /dir1/%s.w4 $filesize 0x1400'
107                    % (fs_type, ADDR, MIN_FILE))
108            assert('20480 bytes written' in output)
109
110            # Test Case 4b - Check size of written file
111            output = u_boot_console.run_command_list([
112                '%ssize host 0:0 /dir1/%s.w4' % (fs_type, MIN_FILE),
113                'printenv filesize',
114                'setenv filesize'])
115            assert('filesize=6400' in ''.join(output))
116
117            # Test Case 4c - Check md5 of file content
118            output = u_boot_console.run_command_list([
119                'mw.b %x 00 100' % ADDR,
120                '%sload host 0:0 %x /dir1/%s.w4' % (fs_type, ADDR, MIN_FILE),
121                'md5sum %x $filesize' % ADDR,
122                'setenv filesize'])
123            assert(md5val[1] in ''.join(output))
124            assert_fs_integrity(fs_type, fs_img)
125
126    def test_fs_ext5(self, u_boot_console, fs_obj_ext):
127        """
128        Test Case 5 - write at non-zero offset, shrinking file size
129        """
130        fs_type,fs_img,md5val = fs_obj_ext
131        with u_boot_console.log.section('Test Case 5 - write at non-zero offset, shrinking file size'):
132            # Test Case 5a - Check if command successfully returned
133            output = u_boot_console.run_command_list([
134                'host bind 0 %s' % fs_img,
135                '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
136                '%swrite host 0:0 %x /dir1/%s.w5 $filesize'
137                    % (fs_type, ADDR, MIN_FILE)])
138            output = u_boot_console.run_command(
139                '%swrite host 0:0 %x /dir1/%s.w5 0x1400 0x1400'
140                    % (fs_type, ADDR, MIN_FILE))
141            assert('5120 bytes written' in output)
142
143            # Test Case 5b - Check size of written file
144            output = u_boot_console.run_command_list([
145                '%ssize host 0:0 /dir1/%s.w5' % (fs_type, MIN_FILE),
146                'printenv filesize',
147                'setenv filesize'])
148            assert('filesize=2800' in ''.join(output))
149
150            # Test Case 5c - Check md5 of file content
151            output = u_boot_console.run_command_list([
152                'mw.b %x 00 100' % ADDR,
153                '%sload host 0:0 %x /dir1/%s.w5' % (fs_type, ADDR, MIN_FILE),
154                'md5sum %x $filesize' % ADDR,
155                'setenv filesize'])
156            assert(md5val[2] in ''.join(output))
157            assert_fs_integrity(fs_type, fs_img)
158
159    def test_fs_ext6(self, u_boot_console, fs_obj_ext):
160        """
161        Test Case 6 - write nothing at the start, truncating to zero
162        """
163        fs_type,fs_img,md5val = fs_obj_ext
164        with u_boot_console.log.section('Test Case 6 - write nothing at the start, truncating to zero'):
165            # Test Case 6a - Check if command successfully returned
166            output = u_boot_console.run_command_list([
167                'host bind 0 %s' % fs_img,
168                '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
169                '%swrite host 0:0 %x /dir1/%s.w6 $filesize'
170                    % (fs_type, ADDR, MIN_FILE)])
171            output = u_boot_console.run_command(
172                '%swrite host 0:0 %x /dir1/%s.w6 0 0'
173                    % (fs_type, ADDR, MIN_FILE))
174            assert('0 bytes written' in output)
175
176            # Test Case 6b - Check size of written file
177            output = u_boot_console.run_command_list([
178                '%ssize host 0:0 /dir1/%s.w6' % (fs_type, MIN_FILE),
179                'printenv filesize',
180                'setenv filesize'])
181            assert('filesize=0' in ''.join(output))
182            assert_fs_integrity(fs_type, fs_img)
183
184    def test_fs_ext7(self, u_boot_console, fs_obj_ext):
185        """
186        Test Case 7 - write at the end (append)
187        """
188        fs_type,fs_img,md5val = fs_obj_ext
189        with u_boot_console.log.section('Test Case 7 - write at the end (append)'):
190            # Test Case 7a - Check if command successfully returned
191            output = u_boot_console.run_command_list([
192                'host bind 0 %s' % fs_img,
193                '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
194                '%swrite host 0:0 %x /dir1/%s.w7 $filesize'
195                    % (fs_type, ADDR, MIN_FILE)])
196            output = u_boot_console.run_command(
197                '%swrite host 0:0 %x /dir1/%s.w7 $filesize $filesize'
198                    % (fs_type, ADDR, MIN_FILE))
199            assert('20480 bytes written' in output)
200
201            # Test Case 7b - Check size of written file
202            output = u_boot_console.run_command_list([
203                '%ssize host 0:0 /dir1/%s.w7' % (fs_type, MIN_FILE),
204                'printenv filesize',
205                'setenv filesize'])
206            assert('filesize=a000' in ''.join(output))
207
208            # Test Case 7c - Check md5 of file content
209            output = u_boot_console.run_command_list([
210                'mw.b %x 00 100' % ADDR,
211                '%sload host 0:0 %x /dir1/%s.w7' % (fs_type, ADDR, MIN_FILE),
212                'md5sum %x $filesize' % ADDR,
213                'setenv filesize'])
214            assert(md5val[3] in ''.join(output))
215            assert_fs_integrity(fs_type, fs_img)
216
217    def test_fs_ext8(self, u_boot_console, fs_obj_ext):
218        """
219        Test Case 8 - write at offset beyond the end of file
220        """
221        fs_type,fs_img,md5val = fs_obj_ext
222        with u_boot_console.log.section('Test Case 8 - write beyond the end'):
223            # Test Case 8a - Check if command expectedly failed
224            output = u_boot_console.run_command_list([
225                'host bind 0 %s' % fs_img,
226                '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
227                '%swrite host 0:0 %x /dir1/%s.w8 $filesize'
228                    % (fs_type, ADDR, MIN_FILE)])
229            output = u_boot_console.run_command(
230                '%swrite host 0:0 %x /dir1/%s.w8 0x1400 %x'
231                    % (fs_type, ADDR, MIN_FILE, 0x100000 + 0x1400))
232            assert('Unable to write file /dir1' in output)
233            assert_fs_integrity(fs_type, fs_img)
234
235    def test_fs_ext9(self, u_boot_console, fs_obj_ext):
236        """
237        Test Case 9 - write to a non-existing file at non-zero offset
238        """
239        fs_type,fs_img,md5val = fs_obj_ext
240        with u_boot_console.log.section('Test Case 9 - write to non-existing file with non-zero offset'):
241            # Test Case 9a - Check if command expectedly failed
242            output = u_boot_console.run_command_list([
243                'host bind 0 %s' % fs_img,
244                '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
245                '%swrite host 0:0 %x /dir1/%s.w9 0x1400 0x1400'
246                    % (fs_type, ADDR, MIN_FILE)])
247            assert('Unable to write file /dir1' in ''.join(output))
248            assert_fs_integrity(fs_type, fs_img)
249
250    def test_fs_ext10(self, u_boot_console, fs_obj_ext):
251        """
252        'Test Case 10 - create/delete as many directories under root directory
253        as amount of directory entries goes beyond one cluster size)'
254        """
255        fs_type,fs_img,md5val = fs_obj_ext
256        with u_boot_console.log.section('Test Case 10 - create/delete (many)'):
257            # Test Case 10a - Create many files
258            #   Please note that the size of directory entry is 32 bytes.
259            #   So one typical cluster may holds 64 (2048/32) entries.
260            output = u_boot_console.run_command(
261                'host bind 0 %s' % fs_img)
262
263            for i in range(0, 66):
264                output = u_boot_console.run_command(
265                    '%swrite host 0:0 %x /FILE0123456789_%02x 100'
266                    % (fs_type, ADDR, i))
267            output = u_boot_console.run_command('%sls host 0:0 /' % fs_type)
268            assert('FILE0123456789_00' in output)
269            assert('FILE0123456789_41' in output)
270
271            # Test Case 10b - Delete many files
272            for i in range(0, 66):
273                output = u_boot_console.run_command(
274                    '%srm host 0:0 /FILE0123456789_%02x'
275                    % (fs_type, i))
276            output = u_boot_console.run_command('%sls host 0:0 /' % fs_type)
277            assert(not 'FILE0123456789_00' in output)
278            assert(not 'FILE0123456789_41' in output)
279
280            # Test Case 10c - Create many files again
281            # Please note no.64 and 65 are intentionally re-created
282            for i in range(64, 128):
283                output = u_boot_console.run_command(
284                    '%swrite host 0:0 %x /FILE0123456789_%02x 100'
285                    % (fs_type, ADDR, i))
286            output = u_boot_console.run_command('%sls host 0:0 /' % fs_type)
287            assert('FILE0123456789_40' in output)
288            assert('FILE0123456789_79' in output)
289
290            assert_fs_integrity(fs_type, fs_img)
291
292    def test_fs_ext11(self, u_boot_console, fs_obj_ext):
293        """
294        'Test Case 11 - create/delete as many directories under non-root
295        directory as amount of directory entries goes beyond one cluster size)'
296        """
297        fs_type,fs_img,md5val = fs_obj_ext
298        with u_boot_console.log.section('Test Case 11 - create/delete (many)'):
299            # Test Case 11a - Create many files
300            #   Please note that the size of directory entry is 32 bytes.
301            #   So one typical cluster may holds 64 (2048/32) entries.
302            output = u_boot_console.run_command(
303                'host bind 0 %s' % fs_img)
304
305            for i in range(0, 66):
306                output = u_boot_console.run_command(
307                    '%swrite host 0:0 %x /dir1/FILE0123456789_%02x 100'
308                    % (fs_type, ADDR, i))
309            output = u_boot_console.run_command('%sls host 0:0 /dir1' % fs_type)
310            assert('FILE0123456789_00' in output)
311            assert('FILE0123456789_41' in output)
312
313            # Test Case 11b - Delete many files
314            for i in range(0, 66):
315                output = u_boot_console.run_command(
316                    '%srm host 0:0 /dir1/FILE0123456789_%02x'
317                    % (fs_type, i))
318            output = u_boot_console.run_command('%sls host 0:0 /dir1' % fs_type)
319            assert(not 'FILE0123456789_00' in output)
320            assert(not 'FILE0123456789_41' in output)
321
322            # Test Case 11c - Create many files again
323            # Please note no.64 and 65 are intentionally re-created
324            for i in range(64, 128):
325                output = u_boot_console.run_command(
326                    '%swrite host 0:0 %x /dir1/FILE0123456789_%02x 100'
327                    % (fs_type, ADDR, i))
328            output = u_boot_console.run_command('%sls host 0:0 /dir1' % fs_type)
329            assert('FILE0123456789_40' in output)
330            assert('FILE0123456789_79' in output)
331
332            assert_fs_integrity(fs_type, fs_img)
333
334    def test_fs_ext12(self, u_boot_console, fs_obj_ext):
335        """
336        Test Case 12 - write plain and mangle file
337        """
338        fs_type,fs_img,md5val = fs_obj_ext
339        with u_boot_console.log.section('Test Case 12 - write plain and mangle file'):
340            # Test Case 12a - Check if command successfully returned
341            output = u_boot_console.run_command_list([
342                'host bind 0 %s' % fs_img,
343                '%swrite host 0:0 %x /%s 0'
344                    % (fs_type, ADDR, PLAIN_FILE),
345                '%swrite host 0:0 %x /%s 0'
346                    % (fs_type, ADDR, MANGLE_FILE)])
347            assert('0 bytes written' in ''.join(output))
348            # Test Case 12b - Read file system content
349            output = check_output('mdir -i %s' % fs_img, shell=True).decode()
350            # Test Case 12c - Check if short filename is not mangled
351            assert(str2fat(PLAIN_FILE) in ''.join(output))
352            # Test Case 12d - Check if long filename is mangled
353            assert(str2fat(MANGLE_FILE) in ''.join(output))
354
355            assert_fs_integrity(fs_type, fs_img)
356