diff --git a/.codecov.yml b/.codecov.yml index c73b831a..f2ab3be5 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -6,4 +6,4 @@ ignore: - "**/*_generated.h" - "src/mocks/**" - "src/lib/homestore/tests/**" - - "src/lib/memory/tests/**" + - "src/lib/tests/**" diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 1ecab4af..3c0ed3e0 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -12,6 +12,9 @@ target_link_libraries(${PROJECT_NAME}_core ${COMMON_DEPS} ) +if(BUILD_TESTING) +add_subdirectory(tests) +endif() add_subdirectory(homestore) add_subdirectory(memory) diff --git a/src/lib/memory/CMakeLists.txt b/src/lib/memory/CMakeLists.txt index 60df38a1..ac7c7083 100644 --- a/src/lib/memory/CMakeLists.txt +++ b/src/lib/memory/CMakeLists.txt @@ -12,5 +12,27 @@ target_link_libraries("${PROJECT_NAME}_memory" ) if(BUILD_TESTING) - add_subdirectory(tests) +add_executable (pg_memory_test) +target_sources(pg_memory_test PRIVATE $) +target_link_libraries(pg_memory_test + homeobject_memory + ${COMMON_TEST_DEPS} + ) +add_test(NAME PGMemoryTest COMMAND pg_memory_test -csv error) + +add_executable (shard_memory_test) +target_sources(shard_memory_test PRIVATE $) +target_link_libraries(shard_memory_test + homeobject_memory + ${COMMON_TEST_DEPS} + ) +add_test(NAME ShardMemoryTest COMMAND shard_memory_test -csv error) + +add_executable (blob_memory_test) +target_sources(blob_memory_test PRIVATE $) +target_link_libraries(blob_memory_test + homeobject_memory + ${COMMON_TEST_DEPS} + ) +add_test(NAME BlobMemoryTest COMMAND blob_memory_test -csv error) endif() diff --git a/src/lib/memory/tests/BlobManagerTest.cpp b/src/lib/memory/tests/BlobManagerTest.cpp deleted file mode 100644 index bf4816ea..00000000 --- a/src/lib/memory/tests/BlobManagerTest.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "lib/memory/homeobject.hpp" - -using homeobject::Blob; -using homeobject::blob_id; -using homeobject::BlobError; -using homeobject::peer_id; - -SISL_LOGGING_INIT(logging, HOMEOBJECT_LOG_MODS) -SISL_OPTIONS_ENABLE(logging) - -class FixtureApp : public homeobject::HomeObjectApplication { -public: - bool spdk_mode() const override { return false; } - uint32_t threads() const override { return 2; } - std::list< std::filesystem::path > devices() const override { return std::list< std::filesystem::path >(); } - homeobject::peer_id discover_svcid(std::optional< homeobject::peer_id > const& p) const override { - return p.value(); - } - std::string lookup_peer(homeobject::peer_id const&) const override { return "test_fixture.com"; } -}; - -class BlobManagerFixture : public ::testing::Test { - std::shared_ptr< FixtureApp > app; - -public: - homeobject::ShardInfo _shard_1; - homeobject::ShardInfo _shard_2; - homeobject::pg_id _pg_id{1u}; - peer_id _peer1; - peer_id _peer2; - blob_id _blob_id; - - void SetUp() override { - app = std::make_shared< FixtureApp >(); - m_memory_homeobj = homeobject::init_homeobject(std::weak_ptr< homeobject::HomeObjectApplication >(app)); - _peer1 = m_memory_homeobj->our_uuid(); - _peer2 = boost::uuids::random_generator()(); - - auto info = homeobject::PGInfo(_pg_id); - info.members.insert(homeobject::PGMember{_peer1, "peer1", 1}); - info.members.insert(homeobject::PGMember{_peer2, "peer2", 0}); - - LOGDEBUG("Setup Pg"); - EXPECT_TRUE(m_memory_homeobj->pg_manager()->create_pg(std::move(info)).get()); - - LOGDEBUG("Setup Shards"); - auto s_e = m_memory_homeobj->shard_manager()->create_shard(_pg_id, Mi).get(); - ASSERT_TRUE(!!s_e); - s_e.then([this](auto&& i) { _shard_1 = std::move(i); }); - - s_e = m_memory_homeobj->shard_manager()->create_shard(_pg_id, Mi).get(); - ASSERT_TRUE(!!s_e); - s_e.then([this](auto&& i) { _shard_2 = std::move(i); }); - - LOGDEBUG("Get on empty Shard: {}", _shard_1.id); - auto g_e = m_memory_homeobj->blob_manager()->get(_shard_1.id, 0).get(); - ASSERT_FALSE(g_e); - EXPECT_EQ(BlobError::UNKNOWN_BLOB, g_e.error()); - - LOGDEBUG("Insert Blob to: {}", _shard_1.id); - auto o_e = m_memory_homeobj->blob_manager() - ->put(_shard_1.id, Blob{sisl::io_blob_safe(4 * Ki, 512u), "test_blob", 4 * Mi}) - .get(); - EXPECT_TRUE(!!o_e); - o_e.then([this](auto&& b) mutable { _blob_id = std::move(b); }); - } - -protected: - std::shared_ptr< homeobject::HomeObject > m_memory_homeobj; -}; - -TEST_F(BlobManagerFixture, BasicTests) { - auto const batch_sz = 4; - std::mutex call_lock; - auto calls = std::list< folly::SemiFuture< folly::Unit > >(); - - auto t_v = std::vector< std::thread >(); - for (auto k = 0; batch_sz > k; ++k) { - t_v.push_back(std::thread([this, &call_lock, &calls, batch_sz]() mutable { - auto our_calls = std::list< folly::SemiFuture< folly::Unit > >(); - for (auto i = _blob_id + _shard_2.id + 1; (_blob_id + _shard_1.id + 1) + ((100 * Ki) / batch_sz) > i; ++i) { - our_calls.push_back( - m_memory_homeobj->blob_manager()->get(_shard_1.id, _blob_id).deferValue([](auto const& e) { - EXPECT_TRUE(!!e); - e.then([](auto const& blob) { - EXPECT_STREQ(blob.user_key.c_str(), "test_blob"); - EXPECT_EQ(blob.object_off, 4 * Mi); - }); - })); - our_calls.push_back( - m_memory_homeobj->blob_manager()->get(i, _blob_id).deferValue([](auto const& e) {})); - our_calls.push_back( - m_memory_homeobj->blob_manager()->get(_shard_1.id, (i - _shard_2.id)).deferValue([](auto const&) { - })); - our_calls.push_back( - m_memory_homeobj->blob_manager()->get(_shard_2.id, (i - _shard_2.id)).deferValue([](auto const&) { - })); - our_calls.push_back( - m_memory_homeobj->blob_manager() - ->put(i, Blob{sisl::io_blob_safe(512u, 512u), "test_blob", 0ul}) - .deferValue([](auto const& e) { EXPECT_EQ(BlobError::UNKNOWN_SHARD, e.error()); })); - our_calls.push_back(m_memory_homeobj->blob_manager() - ->put(_shard_1.id, Blob{sisl::io_blob_safe(4 * Ki, 512u), "test_blob", 4 * Mi}) - .deferValue([](auto const& e) { EXPECT_TRUE(!!e); })); - our_calls.push_back( - m_memory_homeobj->blob_manager() - ->put(_shard_2.id, Blob{sisl::io_blob_safe(8 * Ki, 512u), "test_blob_2", 4 * Mi}) - .deferValue([](auto const& e) { EXPECT_TRUE(!!e); })); - our_calls.push_back( - m_memory_homeobj->blob_manager()->del(i, _blob_id).deferValue([](auto const& e) {})); - our_calls.push_back( - m_memory_homeobj->blob_manager()->del(_shard_1.id, (i - _shard_2.id)).deferValue([](auto const& e) { - EXPECT_EQ(BlobError::UNKNOWN_BLOB, e.error()); - })); - } - - auto lg = std::scoped_lock(call_lock); - calls.splice(calls.end(), std::move(our_calls)); - })); - } - for (auto& t : t_v) - t.join(); - folly::collectAll(calls).via(folly::getGlobalCPUExecutor()).get(); - EXPECT_TRUE(m_memory_homeobj->shard_manager()->seal_shard(_shard_1.id).get()); - auto p_e = m_memory_homeobj->blob_manager() - ->put(_shard_1.id, Blob{sisl::io_blob_safe(4 * Ki, 512u), "test_blob", 4 * Mi}) - .get(); - ASSERT_TRUE(!p_e); - EXPECT_EQ(BlobError::INVALID_ARG, p_e.error()); - - EXPECT_TRUE(m_memory_homeobj->blob_manager()->del(_shard_1.id, _blob_id).get()); - EXPECT_EQ(BlobError::UNKNOWN_BLOB, m_memory_homeobj->blob_manager()->get(_shard_1.id, _blob_id).get().error()); - EXPECT_EQ(BlobError::UNKNOWN_BLOB, m_memory_homeobj->blob_manager()->del(_shard_1.id, _blob_id).get().error()); -} - -int main(int argc, char* argv[]) { - int parsed_argc = argc; - ::testing::InitGoogleTest(&parsed_argc, argv); - SISL_OPTIONS_LOAD(parsed_argc, argv, logging); - sisl::logging::SetLogger(std::string(argv[0])); - spdlog::set_pattern("[%D %T.%e] [%n] [%^%l%$] [%t] %v"); - parsed_argc = 1; - auto f = ::folly::Init(&parsed_argc, &argv, true); - return RUN_ALL_TESTS(); -} diff --git a/src/lib/memory/tests/CMakeLists.txt b/src/lib/memory/tests/CMakeLists.txt deleted file mode 100644 index 2c01e2ce..00000000 --- a/src/lib/memory/tests/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -cmake_minimum_required (VERSION 3.11) - -find_package(GTest REQUIRED) - -include_directories(BEFORE ${homeobject_INCLUDE_DIRS}) - -add_executable (pg_memory_test) -target_sources(pg_memory_test PRIVATE PGManagerTest.cpp) -target_link_libraries(pg_memory_test - homeobject_memory - ${COMMON_TEST_DEPS} - ) -add_test(NAME PGMemoryTest COMMAND pg_memory_test -csv error) - -add_executable (shard_memory_test) -target_sources(shard_memory_test PRIVATE ShardManagerTest.cpp) -target_link_libraries(shard_memory_test - homeobject_memory - ${COMMON_TEST_DEPS} - ) -add_test(NAME ShardMemoryTest COMMAND shard_memory_test -csv error) - -add_executable (blob_memory_test) -target_sources(blob_memory_test PRIVATE BlobManagerTest.cpp) -target_link_libraries(blob_memory_test - homeobject_memory - ${COMMON_TEST_DEPS} - ) -add_test(NAME BlobMemoryTest COMMAND blob_memory_test -csv error) diff --git a/src/lib/memory/tests/PGManagerTest.cpp b/src/lib/memory/tests/PGManagerTest.cpp deleted file mode 100644 index 53c52d19..00000000 --- a/src/lib/memory/tests/PGManagerTest.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include - -#include -#include -#include -#include - -#include -#include - -#include "lib/memory/homeobject.hpp" - -using homeobject::PGError; -using homeobject::PGInfo; -using homeobject::PGMember; - -SISL_LOGGING_INIT(logging, HOMEOBJECT_LOG_MODS) -SISL_OPTIONS_ENABLE(logging) - -class FixtureApp : public homeobject::HomeObjectApplication { -public: - bool spdk_mode() const override { return false; } - uint32_t threads() const override { return 2; } - std::list< std::filesystem::path > devices() const override { return std::list< std::filesystem::path >(); } - homeobject::peer_id discover_svcid(std::optional< homeobject::peer_id > const& p) const override { - return p.value(); - } - std::string lookup_peer(homeobject::peer_id const&) const override { return "test_fixture.com"; } -}; - -class PgManagerFixture : public ::testing::Test { -public: - void SetUp() override { - app = std::make_shared< FixtureApp >(); - m_memory_homeobj = homeobject::init_homeobject(std::weak_ptr< homeobject::HomeObjectApplication >(app)); - } - -protected: - std::shared_ptr< FixtureApp > app; - std::shared_ptr< homeobject::HomeObject > m_memory_homeobj; -}; - -TEST_F(PgManagerFixture, CreatePgEmpty) { - EXPECT_EQ(m_memory_homeobj->pg_manager()->create_pg(PGInfo(0u)).get().error(), PGError::INVALID_ARG); -} - -TEST_F(PgManagerFixture, CreatePgNoLeader) { - auto info = PGInfo(0u); - info.members.insert(PGMember{boost::uuids::random_generator()()}); - EXPECT_EQ(m_memory_homeobj->pg_manager()->create_pg(std::move(info)).get().error(), PGError::INVALID_ARG); -} - -TEST_F(PgManagerFixture, CreatePgNotMember) { - auto info = PGInfo(0u); - info.members.insert(PGMember{boost::uuids::random_generator()(), "unknown", 1}); - EXPECT_EQ(m_memory_homeobj->pg_manager()->create_pg(std::move(info)).get().error(), PGError::INVALID_ARG); -} - -class PgManagerFixtureWPg : public PgManagerFixture { -public: - homeobject::pg_id _pg_id{1u}; - homeobject::peer_id _peer1; - homeobject::peer_id _peer2; - - void SetUp() override { - PgManagerFixture::SetUp(); - _peer1 = m_memory_homeobj->our_uuid(); - _peer2 = boost::uuids::random_generator()(); - - auto info = PGInfo(_pg_id); - info.members.insert(PGMember{_peer1, "peer1", 1}); - info.members.insert(PGMember{_peer2, "peer2", 0}); - EXPECT_TRUE(m_memory_homeobj->pg_manager()->create_pg(std::move(info)).get()); - } -}; - -TEST_F(PgManagerFixtureWPg, CreateDuplicatePg) { - auto info = PGInfo(_pg_id); - info.members.insert(PGMember{boost::uuids::random_generator()(), "peer3", 6}); - info.members.insert(PGMember{boost::uuids::random_generator()(), "peer4", 2}); - EXPECT_EQ(m_memory_homeobj->pg_manager()->create_pg(std::move(info)).get().error(), PGError::INVALID_ARG); -} - -TEST_F(PgManagerFixtureWPg, Migrate) { - EXPECT_EQ(m_memory_homeobj->pg_manager() - ->replace_member(UINT16_MAX, boost::uuids::random_generator()(), - PGMember{boost::uuids::random_generator()()}) - .get() - .error(), - PGError::UNKNOWN_PG); - EXPECT_EQ( - m_memory_homeobj->pg_manager() - ->replace_member(_pg_id, boost::uuids::random_generator()(), PGMember{boost::uuids::random_generator()()}) - .get() - .error(), - PGError::UNKNOWN_PEER); - EXPECT_EQ(m_memory_homeobj->pg_manager()->replace_member(_pg_id, _peer1, PGMember{_peer1}).get().error(), - PGError::INVALID_ARG); - EXPECT_EQ(m_memory_homeobj->pg_manager()->replace_member(_pg_id, _peer1, PGMember{_peer2}).get().error(), - PGError::INVALID_ARG); - EXPECT_EQ(m_memory_homeobj->pg_manager() - ->replace_member(_pg_id, _peer1, PGMember{boost::uuids::random_generator()()}) - .get() - .error(), - PGError::INVALID_ARG); - EXPECT_TRUE(m_memory_homeobj->pg_manager() - ->replace_member(_pg_id, _peer2, PGMember{boost::uuids::random_generator()()}) - .get()); -} - -int main(int argc, char* argv[]) { - int parsed_argc = argc; - ::testing::InitGoogleTest(&parsed_argc, argv); - SISL_OPTIONS_LOAD(parsed_argc, argv, logging); - sisl::logging::SetLogger(std::string(argv[0])); - spdlog::set_pattern("[%D %T.%e] [%n] [%^%l%$] [%t] %v"); - parsed_argc = 1; - auto f = ::folly::Init(&parsed_argc, &argv, true); - return RUN_ALL_TESTS(); -} diff --git a/src/lib/memory/tests/ShardManagerTest.cpp b/src/lib/memory/tests/ShardManagerTest.cpp deleted file mode 100644 index f2b1f8ef..00000000 --- a/src/lib/memory/tests/ShardManagerTest.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include - -#include -#include -#include -#include - -#include -#include - -#include "lib/memory/homeobject.hpp" - -using homeobject::shard_id; -using homeobject::ShardError; -using homeobject::ShardInfo; - -SISL_LOGGING_INIT(logging, HOMEOBJECT_LOG_MODS) -SISL_OPTIONS_ENABLE(logging) - -class FixtureApp : public homeobject::HomeObjectApplication { -public: - bool spdk_mode() const override { return false; } - uint32_t threads() const override { return 2; } - std::list< std::filesystem::path > devices() const override { return std::list< std::filesystem::path >(); } - homeobject::peer_id discover_svcid(std::optional< homeobject::peer_id > const& p) const override { - return p.value(); - } - std::string lookup_peer(homeobject::peer_id const&) const override { return "test_fixture.com"; } -}; - -class ShardManagerFixture : public ::testing::Test { -public: - homeobject::pg_id _pg_id{1u}; - homeobject::peer_id _peer1; - homeobject::peer_id _peer2; - - void SetUp() override { - app = std::make_shared< FixtureApp >(); - m_memory_homeobj = homeobject::init_homeobject(std::weak_ptr< homeobject::HomeObjectApplication >(app)); - _peer1 = m_memory_homeobj->our_uuid(); - _peer2 = boost::uuids::random_generator()(); - - auto info = homeobject::PGInfo(_pg_id); - info.members.insert(homeobject::PGMember{_peer1, "peer1", 1}); - info.members.insert(homeobject::PGMember{_peer2, "peer2", 0}); - EXPECT_TRUE(m_memory_homeobj->pg_manager()->create_pg(std::move(info)).get()); - } - -protected: - std::shared_ptr< FixtureApp > app; - std::shared_ptr< homeobject::HomeObject > m_memory_homeobj; -}; - -TEST_F(ShardManagerFixture, CreateShardTooBig) { - EXPECT_EQ(ShardError::INVALID_ARG, - m_memory_homeobj->shard_manager() - ->create_shard(_pg_id, homeobject::ShardManager::max_shard_size() + 1) - .get() - .error()); -} - -TEST_F(ShardManagerFixture, CreateShardTooSmall) { - EXPECT_EQ(ShardError::INVALID_ARG, m_memory_homeobj->shard_manager()->create_shard(_pg_id, 0ul).get().error()); -} - -TEST_F(ShardManagerFixture, CreateShardNoPg) { - EXPECT_EQ(ShardError::UNKNOWN_PG, m_memory_homeobj->shard_manager()->create_shard(_pg_id + 1, Mi).get().error()); -} - -class ShardManagerFixtureWShard : public ShardManagerFixture { -public: - ShardInfo _shard; - void SetUp() override { - ShardManagerFixture::SetUp(); - auto e = m_memory_homeobj->shard_manager()->create_shard(_pg_id, Mi).get(); - ASSERT_TRUE(!!e); - e.then([this](auto&& i) { _shard = std::move(i); }); - EXPECT_EQ(ShardInfo::State::OPEN, _shard.state); - EXPECT_EQ(Mi, _shard.total_capacity_bytes); - EXPECT_EQ(Mi, _shard.available_capacity_bytes); - EXPECT_EQ(0ul, _shard.deleted_capacity_bytes); - EXPECT_EQ(_pg_id, _shard.placement_group); - } -}; - -TEST_F(ShardManagerFixtureWShard, GetUnknownShard) { - EXPECT_EQ(ShardError::UNKNOWN_SHARD, m_memory_homeobj->shard_manager()->get_shard(_shard.id + 1).get().error()); -} - -TEST_F(ShardManagerFixtureWShard, GetKnownShard) { - auto e = m_memory_homeobj->shard_manager()->get_shard(_shard.id).get(); - ASSERT_TRUE(!!e); - e.then([this](auto const& info) { - EXPECT_TRUE(info.id == _shard.id); - EXPECT_TRUE(info.placement_group == _shard.placement_group); - EXPECT_EQ(info.state, ShardInfo::State::OPEN); - }); -} - -TEST_F(ShardManagerFixtureWShard, ListShardsNoPg) { - EXPECT_EQ(ShardError::UNKNOWN_PG, m_memory_homeobj->shard_manager()->list_shards(_pg_id + 1).get().error()); -} - -TEST_F(ShardManagerFixtureWShard, ListShards) { - auto e = m_memory_homeobj->shard_manager()->list_shards(_pg_id).get(); - ASSERT_TRUE(!!e); - e.then([this](auto const& info_list) { - ASSERT_EQ(info_list.size(), 1); - EXPECT_TRUE(info_list.begin()->id == _shard.id); - EXPECT_TRUE(info_list.begin()->placement_group == _shard.placement_group); - EXPECT_EQ(info_list.begin()->state, ShardInfo::State::OPEN); - }); -} - -TEST_F(ShardManagerFixtureWShard, SealShardNoShard) { - EXPECT_EQ(ShardError::UNKNOWN_SHARD, m_memory_homeobj->shard_manager()->seal_shard(_shard.id + 1).get().error()); -} - -TEST_F(ShardManagerFixtureWShard, SealShard) { - for (auto i = 0; 2 > i; ++i) { - auto e = m_memory_homeobj->shard_manager()->seal_shard(_shard.id).get(); - ASSERT_TRUE(!!e); - e.then([this](auto const& info) { - EXPECT_TRUE(info.id == _shard.id); - EXPECT_TRUE(info.placement_group == _shard.placement_group); - EXPECT_EQ(info.state, ShardInfo::State::SEALED); - }); - } -} - -int main(int argc, char* argv[]) { - int parsed_argc = argc; - ::testing::InitGoogleTest(&parsed_argc, argv); - SISL_OPTIONS_LOAD(parsed_argc, argv, logging); - sisl::logging::SetLogger(std::string(argv[0])); - spdlog::set_pattern("[%D %T.%e] [%n] [%^%l%$] [%t] %v"); - parsed_argc = 1; - auto f = ::folly::Init(&parsed_argc, &argv, true); - return RUN_ALL_TESTS(); -} diff --git a/src/lib/tests/BlobManagerTest.cpp b/src/lib/tests/BlobManagerTest.cpp new file mode 100644 index 00000000..1da3bc78 --- /dev/null +++ b/src/lib/tests/BlobManagerTest.cpp @@ -0,0 +1,76 @@ +#include + +#include +#include + +#include +#include "lib/tests/fixture_app.hpp" + +TEST_F(TestFixture, BasicTests) { + auto const batch_sz = 4; + std::mutex call_lock; + auto calls = std::list< folly::SemiFuture< folly::Unit > >(); + + auto t_v = std::vector< std::thread >(); + for (auto k = 0; batch_sz > k; ++k) { + t_v.push_back(std::thread([this, &call_lock, &calls, batch_sz]() mutable { + auto our_calls = std::list< folly::SemiFuture< folly::Unit > >(); + for (auto i = _blob_id + _shard_2.id + 1; (_blob_id + _shard_1.id + 1) + ((100 * Ki) / batch_sz) > i; ++i) { + our_calls.push_back(homeobj_->blob_manager()->get(_shard_1.id, _blob_id).deferValue([](auto const& e) { + EXPECT_TRUE(!!e); + e.then([](auto const& blob) { + EXPECT_STREQ(blob.user_key.c_str(), "test_blob"); + EXPECT_EQ(blob.object_off, 4 * Mi); + }); + })); + our_calls.push_back(homeobj_->blob_manager()->get(i, _blob_id).deferValue([](auto const& e) {})); + our_calls.push_back( + homeobj_->blob_manager()->get(_shard_1.id, (i - _shard_2.id)).deferValue([](auto const&) {})); + our_calls.push_back( + homeobj_->blob_manager()->get(_shard_2.id, (i - _shard_2.id)).deferValue([](auto const&) {})); + our_calls.push_back( + homeobj_->blob_manager() + ->put(i, Blob{sisl::io_blob_safe(512u, 512u), "test_blob", 0ul}) + .deferValue([](auto const& e) { EXPECT_EQ(BlobError::UNKNOWN_SHARD, e.error()); })); + our_calls.push_back(homeobj_->blob_manager() + ->put(_shard_1.id, Blob{sisl::io_blob_safe(4 * Ki, 512u), "test_blob", 4 * Mi}) + .deferValue([](auto const& e) { EXPECT_TRUE(!!e); })); + our_calls.push_back( + homeobj_->blob_manager() + ->put(_shard_2.id, Blob{sisl::io_blob_safe(8 * Ki, 512u), "test_blob_2", 4 * Mi}) + .deferValue([](auto const& e) { EXPECT_TRUE(!!e); })); + our_calls.push_back(homeobj_->blob_manager()->del(i, _blob_id).deferValue([](auto const& e) {})); + our_calls.push_back( + homeobj_->blob_manager()->del(_shard_1.id, (i - _shard_2.id)).deferValue([](auto const& e) { + EXPECT_EQ(BlobError::UNKNOWN_BLOB, e.error()); + })); + } + + auto lg = std::scoped_lock(call_lock); + calls.splice(calls.end(), std::move(our_calls)); + })); + } + for (auto& t : t_v) + t.join(); + folly::collectAll(calls).via(folly::getGlobalCPUExecutor()).get(); + EXPECT_TRUE(homeobj_->shard_manager()->seal_shard(_shard_1.id).get()); + auto p_e = + homeobj_->blob_manager()->put(_shard_1.id, Blob{sisl::io_blob_safe(4 * Ki, 512u), "test_blob", 4 * Mi}).get(); + ASSERT_TRUE(!p_e); + EXPECT_EQ(BlobError::INVALID_ARG, p_e.error()); + + EXPECT_TRUE(homeobj_->blob_manager()->del(_shard_1.id, _blob_id).get()); + EXPECT_EQ(BlobError::UNKNOWN_BLOB, homeobj_->blob_manager()->get(_shard_1.id, _blob_id).get().error()); + EXPECT_EQ(BlobError::UNKNOWN_BLOB, homeobj_->blob_manager()->del(_shard_1.id, _blob_id).get().error()); +} + +int main(int argc, char* argv[]) { + int parsed_argc = argc; + ::testing::InitGoogleTest(&parsed_argc, argv); + SISL_OPTIONS_LOAD(parsed_argc, argv, logging); + sisl::logging::SetLogger(std::string(argv[0])); + spdlog::set_pattern("[%D %T.%e] [%n] [%^%l%$] [%t] %v"); + parsed_argc = 1; + auto f = ::folly::Init(&parsed_argc, &argv, true); + return RUN_ALL_TESTS(); +} diff --git a/src/lib/tests/CMakeLists.txt b/src/lib/tests/CMakeLists.txt new file mode 100644 index 00000000..083c149b --- /dev/null +++ b/src/lib/tests/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required (VERSION 3.11) + +add_library (pg_test OBJECT) +target_sources(pg_test PRIVATE PGManagerTest.cpp) +target_link_libraries(pg_test + ${COMMON_TEST_DEPS} + ) + +add_library (shard_test OBJECT) +target_sources(shard_test PRIVATE ShardManagerTest.cpp) +target_link_libraries(shard_test + ${COMMON_TEST_DEPS} + ) + +add_library (blob_test OBJECT) +target_sources(blob_test PRIVATE BlobManagerTest.cpp) +target_link_libraries(blob_test + ${COMMON_TEST_DEPS} + ) diff --git a/src/lib/tests/PGManagerTest.cpp b/src/lib/tests/PGManagerTest.cpp new file mode 100644 index 00000000..64b07249 --- /dev/null +++ b/src/lib/tests/PGManagerTest.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +#include +#include "lib/tests/fixture_app.hpp" + +using homeobject::PGError; +using homeobject::PGInfo; +using homeobject::PGMember; + +TEST_F(TestFixture, CreatePgEmpty) { + EXPECT_EQ(homeobj_->pg_manager()->create_pg(PGInfo(0u)).get().error(), PGError::INVALID_ARG); +} + +TEST_F(TestFixture, CreatePgNoLeader) { + auto info = PGInfo(0u); + info.members.insert(PGMember{boost::uuids::random_generator()()}); + EXPECT_EQ(homeobj_->pg_manager()->create_pg(std::move(info)).get().error(), PGError::INVALID_ARG); +} + +TEST_F(TestFixture, CreatePgNotMember) { + auto info = PGInfo(0u); + info.members.insert(PGMember{boost::uuids::random_generator()(), "unknown", 1}); + EXPECT_EQ(homeobj_->pg_manager()->create_pg(std::move(info)).get().error(), PGError::INVALID_ARG); +} + +TEST_F(TestFixture, CreateDuplicatePg) { + auto info = PGInfo(_pg_id); + info.members.insert(PGMember{boost::uuids::random_generator()(), "peer3", 6}); + info.members.insert(PGMember{boost::uuids::random_generator()(), "peer4", 2}); + EXPECT_EQ(homeobj_->pg_manager()->create_pg(std::move(info)).get().error(), PGError::INVALID_ARG); +} + +TEST_F(TestFixture, Migrate) { + EXPECT_EQ(homeobj_->pg_manager() + ->replace_member(UINT16_MAX, boost::uuids::random_generator()(), + PGMember{boost::uuids::random_generator()()}) + .get() + .error(), + PGError::UNKNOWN_PG); + EXPECT_EQ( + homeobj_->pg_manager() + ->replace_member(_pg_id, boost::uuids::random_generator()(), PGMember{boost::uuids::random_generator()()}) + .get() + .error(), + PGError::UNKNOWN_PEER); + EXPECT_EQ(homeobj_->pg_manager()->replace_member(_pg_id, _peer1, PGMember{_peer1}).get().error(), + PGError::INVALID_ARG); + EXPECT_EQ(homeobj_->pg_manager()->replace_member(_pg_id, _peer1, PGMember{_peer2}).get().error(), + PGError::INVALID_ARG); + EXPECT_EQ(homeobj_->pg_manager() + ->replace_member(_pg_id, _peer1, PGMember{boost::uuids::random_generator()()}) + .get() + .error(), + PGError::INVALID_ARG); + EXPECT_TRUE( + homeobj_->pg_manager()->replace_member(_pg_id, _peer2, PGMember{boost::uuids::random_generator()()}).get()); +} + +int main(int argc, char* argv[]) { + int parsed_argc = argc; + ::testing::InitGoogleTest(&parsed_argc, argv); + SISL_OPTIONS_LOAD(parsed_argc, argv, logging); + sisl::logging::SetLogger(std::string(argv[0])); + spdlog::set_pattern("[%D %T.%e] [%n] [%^%l%$] [%t] %v"); + parsed_argc = 1; + auto f = ::folly::Init(&parsed_argc, &argv, true); + return RUN_ALL_TESTS(); +} diff --git a/src/lib/tests/ShardManagerTest.cpp b/src/lib/tests/ShardManagerTest.cpp new file mode 100644 index 00000000..a507e948 --- /dev/null +++ b/src/lib/tests/ShardManagerTest.cpp @@ -0,0 +1,79 @@ +#include +#include + +#include +#include "lib/tests/fixture_app.hpp" + +using homeobject::shard_id; +using homeobject::ShardError; +using homeobject::ShardInfo; + +TEST_F(TestFixture, CreateShardTooBig) { + EXPECT_EQ( + ShardError::INVALID_ARG, + homeobj_->shard_manager()->create_shard(_pg_id, homeobject::ShardManager::max_shard_size() + 1).get().error()); +} + +TEST_F(TestFixture, CreateShardTooSmall) { + EXPECT_EQ(ShardError::INVALID_ARG, homeobj_->shard_manager()->create_shard(_pg_id, 0ul).get().error()); +} + +TEST_F(TestFixture, CreateShardNoPg) { + EXPECT_EQ(ShardError::UNKNOWN_PG, homeobj_->shard_manager()->create_shard(_pg_id + 1, Mi).get().error()); +} + +TEST_F(TestFixture, GetUnknownShard) { + EXPECT_EQ(ShardError::UNKNOWN_SHARD, homeobj_->shard_manager()->get_shard(_shard_2.id + 1).get().error()); +} + +TEST_F(TestFixture, GetKnownShard) { + auto e = homeobj_->shard_manager()->get_shard(_shard_1.id).get(); + ASSERT_TRUE(!!e); + e.then([this](auto const& info) { + EXPECT_TRUE(info.id == _shard_1.id); + EXPECT_TRUE(info.placement_group == _shard_1.placement_group); + EXPECT_EQ(info.state, ShardInfo::State::OPEN); + }); +} + +TEST_F(TestFixture, ListShardsNoPg) { + EXPECT_EQ(ShardError::UNKNOWN_PG, homeobj_->shard_manager()->list_shards(_pg_id + 1).get().error()); +} + +TEST_F(TestFixture, ListShards) { + auto e = homeobj_->shard_manager()->list_shards(_pg_id).get(); + ASSERT_TRUE(!!e); + e.then([this](auto const& info_list) { + ASSERT_EQ(info_list.size(), 2); + EXPECT_TRUE(info_list.begin()->id == _shard_1.id); + EXPECT_TRUE(info_list.begin()->placement_group == _shard_1.placement_group); + EXPECT_EQ(info_list.begin()->state, ShardInfo::State::OPEN); + }); +} + +TEST_F(TestFixture, SealShardNoShard) { + EXPECT_EQ(ShardError::UNKNOWN_SHARD, homeobj_->shard_manager()->seal_shard(_shard_2.id + 1).get().error()); +} + +TEST_F(TestFixture, SealShard) { + for (auto i = 0; 2 > i; ++i) { + auto e = homeobj_->shard_manager()->seal_shard(_shard_1.id).get(); + ASSERT_TRUE(!!e); + e.then([this](auto const& info) { + EXPECT_TRUE(info.id == _shard_1.id); + EXPECT_TRUE(info.placement_group == _shard_1.placement_group); + EXPECT_EQ(info.state, ShardInfo::State::SEALED); + }); + } +} + +int main(int argc, char* argv[]) { + int parsed_argc = argc; + ::testing::InitGoogleTest(&parsed_argc, argv); + SISL_OPTIONS_LOAD(parsed_argc, argv, logging); + sisl::logging::SetLogger(std::string(argv[0])); + spdlog::set_pattern("[%D %T.%e] [%n] [%^%l%$] [%t] %v"); + parsed_argc = 1; + auto f = ::folly::Init(&parsed_argc, &argv, true); + return RUN_ALL_TESTS(); +} diff --git a/src/lib/tests/fixture_app.hpp b/src/lib/tests/fixture_app.hpp new file mode 100644 index 00000000..be10bd36 --- /dev/null +++ b/src/lib/tests/fixture_app.hpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +SISL_LOGGING_INIT(logging, HOMEOBJECT_LOG_MODS) +SISL_OPTIONS_ENABLE(logging) + +using homeobject::Blob; +using homeobject::blob_id; +using homeobject::BlobError; +using homeobject::peer_id; + +class FixtureApp : public homeobject::HomeObjectApplication { + std::string path_{"/tmp/test_homestore.data"}; + +public: + FixtureApp() { + clean(); + LOGINFO("creating device {} file with size {} ", path_, homestore::in_bytes(2 * Gi)); + std::ofstream ofs{path_, std::ios::binary | std::ios::out | std::ios::trunc}; + std::filesystem::resize_file(path_, 2 * Gi); + } + + ~FixtureApp() override { clean(); } + + bool spdk_mode() const override { return false; } + uint32_t threads() const override { return 2; } + + void clean() { + if (std::filesystem::exists(path_)) { std::filesystem::remove(path_); } + } + + std::list< std::filesystem::path > devices() const override { + auto device_info = std::list< std::filesystem::path >(); + device_info.emplace_back(std::filesystem::canonical(path_)); + return device_info; + } + + homeobject::peer_id discover_svcid(std::optional< homeobject::peer_id > const& p) const override { + return p.value(); + } + std::string lookup_peer(homeobject::peer_id const&) const override { return "test_fixture.com"; } +}; + +class TestFixture : public ::testing::Test { + std::shared_ptr< FixtureApp > app; + +public: + homeobject::ShardInfo _shard_1; + homeobject::ShardInfo _shard_2; + homeobject::pg_id _pg_id{1u}; + peer_id _peer1; + peer_id _peer2; + blob_id _blob_id; + + void SetUp() override { + app = std::make_shared< FixtureApp >(); + homeobj_ = homeobject::init_homeobject(std::weak_ptr< homeobject::HomeObjectApplication >(app)); + _peer1 = homeobj_->our_uuid(); + _peer2 = boost::uuids::random_generator()(); + + auto info = homeobject::PGInfo(_pg_id); + info.members.insert(homeobject::PGMember{_peer1, "peer1", 1}); + info.members.insert(homeobject::PGMember{_peer2, "peer2", 0}); + + LOGDEBUG("Setup Pg"); + EXPECT_TRUE(homeobj_->pg_manager()->create_pg(std::move(info)).get()); + + LOGDEBUG("Setup Shards"); + auto s_e = homeobj_->shard_manager()->create_shard(_pg_id, Mi).get(); + ASSERT_TRUE(!!s_e); + s_e.then([this](auto&& i) { _shard_1 = std::move(i); }); + + s_e = homeobj_->shard_manager()->create_shard(_pg_id, Mi).get(); + ASSERT_TRUE(!!s_e); + s_e.then([this](auto&& i) { _shard_2 = std::move(i); }); + + LOGDEBUG("Get on empty Shard: {}", _shard_1.id); + auto g_e = homeobj_->blob_manager()->get(_shard_1.id, 0).get(); + ASSERT_FALSE(g_e); + EXPECT_EQ(BlobError::UNKNOWN_BLOB, g_e.error()); + + LOGDEBUG("Insert Blob to: {}", _shard_1.id); + auto o_e = homeobj_->blob_manager() + ->put(_shard_1.id, Blob{sisl::io_blob_safe(4 * Ki, 512u), "test_blob", 4 * Mi}) + .get(); + EXPECT_TRUE(!!o_e); + o_e.then([this](auto&& b) mutable { _blob_id = std::move(b); }); + } + +protected: + std::shared_ptr< homeobject::HomeObject > homeobj_; +};