| # SPDX-License-Identifier: GPL-2.0+ | |
| # Copyright (C) 2022 Huang Jianan <jnhuang95@gmail.com> | |
| # Author: Huang Jianan <jnhuang95@gmail.com> | |
| import os | |
| import pytest | |
| import shutil | |
| import subprocess | |
| EROFS_SRC_DIR = 'erofs_src_dir' | |
| EROFS_IMAGE_NAME = 'erofs.img' | |
| def generate_file(name, size): | |
| """ | |
| Generates a file filled with 'x'. | |
| """ | |
| content = 'x' * size | |
| file = open(name, 'w') | |
| file.write(content) | |
| file.close() | |
| def make_erofs_image(build_dir): | |
| """ | |
| Makes the EROFS images used for the test. | |
| The image is generated at build_dir with the following structure: | |
| erofs_src_dir/ | |
| ├── f4096 | |
| ├── f7812 | |
| ├── subdir/ | |
| │ └── subdir-file | |
| ├── symdir -> subdir | |
| └── symfile -> f5096 | |
| """ | |
| root = os.path.join(build_dir, EROFS_SRC_DIR) | |
| os.makedirs(root) | |
| # 4096: uncompressed file | |
| generate_file(os.path.join(root, 'f4096'), 4096) | |
| # 7812: Compressed file | |
| generate_file(os.path.join(root, 'f7812'), 7812) | |
| # sub-directory with a single file inside | |
| subdir_path = os.path.join(root, 'subdir') | |
| os.makedirs(subdir_path) | |
| generate_file(os.path.join(subdir_path, 'subdir-file'), 100) | |
| # symlink | |
| os.symlink('subdir', os.path.join(root, 'symdir')) | |
| os.symlink('f7812', os.path.join(root, 'symfile')) | |
| input_path = os.path.join(build_dir, EROFS_SRC_DIR) | |
| output_path = os.path.join(build_dir, EROFS_IMAGE_NAME) | |
| args = ' '.join([output_path, input_path]) | |
| subprocess.run(['mkfs.erofs -zlz4 ' + args], shell=True, check=True, | |
| stdout=subprocess.DEVNULL) | |
| def clean_erofs_image(build_dir): | |
| """ | |
| Deletes the image and src_dir at build_dir. | |
| """ | |
| path = os.path.join(build_dir, EROFS_SRC_DIR) | |
| shutil.rmtree(path) | |
| image_path = os.path.join(build_dir, EROFS_IMAGE_NAME) | |
| os.remove(image_path) | |
| def erofs_ls_at_root(u_boot_console): | |
| """ | |
| Test if all the present files and directories were listed. | |
| """ | |
| no_slash = u_boot_console.run_command('erofsls host 0') | |
| slash = u_boot_console.run_command('erofsls host 0 /') | |
| assert no_slash == slash | |
| expected_lines = ['./', '../', '4096 f4096', '7812 f7812', 'subdir/', | |
| '<SYM> symdir', '<SYM> symfile', '4 file(s), 3 dir(s)'] | |
| output = u_boot_console.run_command('erofsls host 0') | |
| for line in expected_lines: | |
| assert line in output | |
| def erofs_ls_at_subdir(u_boot_console): | |
| """ | |
| Test if the path resolution works. | |
| """ | |
| expected_lines = ['./', '../', '100 subdir-file', '1 file(s), 2 dir(s)'] | |
| output = u_boot_console.run_command('erofsls host 0 subdir') | |
| for line in expected_lines: | |
| assert line in output | |
| def erofs_ls_at_symlink(u_boot_console): | |
| """ | |
| Test if the symbolic link's target resolution works. | |
| """ | |
| output = u_boot_console.run_command('erofsls host 0 symdir') | |
| output_subdir = u_boot_console.run_command('erofsls host 0 subdir') | |
| assert output == output_subdir | |
| expected_lines = ['./', '../', '100 subdir-file', '1 file(s), 2 dir(s)'] | |
| for line in expected_lines: | |
| assert line in output | |
| def erofs_ls_at_non_existent_dir(u_boot_console): | |
| """ | |
| Test if the EROFS support will crash when get a nonexistent directory. | |
| """ | |
| out_non_existent = u_boot_console.run_command('erofsls host 0 fff') | |
| out_not_dir = u_boot_console.run_command('erofsls host 0 f1000') | |
| assert out_non_existent == out_not_dir | |
| assert '' in out_non_existent | |
| def erofs_load_files(u_boot_console, files, sizes, address): | |
| """ | |
| Loads files and asserts their checksums. | |
| """ | |
| build_dir = u_boot_console.config.build_dir | |
| for (file, size) in zip(files, sizes): | |
| out = u_boot_console.run_command('erofsload host 0 {} {}'.format(address, file)) | |
| # check if the right amount of bytes was read | |
| assert size in out | |
| # calculate u-boot file's checksum | |
| out = u_boot_console.run_command('md5sum {} {}'.format(address, hex(int(size)))) | |
| u_boot_checksum = out.split()[-1] | |
| # calculate original file's checksum | |
| original_file_path = os.path.join(build_dir, EROFS_SRC_DIR + '/' + file) | |
| out = subprocess.run(['md5sum ' + original_file_path], shell=True, check=True, | |
| capture_output=True, text=True) | |
| original_checksum = out.stdout.split()[0] | |
| # compare checksum | |
| assert u_boot_checksum == original_checksum | |
| def erofs_load_files_at_root(u_boot_console): | |
| """ | |
| Test load file from the root directory. | |
| """ | |
| files = ['f4096', 'f7812'] | |
| sizes = ['4096', '7812'] | |
| address = '$kernel_addr_r' | |
| erofs_load_files(u_boot_console, files, sizes, address) | |
| def erofs_load_files_at_subdir(u_boot_console): | |
| """ | |
| Test load file from the subdirectory. | |
| """ | |
| files = ['subdir/subdir-file'] | |
| sizes = ['100'] | |
| address = '$kernel_addr_r' | |
| erofs_load_files(u_boot_console, files, sizes, address) | |
| def erofs_load_files_at_symlink(u_boot_console): | |
| """ | |
| Test load file from the symlink. | |
| """ | |
| files = ['symfile'] | |
| sizes = ['7812'] | |
| address = '$kernel_addr_r' | |
| erofs_load_files(u_boot_console, files, sizes, address) | |
| def erofs_load_non_existent_file(u_boot_console): | |
| """ | |
| Test if the EROFS support will crash when load a nonexistent file. | |
| """ | |
| address = '$kernel_addr_r' | |
| file = 'non-existent' | |
| out = u_boot_console.run_command('erofsload host 0 {} {}'.format(address, file)) | |
| assert 'Failed to load' in out | |
| def erofs_run_all_tests(u_boot_console): | |
| """ | |
| Runs all test cases. | |
| """ | |
| erofs_ls_at_root(u_boot_console) | |
| erofs_ls_at_subdir(u_boot_console) | |
| erofs_ls_at_symlink(u_boot_console) | |
| erofs_ls_at_non_existent_dir(u_boot_console) | |
| erofs_load_files_at_root(u_boot_console) | |
| erofs_load_files_at_subdir(u_boot_console) | |
| erofs_load_files_at_symlink(u_boot_console) | |
| erofs_load_non_existent_file(u_boot_console) | |
| @pytest.mark.boardspec('sandbox') | |
| @pytest.mark.buildconfigspec('cmd_fs_generic') | |
| @pytest.mark.buildconfigspec('cmd_erofs') | |
| @pytest.mark.buildconfigspec('fs_erofs') | |
| @pytest.mark.requiredtool('mkfs.erofs') | |
| @pytest.mark.requiredtool('md5sum') | |
| def test_erofs(u_boot_console): | |
| """ | |
| Executes the erofs test suite. | |
| """ | |
| build_dir = u_boot_console.config.build_dir | |
| # If the EFI subsystem is enabled and initialized, EFI subsystem tries to | |
| # add EFI boot option when the new disk is detected. If there is no EFI | |
| # System Partition exists, EFI subsystem outputs error messages and | |
| # it ends up with test failure. | |
| # Restart U-Boot to clear the previous state. | |
| # TODO: Ideally EFI test cases need to be fixed, but it will | |
| # increase the number of system reset. | |
| u_boot_console.restart_uboot() | |
| try: | |
| # setup test environment | |
| make_erofs_image(build_dir) | |
| image_path = os.path.join(build_dir, EROFS_IMAGE_NAME) | |
| u_boot_console.run_command('host bind 0 {}'.format(image_path)) | |
| # run all tests | |
| erofs_run_all_tests(u_boot_console) | |
| except: | |
| clean_erofs_image(build_dir) | |
| raise AssertionError | |
| # clean test environment | |
| clean_erofs_image(build_dir) |