~aleteoryx/muditaos

879213397dbbd3377c34c9be1d8c906e611a4979 — Jakub Pyszczak 5 years ago e7f176a
[EGD-4757] Add unit test for new filesystem

Due to vfs deprecation new filesystem needs
unit tests to verify it's behaviour.This PR
covers core filesystem operations.
M module-vfs/include/user/purefs/fs/filesystem.hpp => module-vfs/include/user/purefs/fs/filesystem.hpp +5 -0
@@ 16,6 16,7 @@
#include <purefs/fs/file_handle.hpp>
#include <purefs/fs/directory_handle.hpp>
#include <purefs/fs/mount_point.hpp>
#include <type_traits>

struct statvfs;
struct stat;


@@ 70,6 71,10 @@ namespace purefs::fs
         */
        template <typename T> auto register_filesystem(std::string_view fsname, std::shared_ptr<T> fops) -> int
        {
            if (!fops || !std::is_convertible_v<T *, filesystem_operations *>) {
                LOG_ERROR("Filesystem not valid");
                return -EINVAL;
            }
            return register_filesystem(fsname, std::shared_ptr<filesystem_operations>(fops));
        }
        auto register_filesystem(std::string_view fsname, std::shared_ptr<filesystem_operations> fops) -> int;

M module-vfs/src/purefs/fs/filesystem.cpp => module-vfs/src/purefs/fs/filesystem.cpp +4 -0
@@ 17,6 17,10 @@ namespace purefs::fs

    auto filesystem::register_filesystem(std::string_view fsname, std::shared_ptr<filesystem_operations> fops) -> int
    {
        if (fops == nullptr) {
            LOG_ERROR("Filesystem operations doesn't exists");
            return -EINVAL;
        }
        cpp_freertos::LockGuard _lck(m_lock);
        const auto it = m_fstypes.find(std::string(fsname));
        if (it != std::end(m_fstypes)) {

M module-vfs/src/purefs/fs/filesystem_syscalls.cpp => module-vfs/src/purefs/fs/filesystem_syscalls.cpp +8 -1
@@ 55,7 55,6 @@ namespace purefs::fs
        return invoke_fops(&filesystem_operations::chmod, path, mode);
    }


    auto filesystem::write(int fd, const char *ptr, size_t len) noexcept -> ssize_t
    {
        return invoke_fops(&filesystem_operations::write, fd, ptr, len);


@@ 172,11 171,19 @@ namespace purefs::fs

    auto filesystem::dirnext(fsdir dirstate, std::string &filename, struct stat &filestat) noexcept -> int
    {
        if (!dirstate) {
            LOG_ERROR("No directory handle");
            return -ENXIO;
        }
        return invoke_fops(&filesystem_operations::dirnext, dirstate, filename, filestat);
    }

    auto filesystem::dirclose(fsdir dirstate) noexcept -> int
    {
        if (!dirstate) {
            LOG_ERROR("No directory handle");
            return -ENXIO;
        }
        return invoke_fops(&filesystem_operations::dirclose, dirstate);
    }


M module-vfs/tests/unittest_filesystem_core.cpp => module-vfs/tests/unittest_filesystem_core.cpp +164 -1
@@ 9,6 9,8 @@
#include <purefs/fs/drivers/filesystem_vfat.hpp>
#include <sys/statvfs.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <tuple>

namespace
{


@@ 105,4 107,165 @@ TEST_CASE("Corefs: Basic API test")
            dirhandle = nullptr;
        }
    }
}
\ No newline at end of file
    REQUIRE(fscore.umount("/sys") == 0);
}

TEST_CASE("Corefs: Create new file, write, read from it")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);
    const auto vfs_vfat = std::make_shared<fs::drivers::filesystem_vfat>();
    REQUIRE(vfs_vfat->mount_count() == 0);
    auto ret = fscore.register_filesystem("vfat", vfs_vfat);
    REQUIRE(ret == 0);
    REQUIRE(fscore.mount("emmc0part0", "/sys", "vfat") == 0);

    int hwnd = fscore.open("/sys/test.txt", O_RDWR | O_CREAT, 0660);
    REQUIRE(hwnd >= 3);
    const std::string text = "test";
    fscore.write(hwnd, text.c_str(), text.size());

    REQUIRE(fscore.close(hwnd) == 0);
    SECTION("Read from file")
    {
        int hwnd = fscore.open("/sys/test.txt", O_RDONLY, 0);
        REQUIRE(hwnd >= 3);
        char buf[sizeof(text.c_str())] = {0};
        REQUIRE(fscore.read(hwnd, buf, sizeof(buf)) == 4);
        REQUIRE(strcmp(buf, text.c_str()) == 0);
        fscore.close(hwnd);
        REQUIRE(fscore.umount("/sys") == 0);
    }

    SECTION("Test seek file")
    {
        int hwnd = fscore.open("/sys/test.txt", O_RDONLY, 0);
        REQUIRE(hwnd >= 3);
        char buf[4096]{};
        REQUIRE(fscore.read(hwnd, buf, sizeof(buf)) == 4);
        REQUIRE(fscore.seek(hwnd, 0, SEEK_END) == 0);
        REQUIRE(fscore.read(hwnd, buf, sizeof(buf)) == 0);
        REQUIRE(fscore.seek(hwnd, 0, SEEK_SET) == 0);
        fscore.close(hwnd);
        REQUIRE(fscore.umount("/sys") == 0);
    }
}

TEST_CASE("Corefs: Register null filesystem")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);
    REQUIRE(fscore.register_filesystem("vfat", nullptr) == -EINVAL);
}

TEST_CASE("Corefs: Mount empty strings")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);
    const auto vfs_vfat = std::make_shared<fs::drivers::filesystem_vfat>();
    REQUIRE(vfs_vfat->mount_count() == 0);
    auto ret = fscore.register_filesystem("vfat", vfs_vfat);
    REQUIRE(ret == 0);
    REQUIRE(fscore.mount("", "", "") == -EINVAL);
    REQUIRE(fscore.umount("") == -ENOENT);
}

TEST_CASE("Corefs: Write to not valid file descriptor")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);
    const auto vfs_vfat = std::make_shared<fs::drivers::filesystem_vfat>();
    REQUIRE(vfs_vfat->mount_count() == 0);
    auto ret = fscore.register_filesystem("vfat", vfs_vfat);
    REQUIRE(ret == 0);
    REQUIRE(fscore.mount("emmc0part0", "/sys", "vfat") == 0);

    const auto fd = fscore.open("/sys/.boot.json", 0, 0);
    REQUIRE(fd >= 3);
    const auto text = "test";
    REQUIRE(fscore.write(0, text, sizeof(text)) == -EBADF);
    REQUIRE(fscore.close(fd) == 0);
    REQUIRE(fscore.umount("/sys") == 0);
}

TEST_CASE("Corefs: Directory operations")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);
    const auto vfs_vfat = std::make_shared<fs::drivers::filesystem_vfat>();
    REQUIRE(vfs_vfat->mount_count() == 0);
    auto ret = fscore.register_filesystem("vfat", vfs_vfat);
    REQUIRE(ret == 0);
    REQUIRE(fscore.mount("emmc0part0", "/sys", "vfat") == 0);

    const auto dirhandle = fscore.diropen("/sys/user");
    REQUIRE(dirhandle);
    REQUIRE(dirhandle->error() == 0);

    SECTION("Null pointer handle dirnext")
    {
        struct stat st;
        std::string fnm;
        REQUIRE(fscore.dirnext(nullptr, fnm, st) == -ENXIO);
        REQUIRE(fscore.dirclose(dirhandle) == 0);
        REQUIRE(fscore.umount("/sys") == 0);
    }

    SECTION("Null pointer handle dirclose")
    {
        REQUIRE(fscore.dirclose(nullptr) == -ENXIO);
        REQUIRE(fscore.dirclose(dirhandle) == 0);
        REQUIRE(fscore.umount("/sys") == 0);
    }

    SECTION("Directory reset")
    {
        struct stat st;
        std::vector<std::tuple<std::string, struct stat>> vec;
        for (std::string fnm;;) {
            if (fscore.dirnext(dirhandle, fnm, st) != 0) {
                break;
            }
            else {
                vec.push_back(std::make_tuple(fnm, st));
                std::cout << "name " << fnm << " size " << st.st_size << std::endl;
            }
        }

        fscore.dirreset(dirhandle);
        int i = 0;
        for (std::string fnm;; i++) {
            if (fscore.dirnext(dirhandle, fnm, st) != 0) {
                break;
            }
            else {
                const auto [fnm_vec, st_vec] = vec[i];
                REQUIRE(fnm == fnm_vec);
                REQUIRE(st_vec.st_size == st.st_size);
                std::cout << "name " << fnm << " size " << st.st_size << std::endl;
            }
        }
        REQUIRE(fscore.dirclose(dirhandle) == 0);
        REQUIRE(fscore.umount("/sys") == 0);
    }
}