318 lines
8.5 KiB
C
318 lines
8.5 KiB
C
/*
|
|
* Copyright (c) 2019 Peter Bigot Consulting, LLC
|
|
* Copyright (c) 2023 Antmicro
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/ztest.h>
|
|
#include <zephyr/fs/fs.h>
|
|
|
|
#include "test_fs_util.h"
|
|
|
|
/* Mount point for the tests should be provided by test runner.
|
|
* File system should be mounted before tests are started.
|
|
*/
|
|
extern struct fs_mount_t *fs_dirops_test_mp;
|
|
|
|
static struct testfs_bcmd test_hierarchy[] = {
|
|
TESTFS_BCMD_FILE("f1", 1, 1),
|
|
TESTFS_BCMD_FILE("f2", 2, 100),
|
|
TESTFS_BCMD_ENTER_DIR("d1"),
|
|
TESTFS_BCMD_FILE("d1f1", 11, 23),
|
|
TESTFS_BCMD_FILE("d1f2", 12, 612),
|
|
TESTFS_BCMD_EXIT_DIR(),
|
|
TESTFS_BCMD_FILE("f3", 3, 10000),
|
|
TESTFS_BCMD_END(),
|
|
};
|
|
|
|
static int check_mkdir(struct fs_mount_t *mp)
|
|
{
|
|
struct testfs_path dpath;
|
|
|
|
TC_PRINT("checking dir create unlink\n");
|
|
zassert_equal(testfs_path_init(&dpath, mp,
|
|
"dir",
|
|
TESTFS_PATH_END),
|
|
dpath.path,
|
|
"root init failed");
|
|
|
|
zassert_equal(fs_mkdir(dpath.path),
|
|
0,
|
|
"mkdir failed");
|
|
|
|
struct fs_file_t file;
|
|
struct testfs_path fpath;
|
|
|
|
fs_file_t_init(&file);
|
|
zassert_equal(fs_open(&file,
|
|
testfs_path_extend(testfs_path_copy(&fpath,
|
|
&dpath),
|
|
"file",
|
|
TESTFS_PATH_END),
|
|
FS_O_CREATE | FS_O_RDWR),
|
|
0,
|
|
"creat in dir failed");
|
|
zassert_equal(fs_close(&file), 0,
|
|
"close file failed");
|
|
|
|
struct fs_dirent stat;
|
|
|
|
zassert_equal(fs_stat(fpath.path, &stat), 0,
|
|
"stat file failed");
|
|
|
|
zassert_equal(fs_unlink(dpath.path),
|
|
-ENOTEMPTY,
|
|
"unlink bad failure");
|
|
|
|
zassert_equal(fs_unlink(fpath.path),
|
|
0,
|
|
"unlink file failed");
|
|
|
|
zassert_equal(fs_unlink(dpath.path),
|
|
0,
|
|
"unlink dir failed");
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
static int build_layout(struct fs_mount_t *mp,
|
|
const struct testfs_bcmd *cp)
|
|
{
|
|
struct testfs_path path;
|
|
struct fs_statvfs stat;
|
|
|
|
TC_PRINT("building layout on %s\n", mp->mnt_point);
|
|
|
|
zassert_equal(fs_statvfs(mp->mnt_point, &stat), 0,
|
|
"statvfs failed");
|
|
|
|
TC_PRINT("before: bsize %lu ; frsize %lu ; blocks %lu ; bfree %lu\n",
|
|
stat.f_bsize, stat.f_frsize, stat.f_blocks, stat.f_bfree);
|
|
|
|
zassert_equal(testfs_path_init(&path, mp, TESTFS_PATH_END),
|
|
path.path,
|
|
"root init failed");
|
|
|
|
zassert_equal(testfs_build(&path, cp),
|
|
0,
|
|
"Build_layout failed");
|
|
|
|
zassert_equal(fs_statvfs(mp->mnt_point, &stat), 0,
|
|
"statvfs failed");
|
|
|
|
TC_PRINT("after: bsize %lu ; frsize %lu ; blocks %lu ; bfree %lu\n",
|
|
stat.f_bsize, stat.f_frsize, stat.f_blocks, stat.f_bfree);
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
static int check_layout(struct fs_mount_t *mp,
|
|
struct testfs_bcmd *layout)
|
|
{
|
|
struct testfs_path path;
|
|
struct testfs_bcmd *end_layout = testfs_bcmd_end(layout);
|
|
|
|
TC_PRINT("checking layout\n");
|
|
|
|
zassert_equal(testfs_path_init(&path, mp, TESTFS_PATH_END),
|
|
path.path,
|
|
"root init failed");
|
|
|
|
int rc = testfs_bcmd_verify_layout(&path, layout, end_layout);
|
|
|
|
zassert_true(rc >= 0, "layout check failed");
|
|
|
|
zassert_equal(rc, 0,
|
|
"layout found foreign");
|
|
|
|
struct testfs_bcmd *cp = layout;
|
|
|
|
while (!TESTFS_BCMD_IS_END(cp)) {
|
|
if (cp->name != NULL) {
|
|
TC_PRINT("verifying %s%s %u\n",
|
|
cp->name,
|
|
(cp->type == FS_DIR_ENTRY_DIR) ? "/" : "",
|
|
cp->size);
|
|
zassert_true(cp->matched,
|
|
"Unmatched layout entry");
|
|
}
|
|
++cp;
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
static int check_rename(struct fs_mount_t *mp)
|
|
{
|
|
struct testfs_path root;
|
|
struct testfs_path from_path;
|
|
const char *from = from_path.path;
|
|
struct testfs_path to_path;
|
|
const char *to = to_path.path;
|
|
struct fs_dirent stat;
|
|
struct testfs_bcmd from_bcmd[] = {
|
|
TESTFS_BCMD_FILE("f1f", 1, 8), /* from f1f to f1t */
|
|
TESTFS_BCMD_FILE("f2f", 2, 8), /* from f2f to f2t */
|
|
TESTFS_BCMD_FILE("f2t", 3, 8), /* target for f2f clobber, replaced */
|
|
TESTFS_BCMD_FILE("f3f", 4, 8), /* from f3f to d1f/d1f2t */
|
|
TESTFS_BCMD_FILE("f4f", 5, 8), /* from f4f to d2t, reject */
|
|
TESTFS_BCMD_ENTER_DIR("d1f"), /* from d1f to d1t */
|
|
TESTFS_BCMD_FILE("d1f1", 5, 16),
|
|
TESTFS_BCMD_EXIT_DIR(),
|
|
TESTFS_BCMD_ENTER_DIR("d2t"), /* target for d1f, unchanged */
|
|
TESTFS_BCMD_FILE("d2f1", 6, 16),
|
|
TESTFS_BCMD_EXIT_DIR(),
|
|
TESTFS_BCMD_END(),
|
|
};
|
|
struct testfs_bcmd *from_end_bcmd = testfs_bcmd_end(from_bcmd);
|
|
struct testfs_bcmd to_bcmd[] = {
|
|
TESTFS_BCMD_FILE("f1t", 1, 8), /* from f1f to f1t */
|
|
TESTFS_BCMD_FILE("f2t", 2, 8), /* from f2f to f2t */
|
|
TESTFS_BCMD_FILE("f4f", 5, 8), /* from f4f to d2t, reject */
|
|
TESTFS_BCMD_ENTER_DIR("d1t"), /* from d1f to d1t */
|
|
TESTFS_BCMD_FILE("d1f1", 5, 16),
|
|
TESTFS_BCMD_FILE("d1f2t", 4, 8), /* from f3f to d1f/d1f2t */
|
|
TESTFS_BCMD_EXIT_DIR(),
|
|
TESTFS_BCMD_ENTER_DIR("d2t"), /* target for d1f, unchanged */
|
|
TESTFS_BCMD_FILE("d2f1", 6, 16),
|
|
TESTFS_BCMD_EXIT_DIR(),
|
|
TESTFS_BCMD_END(),
|
|
};
|
|
struct testfs_bcmd *to_end_bcmd = testfs_bcmd_end(to_bcmd);
|
|
|
|
zassert_equal(testfs_path_init(&root, mp,
|
|
"rename",
|
|
TESTFS_PATH_END),
|
|
root.path,
|
|
"root init failed");
|
|
|
|
zassert_equal(fs_mkdir(root.path),
|
|
0,
|
|
"rename mkdir failed");
|
|
zassert_equal(testfs_build(&root, from_bcmd),
|
|
0,
|
|
"rename build failed");
|
|
|
|
zassert_equal(testfs_bcmd_verify_layout(&root, from_bcmd, from_end_bcmd),
|
|
0,
|
|
"layout check failed");
|
|
|
|
testfs_path_extend(testfs_path_copy(&from_path, &root),
|
|
"nofile",
|
|
TESTFS_PATH_END);
|
|
testfs_path_extend(testfs_path_copy(&to_path, &root),
|
|
"f1t",
|
|
TESTFS_PATH_END);
|
|
TC_PRINT("%s => %s -ENOENT\n", from, to);
|
|
zassert_equal(fs_rename(from, to),
|
|
-ENOENT,
|
|
"rename noent failed");
|
|
|
|
/* f1f => f1t : ok */
|
|
testfs_path_extend(testfs_path_copy(&from_path, &root),
|
|
"f1f",
|
|
TESTFS_PATH_END);
|
|
TC_PRINT("%s => %s ok\n", from, to);
|
|
zassert_equal(fs_rename(from, to),
|
|
0,
|
|
"rename noent failed");
|
|
|
|
/* f2f => f2t : clobbers */
|
|
testfs_path_extend(testfs_path_copy(&from_path, &root),
|
|
"f2f",
|
|
TESTFS_PATH_END);
|
|
testfs_path_extend(testfs_path_copy(&to_path, &root),
|
|
"f2t",
|
|
TESTFS_PATH_END);
|
|
TC_PRINT("%s => %s clobber ok\n", from, to);
|
|
zassert_equal(fs_rename(from, to),
|
|
0,
|
|
"rename clobber failed");
|
|
zassert_equal(fs_stat(from, &stat),
|
|
-ENOENT,
|
|
"rename clobber left from");
|
|
|
|
/* f3f => d1f/d1f2t : moves */
|
|
testfs_path_extend(testfs_path_copy(&from_path, &root),
|
|
"f3f",
|
|
TESTFS_PATH_END);
|
|
testfs_path_extend(testfs_path_copy(&to_path, &root),
|
|
"d1f", "d1f2t",
|
|
TESTFS_PATH_END);
|
|
TC_PRINT("%s => %s move ok\n", from, to);
|
|
zassert_equal(fs_rename(from, to),
|
|
0,
|
|
"rename to subdir failed");
|
|
zassert_equal(fs_stat(from, &stat),
|
|
-ENOENT,
|
|
"rename to subdir left from");
|
|
|
|
/* d1f => d2t : reject */
|
|
testfs_path_extend(testfs_path_copy(&from_path, &root),
|
|
"d1f",
|
|
TESTFS_PATH_END);
|
|
testfs_path_extend(testfs_path_copy(&to_path, &root),
|
|
"d2t",
|
|
TESTFS_PATH_END);
|
|
TC_PRINT("%s => %s -ENOTEMPTY\n", from, to);
|
|
zassert_equal(fs_rename(from, to),
|
|
-ENOTEMPTY,
|
|
"rename to existing dir failed");
|
|
|
|
/* d1f => d1t : rename */
|
|
testfs_path_extend(testfs_path_copy(&from_path, &root),
|
|
"d1f",
|
|
TESTFS_PATH_END);
|
|
testfs_path_extend(testfs_path_copy(&to_path, &root),
|
|
"d1t",
|
|
TESTFS_PATH_END);
|
|
TC_PRINT("%s => %s ok\n", from, to);
|
|
zassert_equal(fs_rename(from, to),
|
|
0,
|
|
"rename to new dir failed");
|
|
zassert_equal(fs_stat(from, &stat),
|
|
-ENOENT,
|
|
"rename to new dir left from");
|
|
|
|
zassert_equal(testfs_bcmd_verify_layout(&root, to_bcmd, to_end_bcmd),
|
|
0,
|
|
"layout verification failed");
|
|
|
|
struct testfs_bcmd *cp = to_bcmd;
|
|
|
|
while (cp != to_end_bcmd) {
|
|
if (cp->name) {
|
|
zassert_true(cp->matched, "foreign file retained");
|
|
}
|
|
++cp;
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
void test_fs_dirops(void)
|
|
{
|
|
zassert_equal(fs_mount(fs_dirops_test_mp), 0,
|
|
"mount failed");
|
|
|
|
zassert_equal(check_mkdir(fs_dirops_test_mp), TC_PASS,
|
|
"check mkdir failed");
|
|
|
|
k_sleep(K_MSEC(100)); /* flush log messages */
|
|
zassert_equal(build_layout(fs_dirops_test_mp, test_hierarchy), TC_PASS,
|
|
"build test hierarchy failed");
|
|
|
|
k_sleep(K_MSEC(100)); /* flush log messages */
|
|
zassert_equal(check_layout(fs_dirops_test_mp, test_hierarchy), TC_PASS,
|
|
"check test hierarchy failed");
|
|
|
|
k_sleep(K_MSEC(100)); /* flush log messages */
|
|
zassert_equal(check_rename(fs_dirops_test_mp), TC_PASS,
|
|
"check rename failed");
|
|
|
|
k_sleep(K_MSEC(100)); /* flush log messages */
|
|
zassert_equal(fs_unmount(fs_dirops_test_mp), 0,
|
|
"unmount small failed");
|
|
}
|