zephyr/tests/subsys/fs/common/test_fs_basic.c

414 lines
10 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"
#define HELLO "hello"
#define GOODBYE "goodbye"
/* 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_basic_test_mp;
static int create_write_hello(const struct fs_mount_t *mp)
{
struct testfs_path path;
struct fs_file_t file;
fs_file_t_init(&file);
TC_PRINT("creating and writing file\n");
zassert_equal(fs_open(&file,
testfs_path_init(&path, mp,
HELLO,
TESTFS_PATH_END),
FS_O_CREATE | FS_O_RDWR),
0,
"open hello failed");
struct fs_dirent stat;
zassert_equal(fs_stat(path.path, &stat),
0,
"stat new hello failed");
zassert_equal(stat.type, FS_DIR_ENTRY_FILE,
"stat new hello not file");
zassert_equal(strcmp(stat.name, HELLO), 0,
"stat new hello not hello");
zassert_equal(stat.size, 0,
"stat new hello not empty");
zassert_equal(testfs_write_incrementing(&file, 0, TESTFS_BUFFER_SIZE),
TESTFS_BUFFER_SIZE,
"write constant failed");
zassert_equal(fs_stat(path.path, &stat),
0,
"stat written hello failed");
zassert_equal(stat.type, FS_DIR_ENTRY_FILE,
"stat written hello not file");
zassert_equal(strcmp(stat.name, HELLO), 0,
"stat written hello not hello");
/* Anomalous behavior requiring upstream response */
if (mp->type == FS_LITTLEFS) {
/* VARIATION POINT: littlefs does not update the file size of
* an open file. See upstream issue #250.
*/
zassert_equal(stat.size, 0,
"stat written hello bad size");
}
zassert_equal(fs_close(&file), 0,
"close hello failed");
zassert_equal(fs_stat(path.path, &stat),
0,
"stat closed hello failed");
zassert_equal(stat.type, FS_DIR_ENTRY_FILE,
"stat closed hello not file");
zassert_equal(strcmp(stat.name, HELLO), 0,
"stat closed hello not hello");
zassert_equal(stat.size, TESTFS_BUFFER_SIZE,
"stat closed hello badsize");
return TC_PASS;
}
static int verify_hello(const struct fs_mount_t *mp)
{
struct testfs_path path;
struct fs_file_t file;
fs_file_t_init(&file);
TC_PRINT("opening and verifying file\n");
zassert_equal(fs_open(&file,
testfs_path_init(&path, mp,
HELLO,
TESTFS_PATH_END),
FS_O_CREATE | FS_O_RDWR),
0,
"verify hello open failed");
zassert_equal(fs_tell(&file), 0U,
"verify hello open tell failed");
zassert_equal(testfs_verify_incrementing(&file, 0, TESTFS_BUFFER_SIZE),
TESTFS_BUFFER_SIZE,
"verify hello at start failed");
zassert_equal(fs_tell(&file), TESTFS_BUFFER_SIZE,
"verify hello read tell failed");
zassert_equal(fs_close(&file), 0,
"verify close hello failed");
return TC_PASS;
}
static int seek_within_hello(const struct fs_mount_t *mp)
{
struct testfs_path path;
struct fs_file_t file;
fs_file_t_init(&file);
TC_PRINT("seek and tell in file\n");
zassert_equal(fs_open(&file,
testfs_path_init(&path, mp,
HELLO,
TESTFS_PATH_END),
FS_O_CREATE | FS_O_RDWR),
0,
"verify hello open failed");
zassert_equal(fs_tell(&file), 0U,
"verify hello open tell failed");
struct fs_dirent stat;
zassert_equal(fs_stat(path.path, &stat),
0,
"stat old hello failed");
zassert_equal(stat.size, TESTFS_BUFFER_SIZE,
"stat old hello bad size");
off_t pos = stat.size / 4;
zassert_equal(fs_seek(&file, pos, FS_SEEK_SET),
0,
"verify hello seek near mid failed");
zassert_equal(fs_tell(&file), pos,
"verify hello tell near mid failed");
zassert_equal(testfs_verify_incrementing(&file, pos, TESTFS_BUFFER_SIZE),
TESTFS_BUFFER_SIZE - pos,
"verify hello at middle failed");
zassert_equal(fs_tell(&file), stat.size,
"verify hello read middle tell failed");
zassert_equal(fs_seek(&file, -stat.size, FS_SEEK_CUR),
0,
"verify hello seek back from cur failed");
zassert_equal(fs_tell(&file), 0U,
"verify hello tell back from cur failed");
zassert_equal(fs_seek(&file, -pos, FS_SEEK_END),
0,
"verify hello seek from end failed");
zassert_equal(fs_tell(&file), stat.size - pos,
"verify hello tell from end failed");
zassert_equal(testfs_verify_incrementing(&file, stat.size - pos,
TESTFS_BUFFER_SIZE),
pos,
"verify hello at post middle failed");
zassert_equal(fs_close(&file), 0,
"verify close hello failed");
return TC_PASS;
}
static int truncate_hello(const struct fs_mount_t *mp)
{
struct testfs_path path;
struct fs_file_t file;
fs_file_t_init(&file);
TC_PRINT("truncate in file\n");
zassert_equal(fs_open(&file,
testfs_path_init(&path, mp,
HELLO,
TESTFS_PATH_END),
FS_O_CREATE | FS_O_RDWR),
0,
"verify hello open failed");
struct fs_dirent stat;
zassert_equal(fs_stat(path.path, &stat),
0,
"stat old hello failed");
zassert_equal(stat.size, TESTFS_BUFFER_SIZE,
"stat old hello bad size");
off_t pos = 3 * stat.size / 4;
zassert_equal(fs_tell(&file), 0U,
"truncate initial tell failed");
zassert_equal(fs_truncate(&file, pos),
0,
"truncate 3/4 failed");
zassert_equal(fs_tell(&file), 0U,
"truncate post tell failed");
zassert_equal(fs_stat(path.path, &stat),
0,
"stat open 3/4 failed");
/* Anomalous behavior requiring upstream response */
if (mp->type == FS_LITTLEFS) {
/* VARIATION POINT: littlefs does not update the file size of
* an open file. See upstream issue #250.
*/
zassert_equal(stat.size, TESTFS_BUFFER_SIZE,
"stat open 3/4 bad size");
}
zassert_equal(testfs_verify_incrementing(&file, 0, 64),
48,
"post truncate content unexpected");
zassert_equal(fs_close(&file), 0,
"post truncate close failed");
/* After close size is correct. */
zassert_equal(fs_stat(path.path, &stat),
0,
"stat closed truncated failed");
zassert_equal(stat.size, pos,
"stat closed truncated bad size");
return TC_PASS;
}
static int unlink_hello(const struct fs_mount_t *mp)
{
struct testfs_path path;
TC_PRINT("unlink hello\n");
testfs_path_init(&path, mp,
HELLO,
TESTFS_PATH_END);
struct fs_dirent stat;
zassert_equal(fs_stat(path.path, &stat),
0,
"stat existing hello failed");
zassert_equal(fs_unlink(path.path),
0,
"unlink hello failed");
zassert_equal(fs_stat(path.path, &stat),
-ENOENT,
"stat existing hello failed");
return TC_PASS;
}
static int sync_goodbye(const struct fs_mount_t *mp)
{
struct testfs_path path;
struct fs_file_t file;
fs_file_t_init(&file);
TC_PRINT("sync goodbye\n");
zassert_equal(fs_open(&file,
testfs_path_init(&path, mp,
GOODBYE,
TESTFS_PATH_END),
FS_O_CREATE | FS_O_RDWR),
0,
"sync goodbye failed");
struct fs_dirent stat;
zassert_equal(fs_stat(path.path, &stat),
0,
"stat existing hello failed");
zassert_equal(stat.size, 0,
"stat new goodbye not empty");
zassert_equal(testfs_write_incrementing(&file, 0, TESTFS_BUFFER_SIZE),
TESTFS_BUFFER_SIZE,
"write goodbye failed");
zassert_equal(fs_tell(&file), TESTFS_BUFFER_SIZE,
"tell goodbye failed");
if (true && mp->type == FS_LITTLEFS) {
/* Upstream issue #250 */
zassert_equal(stat.size, 0,
"stat new goodbye not empty");
}
zassert_equal(fs_sync(&file), 0,
"sync goodbye failed");
zassert_equal(fs_tell(&file), TESTFS_BUFFER_SIZE,
"tell synced moved");
zassert_equal(fs_stat(path.path, &stat),
0,
"stat existing hello failed");
printk("sync size %u\n", (uint32_t)stat.size);
zassert_equal(stat.size, TESTFS_BUFFER_SIZE,
"stat synced goodbye not correct");
zassert_equal(fs_close(&file), 0,
"post sync close failed");
/* After close size is correct. */
zassert_equal(fs_stat(path.path, &stat),
0,
"stat sync failed");
zassert_equal(stat.size, TESTFS_BUFFER_SIZE,
"stat sync bad size");
return TC_PASS;
}
static int verify_goodbye(const struct fs_mount_t *mp)
{
struct testfs_path path;
struct fs_file_t file;
fs_file_t_init(&file);
TC_PRINT("verify goodbye\n");
zassert_equal(fs_open(&file,
testfs_path_init(&path, mp,
GOODBYE,
TESTFS_PATH_END),
FS_O_CREATE | FS_O_RDWR),
0,
"verify goodbye failed");
zassert_equal(testfs_verify_incrementing(&file, 0, TESTFS_BUFFER_SIZE),
TESTFS_BUFFER_SIZE,
"write goodbye failed");
zassert_equal(fs_close(&file), 0,
"post sync close failed");
return TC_PASS;
}
void test_fs_basic(void)
{
zassert_equal(fs_mount(fs_basic_test_mp), 0,
"mount failed");
zassert_equal(create_write_hello(fs_basic_test_mp), TC_PASS,
"write hello failed");
zassert_equal(verify_hello(fs_basic_test_mp), TC_PASS,
"verify hello failed");
zassert_equal(seek_within_hello(fs_basic_test_mp), TC_PASS,
"seek within hello failed");
zassert_equal(truncate_hello(fs_basic_test_mp), TC_PASS,
"truncate hello failed");
zassert_equal(unlink_hello(fs_basic_test_mp), TC_PASS,
"unlink hello failed");
zassert_equal(sync_goodbye(fs_basic_test_mp), TC_PASS,
"sync goodbye failed");
TC_PRINT("unmounting %s\n", fs_basic_test_mp->mnt_point);
zassert_equal(fs_unmount(fs_basic_test_mp), 0,
"unmount small failed");
k_sleep(K_MSEC(100)); /* flush log messages */
TC_PRINT("checking double unmount diagnoses\n");
zassert_equal(fs_unmount(fs_basic_test_mp), -EINVAL,
"unmount unmounted failed");
zassert_equal(fs_mount(fs_basic_test_mp), 0,
"mount failed");
zassert_equal(verify_goodbye(fs_basic_test_mp), TC_PASS,
"verify goodbye failed");
zassert_equal(fs_unmount(fs_basic_test_mp), 0,
"unmount2 small failed");
}