Cover LoadBalancer with tests (#1394)

Fixes #680. Fixes #1222.
This commit is contained in:
Sergey Kuznetsov
2024-05-15 14:02:36 +01:00
committed by GitHub
parent f74b89cc8d
commit da10535bc0
61 changed files with 2769 additions and 1466 deletions

View File

@@ -195,23 +195,8 @@ protected:
template <template <typename> typename MockType = ::testing::NiceMock>
struct MockBackendTestBase : virtual public NoLoggerFixture {
void
SetUp() override
{
backend.reset();
}
class BackendProxy {
std::shared_ptr<BackendInterface> backend;
private:
void
reset()
{
backend = std::make_shared<MockType<MockBackend>>(util::Config{});
}
friend MockBackendTestBase;
std::shared_ptr<MockType<MockBackend>> backend = std::make_shared<MockType<MockBackend>>(util::Config{});
public:
auto
@@ -230,11 +215,10 @@ struct MockBackendTestBase : virtual public NoLoggerFixture {
return backend;
}
operator MockBackend*()
MockType<MockBackend>&
operator*()
{
MockBackend* ret = dynamic_cast<MockBackend*>(backend.get());
[&] { ASSERT_NE(ret, nullptr); }();
return ret;
return *backend;
}
};
@@ -266,14 +250,6 @@ using MockBackendTestNaggy = MockBackendTestBase<::testing::NaggyMock>;
*/
using MockBackendTestStrict = MockBackendTestBase<::testing::StrictMock>;
/**
* @brief Fixture with a mock subscription manager
*/
struct MockSubscriptionManagerTest : virtual public NoLoggerFixture {
protected:
std::shared_ptr<MockSubscriptionManager> mockSubscriptionManagerPtr = std::make_shared<MockSubscriptionManager>();
};
/**
* @brief Fixture with a mock etl balancer
*/
@@ -283,7 +259,7 @@ protected:
};
/**
* @brief Fixture with a mock subscription manager
* @brief Fixture with a mock etl service
*/
template <template <typename> typename MockType = ::testing::NiceMock>
struct MockETLServiceTestBase : virtual public NoLoggerFixture {
@@ -328,15 +304,14 @@ protected:
* HandlerBaseTestStrict.
*/
template <template <typename> typename MockType = ::testing::NiceMock>
struct HandlerBaseTestBase : public MockBackendTestBase<MockType>,
public util::prometheus::WithPrometheus,
public SyncAsioContextTest,
public MockETLServiceTestBase<MockType> {
struct HandlerBaseTestBase : util::prometheus::WithPrometheus,
MockBackendTestBase<MockType>,
SyncAsioContextTest,
MockETLServiceTestBase<MockType> {
protected:
void
SetUp() override
{
MockBackendTestBase<MockType>::SetUp();
SyncAsioContextTest::SetUp();
MockETLServiceTestBase<MockType>::SetUp();
}
@@ -346,7 +321,6 @@ protected:
{
MockETLServiceTestBase<MockType>::TearDown();
SyncAsioContextTest::TearDown();
MockBackendTestBase<MockType>::TearDown();
}
};

View File

@@ -19,13 +19,36 @@
#pragma once
#include "etl/ETLHelpers.hpp"
#include <gmock/gmock.h>
#include <cstdint>
#include <memory>
#include <optional>
struct MockNetworkValidatedLedgers {
MOCK_METHOD(void, push, (uint32_t), ());
MOCK_METHOD(std::optional<uint32_t>, getMostRecent, (), ());
MOCK_METHOD(bool, waitUntilValidatedByNetwork, (uint32_t), ());
struct MockNetworkValidatedLedgers : public etl::NetworkValidatedLedgersInterface {
MOCK_METHOD(void, push, (uint32_t), (override));
MOCK_METHOD(std::optional<uint32_t>, getMostRecent, (), (override));
MOCK_METHOD(bool, waitUntilValidatedByNetwork, (uint32_t, std::optional<uint32_t>), (override));
};
template <template <typename> typename MockType>
struct MockNetworkValidatedLedgersPtrImpl {
std::shared_ptr<MockType<MockNetworkValidatedLedgers>> ptr =
std::make_shared<MockType<MockNetworkValidatedLedgers>>();
operator std::shared_ptr<etl::NetworkValidatedLedgersInterface>() const
{
return ptr;
}
MockType<MockNetworkValidatedLedgers>&
operator*()
{
return *ptr;
}
};
using MockNetworkValidatedLedgersPtr = MockNetworkValidatedLedgersPtrImpl<testing::NiceMock>;
using StrictMockNetworkValidatedLedgersPtr = MockNetworkValidatedLedgersPtrImpl<testing::StrictMock>;

View File

@@ -18,41 +18,180 @@
//==============================================================================
#pragma once
#include "data/BackendInterface.hpp"
#include "etl/ETLHelpers.hpp"
#include "etl/Source.hpp"
#include "feed/SubscriptionManagerInterface.hpp"
#include "util/config/Config.hpp"
#include <boost/asio/io_context.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/json/object.hpp>
#include <boost/uuid/uuid.hpp>
#include <gmock/gmock.h>
#include <grpcpp/support/status.h>
#include <gtest/gtest.h>
#include <org/xrpl/rpc/v1/get_ledger.pb.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
class MockSource {
public:
MOCK_METHOD(bool, isConnected, (), (const));
MOCK_METHOD(boost::json::object, toJson, (), (const));
MOCK_METHOD(void, run, ());
MOCK_METHOD(void, pause, ());
MOCK_METHOD(void, resume, ());
MOCK_METHOD(std::string, toString, (), (const));
MOCK_METHOD(bool, hasLedger, (uint32_t), (const));
MOCK_METHOD((std::pair<grpc::Status, org::xrpl::rpc::v1::GetLedgerResponse>), fetchLedger, (uint32_t, bool, bool));
MOCK_METHOD((std::pair<std::vector<std::string>, bool>), loadInitialLedger, (uint32_t, uint32_t, bool));
struct MockSource : etl::SourceBase {
MOCK_METHOD(void, run, (), (override));
MOCK_METHOD(bool, isConnected, (), (const, override));
MOCK_METHOD(void, setForwarding, (bool), (override));
MOCK_METHOD(boost::json::object, toJson, (), (const, override));
MOCK_METHOD(std::string, toString, (), (const, override));
MOCK_METHOD(bool, hasLedger, (uint32_t), (const, override));
MOCK_METHOD(
(std::pair<grpc::Status, org::xrpl::rpc::v1::GetLedgerResponse>),
fetchLedger,
(uint32_t, bool, bool),
(override)
);
MOCK_METHOD((std::pair<std::vector<std::string>, bool>), loadInitialLedger, (uint32_t, uint32_t, bool), (override));
MOCK_METHOD(
std::optional<boost::json::object>,
forwardToRippled,
(boost::json::object const&, std::optional<std::string> const&, boost::asio::yield_context),
(const)
(const, override)
);
MOCK_METHOD(
std::optional<boost::json::object>,
requestFromRippled,
(boost::json::object const&, std::optional<std::string> const&, boost::asio::yield_context),
(const)
);
MOCK_METHOD(boost::uuids::uuid, token, (), (const));
};
template <template <typename> typename MockType>
using MockSourcePtr = std::shared_ptr<MockType<MockSource>>;
template <template <typename> typename MockType>
class MockSourceWrapper : public etl::SourceBase {
MockSourcePtr<MockType> mock_;
public:
MockSourceWrapper(MockSourcePtr<MockType> mockData) : mock_(std::move(mockData))
{
}
void
run() override
{
mock_->run();
}
bool
isConnected() const override
{
return mock_->isConnected();
}
void
setForwarding(bool isForwarding) override
{
mock_->setForwarding(isForwarding);
}
boost::json::object
toJson() const override
{
return mock_->toJson();
}
std::string
toString() const override
{
return mock_->toString();
}
bool
hasLedger(uint32_t sequence) const override
{
return mock_->hasLedger(sequence);
}
std::pair<grpc::Status, org::xrpl::rpc::v1::GetLedgerResponse>
fetchLedger(uint32_t sequence, bool getObjects, bool getObjectNeighbors) override
{
return mock_->fetchLedger(sequence, getObjects, getObjectNeighbors);
}
std::pair<std::vector<std::string>, bool>
loadInitialLedger(uint32_t sequence, uint32_t maxLedger, bool getObjects) override
{
return mock_->loadInitialLedger(sequence, maxLedger, getObjects);
}
std::optional<boost::json::object>
forwardToRippled(
boost::json::object const& request,
std::optional<std::string> const& forwardToRippledClientIp,
boost::asio::yield_context yield
) const override
{
return mock_->forwardToRippled(request, forwardToRippledClientIp, yield);
}
};
struct MockSourceCallbacks {
etl::SourceBase::OnDisconnectHook onDisconnect;
etl::SourceBase::OnConnectHook onConnect;
etl::SourceBase::OnLedgerClosedHook onLedgerClosed;
};
template <template <typename> typename MockType>
struct MockSourceData {
MockSourcePtr<MockType> source = std::make_shared<MockType<MockSource>>();
std::optional<MockSourceCallbacks> callbacks;
};
template <template <typename> typename MockType = testing::NiceMock>
class MockSourceFactoryImpl {
std::vector<MockSourceData<MockType>> mockData_;
public:
MockSourceFactoryImpl(size_t numSources)
{
mockData_.reserve(numSources);
std::ranges::generate_n(std::back_inserter(mockData_), numSources, [] { return MockSourceData<MockType>{}; });
}
etl::SourcePtr
makeSourceMock(
util::Config const&,
boost::asio::io_context&,
std::shared_ptr<BackendInterface>,
std::shared_ptr<feed::SubscriptionManagerInterface>,
std::shared_ptr<etl::NetworkValidatedLedgersInterface>,
etl::SourceBase::OnConnectHook onConnect,
etl::SourceBase::OnDisconnectHook onDisconnect,
etl::SourceBase::OnLedgerClosedHook onLedgerClosed
)
{
auto it = std::ranges::find_if(mockData_, [](auto const& d) { return not d.callbacks.has_value(); });
[&]() { ASSERT_NE(it, mockData_.end()) << "Make source called more than expected"; }();
it->callbacks = MockSourceCallbacks{std::move(onDisconnect), std::move(onConnect), std::move(onLedgerClosed)};
return std::make_unique<MockSourceWrapper<MockType>>(it->source);
}
MockType<MockSource>&
sourceAt(size_t index)
{
return *mockData_.at(index).source;
}
MockSourceCallbacks&
callbacksAt(size_t index)
{
auto& callbacks = mockData_.at(index).callbacks;
[&]() { ASSERT_TRUE(callbacks.has_value()) << "Callbacks not set"; }();
return *callbacks;
}
};
using MockSourceFactory = MockSourceFactoryImpl<>;
using StrictMockSourceFactory = MockSourceFactoryImpl<testing::StrictMock>;

View File

@@ -20,7 +20,8 @@
#pragma once
#include "data/Types.hpp"
#include "web/interface/ConnectionBase.hpp"
#include "feed/SubscriptionManagerInterface.hpp"
#include "feed/Types.hpp"
#include <boost/asio/spawn.hpp>
#include <boost/json.hpp>
@@ -36,70 +37,89 @@
#include <string>
#include <vector>
struct MockSubscriptionManager {
public:
using session_ptr = std::shared_ptr<web::ConnectionBase>;
MockSubscriptionManager() = default;
MOCK_METHOD(boost::json::object, subLedger, (boost::asio::yield_context, session_ptr), ());
struct MockSubscriptionManager : feed::SubscriptionManagerInterface {
MOCK_METHOD(
boost::json::object,
subLedger,
(boost::asio::yield_context, feed::SubscriberSharedPtr const&),
(override)
);
MOCK_METHOD(
void,
pubLedger,
(ripple::LedgerInfo const&, ripple::Fees const&, std::string const&, std::uint32_t),
()
(ripple::LedgerHeader const&, ripple::Fees const&, std::string const&, std::uint32_t),
(const, override)
);
MOCK_METHOD(
void,
pubBookChanges,
(ripple::LedgerInfo const&, std::vector<data::TransactionAndMetadata> const&),
()
(const, override)
);
MOCK_METHOD(void, unsubLedger, (session_ptr), ());
MOCK_METHOD(void, unsubLedger, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, subTransactions, (session_ptr), ());
MOCK_METHOD(void, subTransactions, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, unsubTransactions, (session_ptr), ());
MOCK_METHOD(void, unsubTransactions, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, pubTransaction, (data::TransactionAndMetadata const&, ripple::LedgerInfo const&), ());
MOCK_METHOD(void, pubTransaction, (data::TransactionAndMetadata const&, ripple::LedgerInfo const&), (override));
MOCK_METHOD(void, subAccount, (ripple::AccountID const&, session_ptr&), ());
MOCK_METHOD(void, subAccount, (ripple::AccountID const&, feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, unsubAccount, (ripple::AccountID const&, session_ptr const&), ());
MOCK_METHOD(void, unsubAccount, (ripple::AccountID const&, feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, subBook, (ripple::Book const&, session_ptr), ());
MOCK_METHOD(void, subBook, (ripple::Book const&, feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, unsubBook, (ripple::Book const&, session_ptr), ());
MOCK_METHOD(void, unsubBook, (ripple::Book const&, feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, subBookChanges, (session_ptr), ());
MOCK_METHOD(void, subBookChanges, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, unsubBookChanges, (session_ptr), ());
MOCK_METHOD(void, unsubBookChanges, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, subManifest, (session_ptr), ());
MOCK_METHOD(void, subManifest, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, unsubManifest, (session_ptr), ());
MOCK_METHOD(void, unsubManifest, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, subValidation, (session_ptr), ());
MOCK_METHOD(void, subValidation, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, unsubValidation, (session_ptr), ());
MOCK_METHOD(void, unsubValidation, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, forwardProposedTransaction, (boost::json::object const&), ());
MOCK_METHOD(void, forwardProposedTransaction, (boost::json::object const&), (override));
MOCK_METHOD(void, forwardManifest, (boost::json::object const&), ());
MOCK_METHOD(void, forwardManifest, (boost::json::object const&), (const, override));
MOCK_METHOD(void, forwardValidation, (boost::json::object const&), ());
MOCK_METHOD(void, forwardValidation, (boost::json::object const&), (const, override));
MOCK_METHOD(void, subProposedAccount, (ripple::AccountID const&, session_ptr), ());
MOCK_METHOD(void, subProposedAccount, (ripple::AccountID const&, feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, unsubProposedAccount, (ripple::AccountID const&, session_ptr), ());
MOCK_METHOD(void, unsubProposedAccount, (ripple::AccountID const&, feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, subProposedTransactions, (session_ptr), ());
MOCK_METHOD(void, subProposedTransactions, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, unsubProposedTransactions, (session_ptr), ());
MOCK_METHOD(void, unsubProposedTransactions, (feed::SubscriberSharedPtr const&), (override));
MOCK_METHOD(void, cleanup, (session_ptr), ());
MOCK_METHOD(boost::json::object, report, (), (const));
MOCK_METHOD(boost::json::object, report, (), (const, override));
};
template <template <typename> typename MockType = ::testing::NiceMock>
struct MockSubscriptionManagerSharedPtrImpl {
std::shared_ptr<MockType<MockSubscriptionManager>> subscriptionManagerMock =
std::make_shared<MockType<MockSubscriptionManager>>();
operator std::shared_ptr<feed::SubscriptionManagerInterface>()
{
return subscriptionManagerMock;
}
MockType<MockSubscriptionManager>&
operator*()
{
return *subscriptionManagerMock;
}
};
using MockSubscriptionManagerSharedPtr = MockSubscriptionManagerSharedPtrImpl<>;
using StrictMockSubscriptionManagerSharedPtr = MockSubscriptionManagerSharedPtrImpl<testing::StrictMock>;