mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
45c473d721
This has the following advantages: - faster and leaner when C11 atomics are not efficient (e.g. on LLVM this is almost always the case, as LLVM will only use efficient atomics if it doesn't has to bail out to library calls even for exotic things) - Even for GCC e.g. on the nucleo-f429zi this safes 72 B of .text for examples/filesystem despite runtime checks added for over- and underflow - less pain in the ass for C++ and rust users, as both C++ and c2rust are incompatible with C11 atomics - adds test for overflow of the open file counter for more robust operation - adds `assumes()` so that underflows are detected in non-production code
183 lines
4.7 KiB
C
183 lines
4.7 KiB
C
/*
|
|
* Copyright (C) 2016 Eistec AB
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Transparent-box unit tests of vfs functions stubs used when the file
|
|
* system does not implement the requested function.
|
|
*/
|
|
#include <errno.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "atomic_utils.h"
|
|
#include "embUnit/embUnit.h"
|
|
|
|
#include "vfs.h"
|
|
|
|
#include "tests-vfs.h"
|
|
|
|
static const vfs_file_system_ops_t null_fs_ops = {
|
|
.mount = NULL,
|
|
.umount = NULL,
|
|
.unlink = NULL,
|
|
.statvfs = NULL,
|
|
.stat = NULL,
|
|
};
|
|
|
|
static const vfs_file_ops_t null_file_ops = {
|
|
.close = NULL,
|
|
.fstat = NULL,
|
|
.lseek = NULL,
|
|
.open = NULL,
|
|
.read = NULL,
|
|
.write = NULL,
|
|
};
|
|
|
|
static const vfs_dir_ops_t null_dir_ops = {
|
|
.opendir = NULL,
|
|
.readdir = NULL,
|
|
.closedir = NULL,
|
|
};
|
|
|
|
static const vfs_file_system_t null_file_system = {
|
|
.f_op = &null_file_ops,
|
|
.fs_op = &null_fs_ops,
|
|
.d_op = &null_dir_ops,
|
|
};
|
|
|
|
static vfs_mount_t _test_vfs_mount_null = {
|
|
.mount_point = "/test",
|
|
.fs = &null_file_system,
|
|
.private_data = NULL,
|
|
};
|
|
|
|
static int _test_vfs_fs_op_mount_res = -1;
|
|
|
|
static void setup(void)
|
|
{
|
|
_test_vfs_fs_op_mount_res = vfs_mount(&_test_vfs_mount_null);
|
|
}
|
|
|
|
static void teardown(void)
|
|
{
|
|
vfs_umount(&_test_vfs_mount_null, false);
|
|
atomic_store_u16(&_test_vfs_mount_null.open_files, 0);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_mount(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
int res = vfs_mount(&_test_vfs_mount_null);
|
|
/* Already mounted */
|
|
TEST_ASSERT_EQUAL_INT(-EBUSY, res);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_umount(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
int res = vfs_umount(&_test_vfs_mount_null, false);
|
|
TEST_ASSERT_EQUAL_INT(0, res);
|
|
res = vfs_umount(&_test_vfs_mount_null, false);
|
|
/* Not mounted */
|
|
TEST_ASSERT_EQUAL_INT(-EINVAL, res);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_umount__EBUSY(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
uint16_t before = atomic_fetch_add_u16(&_test_vfs_mount_null.open_files, 1);
|
|
TEST_ASSERT(before < UINT16_MAX);
|
|
int res = vfs_umount(&_test_vfs_mount_null, false);
|
|
TEST_ASSERT_EQUAL_INT(-EBUSY, res);
|
|
/* force unmount */
|
|
res = vfs_umount(&_test_vfs_mount_null, true);
|
|
TEST_ASSERT_EQUAL_INT(0, res);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_rename(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
int res = vfs_rename("/test/foo", "/test/bar");
|
|
TEST_ASSERT_EQUAL_INT(-EROFS, res);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_unlink(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
int res = vfs_unlink("/test/foo");
|
|
TEST_ASSERT_EQUAL_INT(-EROFS, res);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_mkdir(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
int res = vfs_mkdir("/test/foodir", 0);
|
|
TEST_ASSERT_EQUAL_INT(-EROFS, res);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_rmdir(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
int res = vfs_rmdir("/test/foodir");
|
|
TEST_ASSERT_EQUAL_INT(-EROFS, res);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_stat(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
struct stat buf;
|
|
int res = vfs_stat("/test/foo", &buf);
|
|
TEST_ASSERT_EQUAL_INT(-EPERM, res);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_statvfs(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
struct statvfs buf;
|
|
int res = vfs_statvfs("/test", &buf);
|
|
TEST_ASSERT_EQUAL_INT(-EPERM, res);
|
|
}
|
|
|
|
static void test_vfs_null_fs_ops_fstatvfs(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(0, _test_vfs_fs_op_mount_res);
|
|
int fd = vfs_open("/test/baz", O_RDONLY, 0);
|
|
TEST_ASSERT(fd >= 0);
|
|
struct statvfs buf;
|
|
int res = vfs_fstatvfs(fd, &buf);
|
|
TEST_ASSERT_EQUAL_INT(-EINVAL, res);
|
|
}
|
|
|
|
Test *tests_vfs_null_file_system_ops_tests(void)
|
|
{
|
|
EMB_UNIT_TESTFIXTURES(fixtures) {
|
|
new_TestFixture(test_vfs_null_fs_ops_mount),
|
|
new_TestFixture(test_vfs_null_fs_ops_umount),
|
|
new_TestFixture(test_vfs_null_fs_ops_umount__EBUSY),
|
|
new_TestFixture(test_vfs_null_fs_ops_rename),
|
|
new_TestFixture(test_vfs_null_fs_ops_unlink),
|
|
new_TestFixture(test_vfs_null_fs_ops_mkdir),
|
|
new_TestFixture(test_vfs_null_fs_ops_rmdir),
|
|
new_TestFixture(test_vfs_null_fs_ops_stat),
|
|
new_TestFixture(test_vfs_null_fs_ops_statvfs),
|
|
new_TestFixture(test_vfs_null_fs_ops_fstatvfs),
|
|
};
|
|
|
|
EMB_UNIT_TESTCALLER(vfs_fs_op_tests, setup, teardown, fixtures);
|
|
|
|
return (Test *)&vfs_fs_op_tests;
|
|
}
|
|
|
|
/** @} */
|