Files
u-boot/test/fs/ext4l.c
Simon Glass 0e9c88b170 ext4l: Add exists() support
Implement ext4l_exists() to check if a file or directory exists on the
filesystem. This uses ext4l_resolve_path() to look up the path and
returns 1 if found, 0 otherwise.

Wire the function into fs_legacy.c and add a basic test.

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-27 13:35:42 -07:00

226 lines
6.3 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Tests for ext4l filesystem (Linux ext4 port)
*
* Copyright 2025 Canonical Ltd
* Written by Simon Glass <simon.glass@canonical.com>
*/
#include <command.h>
#include <env.h>
#include <ext4l.h>
#include <fs.h>
#include <fs_legacy.h>
#include <u-boot/uuid.h>
#include <test/test.h>
#include <test/ut.h>
#include <test/fs.h>
#define EXT4L_ARG_IMAGE 0 /* fs_image: path to filesystem image */
/**
* fs_test_ext4l_probe_norun() - Test probing an ext4l filesystem
*
* This test verifies that the ext4l driver can successfully probe and
* mount an ext4 filesystem image.
*
* Arguments:
* fs_image: Path to the ext4 filesystem image
*/
static int fs_test_ext4l_probe_norun(struct unit_test_state *uts)
{
const char *fs_image = ut_str(EXT4L_ARG_IMAGE);
ut_assertnonnull(fs_image);
ut_assertok(run_commandf("host bind 0 %s", fs_image));
ut_assertok(fs_set_blk_dev("host", "0", FS_TYPE_ANY));
return 0;
}
FS_TEST_ARGS(fs_test_ext4l_probe_norun, UTF_SCAN_FDT | UTF_CONSOLE | UTF_MANUAL,
{ "fs_image", UT_ARG_STR });
/**
* fs_test_ext4l_msgs_norun() - Test ext4l_msgs env var output
*
* This test verifies that setting ext4l_msgs=y causes mount messages
* to be printed when probing an ext4 filesystem.
*
* Arguments:
* fs_image: Path to the ext4 filesystem image
*/
static int fs_test_ext4l_msgs_norun(struct unit_test_state *uts)
{
const char *fs_image = ut_str(EXT4L_ARG_IMAGE);
char uuid_str[UUID_STR_LEN + 1];
u8 uuid[16];
ut_assertnonnull(fs_image);
ut_assertok(env_set("ext4l_msgs", "y"));
console_record_reset_enable();
ut_assertok(run_commandf("host bind 0 %s", fs_image));
ut_assertok(fs_set_blk_dev("host", "0", FS_TYPE_ANY));
/* Get the UUID and clear the env var now we have the output */
ut_assertok(ext4l_get_uuid(uuid));
uuid_bin_to_str(uuid, uuid_str, UUID_STR_FORMAT_STD);
ut_assertok(env_set("ext4l_msgs", NULL));
/*
* Check messages. The probe test runs first and doesn't unmount,
* so the journal needs recovery. The filesystem may be mounted
* multiple times during probe operations. Just verify we see the
* expected mount message at least once.
*/
ut_assert_skip_to_line("EXT4-fs (ext4l_mmc0): mounted filesystem %s r/w"
" with ordered data mode. Quota mode: disabled.",
uuid_str);
/* Skip any remaining messages */
return 0;
}
FS_TEST_ARGS(fs_test_ext4l_msgs_norun, UTF_SCAN_FDT | UTF_CONSOLE | UTF_MANUAL,
{ "fs_image", UT_ARG_STR });
/**
* fs_test_ext4l_ls_norun() - Test ext4l ls command
*
* This test verifies that the ext4l driver can list directory contents.
*
* Arguments:
* fs_image: Path to the ext4 filesystem image
*/
static int fs_test_ext4l_ls_norun(struct unit_test_state *uts)
{
const char *fs_image = ut_str(EXT4L_ARG_IMAGE);
ut_assertnonnull(fs_image);
ut_assertok(run_commandf("host bind 0 %s", fs_image));
console_record_reset_enable();
ut_assertok(run_commandf("ls host 0"));
/*
* The Python test adds testfile.txt (12 bytes) to the image.
* Directory entries appear in hash order which varies between runs.
* Verify the file entry appears with correct size (12 bytes).
* Other entries like ., .., subdir, lost+found may also appear.
*/
ut_assert_skip_to_line(" 12 testfile.txt");
/* Skip any remaining entries */
return 0;
}
FS_TEST_ARGS(fs_test_ext4l_ls_norun, UTF_SCAN_FDT | UTF_CONSOLE | UTF_MANUAL,
{ "fs_image", UT_ARG_STR });
/**
* fs_test_ext4l_opendir_norun() - Test ext4l opendir/readdir/closedir
*
* Verifies that the ext4l driver can iterate through directory entries using
* the opendir/readdir/closedir interface. It checks:
* - Regular files (testfile.txt)
* - Subdirectories (subdir)
* - Symlinks (link.txt)
* - Files in subdirectories (subdir/nested.txt)
*
* Arguments:
* fs_image: Path to the ext4 filesystem image
*/
static int fs_test_ext4l_opendir_norun(struct unit_test_state *uts)
{
const char *fs_image = ut_str(EXT4L_ARG_IMAGE);
struct fs_dir_stream *dirs;
struct fs_dirent *dent;
bool found_testfile = false;
bool found_subdir = false;
bool found_symlink = false;
bool found_nested = false;
int count = 0;
ut_assertnonnull(fs_image);
ut_assertok(run_commandf("host bind 0 %s", fs_image));
ut_assertok(fs_set_blk_dev("host", "0", FS_TYPE_ANY));
/* Open root directory */
ut_assertok(ext4l_opendir("/", &dirs));
ut_assertnonnull(dirs);
/* Iterate through entries */
while (!ext4l_readdir(dirs, &dent)) {
ut_assertnonnull(dent);
count++;
if (!strcmp(dent->name, "testfile.txt")) {
found_testfile = true;
ut_asserteq(FS_DT_REG, dent->type);
ut_asserteq(12, dent->size);
} else if (!strcmp(dent->name, "subdir")) {
found_subdir = true;
ut_asserteq(FS_DT_DIR, dent->type);
} else if (!strcmp(dent->name, "link.txt")) {
found_symlink = true;
ut_asserteq(FS_DT_LNK, dent->type);
}
}
ext4l_closedir(dirs);
/* Verify we found expected entries */
ut_assert(found_testfile);
ut_assert(found_subdir);
ut_assert(found_symlink);
/* At least ., .., testfile.txt, subdir, link.txt */
ut_assert(count >= 5);
/* Now test reading the subdirectory */
ut_assertok(fs_set_blk_dev("host", "0", FS_TYPE_ANY));
ut_assertok(ext4l_opendir("/subdir", &dirs));
ut_assertnonnull(dirs);
count = 0;
while (!ext4l_readdir(dirs, &dent)) {
ut_assertnonnull(dent);
count++;
if (!strcmp(dent->name, "nested.txt")) {
found_nested = true;
ut_asserteq(FS_DT_REG, dent->type);
ut_asserteq(12, dent->size);
}
}
ext4l_closedir(dirs);
ut_assert(found_nested);
/* At least ., .., nested.txt */
ut_assert(count >= 3);
return 0;
}
FS_TEST_ARGS(fs_test_ext4l_opendir_norun, UTF_SCAN_FDT | UTF_CONSOLE |
UTF_MANUAL, { "fs_image", UT_ARG_STR });
/**
* fs_test_ext4l_exists_norun() - Test ext4l_exists function
*
* Verifies that ext4l_exists correctly reports file existence.
*
* Arguments:
* fs_image: Path to the ext4 filesystem image
*/
static int fs_test_ext4l_exists_norun(struct unit_test_state *uts)
{
const char *fs_image = ut_str(EXT4L_ARG_IMAGE);
ut_assertnonnull(fs_image);
ut_assertok(run_commandf("host bind 0 %s", fs_image));
ut_assertok(fs_set_blk_dev("host", "0", FS_TYPE_ANY));
/* Test existing directory */
ut_asserteq(1, ext4l_exists("/"));
/* Test non-existent paths */
ut_asserteq(0, ext4l_exists("/no/such/path"));
return 0;
}
FS_TEST_ARGS(fs_test_ext4l_exists_norun, UTF_SCAN_FDT | UTF_CONSOLE |
UTF_MANUAL, { "fs_image", UT_ARG_STR });