From fdd49b7983a8f04073b3fa9ea8604d39c27ce316 Mon Sep 17 00:00:00 2001 From: Andi Skrgat Date: Mon, 18 Mar 2024 08:50:34 +0100 Subject: [PATCH] Add tests for CoordinatorStateMachine --- .../include/coordination/raft_state.hpp | 1 - tests/unit/CMakeLists.txt | 10 +- tests/unit/coordinator_state_machine.cpp | 131 ++++++++++++++++++ 3 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 tests/unit/coordinator_state_machine.cpp diff --git a/src/coordination/include/coordination/raft_state.hpp b/src/coordination/include/coordination/raft_state.hpp index 03e00df06..5c4e6cbe5 100644 --- a/src/coordination/include/coordination/raft_state.hpp +++ b/src/coordination/include/coordination/raft_state.hpp @@ -92,7 +92,6 @@ class RaftState { auto IsLockOpened() const -> bool; private: - // TODO: (andi) I think variables below can be abstracted/clean them. io::network::Endpoint raft_endpoint_; uint32_t coordinator_id_; diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 008211af3..be1824477 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -453,9 +453,17 @@ target_link_libraries(${test_prefix}coordinator_cluster_state gflags mg-coordina target_include_directories(${test_prefix}coordinator_cluster_state PRIVATE ${CMAKE_SOURCE_DIR}/include) endif() -# Test Raft log serialization +# TODO: (andi) Move into appropriate test suite +# Test Routing table if(MG_ENTERPRISE) add_unit_test(routing_table.cpp) target_link_libraries(${test_prefix}routing_table gflags mg-coordination mg-repl_coord_glue) target_include_directories(${test_prefix}routing_table PRIVATE ${CMAKE_SOURCE_DIR}/include) endif() + +# Test coordinator state machine +if(MG_ENTERPRISE) +add_unit_test(coordinator_state_machine.cpp) +target_link_libraries(${test_prefix}coordinator_state_machine gflags mg-coordination mg-repl_coord_glue) +target_include_directories(${test_prefix}coordinator_state_machine PRIVATE ${CMAKE_SOURCE_DIR}/include) +endif() diff --git a/tests/unit/coordinator_state_machine.cpp b/tests/unit/coordinator_state_machine.cpp new file mode 100644 index 000000000..ab6f991f9 --- /dev/null +++ b/tests/unit/coordinator_state_machine.cpp @@ -0,0 +1,131 @@ +// Copyright 2024 Memgraph Ltd. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +// License, and you may not use this file except in compliance with the Business Source License. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +#include "nuraft/coordinator_state_machine.hpp" +#include "utils/file.hpp" + +#include +#include +#include "json/json.hpp" + +#include "libnuraft/nuraft.hxx" + +using memgraph::coordination::CoordinatorStateMachine; +using memgraph::coordination::CoordinatorToCoordinatorConfig; +using memgraph::coordination::CoordinatorToReplicaConfig; +using memgraph::coordination::RaftLogAction; +using memgraph::io::network::Endpoint; +using memgraph::replication_coordination_glue::ReplicationMode; +using memgraph::utils::UUID; +using nuraft::buffer; +using nuraft::buffer_serializer; +using nuraft::ptr; + +class CoordinatorStateMachineTest : public ::testing::Test { + protected: + void SetUp() override {} + + void TearDown() override {} + + std::filesystem::path test_folder_{std::filesystem::temp_directory_path() / + "MG_tests_unit_coordinator_state_machine"}; +}; + +TEST_F(CoordinatorStateMachineTest, SerializeRegisterReplicationInstance) { + auto config = + CoordinatorToReplicaConfig{.instance_name = "instance3", + .mgt_server = Endpoint{"127.0.0.1", 10112}, + .bolt_server = Endpoint{"127.0.0.1", 7687}, + .replication_client_info = {.instance_name = "instance_name", + .replication_mode = ReplicationMode::ASYNC, + .replication_server = Endpoint{"127.0.0.1", 10001}}, + .instance_health_check_frequency_sec = std::chrono::seconds{1}, + .instance_down_timeout_sec = std::chrono::seconds{5}, + .instance_get_uuid_frequency_sec = std::chrono::seconds{10}, + .ssl = std::nullopt}; + + ptr data = CoordinatorStateMachine::SerializeRegisterInstance(config); + buffer_serializer bs(*data); + auto const expected = nlohmann::json{{"action", RaftLogAction::REGISTER_REPLICATION_INSTANCE}, {"info", config}}; + ASSERT_EQ(bs.get_str(), expected.dump()); +} + +TEST_F(CoordinatorStateMachineTest, SerializeUnregisterReplicationInstance) { + auto config = + CoordinatorToReplicaConfig{.instance_name = "instance3", + .mgt_server = Endpoint{"127.0.0.1", 10112}, + .bolt_server = Endpoint{"127.0.0.1", 7687}, + .replication_client_info = {.instance_name = "instance_name", + .replication_mode = ReplicationMode::ASYNC, + .replication_server = Endpoint{"127.0.0.1", 10001}}, + .instance_health_check_frequency_sec = std::chrono::seconds{1}, + .instance_down_timeout_sec = std::chrono::seconds{5}, + .instance_get_uuid_frequency_sec = std::chrono::seconds{10}, + .ssl = std::nullopt}; + + CoordinatorStateMachine::SerializeRegisterInstance(config); + ptr data = CoordinatorStateMachine::SerializeUnregisterInstance("instance3"); + buffer_serializer bs(*data); + + auto const expected = + nlohmann::json{{"action", RaftLogAction::UNREGISTER_REPLICATION_INSTANCE}, {"info", "instance3"}}; + ASSERT_EQ(bs.get_str(), expected.dump()); +} + +TEST_F(CoordinatorStateMachineTest, SerializeAddCoordinatorInstance) { + CoordinatorToCoordinatorConfig config{.coordinator_server_id = 1, + .bolt_server = Endpoint{"127.0.0.1", 7687}, + .coordinator_server = Endpoint{"127.0.0.1", 10111}}; + + ptr data = CoordinatorStateMachine::SerializeAddCoordinatorInstance(config); + buffer_serializer bs(*data); + auto const expected = nlohmann::json{{"action", RaftLogAction::ADD_COORDINATOR_INSTANCE}, {"info", config}}; + ASSERT_EQ(bs.get_str(), expected.dump()); +} + +TEST_F(CoordinatorStateMachineTest, SerializeSetInstanceToMain) { + auto config = + CoordinatorToReplicaConfig{.instance_name = "instance3", + .mgt_server = Endpoint{"127.0.0.1", 10112}, + .bolt_server = Endpoint{"127.0.0.1", 7687}, + .replication_client_info = {.instance_name = "instance_name", + .replication_mode = ReplicationMode::ASYNC, + .replication_server = Endpoint{"127.0.0.1", 10001}}, + .instance_health_check_frequency_sec = std::chrono::seconds{1}, + .instance_down_timeout_sec = std::chrono::seconds{5}, + .instance_get_uuid_frequency_sec = std::chrono::seconds{10}, + .ssl = std::nullopt}; + + CoordinatorStateMachine::SerializeRegisterInstance(config); + + { + ptr data = CoordinatorStateMachine::SerializeSetInstanceAsMain("instance3"); + buffer_serializer bs(*data); + auto const expected = nlohmann::json{{"action", RaftLogAction::SET_INSTANCE_AS_MAIN}, {"info", "instance3"}}; + ASSERT_EQ(bs.get_str(), expected.dump()); + } + + { + ptr data = CoordinatorStateMachine::SerializeSetInstanceAsReplica("instance3"); + buffer_serializer bs(*data); + auto const expected = nlohmann::json{{"action", RaftLogAction::SET_INSTANCE_AS_REPLICA}, {"info", "instance3"}}; + ASSERT_EQ(bs.get_str(), expected.dump()); + } +} + +TEST_F(CoordinatorStateMachineTest, SerializeUpdateUUID) { + auto uuid = UUID{}; + + ptr data = CoordinatorStateMachine::SerializeUpdateUUID(uuid); + buffer_serializer bs(*data); + auto const expected = nlohmann::json{{"action", RaftLogAction::UPDATE_UUID}, {"info", uuid}}; + ASSERT_EQ(bs.get_str(), expected.dump()); +}