test_storage_pmdk.cpp 4.43 KiB
Newer Older
/*
  Copyright 2018-2020, Barcelona Supercomputing Center (BSC), Spain
  Copyright 2015-2020, Johannes Gutenberg Universitaet Mainz, Germany

  This software was partially supported by the
  EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).

  This software was partially supported by the
  ADA-FS project under the SPPEXA project funded by the DFG.

  SPDX-License-Identifier: MIT
*/

#include <catch2/catch.hpp>
#include <fmt/format.h>
#include <daemon/backend/data/pmdk/pool.hpp>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;


// FIXME: temporary solution to have correct loggers for tests
#include <spdlog/sinks/basic_file_sink.h>

#include <vector>
#include <list>


namespace {

void
patch_gkfs_loggers(const std::vector<std::string>& loggers_name,
                   spdlog::level::level_enum level, const std::string& path) {

    /* Create common sink */
    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(path);

    /* Create and configure loggers */
    auto loggers = std::list<std::shared_ptr<spdlog::logger>>();
    for (const auto& name: loggers_name) {

        if(spdlog::get(name)) {
            continue;
        }

        auto logger = std::make_shared<spdlog::logger>(name, file_sink);
        logger->flush_on(spdlog::level::trace);
        loggers.push_back(logger);
    }

    /* register loggers */
    for (const auto& logger: loggers) {
        spdlog::register_logger(logger);
    }

    // set logger format
    spdlog::set_pattern("[%C-%m-%d %H:%M:%S.%f] %P [%L][%n] %v");

    spdlog::set_level(level);
}

} // namespace

// end of temporary solution

namespace {

fs::path
create_temporary_directory() {
    auto tmpdir = fs::temp_directory_path() / fs::unique_path();

    boost::system::error_code ec;

    if(!fs::create_directory(tmpdir, ec)) {
        throw std::runtime_error(ec.message());
    }

    return tmpdir;
}

} // namespace


SCENARIO( "PMDK pools can be created", "[pmdk_storage_pool]" ) {


    auto logger_names = std::vector<std::string>{
        "main",
        "MetadataDB",
        "DataModule",
    };

    ::patch_gkfs_loggers(logger_names, spdlog::level::debug, "/dev/stdout");

    GIVEN( "A valid parent directory " ) {

        WHEN( "Size is a positive integer" ) {

            std::size_t pool_size = 420;
            auto tmpdir = create_temporary_directory();

            pmdk::pool p(tmpdir, pool_size);

            THEN( "The pool object is valid " ) {
                REQUIRE(p);
                REQUIRE(p.valid());
                REQUIRE(p.size() == pool_size);
                REQUIRE(p.data() != nullptr);
            }

            AND_THEN( "The mapping file exists and has the correct size" ) {
                REQUIRE(fs::exists(p.path()));
                REQUIRE(fs::file_size(p.path()) == pool_size);
            }
        }

        WHEN( "Size is zero" ) {

            auto tmpdir = create_temporary_directory();

            pmdk::pool p(tmpdir, 0);

            THEN( "The pool object is invalid " ) {
                REQUIRE(!p);
                REQUIRE(!p.valid());

                AND_THEN( "Internal members are default initialized" ) {
                    REQUIRE(p.path().empty());
                    REQUIRE(p.data() == nullptr);
                    REQUIRE(p.size() == 0);
                }
            }
        }

        WHEN( "Size is negative" ) {

            auto tmpdir = create_temporary_directory();

            pmdk::pool p(tmpdir, -1);

            THEN( "The pool object is invalid " ) {
                REQUIRE(!p);
                REQUIRE(!p.valid());

                AND_THEN( "Internal members are default initialized" ) {
                    REQUIRE(p.path().empty());
                    REQUIRE(p.data() == nullptr);
                    REQUIRE(p.size() == 0);
                }
            }
        }
    }

    GIVEN( "An invalid parent directory " ) {

        WHEN( "Parent directory does not exist" ) {

            std::size_t pool_size = 420;
            auto tmpdir = create_temporary_directory();

            pmdk::pool p("/foo/bar/", pool_size);

            THEN( "The pool object is invalid " ) {
                REQUIRE(!p);
                REQUIRE(!p.valid());

                AND_THEN( "Internal members are default initialized" ) {
                    REQUIRE(p.path().empty());
                    REQUIRE(p.data() == nullptr);
                    REQUIRE(p.size() == 0);
                }
            }
        }
    }
}