#include "cluster/Backend.hpp" #include "cluster/ClioNode.hpp" #include "cluster/Metrics.hpp" #include "util/MockPrometheus.hpp" #include "util/prometheus/Gauge.hpp" #include #include #include #include #include #include #include #include #include using namespace cluster; using namespace util::prometheus; using namespace testing; struct MetricsTest : WithMockPrometheus { std::shared_ptr uuid1 = std::make_shared(boost::uuids::random_generator()()); std::shared_ptr uuid2 = std::make_shared(boost::uuids::random_generator()()); std::shared_ptr uuid3 = std::make_shared(boost::uuids::random_generator()()); }; TEST_F(MetricsTest, InitializesMetricsOnConstruction) { auto& nodesInClusterMock = makeMock("cluster_nodes_total_number", ""); auto& isHealthyMock = makeMock("cluster_communication_is_healthy", ""); EXPECT_CALL(nodesInClusterMock, set(1)); EXPECT_CALL(isHealthyMock, set(1)); Metrics const metrics; } TEST_F(MetricsTest, OnNewStateWithValidClusterData) { auto& nodesInClusterMock = makeMock("cluster_nodes_total_number", ""); auto& isHealthyMock = makeMock("cluster_communication_is_healthy", ""); EXPECT_CALL(nodesInClusterMock, set(1)); EXPECT_CALL(isHealthyMock, set(1)); Metrics metrics; ClioNode const node1{ .uuid = uuid1, .updateTime = std::chrono::system_clock::now(), .dbRole = ClioNode::DbRole::Writer, .etlStarted = true, .cacheIsFull = true, .cacheIsCurrentlyLoading = false }; ClioNode const node2{ .uuid = uuid2, .updateTime = std::chrono::system_clock::now(), .dbRole = ClioNode::DbRole::ReadOnly, .etlStarted = true, .cacheIsFull = true, .cacheIsCurrentlyLoading = false }; ClioNode const node3{ .uuid = uuid3, .updateTime = std::chrono::system_clock::now(), .dbRole = ClioNode::DbRole::NotWriter, .etlStarted = true, .cacheIsFull = false, .cacheIsCurrentlyLoading = false }; std::vector const nodes = {node1, node2, node3}; Backend::ClusterData const clusterData = std::expected, std::string>(nodes); auto sharedClusterData = std::make_shared(clusterData); EXPECT_CALL(isHealthyMock, set(1)); EXPECT_CALL(nodesInClusterMock, set(3)); metrics.onNewState(uuid1, sharedClusterData); } TEST_F(MetricsTest, OnNewStateWithEmptyClusterData) { auto& nodesInClusterMock = makeMock("cluster_nodes_total_number", ""); auto& isHealthyMock = makeMock("cluster_communication_is_healthy", ""); EXPECT_CALL(nodesInClusterMock, set(1)); EXPECT_CALL(isHealthyMock, set(1)); Metrics metrics; std::vector const nodes = {}; Backend::ClusterData const clusterData = std::expected, std::string>(nodes); auto sharedClusterData = std::make_shared(clusterData); EXPECT_CALL(isHealthyMock, set(1)); EXPECT_CALL(nodesInClusterMock, set(0)); metrics.onNewState(uuid1, sharedClusterData); } TEST_F(MetricsTest, OnNewStateWithFailedClusterData) { auto& nodesInClusterMock = makeMock("cluster_nodes_total_number", ""); auto& isHealthyMock = makeMock("cluster_communication_is_healthy", ""); EXPECT_CALL(nodesInClusterMock, set(1)); EXPECT_CALL(isHealthyMock, set(1)); Metrics metrics; Backend::ClusterData const clusterData = std::expected, std::string>(std::unexpected("Connection failed")); auto sharedClusterData = std::make_shared(clusterData); EXPECT_CALL(isHealthyMock, set(0)); EXPECT_CALL(nodesInClusterMock, set(1)); metrics.onNewState(uuid1, sharedClusterData); } TEST_F(MetricsTest, OnNewStateWithSingleNode) { auto& nodesInClusterMock = makeMock("cluster_nodes_total_number", ""); auto& isHealthyMock = makeMock("cluster_communication_is_healthy", ""); EXPECT_CALL(nodesInClusterMock, set(1)); EXPECT_CALL(isHealthyMock, set(1)); Metrics metrics; ClioNode const node1{ .uuid = uuid1, .updateTime = std::chrono::system_clock::now(), .dbRole = ClioNode::DbRole::Writer, .etlStarted = true, .cacheIsFull = false, .cacheIsCurrentlyLoading = false }; std::vector const nodes = {node1}; Backend::ClusterData const clusterData = std::expected, std::string>(nodes); auto sharedClusterData = std::make_shared(clusterData); EXPECT_CALL(isHealthyMock, set(1)); EXPECT_CALL(nodesInClusterMock, set(1)); metrics.onNewState(uuid1, sharedClusterData); } TEST_F(MetricsTest, OnNewStateRecoveryFromFailure) { auto& nodesInClusterMock = makeMock("cluster_nodes_total_number", ""); auto& isHealthyMock = makeMock("cluster_communication_is_healthy", ""); EXPECT_CALL(nodesInClusterMock, set(1)); EXPECT_CALL(isHealthyMock, set(1)); Metrics metrics; Backend::ClusterData const clusterData1 = std::expected, std::string>(std::unexpected("Connection timeout")); auto sharedClusterData1 = std::make_shared(clusterData1); EXPECT_CALL(isHealthyMock, set(0)); EXPECT_CALL(nodesInClusterMock, set(1)); metrics.onNewState(uuid1, sharedClusterData1); ClioNode const node1{ .uuid = uuid1, .updateTime = std::chrono::system_clock::now(), .dbRole = ClioNode::DbRole::Writer, .etlStarted = true, .cacheIsFull = true, .cacheIsCurrentlyLoading = false }; ClioNode const node2{ .uuid = uuid2, .updateTime = std::chrono::system_clock::now(), .dbRole = ClioNode::DbRole::ReadOnly, .etlStarted = true, .cacheIsFull = false, .cacheIsCurrentlyLoading = false }; std::vector const nodes = {node1, node2}; Backend::ClusterData const clusterData2 = std::expected, std::string>(nodes); auto sharedClusterData2 = std::make_shared(clusterData2); EXPECT_CALL(isHealthyMock, set(1)); EXPECT_CALL(nodesInClusterMock, set(2)); metrics.onNewState(uuid2, sharedClusterData2); }