#include #include #include #include #include "test_fs.h" // ============================================================================ // Helper function // ============================================================================ static int create_dir(const char *dir_path) { int ret; ret = mkdir(dir_path, 00775); if (ret < 0) { THROW_ERROR("failed to create the dir"); } return 0; } static int remove_dir(const char *dir_path) { int ret; ret = rmdir(dir_path); if (ret < 0) { THROW_ERROR("failed to remove the created dir"); } return 0; } // ============================================================================ // Test cases for mkdir // ============================================================================ static int __test_mkdir(const char *dir_path) { struct stat stat_buf; mode_t mode = 00775; if (mkdir(dir_path, mode) < 0) { THROW_ERROR("failed to mkdir"); } if (stat(dir_path, &stat_buf) < 0) { THROW_ERROR("failed to stat dir"); } if (!S_ISDIR(stat_buf.st_mode)) { THROW_ERROR("failed to check if it is dir"); } return 0; } static int __test_mkdir_with_suffix(const char *dir_path) { struct stat stat_buf; char new_dir_path[PATH_MAX] = { 0 }; snprintf(new_dir_path, sizeof(new_dir_path), "%s/", dir_path); mode_t mode = 00775; if (mkdir(new_dir_path, mode) < 0) { THROW_ERROR("failed to mkdir"); } if (stat(new_dir_path, &stat_buf) < 0) { THROW_ERROR("failed to stat dir"); } if (!S_ISDIR(stat_buf.st_mode)) { THROW_ERROR("failed to check if it is dir"); } return 0; } static int __test_mkdirat(const char *dir_path) { struct stat stat_buf; mode_t mode = 00775; char dir_buf[PATH_MAX] = { 0 }; char base_buf[PATH_MAX] = { 0 }; char *dir_name, *last_name; int dirfd; if (fs_split_path(dir_path, dir_buf, &dir_name, base_buf, &last_name) < 0) { THROW_ERROR("failed to split path"); } dirfd = open(dir_name, O_RDONLY); if (dirfd < 0) { THROW_ERROR("failed to open dir"); } if (mkdirat(dirfd, last_name, mode) < 0) { THROW_ERROR("failed to mkdirat dir with dirfd"); } close(dirfd); if (stat(dir_path, &stat_buf) < 0) { THROW_ERROR("failed to stat dir"); } if (!S_ISDIR(stat_buf.st_mode)) { THROW_ERROR("failed to check if it is dir"); } return 0; } typedef int(*test_mkdir_func_t)(const char *); static int test_mkdir_framework(test_mkdir_func_t fn) { const char *dir_path = "/root/test_filesystem_mkdir"; if (fn(dir_path) < 0) { return -1; } if (remove_dir(dir_path) < 0) { return -1; } return 0; } static int test_mkdir() { return test_mkdir_framework(__test_mkdir); } static int test_mkdir_with_suffix() { return test_mkdir_framework(__test_mkdir_with_suffix); } static int test_mkdirat() { return test_mkdir_framework(__test_mkdirat); } // ============================================================================ // Test cases for chdir // ============================================================================ static int __test_chdir(const char *dir_path) { char buf[128] = { 0 }; char *cwd; if (chdir(dir_path) < 0) { THROW_ERROR("failed to chdir"); } cwd = getcwd(buf, sizeof(buf)); if (cwd != buf) { THROW_ERROR("failed to getcwd"); } if (strcmp(buf, dir_path)) { THROW_ERROR("the cwd is incorrect after chdir"); } // Check getcwd via explicit syscall int ret = syscall(__NR_getcwd, buf, sizeof(buf)); if (ret < 0) { THROW_ERROR("failed to call via explicit syscall"); } if (ret != strlen(dir_path) + 1) { THROW_ERROR("failed to check the return value from kernel"); } return 0; } static int test_chdir_framework(test_mkdir_func_t fn) { const char *dir_path = "/root/test_filesystem_chdir"; if (create_dir(dir_path) < 0) { return -1; } if (fn(dir_path) < 0) { return -1; } if (remove_dir(dir_path) < 0) { return -1; } return 0; } static int test_chdir() { return test_chdir_framework(__test_chdir); } // ============================================================================ // Test cases for rmdir // ============================================================================ static int __test_rmdir_via_unlinkat(const char *dir_path) { struct stat stat_buf; int ret; if (unlinkat(AT_FDCWD, dir_path, AT_REMOVEDIR) < 0) { THROW_ERROR("failed to remove dir"); } ret = stat(dir_path, &stat_buf); if (!(ret < 0 && errno == ENOENT)) { THROW_ERROR("stat on \"%s\" should return ENOENT", dir_path); } return 0; } static int test_rmdir_framework(test_mkdir_func_t fn) { const char *dir_path = "/root/test_filesystem_rmdir"; if (create_dir(dir_path) < 0) { return -1; } if (fn(dir_path) < 0) { return -1; } return 0; } static int test_rmdir_via_unlinkat() { return test_rmdir_framework(__test_rmdir_via_unlinkat); } // ============================================================================ // Test suite main // ============================================================================ static test_case_t test_cases[] = { TEST_CASE(test_mkdir), TEST_CASE(test_mkdir_with_suffix), TEST_CASE(test_mkdirat), TEST_CASE(test_chdir), TEST_CASE(test_rmdir_via_unlinkat), }; int main(int argc, const char *argv[]) { return test_suite_run(test_cases, ARRAY_SIZE(test_cases)); }