Huang Jianan | 11e0443 | 2022-02-26 15:05:51 +0800 | [diff] [blame] | 1 | # SPDX-License-Identifier: GPL-2.0+ |
| 2 | # Copyright (C) 2022 Huang Jianan <jnhuang95@gmail.com> |
| 3 | # Author: Huang Jianan <jnhuang95@gmail.com> |
| 4 | |
| 5 | import os |
| 6 | import pytest |
| 7 | import shutil |
| 8 | import subprocess |
| 9 | |
| 10 | EROFS_SRC_DIR = 'erofs_src_dir' |
| 11 | EROFS_IMAGE_NAME = 'erofs.img' |
| 12 | |
| 13 | def generate_file(name, size): |
| 14 | """ |
| 15 | Generates a file filled with 'x'. |
| 16 | """ |
| 17 | content = 'x' * size |
| 18 | file = open(name, 'w') |
| 19 | file.write(content) |
| 20 | file.close() |
| 21 | |
| 22 | def make_erofs_image(build_dir): |
| 23 | """ |
| 24 | Makes the EROFS images used for the test. |
| 25 | |
| 26 | The image is generated at build_dir with the following structure: |
| 27 | erofs_src_dir/ |
| 28 | ├── f4096 |
| 29 | ├── f7812 |
| 30 | ├── subdir/ |
| 31 | │ └── subdir-file |
| 32 | ├── symdir -> subdir |
| 33 | └── symfile -> f5096 |
| 34 | """ |
| 35 | root = os.path.join(build_dir, EROFS_SRC_DIR) |
| 36 | os.makedirs(root) |
| 37 | |
| 38 | # 4096: uncompressed file |
| 39 | generate_file(os.path.join(root, 'f4096'), 4096) |
| 40 | |
| 41 | # 7812: Compressed file |
| 42 | generate_file(os.path.join(root, 'f7812'), 7812) |
| 43 | |
| 44 | # sub-directory with a single file inside |
| 45 | subdir_path = os.path.join(root, 'subdir') |
| 46 | os.makedirs(subdir_path) |
| 47 | generate_file(os.path.join(subdir_path, 'subdir-file'), 100) |
| 48 | |
| 49 | # symlink |
| 50 | os.symlink('subdir', os.path.join(root, 'symdir')) |
| 51 | os.symlink('f7812', os.path.join(root, 'symfile')) |
| 52 | |
| 53 | input_path = os.path.join(build_dir, EROFS_SRC_DIR) |
| 54 | output_path = os.path.join(build_dir, EROFS_IMAGE_NAME) |
| 55 | args = ' '.join([output_path, input_path]) |
| 56 | subprocess.run(['mkfs.erofs -zlz4 ' + args], shell=True, check=True, |
| 57 | stdout=subprocess.DEVNULL) |
| 58 | |
| 59 | def clean_erofs_image(build_dir): |
| 60 | """ |
| 61 | Deletes the image and src_dir at build_dir. |
| 62 | """ |
| 63 | path = os.path.join(build_dir, EROFS_SRC_DIR) |
| 64 | shutil.rmtree(path) |
| 65 | image_path = os.path.join(build_dir, EROFS_IMAGE_NAME) |
| 66 | os.remove(image_path) |
| 67 | |
| 68 | def erofs_ls_at_root(u_boot_console): |
| 69 | """ |
| 70 | Test if all the present files and directories were listed. |
| 71 | """ |
| 72 | no_slash = u_boot_console.run_command('erofsls host 0') |
| 73 | slash = u_boot_console.run_command('erofsls host 0 /') |
| 74 | assert no_slash == slash |
| 75 | |
| 76 | expected_lines = ['./', '../', '4096 f4096', '7812 f7812', 'subdir/', |
| 77 | '<SYM> symdir', '<SYM> symfile', '4 file(s), 3 dir(s)'] |
| 78 | |
| 79 | output = u_boot_console.run_command('erofsls host 0') |
| 80 | for line in expected_lines: |
| 81 | assert line in output |
| 82 | |
| 83 | def erofs_ls_at_subdir(u_boot_console): |
| 84 | """ |
| 85 | Test if the path resolution works. |
| 86 | """ |
| 87 | expected_lines = ['./', '../', '100 subdir-file', '1 file(s), 2 dir(s)'] |
| 88 | output = u_boot_console.run_command('erofsls host 0 subdir') |
| 89 | for line in expected_lines: |
| 90 | assert line in output |
| 91 | |
| 92 | def erofs_ls_at_symlink(u_boot_console): |
| 93 | """ |
| 94 | Test if the symbolic link's target resolution works. |
| 95 | """ |
| 96 | output = u_boot_console.run_command('erofsls host 0 symdir') |
| 97 | output_subdir = u_boot_console.run_command('erofsls host 0 subdir') |
| 98 | assert output == output_subdir |
| 99 | |
| 100 | expected_lines = ['./', '../', '100 subdir-file', '1 file(s), 2 dir(s)'] |
| 101 | for line in expected_lines: |
| 102 | assert line in output |
| 103 | |
| 104 | def erofs_ls_at_non_existent_dir(u_boot_console): |
| 105 | """ |
| 106 | Test if the EROFS support will crash when get a nonexistent directory. |
| 107 | """ |
| 108 | out_non_existent = u_boot_console.run_command('erofsls host 0 fff') |
| 109 | out_not_dir = u_boot_console.run_command('erofsls host 0 f1000') |
| 110 | assert out_non_existent == out_not_dir |
| 111 | assert '' in out_non_existent |
| 112 | |
| 113 | def erofs_load_files(u_boot_console, files, sizes, address): |
| 114 | """ |
| 115 | Loads files and asserts their checksums. |
| 116 | """ |
| 117 | build_dir = u_boot_console.config.build_dir |
| 118 | for (file, size) in zip(files, sizes): |
| 119 | out = u_boot_console.run_command('erofsload host 0 {} {}'.format(address, file)) |
| 120 | |
| 121 | # check if the right amount of bytes was read |
| 122 | assert size in out |
| 123 | |
| 124 | # calculate u-boot file's checksum |
| 125 | out = u_boot_console.run_command('md5sum {} {}'.format(address, hex(int(size)))) |
| 126 | u_boot_checksum = out.split()[-1] |
| 127 | |
| 128 | # calculate original file's checksum |
| 129 | original_file_path = os.path.join(build_dir, EROFS_SRC_DIR + '/' + file) |
| 130 | out = subprocess.run(['md5sum ' + original_file_path], shell=True, check=True, |
| 131 | capture_output=True, text=True) |
| 132 | original_checksum = out.stdout.split()[0] |
| 133 | |
| 134 | # compare checksum |
| 135 | assert u_boot_checksum == original_checksum |
| 136 | |
| 137 | def erofs_load_files_at_root(u_boot_console): |
| 138 | """ |
| 139 | Test load file from the root directory. |
| 140 | """ |
| 141 | files = ['f4096', 'f7812'] |
| 142 | sizes = ['4096', '7812'] |
| 143 | address = '$kernel_addr_r' |
| 144 | erofs_load_files(u_boot_console, files, sizes, address) |
| 145 | |
| 146 | def erofs_load_files_at_subdir(u_boot_console): |
| 147 | """ |
| 148 | Test load file from the subdirectory. |
| 149 | """ |
| 150 | files = ['subdir/subdir-file'] |
| 151 | sizes = ['100'] |
| 152 | address = '$kernel_addr_r' |
| 153 | erofs_load_files(u_boot_console, files, sizes, address) |
| 154 | |
| 155 | def erofs_load_files_at_symlink(u_boot_console): |
| 156 | """ |
| 157 | Test load file from the symlink. |
| 158 | """ |
| 159 | files = ['symfile'] |
| 160 | sizes = ['7812'] |
| 161 | address = '$kernel_addr_r' |
| 162 | erofs_load_files(u_boot_console, files, sizes, address) |
| 163 | |
| 164 | def erofs_load_non_existent_file(u_boot_console): |
| 165 | """ |
| 166 | Test if the EROFS support will crash when load a nonexistent file. |
| 167 | """ |
| 168 | address = '$kernel_addr_r' |
| 169 | file = 'non-existent' |
| 170 | out = u_boot_console.run_command('erofsload host 0 {} {}'.format(address, file)) |
| 171 | assert 'Failed to load' in out |
| 172 | |
| 173 | def erofs_run_all_tests(u_boot_console): |
| 174 | """ |
| 175 | Runs all test cases. |
| 176 | """ |
| 177 | erofs_ls_at_root(u_boot_console) |
| 178 | erofs_ls_at_subdir(u_boot_console) |
| 179 | erofs_ls_at_symlink(u_boot_console) |
| 180 | erofs_ls_at_non_existent_dir(u_boot_console) |
| 181 | erofs_load_files_at_root(u_boot_console) |
| 182 | erofs_load_files_at_subdir(u_boot_console) |
| 183 | erofs_load_files_at_symlink(u_boot_console) |
| 184 | erofs_load_non_existent_file(u_boot_console) |
| 185 | |
| 186 | @pytest.mark.boardspec('sandbox') |
| 187 | @pytest.mark.buildconfigspec('cmd_fs_generic') |
| 188 | @pytest.mark.buildconfigspec('cmd_erofs') |
| 189 | @pytest.mark.buildconfigspec('fs_erofs') |
| 190 | @pytest.mark.requiredtool('mkfs.erofs') |
| 191 | @pytest.mark.requiredtool('md5sum') |
| 192 | |
| 193 | def test_erofs(u_boot_console): |
| 194 | """ |
| 195 | Executes the erofs test suite. |
| 196 | """ |
| 197 | build_dir = u_boot_console.config.build_dir |
| 198 | |
Raymond Mao | 1fcaf95 | 2023-11-10 13:25:37 +0900 | [diff] [blame] | 199 | # If the EFI subsystem is enabled and initialized, EFI subsystem tries to |
| 200 | # add EFI boot option when the new disk is detected. If there is no EFI |
| 201 | # System Partition exists, EFI subsystem outputs error messages and |
| 202 | # it ends up with test failure. |
| 203 | # Restart U-Boot to clear the previous state. |
| 204 | # TODO: Ideally EFI test cases need to be fixed, but it will |
| 205 | # increase the number of system reset. |
| 206 | u_boot_console.restart_uboot() |
| 207 | |
Huang Jianan | 11e0443 | 2022-02-26 15:05:51 +0800 | [diff] [blame] | 208 | try: |
| 209 | # setup test environment |
| 210 | make_erofs_image(build_dir) |
| 211 | image_path = os.path.join(build_dir, EROFS_IMAGE_NAME) |
| 212 | u_boot_console.run_command('host bind 0 {}'.format(image_path)) |
| 213 | # run all tests |
| 214 | erofs_run_all_tests(u_boot_console) |
| 215 | except: |
| 216 | clean_erofs_image(build_dir) |
| 217 | raise AssertionError |
| 218 | |
| 219 | # clean test environment |
| 220 | clean_erofs_image(build_dir) |