1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/tests/unittests/tests-vfs/tests-vfs-file-system-ops.c
Marian Buschsieweke 45c473d721
sys/vfs: use atomic_utils rather C11 atomics
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
2024-03-27 11:26:15 +01:00

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;
}
/** @} */