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

@@ -34,7 +34,7 @@
// Base class for feed tests, providing easy way to access the received feed
template <typename TestedFeed>
class FeedBaseTest : public util::prometheus::WithPrometheus, public SyncAsioContextTest, public MockBackendTest {
struct FeedBaseTest : util::prometheus::WithPrometheus, SyncAsioContextTest, MockBackendTest {
protected:
std::shared_ptr<web::ConnectionBase> sessionPtr;
std::shared_ptr<TestedFeed> testFeedPtr;
@@ -44,7 +44,6 @@ protected:
SetUp() override
{
SyncAsioContextTest::SetUp();
MockBackendTest::SetUp();
testFeedPtr = std::make_shared<TestedFeed>(ctx);
sessionPtr = std::make_shared<MockSession>();
sessionPtr->apiSubVersion = 1;
@@ -56,7 +55,6 @@ protected:
{
sessionPtr.reset();
testFeedPtr.reset();
MockBackendTest::TearDown();
SyncAsioContextTest::TearDown();
}
};

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>;

View File

@@ -26,8 +26,8 @@ target_sources(
etl/ForwardingSourceTests.cpp
etl/GrpcSourceTests.cpp
etl/LedgerPublisherTests.cpp
etl/SourceTests.cpp
etl/SubscriptionSourceDependenciesTests.cpp
etl/LoadBalancerTests.cpp
etl/SourceImplTests.cpp
etl/SubscriptionSourceTests.cpp
etl/TransformerTests.cpp
# Feed
@@ -114,6 +114,7 @@ target_sources(
util/requests/RequestBuilderTests.cpp
util/requests/SslContextTests.cpp
util/requests/WsConnectionTests.cpp
util/RandomTests.cpp
util/RetryTests.cpp
util/SignalsHandlerTests.cpp
util/TxUtilTests.cpp

View File

@@ -40,7 +40,7 @@ using namespace testing;
constexpr static auto MAXSEQ = 30;
constexpr static auto MINSEQ = 10;
struct BackendInterfaceTest : MockBackendTestNaggy, SyncAsioContextTest, WithPrometheus {};
struct BackendInterfaceTest : WithPrometheus, MockBackendTestNaggy, SyncAsioContextTest {};
TEST_F(BackendInterfaceTest, FetchFeesSuccessPath)
{

View File

@@ -45,19 +45,6 @@ namespace {
constexpr auto SEQ = 30;
struct CacheLoaderTest : util::prometheus::WithPrometheus, MockBackendTest {
void
SetUp() override
{
MockBackendTest::SetUp();
}
void
TearDown() override
{
MockBackendTest::TearDown();
}
protected:
DiffProvider diffProvider;
MockCache cache;
};

View File

@@ -76,3 +76,15 @@ TEST_F(ETLStateTest, NetworkIdInvalid)
ASSERT_TRUE(state.has_value());
EXPECT_FALSE(state->networkID.has_value());
}
TEST_F(ETLStateTest, ResponseHasError)
{
auto const json = json::parse(
R"JSON({
"error": "error"
})JSON"
);
EXPECT_CALL(source, forwardToRippled).WillOnce(Return(json.as_object()));
auto const state = etl::ETLState::fetchETLStateFromSource(source);
EXPECT_FALSE(state.has_value());
}

View File

@@ -29,7 +29,6 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <memory>
#include <optional>
using namespace testing;
@@ -38,127 +37,96 @@ using namespace etl;
struct ETLExtractorTest : util::prometheus::WithPrometheus, NoLoggerFixture {
using ExtractionDataPipeType = MockExtractionDataPipe;
using LedgerFetcherType = MockLedgerFetcher;
using ExtractorType = etl::impl::Extractor<ExtractionDataPipeType, MockNetworkValidatedLedgers, LedgerFetcherType>;
using ExtractorType = etl::impl::Extractor<ExtractionDataPipeType, LedgerFetcherType>;
ExtractionDataPipeType dataPipe_;
std::shared_ptr<MockNetworkValidatedLedgers> networkValidatedLedgers_ =
std::make_shared<MockNetworkValidatedLedgers>();
MockNetworkValidatedLedgersPtr networkValidatedLedgers_;
LedgerFetcherType ledgerFetcher_;
SystemState state_;
std::unique_ptr<ExtractorType> extractor_;
void
SetUp() override
ETLExtractorTest()
{
state_.isStopping = false;
state_.writeConflict = false;
state_.isReadOnly = false;
state_.isWriting = false;
}
void
TearDown() override
{
extractor_.reset();
}
};
TEST_F(ETLExtractorTest, StopsWhenCurrentSequenceExceedsFinishSequence)
{
auto const rawNetworkValidatedLedgersPtr = networkValidatedLedgers_.get();
ON_CALL(*rawNetworkValidatedLedgersPtr, waitUntilValidatedByNetwork).WillByDefault(Return(true));
EXPECT_CALL(*rawNetworkValidatedLedgersPtr, waitUntilValidatedByNetwork).Times(3);
ON_CALL(dataPipe_, getStride).WillByDefault(Return(4));
EXPECT_CALL(dataPipe_, getStride).Times(3);
EXPECT_CALL(*networkValidatedLedgers_, waitUntilValidatedByNetwork).Times(3).WillRepeatedly(Return(true));
EXPECT_CALL(dataPipe_, getStride).Times(3).WillRepeatedly(Return(4));
auto response = FakeFetchResponse{};
ON_CALL(ledgerFetcher_, fetchDataAndDiff(_)).WillByDefault(Return(response));
EXPECT_CALL(ledgerFetcher_, fetchDataAndDiff).Times(3);
EXPECT_CALL(ledgerFetcher_, fetchDataAndDiff).Times(3).WillRepeatedly(Return(response));
EXPECT_CALL(dataPipe_, push).Times(3);
EXPECT_CALL(dataPipe_, finish(0)).Times(1);
// expected to invoke for seq 0, 4, 8 and finally stop as seq will be greater than finishing seq
extractor_ = std::make_unique<ExtractorType>(dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 11, state_);
ExtractorType{dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 11, state_};
}
TEST_F(ETLExtractorTest, StopsOnWriteConflict)
{
EXPECT_CALL(dataPipe_, finish(0)).Times(1);
EXPECT_CALL(dataPipe_, finish(0));
state_.writeConflict = true;
// despite finish sequence being far ahead, we set writeConflict and so exit the loop immediately
extractor_ = std::make_unique<ExtractorType>(dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 64, state_);
ExtractorType{dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 64, state_};
}
TEST_F(ETLExtractorTest, StopsOnServerShutdown)
{
EXPECT_CALL(dataPipe_, finish(0)).Times(1);
EXPECT_CALL(dataPipe_, finish(0));
state_.isStopping = true;
// despite finish sequence being far ahead, we set isStopping and so exit the loop immediately
extractor_ = std::make_unique<ExtractorType>(dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 64, state_);
ExtractorType{dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 64, state_};
}
// stop extractor thread if fetcheResponse is empty
TEST_F(ETLExtractorTest, StopsIfFetchIsUnsuccessful)
{
auto const rawNetworkValidatedLedgersPtr = networkValidatedLedgers_.get();
EXPECT_CALL(*networkValidatedLedgers_, waitUntilValidatedByNetwork).WillOnce(Return(true));
ON_CALL(*rawNetworkValidatedLedgersPtr, waitUntilValidatedByNetwork).WillByDefault(Return(true));
EXPECT_CALL(*rawNetworkValidatedLedgersPtr, waitUntilValidatedByNetwork).Times(1);
ON_CALL(ledgerFetcher_, fetchDataAndDiff(_)).WillByDefault(Return(std::nullopt));
EXPECT_CALL(ledgerFetcher_, fetchDataAndDiff).Times(1);
EXPECT_CALL(dataPipe_, finish(0)).Times(1);
EXPECT_CALL(ledgerFetcher_, fetchDataAndDiff).WillOnce(Return(std::nullopt));
EXPECT_CALL(dataPipe_, finish(0));
// we break immediately because fetchDataAndDiff returns nullopt
extractor_ = std::make_unique<ExtractorType>(dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 64, state_);
ExtractorType{dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 64, state_};
}
TEST_F(ETLExtractorTest, StopsIfWaitingUntilValidatedByNetworkTimesOut)
{
auto const rawNetworkValidatedLedgersPtr = networkValidatedLedgers_.get();
// note that in actual clio code we don't return false unless a timeout is specified and exceeded
ON_CALL(*rawNetworkValidatedLedgersPtr, waitUntilValidatedByNetwork).WillByDefault(Return(false));
EXPECT_CALL(*rawNetworkValidatedLedgersPtr, waitUntilValidatedByNetwork).Times(1);
EXPECT_CALL(*networkValidatedLedgers_, waitUntilValidatedByNetwork).WillOnce(Return(false));
EXPECT_CALL(dataPipe_, finish(0)).Times(1);
// we emulate waitUntilValidatedByNetwork timing out which would lead to shutdown of the extractor thread
extractor_ = std::make_unique<ExtractorType>(dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 64, state_);
ExtractorType{dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 64, state_};
}
TEST_F(ETLExtractorTest, SendsCorrectResponseToDataPipe)
{
auto const rawNetworkValidatedLedgersPtr = networkValidatedLedgers_.get();
ON_CALL(*rawNetworkValidatedLedgersPtr, waitUntilValidatedByNetwork).WillByDefault(Return(true));
EXPECT_CALL(*rawNetworkValidatedLedgersPtr, waitUntilValidatedByNetwork).Times(1);
ON_CALL(dataPipe_, getStride).WillByDefault(Return(4));
EXPECT_CALL(dataPipe_, getStride).Times(1);
EXPECT_CALL(*networkValidatedLedgers_, waitUntilValidatedByNetwork).WillOnce(Return(true));
EXPECT_CALL(dataPipe_, getStride).WillOnce(Return(4));
auto response = FakeFetchResponse{1234};
auto optionalResponse = std::optional<FakeFetchResponse>{};
ON_CALL(ledgerFetcher_, fetchDataAndDiff(_)).WillByDefault(Return(response));
EXPECT_CALL(ledgerFetcher_, fetchDataAndDiff).Times(1);
EXPECT_CALL(dataPipe_, push).Times(1).WillOnce(SaveArg<1>(&optionalResponse));
EXPECT_CALL(dataPipe_, finish(0)).Times(1);
EXPECT_CALL(ledgerFetcher_, fetchDataAndDiff).WillOnce(Return(response));
EXPECT_CALL(dataPipe_, push(_, std::optional{response}));
EXPECT_CALL(dataPipe_, finish(0));
// expect to finish after just one response due to finishSequence set to 1
extractor_ = std::make_unique<ExtractorType>(dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 1, state_);
extractor_->waitTillFinished(); // this is what clio does too. waiting for the thread to join
EXPECT_TRUE(optionalResponse.has_value());
EXPECT_EQ(optionalResponse.value(), response);
ExtractorType extractor{dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 0, 1, state_};
extractor.waitTillFinished(); // this is what clio does too. waiting for the thread to join
}
TEST_F(ETLExtractorTest, CallsPipeFinishWithInitialSequenceAtExit)
{
EXPECT_CALL(dataPipe_, finish(123)).Times(1);
EXPECT_CALL(dataPipe_, finish(123));
state_.isStopping = true;
extractor_ = std::make_unique<ExtractorType>(dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 123, 234, state_);
ExtractorType{dataPipe_, networkValidatedLedgers_, ledgerFetcher_, 123, 234, state_};
}

View File

@@ -50,29 +50,22 @@ static auto constexpr LEDGERHASH = "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A
static auto constexpr SEQ = 30;
static auto constexpr AGE = 800;
struct ETLLedgerPublisherTest : util::prometheus::WithPrometheus,
MockBackendTest,
SyncAsioContextTest,
MockSubscriptionManagerTest {
struct ETLLedgerPublisherTest : util::prometheus::WithPrometheus, MockBackendTestStrict, SyncAsioContextTest {
void
SetUp() override
{
MockBackendTest::SetUp();
SyncAsioContextTest::SetUp();
MockSubscriptionManagerTest::SetUp();
}
void
TearDown() override
{
MockSubscriptionManagerTest::TearDown();
SyncAsioContextTest::TearDown();
MockBackendTest::TearDown();
}
protected:
util::Config cfg{json::parse("{}")};
MockCache mockCache;
StrictMockSubscriptionManagerSharedPtr mockSubscriptionManagerPtr;
};
TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoIsWritingFalse)
@@ -83,14 +76,13 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoIsWritingFalse)
impl::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
publisher.publish(dummyLedgerInfo);
ON_CALL(*backend, fetchLedgerDiff(SEQ, _)).WillByDefault(Return(std::vector<LedgerObject>{}));
EXPECT_CALL(*backend, fetchLedgerDiff(SEQ, _)).Times(1);
EXPECT_CALL(*backend, fetchLedgerDiff(SEQ, _)).WillOnce(Return(std::vector<LedgerObject>{}));
// setLastPublishedSequence not in strand, should verify before run
EXPECT_TRUE(publisher.getLastPublishedSequence());
EXPECT_EQ(publisher.getLastPublishedSequence().value(), SEQ);
EXPECT_CALL(mockCache, updateImp).Times(1);
EXPECT_CALL(mockCache, updateImp);
ctx.run();
EXPECT_TRUE(backend->fetchLedgerRange());
@@ -106,8 +98,6 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoIsWritingTrue)
impl::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
publisher.publish(dummyLedgerInfo);
EXPECT_CALL(*backend, fetchLedgerDiff(_, _)).Times(0);
// setLastPublishedSequence not in strand, should verify before run
EXPECT_TRUE(publisher.getLastPublishedSequence());
EXPECT_EQ(publisher.getLastPublishedSequence().value(), SEQ);
@@ -127,33 +117,26 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoInRange)
publisher.publish(dummyLedgerInfo);
EXPECT_CALL(*backend, fetchLedgerDiff(_, _)).Times(0);
// mock fetch fee
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
.WillByDefault(Return(CreateLegacyFeeSettingBlob(1, 2, 3, 4, 0)));
EXPECT_CALL(*backend, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
.WillOnce(Return(CreateLegacyFeeSettingBlob(1, 2, 3, 4, 0)));
// mock fetch transactions
EXPECT_CALL(*backend, fetchAllTransactionsInLedger).Times(1);
TransactionAndMetadata t1;
t1.transaction = CreatePaymentTransactionObject(ACCOUNT, ACCOUNT2, 100, 3, SEQ).getSerializer().peekData();
t1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT, ACCOUNT2, 110, 30).getSerializer().peekData();
t1.ledgerSequence = SEQ;
ON_CALL(*backend, fetchAllTransactionsInLedger(SEQ, _))
.WillByDefault(Return(std::vector<TransactionAndMetadata>{t1}));
// mock fetch transactions
EXPECT_CALL(*backend, fetchAllTransactionsInLedger).WillOnce(Return(std::vector<TransactionAndMetadata>{t1}));
// setLastPublishedSequence not in strand, should verify before run
EXPECT_TRUE(publisher.getLastPublishedSequence());
EXPECT_EQ(publisher.getLastPublishedSequence().value(), SEQ);
MockSubscriptionManager* rawSubscriptionManagerPtr =
dynamic_cast<MockSubscriptionManager*>(mockSubscriptionManagerPtr.get());
EXPECT_CALL(*rawSubscriptionManagerPtr, pubLedger(_, _, fmt::format("{}-{}", SEQ - 1, SEQ), 1)).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, pubBookChanges).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, pubLedger(_, _, fmt::format("{}-{}", SEQ - 1, SEQ), 1));
EXPECT_CALL(*mockSubscriptionManagerPtr, pubBookChanges);
// mock 1 transaction
EXPECT_CALL(*rawSubscriptionManagerPtr, pubTransaction).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, pubTransaction);
ctx.run();
// last publish time should be set
@@ -175,33 +158,27 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoCloseTimeGreaterThanNow)
impl::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
publisher.publish(dummyLedgerInfo);
EXPECT_CALL(*backend, fetchLedgerDiff(_, _)).Times(0);
// mock fetch fee
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
.WillByDefault(Return(CreateLegacyFeeSettingBlob(1, 2, 3, 4, 0)));
EXPECT_CALL(*backend, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
.WillOnce(Return(CreateLegacyFeeSettingBlob(1, 2, 3, 4, 0)));
// mock fetch transactions
EXPECT_CALL(*backend, fetchAllTransactionsInLedger).Times(1);
TransactionAndMetadata t1;
t1.transaction = CreatePaymentTransactionObject(ACCOUNT, ACCOUNT2, 100, 3, SEQ).getSerializer().peekData();
t1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT, ACCOUNT2, 110, 30).getSerializer().peekData();
t1.ledgerSequence = SEQ;
ON_CALL(*backend, fetchAllTransactionsInLedger(SEQ, _))
.WillByDefault(Return(std::vector<TransactionAndMetadata>{t1}));
// mock fetch transactions
EXPECT_CALL(*backend, fetchAllTransactionsInLedger(SEQ, _))
.WillOnce(Return(std::vector<TransactionAndMetadata>{t1}));
// setLastPublishedSequence not in strand, should verify before run
EXPECT_TRUE(publisher.getLastPublishedSequence());
EXPECT_EQ(publisher.getLastPublishedSequence().value(), SEQ);
MockSubscriptionManager* rawSubscriptionManagerPtr =
dynamic_cast<MockSubscriptionManager*>(mockSubscriptionManagerPtr.get());
EXPECT_CALL(*rawSubscriptionManagerPtr, pubLedger(_, _, fmt::format("{}-{}", SEQ - 1, SEQ), 1)).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, pubBookChanges).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, pubLedger(_, _, fmt::format("{}-{}", SEQ - 1, SEQ), 1));
EXPECT_CALL(*mockSubscriptionManagerPtr, pubBookChanges);
// mock 1 transaction
EXPECT_CALL(*rawSubscriptionManagerPtr, pubTransaction).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, pubTransaction);
ctx.run();
// last publish time should be set
@@ -224,11 +201,10 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerSeqMaxAttampt)
static auto constexpr MAX_ATTEMPT = 2;
EXPECT_CALL(*backend, hardFetchLedgerRange).Times(MAX_ATTEMPT);
LedgerRange const range{.minSequence = SEQ - 1, .maxSequence = SEQ - 1};
ON_CALL(*backend, hardFetchLedgerRange(_)).WillByDefault(Return(range));
EXPECT_FALSE(publisher.publish(SEQ, MAX_ATTEMPT));
EXPECT_CALL(*backend, hardFetchLedgerRange).Times(MAX_ATTEMPT).WillRepeatedly(Return(range));
EXPECT_FALSE(publisher.publish(SEQ, MAX_ATTEMPT, std::chrono::milliseconds{1}));
}
TEST_F(ETLLedgerPublisherTest, PublishLedgerSeqStopIsFalse)
@@ -238,16 +214,13 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerSeqStopIsFalse)
impl::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
LedgerRange const range{.minSequence = SEQ, .maxSequence = SEQ};
ON_CALL(*backend, hardFetchLedgerRange(_)).WillByDefault(Return(range));
EXPECT_CALL(*backend, hardFetchLedgerRange).Times(1);
EXPECT_CALL(*backend, hardFetchLedgerRange).WillOnce(Return(range));
auto const dummyLedgerInfo = CreateLedgerInfo(LEDGERHASH, SEQ, AGE);
ON_CALL(*backend, fetchLedgerBySequence(SEQ, _)).WillByDefault(Return(dummyLedgerInfo));
EXPECT_CALL(*backend, fetchLedgerBySequence).Times(1);
EXPECT_CALL(*backend, fetchLedgerBySequence(SEQ, _)).WillOnce(Return(dummyLedgerInfo));
ON_CALL(*backend, fetchLedgerDiff(SEQ, _)).WillByDefault(Return(std::vector<LedgerObject>{}));
EXPECT_CALL(*backend, fetchLedgerDiff(SEQ, _)).Times(1);
EXPECT_CALL(mockCache, updateImp).Times(1);
EXPECT_CALL(*backend, fetchLedgerDiff(SEQ, _)).WillOnce(Return(std::vector<LedgerObject>{}));
EXPECT_CALL(mockCache, updateImp);
EXPECT_TRUE(publisher.publish(SEQ, {}));
ctx.run();
@@ -264,15 +237,10 @@ TEST_F(ETLLedgerPublisherTest, PublishMultipleTxInOrder)
publisher.publish(dummyLedgerInfo);
EXPECT_CALL(*backend, fetchLedgerDiff(_, _)).Times(0);
// mock fetch fee
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
.WillByDefault(Return(CreateLegacyFeeSettingBlob(1, 2, 3, 4, 0)));
EXPECT_CALL(*backend, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
.WillOnce(Return(CreateLegacyFeeSettingBlob(1, 2, 3, 4, 0)));
// mock fetch transactions
EXPECT_CALL(*backend, fetchAllTransactionsInLedger).Times(1);
// t1 index > t2 index
TransactionAndMetadata t1;
t1.transaction = CreatePaymentTransactionObject(ACCOUNT, ACCOUNT2, 100, 3, SEQ).getSerializer().peekData();
@@ -284,22 +252,21 @@ TEST_F(ETLLedgerPublisherTest, PublishMultipleTxInOrder)
t2.metadata = CreatePaymentTransactionMetaObject(ACCOUNT, ACCOUNT2, 110, 30, 1).getSerializer().peekData();
t2.ledgerSequence = SEQ;
t2.date = 2;
ON_CALL(*backend, fetchAllTransactionsInLedger(SEQ, _))
.WillByDefault(Return(std::vector<TransactionAndMetadata>{t1, t2}));
// mock fetch transactions
EXPECT_CALL(*backend, fetchAllTransactionsInLedger(SEQ, _))
.WillOnce(Return(std::vector<TransactionAndMetadata>{t1, t2}));
// setLastPublishedSequence not in strand, should verify before run
EXPECT_TRUE(publisher.getLastPublishedSequence());
EXPECT_EQ(publisher.getLastPublishedSequence().value(), SEQ);
MockSubscriptionManager* rawSubscriptionManagerPtr =
dynamic_cast<MockSubscriptionManager*>(mockSubscriptionManagerPtr.get());
EXPECT_CALL(*rawSubscriptionManagerPtr, pubLedger(_, _, fmt::format("{}-{}", SEQ - 1, SEQ), 2)).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, pubBookChanges).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, pubLedger(_, _, fmt::format("{}-{}", SEQ - 1, SEQ), 2));
EXPECT_CALL(*mockSubscriptionManagerPtr, pubBookChanges);
// should call pubTransaction t2 first (greater tx index)
Sequence const s;
EXPECT_CALL(*rawSubscriptionManagerPtr, pubTransaction(t2, _)).InSequence(s);
EXPECT_CALL(*rawSubscriptionManagerPtr, pubTransaction(t1, _)).InSequence(s);
EXPECT_CALL(*mockSubscriptionManagerPtr, pubTransaction(t2, _)).InSequence(s);
EXPECT_CALL(*mockSubscriptionManagerPtr, pubTransaction(t1, _)).InSequence(s);
ctx.run();
// last publish time should be set

View File

@@ -0,0 +1,568 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "etl/LoadBalancer.hpp"
#include "etl/Source.hpp"
#include "util/Fixtures.hpp"
#include "util/MockNetworkValidatedLedgers.hpp"
#include "util/MockPrometheus.hpp"
#include "util/MockSource.hpp"
#include "util/MockSubscriptionManager.hpp"
#include "util/Random.hpp"
#include "util/config/Config.hpp"
#include <boost/asio/io_context.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/json/array.hpp>
#include <boost/json/object.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/value.hpp>
#include <gmock/gmock.h>
#include <grpcpp/support/status.h>
#include <gtest/gtest.h>
#include <org/xrpl/rpc/v1/get_ledger.pb.h>
#include <chrono>
#include <cstdint>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
using namespace etl;
using testing::Return;
struct LoadBalancerConstructorTests : util::prometheus::WithPrometheus, MockBackendTestStrict {
StrictMockSubscriptionManagerSharedPtr subscriptionManager_;
StrictMockNetworkValidatedLedgersPtr networkManager_;
StrictMockSourceFactory sourceFactory_{2};
boost::asio::io_context ioContext_;
boost::json::value configJson_{{"etl_sources", {"source1", "source2"}}};
std::unique_ptr<LoadBalancer>
makeLoadBalancer()
{
return std::make_unique<LoadBalancer>(
util::Config{configJson_},
ioContext_,
backend,
subscriptionManager_,
networkManager_,
[this](auto&&... args) -> SourcePtr {
return sourceFactory_.makeSourceMock(std::forward<decltype(args)>(args)...);
}
);
}
};
TEST_F(LoadBalancerConstructorTests, construct)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(1), run);
makeLoadBalancer();
}
TEST_F(LoadBalancerConstructorTests, fetchETLState_Source0Fails)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(std::nullopt));
EXPECT_CALL(sourceFactory_.sourceAt(0), toString);
EXPECT_THROW({ makeLoadBalancer(); }, std::logic_error);
}
TEST_F(LoadBalancerConstructorTests, fetchETLState_Source0ReturnsError)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled)
.WillOnce(Return(boost::json::object{{"error", "some error"}}));
EXPECT_CALL(sourceFactory_.sourceAt(0), toString);
EXPECT_THROW({ makeLoadBalancer(); }, std::logic_error);
}
TEST_F(LoadBalancerConstructorTests, fetchETLState_Source1Fails)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled).WillOnce(Return(std::nullopt));
EXPECT_CALL(sourceFactory_.sourceAt(1), toString);
EXPECT_THROW({ makeLoadBalancer(); }, std::logic_error);
}
TEST_F(LoadBalancerConstructorTests, fetchETLState_DifferentNetworkID)
{
auto const source1Json = boost::json::parse(R"({"result": {"info": {"network_id": 0}}})");
auto const source2Json = boost::json::parse(R"({"result": {"info": {"network_id": 1}}})");
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(source1Json.as_object()));
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled).WillOnce(Return(source2Json.as_object()));
EXPECT_THROW({ makeLoadBalancer(); }, std::logic_error);
}
TEST_F(LoadBalancerConstructorTests, fetchETLState_Source1FailsButAllowNoEtlIsTrue)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled).WillOnce(Return(std::nullopt));
EXPECT_CALL(sourceFactory_.sourceAt(1), toString);
EXPECT_CALL(sourceFactory_.sourceAt(1), run);
configJson_.as_object()["allow_no_etl"] = true;
makeLoadBalancer();
}
TEST_F(LoadBalancerConstructorTests, fetchETLState_DifferentNetworkIDButAllowNoEtlIsTrue)
{
auto const source1Json = boost::json::parse(R"({"result": {"info": {"network_id": 0}}})");
auto const source2Json = boost::json::parse(R"({"result": {"info": {"network_id": 1}}})");
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(source1Json.as_object()));
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled).WillOnce(Return(source2Json.as_object()));
EXPECT_CALL(sourceFactory_.sourceAt(1), run);
configJson_.as_object()["allow_no_etl"] = true;
makeLoadBalancer();
}
struct LoadBalancerConstructorDeathTest : LoadBalancerConstructorTests {};
TEST_F(LoadBalancerConstructorDeathTest, numMarkersSpecifiedInConfigIsInvalid)
{
uint32_t const numMarkers = 257;
configJson_.as_object()["num_markers"] = numMarkers;
EXPECT_DEATH({ makeLoadBalancer(); }, ".*");
}
struct LoadBalancerOnConnectHookTests : LoadBalancerConstructorTests {
LoadBalancerOnConnectHookTests()
{
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(1), run);
loadBalancer_ = makeLoadBalancer();
}
std::unique_ptr<LoadBalancer> loadBalancer_;
};
TEST_F(LoadBalancerOnConnectHookTests, sourcesConnect)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
sourceFactory_.callbacksAt(0).onConnect();
sourceFactory_.callbacksAt(1).onConnect();
}
TEST_F(LoadBalancerOnConnectHookTests, sourcesConnect_Source0IsNotConnected)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
sourceFactory_.callbacksAt(0).onConnect(); // assuming it connects and disconnects immediately
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(true));
sourceFactory_.callbacksAt(1).onConnect();
// Nothing is called on another connect
sourceFactory_.callbacksAt(0).onConnect();
}
TEST_F(LoadBalancerOnConnectHookTests, sourcesConnect_BothSourcesAreNotConnected)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
sourceFactory_.callbacksAt(0).onConnect();
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
sourceFactory_.callbacksAt(1).onConnect();
// Then source 0 got connected
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
sourceFactory_.callbacksAt(0).onConnect();
}
struct LoadBalancerOnDisconnectHookTests : LoadBalancerOnConnectHookTests {
LoadBalancerOnDisconnectHookTests()
{
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
sourceFactory_.callbacksAt(0).onConnect();
// nothing happens on source 1 connect
sourceFactory_.callbacksAt(1).onConnect();
}
};
TEST_F(LoadBalancerOnDisconnectHookTests, source0Disconnects)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(true));
sourceFactory_.callbacksAt(0).onDisconnect();
}
TEST_F(LoadBalancerOnDisconnectHookTests, source1Disconnects)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
sourceFactory_.callbacksAt(1).onDisconnect();
}
TEST_F(LoadBalancerOnDisconnectHookTests, source0DisconnectsAndConnectsBack)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(true));
sourceFactory_.callbacksAt(0).onDisconnect();
sourceFactory_.callbacksAt(0).onConnect();
}
TEST_F(LoadBalancerOnDisconnectHookTests, source1DisconnectsAndConnectsBack)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
sourceFactory_.callbacksAt(1).onDisconnect();
sourceFactory_.callbacksAt(1).onConnect();
}
TEST_F(LoadBalancerOnConnectHookTests, bothSourcesDisconnectAndConnectBack)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).Times(2).WillRepeatedly(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(false)).Times(2);
EXPECT_CALL(sourceFactory_.sourceAt(1), isConnected()).Times(2).WillRepeatedly(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false)).Times(2);
sourceFactory_.callbacksAt(0).onDisconnect();
sourceFactory_.callbacksAt(1).onDisconnect();
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
sourceFactory_.callbacksAt(0).onConnect();
sourceFactory_.callbacksAt(1).onConnect();
}
struct LoadBalancer3SourcesTests : LoadBalancerConstructorTests {
LoadBalancer3SourcesTests()
{
sourceFactory_ = StrictMockSourceFactory{3};
configJson_.as_object()["etl_sources"] = {"source1", "source2", "source3"};
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(1), run);
EXPECT_CALL(sourceFactory_.sourceAt(2), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(2), run);
loadBalancer_ = makeLoadBalancer();
}
std::unique_ptr<LoadBalancer> loadBalancer_;
};
TEST_F(LoadBalancer3SourcesTests, forwardingUpdate)
{
// Source 2 is connected first
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(false));
EXPECT_CALL(sourceFactory_.sourceAt(2), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(2), setForwarding(true));
sourceFactory_.callbacksAt(2).onConnect();
// Then source 0 and 1 are getting connected, but nothing should happen
sourceFactory_.callbacksAt(0).onConnect();
sourceFactory_.callbacksAt(1).onConnect();
// Source 0 got disconnected
EXPECT_CALL(sourceFactory_.sourceAt(0), isConnected()).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(0), setForwarding(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), isConnected()).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), setForwarding(true));
EXPECT_CALL(sourceFactory_.sourceAt(2), setForwarding(false)); // only source 1 must be forwarding
sourceFactory_.callbacksAt(0).onDisconnect();
}
struct LoadBalancerLoadInitialLedgerTests : LoadBalancerOnConnectHookTests {
LoadBalancerLoadInitialLedgerTests()
{
util::Random::setSeed(0);
}
uint32_t const sequence_ = 123;
uint32_t const numMarkers_ = 16;
bool const cacheOnly_ = true;
std::pair<std::vector<std::string>, bool> const response_ = {{"1", "2", "3"}, true};
};
TEST_F(LoadBalancerLoadInitialLedgerTests, load)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), loadInitialLedger(sequence_, numMarkers_, cacheOnly_))
.WillOnce(Return(response_));
EXPECT_EQ(loadBalancer_->loadInitialLedger(sequence_, cacheOnly_), response_.first);
}
TEST_F(LoadBalancerLoadInitialLedgerTests, load_source0DoesntHaveLedger)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), hasLedger(sequence_)).WillOnce(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), loadInitialLedger(sequence_, numMarkers_, cacheOnly_))
.WillOnce(Return(response_));
EXPECT_EQ(loadBalancer_->loadInitialLedger(sequence_, cacheOnly_), response_.first);
}
TEST_F(LoadBalancerLoadInitialLedgerTests, load_bothSourcesDontHaveLedger)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), hasLedger(sequence_)).Times(2).WillRepeatedly(Return(false));
EXPECT_CALL(sourceFactory_.sourceAt(1), hasLedger(sequence_)).WillOnce(Return(false)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), loadInitialLedger(sequence_, numMarkers_, cacheOnly_))
.WillOnce(Return(response_));
EXPECT_EQ(loadBalancer_->loadInitialLedger(sequence_, cacheOnly_, std::chrono::milliseconds{1}), response_.first);
}
TEST_F(LoadBalancerLoadInitialLedgerTests, load_source0ReturnsStatusFalse)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), loadInitialLedger(sequence_, numMarkers_, cacheOnly_))
.WillOnce(Return(std::make_pair(std::vector<std::string>{}, false)));
EXPECT_CALL(sourceFactory_.sourceAt(1), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), loadInitialLedger(sequence_, numMarkers_, cacheOnly_))
.WillOnce(Return(response_));
EXPECT_EQ(loadBalancer_->loadInitialLedger(sequence_, cacheOnly_), response_.first);
}
struct LoadBalancerLoadInitialLedgerCustomNumMarkersTests : LoadBalancerConstructorTests {
uint32_t const numMarkers_ = 16;
uint32_t const sequence_ = 123;
bool const cacheOnly_ = true;
std::pair<std::vector<std::string>, bool> const response_ = {{"1", "2", "3"}, true};
};
TEST_F(LoadBalancerLoadInitialLedgerCustomNumMarkersTests, loadInitialLedger)
{
configJson_.as_object()["num_markers"] = numMarkers_;
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(1), run);
auto loadBalancer = makeLoadBalancer();
util::Random::setSeed(0);
EXPECT_CALL(sourceFactory_.sourceAt(0), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), loadInitialLedger(sequence_, numMarkers_, cacheOnly_))
.WillOnce(Return(response_));
EXPECT_EQ(loadBalancer->loadInitialLedger(sequence_, cacheOnly_), response_.first);
}
struct LoadBalancerFetchLegerTests : LoadBalancerOnConnectHookTests {
LoadBalancerFetchLegerTests()
{
util::Random::setSeed(0);
response_.second.set_validated(true);
}
uint32_t const sequence_ = 123;
bool const getObjects_ = true;
bool const getObjectNeighbors_ = false;
std::pair<grpc::Status, org::xrpl::rpc::v1::GetLedgerResponse> response_ =
std::make_pair(grpc::Status::OK, org::xrpl::rpc::v1::GetLedgerResponse{});
};
TEST_F(LoadBalancerFetchLegerTests, fetch)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), fetchLedger(sequence_, getObjects_, getObjectNeighbors_))
.WillOnce(Return(response_));
EXPECT_TRUE(loadBalancer_->fetchLedger(sequence_, getObjects_, getObjectNeighbors_).has_value());
}
TEST_F(LoadBalancerFetchLegerTests, fetch_Source0ReturnsBadStatus)
{
auto source0Response = response_;
source0Response.first = grpc::Status::CANCELLED;
EXPECT_CALL(sourceFactory_.sourceAt(0), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), fetchLedger(sequence_, getObjects_, getObjectNeighbors_))
.WillOnce(Return(source0Response));
EXPECT_CALL(sourceFactory_.sourceAt(1), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), fetchLedger(sequence_, getObjects_, getObjectNeighbors_))
.WillOnce(Return(response_));
EXPECT_TRUE(loadBalancer_->fetchLedger(sequence_, getObjects_, getObjectNeighbors_).has_value());
}
TEST_F(LoadBalancerFetchLegerTests, fetch_Source0ReturnsNotValidated)
{
auto source0Response = response_;
source0Response.second.set_validated(false);
EXPECT_CALL(sourceFactory_.sourceAt(0), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), fetchLedger(sequence_, getObjects_, getObjectNeighbors_))
.WillOnce(Return(source0Response));
EXPECT_CALL(sourceFactory_.sourceAt(1), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), fetchLedger(sequence_, getObjects_, getObjectNeighbors_))
.WillOnce(Return(response_));
EXPECT_TRUE(loadBalancer_->fetchLedger(sequence_, getObjects_, getObjectNeighbors_).has_value());
}
TEST_F(LoadBalancerFetchLegerTests, fetch_bothSourcesFail)
{
auto badResponse = response_;
badResponse.second.set_validated(false);
EXPECT_CALL(sourceFactory_.sourceAt(0), hasLedger(sequence_)).Times(2).WillRepeatedly(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(0), fetchLedger(sequence_, getObjects_, getObjectNeighbors_))
.WillOnce(Return(badResponse))
.WillOnce(Return(response_));
EXPECT_CALL(sourceFactory_.sourceAt(1), hasLedger(sequence_)).WillOnce(Return(true));
EXPECT_CALL(sourceFactory_.sourceAt(1), fetchLedger(sequence_, getObjects_, getObjectNeighbors_))
.WillOnce(Return(badResponse));
EXPECT_TRUE(loadBalancer_->fetchLedger(sequence_, getObjects_, getObjectNeighbors_, std::chrono::milliseconds{1})
.has_value());
}
struct LoadBalancerForwardToRippledTests : LoadBalancerConstructorTests, SyncAsioContextTest {
LoadBalancerForwardToRippledTests()
{
util::Random::setSeed(0);
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(0), run);
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled).WillOnce(Return(boost::json::object{}));
EXPECT_CALL(sourceFactory_.sourceAt(1), run);
}
boost::json::object const request_{{"request", "value"}};
std::optional<std::string> const clientIP_ = "some_ip";
boost::json::object const response_{{"response", "other_value"}};
};
TEST_F(LoadBalancerForwardToRippledTests, forward)
{
auto loadBalancer = makeLoadBalancer();
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled(request_, clientIP_, testing::_))
.WillOnce(Return(response_));
runSpawn([&](boost::asio::yield_context yield) {
EXPECT_EQ(loadBalancer->forwardToRippled(request_, clientIP_, yield), response_);
});
}
TEST_F(LoadBalancerForwardToRippledTests, source0Fails)
{
auto loadBalancer = makeLoadBalancer();
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled(request_, clientIP_, testing::_))
.WillOnce(Return(std::nullopt));
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled(request_, clientIP_, testing::_))
.WillOnce(Return(response_));
runSpawn([&](boost::asio::yield_context yield) {
EXPECT_EQ(loadBalancer->forwardToRippled(request_, clientIP_, yield), response_);
});
}
TEST_F(LoadBalancerForwardToRippledTests, bothSourcesFail)
{
auto loadBalancer = makeLoadBalancer();
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled(request_, clientIP_, testing::_))
.WillOnce(Return(std::nullopt));
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled(request_, clientIP_, testing::_))
.WillOnce(Return(std::nullopt));
runSpawn([&](boost::asio::yield_context yield) {
EXPECT_EQ(loadBalancer->forwardToRippled(request_, clientIP_, yield), std::nullopt);
});
}
TEST_F(LoadBalancerForwardToRippledTests, forwardingCacheEnabled)
{
configJson_.as_object()["forwarding_cache_timeout"] = 10.;
auto loadBalancer = makeLoadBalancer();
auto const request = boost::json::object{{"command", "server_info"}};
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled(request, clientIP_, testing::_))
.WillOnce(Return(response_));
runSpawn([&](boost::asio::yield_context yield) {
EXPECT_EQ(loadBalancer->forwardToRippled(request, clientIP_, yield), response_);
EXPECT_EQ(loadBalancer->forwardToRippled(request, clientIP_, yield), response_);
});
}
TEST_F(LoadBalancerForwardToRippledTests, onLedgerClosedHookInvalidatesCache)
{
configJson_.as_object()["forwarding_cache_timeout"] = 10.;
auto loadBalancer = makeLoadBalancer();
auto const request = boost::json::object{{"command", "server_info"}};
EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled(request, clientIP_, testing::_))
.WillOnce(Return(response_));
EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled(request, clientIP_, testing::_))
.WillOnce(Return(boost::json::object{}));
runSpawn([&](boost::asio::yield_context yield) {
EXPECT_EQ(loadBalancer->forwardToRippled(request, clientIP_, yield), response_);
EXPECT_EQ(loadBalancer->forwardToRippled(request, clientIP_, yield), response_);
sourceFactory_.callbacksAt(0).onLedgerClosed();
EXPECT_EQ(loadBalancer->forwardToRippled(request, clientIP_, yield), boost::json::object{});
});
}
struct LoadBalancerToJsonTests : LoadBalancerOnConnectHookTests {};
TEST_F(LoadBalancerToJsonTests, toJson)
{
EXPECT_CALL(sourceFactory_.sourceAt(0), toJson).WillOnce(Return(boost::json::object{{"source1", "value1"}}));
EXPECT_CALL(sourceFactory_.sourceAt(1), toJson).WillOnce(Return(boost::json::object{{"source2", "value2"}}));
auto const expectedJson =
boost::json::array({boost::json::object{{"source1", "value1"}}, boost::json::object{{"source2", "value2"}}});
EXPECT_EQ(loadBalancer_->toJson(), expectedJson);
}

View File

@@ -17,7 +17,7 @@
*/
//==============================================================================
#include "etl/Source.hpp"
#include "etl/impl/SourceImpl.hpp"
#include <boost/asio/io_context.hpp>
#include <boost/asio/spawn.hpp>
@@ -36,7 +36,7 @@
#include <utility>
#include <vector>
using namespace etl;
using namespace etl::impl;
using testing::Return;
using testing::StrictMock;
@@ -72,7 +72,7 @@ struct ForwardingSourceMock {
);
};
struct SourceTest : public ::testing::Test {
struct SourceImplTest : public ::testing::Test {
boost::asio::io_context ioc_;
StrictMock<GrpcSourceMock> grpcSourceMock_;
@@ -94,25 +94,25 @@ struct SourceTest : public ::testing::Test {
};
};
TEST_F(SourceTest, run)
TEST_F(SourceImplTest, run)
{
EXPECT_CALL(*subscriptionSourceMock_, run());
source_.run();
}
TEST_F(SourceTest, isConnected)
TEST_F(SourceImplTest, isConnected)
{
EXPECT_CALL(*subscriptionSourceMock_, isConnected()).WillOnce(testing::Return(true));
EXPECT_TRUE(source_.isConnected());
}
TEST_F(SourceTest, setForwarding)
TEST_F(SourceImplTest, setForwarding)
{
EXPECT_CALL(*subscriptionSourceMock_, setForwarding(true));
source_.setForwarding(true);
}
TEST_F(SourceTest, toJson)
TEST_F(SourceImplTest, toJson)
{
EXPECT_CALL(*subscriptionSourceMock_, validatedRange()).WillOnce(Return(std::string("some_validated_range")));
EXPECT_CALL(*subscriptionSourceMock_, isConnected()).WillOnce(Return(true));
@@ -130,7 +130,7 @@ TEST_F(SourceTest, toJson)
EXPECT_GE(std::stoi(lastMessageAgeStr), 0);
}
TEST_F(SourceTest, toString)
TEST_F(SourceImplTest, toString)
{
EXPECT_CALL(*subscriptionSourceMock_, validatedRange()).WillOnce(Return(std::string("some_validated_range")));
@@ -141,14 +141,14 @@ TEST_F(SourceTest, toString)
);
}
TEST_F(SourceTest, hasLedger)
TEST_F(SourceImplTest, hasLedger)
{
uint32_t const ledgerSeq = 123;
EXPECT_CALL(*subscriptionSourceMock_, hasLedger(ledgerSeq)).WillOnce(Return(true));
EXPECT_TRUE(source_.hasLedger(ledgerSeq));
}
TEST_F(SourceTest, fetchLedger)
TEST_F(SourceImplTest, fetchLedger)
{
uint32_t const ledgerSeq = 123;
@@ -158,7 +158,7 @@ TEST_F(SourceTest, fetchLedger)
EXPECT_EQ(actualStatus.error_code(), grpc::StatusCode::OK);
}
TEST_F(SourceTest, loadInitialLedger)
TEST_F(SourceImplTest, loadInitialLedger)
{
uint32_t const ledgerSeq = 123;
uint32_t const numMarkers = 3;
@@ -171,7 +171,7 @@ TEST_F(SourceTest, loadInitialLedger)
EXPECT_TRUE(actualSuccess);
}
TEST_F(SourceTest, forwardToRippled)
TEST_F(SourceImplTest, forwardToRippled)
{
boost::json::object const request = {{"some_key", "some_value"}};
std::optional<std::string> const clientIp = "some_client_ip";

View File

@@ -1,70 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "etl/impl/SubscriptionSourceDependencies.hpp"
#include "util/MockNetworkValidatedLedgers.hpp"
#include "util/MockSubscriptionManager.hpp"
#include <boost/json/object.hpp>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <cstdint>
#include <memory>
using namespace etl::impl;
using testing::StrictMock;
struct SubscriptionSourceDependenciesTest : testing::Test {
std::shared_ptr<StrictMock<MockNetworkValidatedLedgers>> networkValidatedLedgers_ =
std::make_shared<StrictMock<MockNetworkValidatedLedgers>>();
std::shared_ptr<StrictMock<MockSubscriptionManager>> subscriptionManager_ =
std::make_shared<StrictMock<MockSubscriptionManager>>();
SubscriptionSourceDependencies dependencies_{networkValidatedLedgers_, subscriptionManager_};
};
TEST_F(SubscriptionSourceDependenciesTest, ForwardProposedTransaction)
{
boost::json::object const txJson = {{"tx", "json"}};
EXPECT_CALL(*subscriptionManager_, forwardProposedTransaction(txJson));
dependencies_.forwardProposedTransaction(txJson);
}
TEST_F(SubscriptionSourceDependenciesTest, ForwardValidation)
{
boost::json::object const validationJson = {{"validation", "json"}};
EXPECT_CALL(*subscriptionManager_, forwardValidation(validationJson));
dependencies_.forwardValidation(validationJson);
}
TEST_F(SubscriptionSourceDependenciesTest, ForwardManifest)
{
boost::json::object const manifestJson = {{"manifest", "json"}};
EXPECT_CALL(*subscriptionManager_, forwardManifest(manifestJson));
dependencies_.forwardManifest(manifestJson);
}
TEST_F(SubscriptionSourceDependenciesTest, PushValidatedLedger)
{
uint32_t const idx = 42;
EXPECT_CALL(*networkValidatedLedgers_, push(idx));
dependencies_.pushValidatedLedger(idx);
}

View File

@@ -43,26 +43,21 @@ using testing::StrictMock;
struct SubscriptionSourceConnectionTests : public NoLoggerFixture {
SubscriptionSourceConnectionTests()
{
subscriptionSource_->run();
subscriptionSource_.run();
}
boost::asio::io_context ioContext_;
TestWsServer wsServer_{ioContext_, "0.0.0.0", 11113};
template <typename T>
using StrictMockPtr = std::shared_ptr<StrictMock<T>>;
StrictMockPtr<MockNetworkValidatedLedgers> networkValidatedLedgers_ =
std::make_shared<StrictMock<MockNetworkValidatedLedgers>>();
StrictMockPtr<MockSubscriptionManager> subscriptionManager_ =
std::make_shared<StrictMock<MockSubscriptionManager>>();
StrictMockNetworkValidatedLedgersPtr networkValidatedLedgers_;
StrictMockSubscriptionManagerSharedPtr subscriptionManager_;
StrictMock<MockFunction<void()>> onConnectHook_;
StrictMock<MockFunction<void()>> onDisconnectHook_;
StrictMock<MockFunction<void()>> onLedgerClosedHook_;
std::unique_ptr<SubscriptionSource> subscriptionSource_ = std::make_unique<SubscriptionSource>(
SubscriptionSource subscriptionSource_{
ioContext_,
"127.0.0.1",
"11113",
@@ -73,7 +68,7 @@ struct SubscriptionSourceConnectionTests : public NoLoggerFixture {
onLedgerClosedHook_.AsStdFunction(),
std::chrono::milliseconds(1),
std::chrono::milliseconds(1)
);
};
[[maybe_unused]] TestWsConnection
serverConnection(boost::asio::yield_context yield)
@@ -99,13 +94,13 @@ struct SubscriptionSourceConnectionTests : public NoLoggerFixture {
TEST_F(SubscriptionSourceConnectionTests, ConnectionFailed)
{
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
TEST_F(SubscriptionSourceConnectionTests, ConnectionFailed_Retry_ConnectionFailed)
{
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
@@ -117,7 +112,7 @@ TEST_F(SubscriptionSourceConnectionTests, ReadError)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
@@ -131,21 +126,23 @@ TEST_F(SubscriptionSourceConnectionTests, ReadError_Reconnect)
});
EXPECT_CALL(onConnectHook_, Call()).Times(2);
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
TEST_F(SubscriptionSourceConnectionTests, IsConnected)
{
EXPECT_FALSE(subscriptionSource_->isConnected());
EXPECT_FALSE(subscriptionSource_.isConnected());
boost::asio::spawn(ioContext_, [this](boost::asio::yield_context yield) {
auto connection = serverConnection(yield);
EXPECT_TRUE(subscriptionSource_->isConnected());
connection.close(yield);
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onConnectHook_, Call()).WillOnce([this]() { EXPECT_TRUE(subscriptionSource_.isConnected()); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() {
EXPECT_FALSE(subscriptionSource_.isConnected());
subscriptionSource_.stop();
});
ioContext_.run();
}
@@ -170,7 +167,7 @@ TEST_F(SubscriptionSourceReadTests, GotWrongMessage_Reconnect)
});
EXPECT_CALL(onConnectHook_, Call()).Times(2);
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
@@ -182,7 +179,7 @@ TEST_F(SubscriptionSourceReadTests, GotResult)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
@@ -194,7 +191,7 @@ TEST_F(SubscriptionSourceReadTests, GotResultWithLedgerIndex)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
EXPECT_CALL(*networkValidatedLedgers_, push(123));
ioContext_.run();
}
@@ -209,7 +206,7 @@ TEST_F(SubscriptionSourceReadTests, GotResultWithLedgerIndexAsString_Reconnect)
});
EXPECT_CALL(onConnectHook_, Call()).Times(2);
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
@@ -223,21 +220,21 @@ TEST_F(SubscriptionSourceReadTests, GotResultWithValidatedLedgersAsNumber_Reconn
});
EXPECT_CALL(onConnectHook_, Call()).Times(2);
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
TEST_F(SubscriptionSourceReadTests, GotResultWithValidatedLedgers)
{
EXPECT_FALSE(subscriptionSource_->hasLedger(123));
EXPECT_FALSE(subscriptionSource_->hasLedger(124));
EXPECT_FALSE(subscriptionSource_->hasLedger(455));
EXPECT_FALSE(subscriptionSource_->hasLedger(456));
EXPECT_FALSE(subscriptionSource_->hasLedger(457));
EXPECT_FALSE(subscriptionSource_->hasLedger(32));
EXPECT_FALSE(subscriptionSource_->hasLedger(31));
EXPECT_FALSE(subscriptionSource_->hasLedger(789));
EXPECT_FALSE(subscriptionSource_->hasLedger(790));
EXPECT_FALSE(subscriptionSource_.hasLedger(123));
EXPECT_FALSE(subscriptionSource_.hasLedger(124));
EXPECT_FALSE(subscriptionSource_.hasLedger(455));
EXPECT_FALSE(subscriptionSource_.hasLedger(456));
EXPECT_FALSE(subscriptionSource_.hasLedger(457));
EXPECT_FALSE(subscriptionSource_.hasLedger(32));
EXPECT_FALSE(subscriptionSource_.hasLedger(31));
EXPECT_FALSE(subscriptionSource_.hasLedger(789));
EXPECT_FALSE(subscriptionSource_.hasLedger(790));
boost::asio::spawn(ioContext_, [this](boost::asio::yield_context yield) {
auto connection = connectAndSendMessage(R"({"result":{"validated_ledgers":"123-456,789,32"}})", yield);
@@ -245,20 +242,20 @@ TEST_F(SubscriptionSourceReadTests, GotResultWithValidatedLedgers)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
EXPECT_TRUE(subscriptionSource_->hasLedger(123));
EXPECT_TRUE(subscriptionSource_->hasLedger(124));
EXPECT_TRUE(subscriptionSource_->hasLedger(455));
EXPECT_TRUE(subscriptionSource_->hasLedger(456));
EXPECT_FALSE(subscriptionSource_->hasLedger(457));
EXPECT_TRUE(subscriptionSource_->hasLedger(32));
EXPECT_FALSE(subscriptionSource_->hasLedger(31));
EXPECT_TRUE(subscriptionSource_->hasLedger(789));
EXPECT_FALSE(subscriptionSource_->hasLedger(790));
EXPECT_TRUE(subscriptionSource_.hasLedger(123));
EXPECT_TRUE(subscriptionSource_.hasLedger(124));
EXPECT_TRUE(subscriptionSource_.hasLedger(455));
EXPECT_TRUE(subscriptionSource_.hasLedger(456));
EXPECT_FALSE(subscriptionSource_.hasLedger(457));
EXPECT_TRUE(subscriptionSource_.hasLedger(32));
EXPECT_FALSE(subscriptionSource_.hasLedger(31));
EXPECT_TRUE(subscriptionSource_.hasLedger(789));
EXPECT_FALSE(subscriptionSource_.hasLedger(790));
EXPECT_EQ(subscriptionSource_->validatedRange(), "123-456,789,32");
EXPECT_EQ(subscriptionSource_.validatedRange(), "123-456,789,32");
}
TEST_F(SubscriptionSourceReadTests, GotResultWithValidatedLedgersWrongValue_Reconnect)
@@ -271,17 +268,17 @@ TEST_F(SubscriptionSourceReadTests, GotResultWithValidatedLedgersWrongValue_Reco
});
EXPECT_CALL(onConnectHook_, Call()).Times(2);
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
TEST_F(SubscriptionSourceReadTests, GotResultWithLedgerIndexAndValidatedLedgers)
{
EXPECT_FALSE(subscriptionSource_->hasLedger(1));
EXPECT_FALSE(subscriptionSource_->hasLedger(1));
EXPECT_FALSE(subscriptionSource_->hasLedger(2));
EXPECT_FALSE(subscriptionSource_->hasLedger(3));
EXPECT_FALSE(subscriptionSource_->hasLedger(4));
EXPECT_FALSE(subscriptionSource_.hasLedger(1));
EXPECT_FALSE(subscriptionSource_.hasLedger(1));
EXPECT_FALSE(subscriptionSource_.hasLedger(2));
EXPECT_FALSE(subscriptionSource_.hasLedger(3));
EXPECT_FALSE(subscriptionSource_.hasLedger(4));
boost::asio::spawn(ioContext_, [this](boost::asio::yield_context yield) {
auto connection = connectAndSendMessage(R"({"result":{"ledger_index":123,"validated_ledgers":"1-3"}})", yield);
@@ -289,16 +286,16 @@ TEST_F(SubscriptionSourceReadTests, GotResultWithLedgerIndexAndValidatedLedgers)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
EXPECT_CALL(*networkValidatedLedgers_, push(123));
ioContext_.run();
EXPECT_EQ(subscriptionSource_->validatedRange(), "1-3");
EXPECT_FALSE(subscriptionSource_->hasLedger(0));
EXPECT_TRUE(subscriptionSource_->hasLedger(1));
EXPECT_TRUE(subscriptionSource_->hasLedger(2));
EXPECT_TRUE(subscriptionSource_->hasLedger(3));
EXPECT_FALSE(subscriptionSource_->hasLedger(4));
EXPECT_EQ(subscriptionSource_.validatedRange(), "1-3");
EXPECT_FALSE(subscriptionSource_.hasLedger(0));
EXPECT_TRUE(subscriptionSource_.hasLedger(1));
EXPECT_TRUE(subscriptionSource_.hasLedger(2));
EXPECT_TRUE(subscriptionSource_.hasLedger(3));
EXPECT_FALSE(subscriptionSource_.hasLedger(4));
}
TEST_F(SubscriptionSourceReadTests, GotLedgerClosed)
@@ -309,13 +306,13 @@ TEST_F(SubscriptionSourceReadTests, GotLedgerClosed)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
TEST_F(SubscriptionSourceReadTests, GotLedgerClosedForwardingIsSet)
{
subscriptionSource_->setForwarding(true);
subscriptionSource_.setForwarding(true);
boost::asio::spawn(ioContext_, [this](boost::asio::yield_context yield) {
auto connection = connectAndSendMessage(R"({"type": "ledgerClosed"})", yield);
@@ -324,7 +321,10 @@ TEST_F(SubscriptionSourceReadTests, GotLedgerClosedForwardingIsSet)
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onLedgerClosedHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() {
EXPECT_FALSE(subscriptionSource_.isForwarding());
subscriptionSource_.stop();
});
ioContext_.run();
}
@@ -336,7 +336,7 @@ TEST_F(SubscriptionSourceReadTests, GotLedgerClosedWithLedgerIndex)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
EXPECT_CALL(*networkValidatedLedgers_, push(123));
ioContext_.run();
}
@@ -351,7 +351,7 @@ TEST_F(SubscriptionSourceReadTests, GotLedgerClosedWithLedgerIndexAsString_Recon
});
EXPECT_CALL(onConnectHook_, Call()).Times(2);
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
@@ -365,16 +365,16 @@ TEST_F(SubscriptionSourceReadTests, GorLedgerClosedWithValidatedLedgersAsNumber_
});
EXPECT_CALL(onConnectHook_, Call()).Times(2);
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([]() {}).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
TEST_F(SubscriptionSourceReadTests, GotLedgerClosedWithValidatedLedgers)
{
EXPECT_FALSE(subscriptionSource_->hasLedger(0));
EXPECT_FALSE(subscriptionSource_->hasLedger(1));
EXPECT_FALSE(subscriptionSource_->hasLedger(2));
EXPECT_FALSE(subscriptionSource_->hasLedger(3));
EXPECT_FALSE(subscriptionSource_.hasLedger(0));
EXPECT_FALSE(subscriptionSource_.hasLedger(1));
EXPECT_FALSE(subscriptionSource_.hasLedger(2));
EXPECT_FALSE(subscriptionSource_.hasLedger(3));
boost::asio::spawn(ioContext_, [this](boost::asio::yield_context yield) {
auto connection = connectAndSendMessage(R"({"type":"ledgerClosed","validated_ledgers":"1-2"})", yield);
@@ -382,22 +382,22 @@ TEST_F(SubscriptionSourceReadTests, GotLedgerClosedWithValidatedLedgers)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
EXPECT_FALSE(subscriptionSource_->hasLedger(0));
EXPECT_TRUE(subscriptionSource_->hasLedger(1));
EXPECT_TRUE(subscriptionSource_->hasLedger(2));
EXPECT_FALSE(subscriptionSource_->hasLedger(3));
EXPECT_EQ(subscriptionSource_->validatedRange(), "1-2");
EXPECT_FALSE(subscriptionSource_.hasLedger(0));
EXPECT_TRUE(subscriptionSource_.hasLedger(1));
EXPECT_TRUE(subscriptionSource_.hasLedger(2));
EXPECT_FALSE(subscriptionSource_.hasLedger(3));
EXPECT_EQ(subscriptionSource_.validatedRange(), "1-2");
}
TEST_F(SubscriptionSourceReadTests, GotLedgerClosedWithLedgerIndexAndValidatedLedgers)
{
EXPECT_FALSE(subscriptionSource_->hasLedger(0));
EXPECT_FALSE(subscriptionSource_->hasLedger(1));
EXPECT_FALSE(subscriptionSource_->hasLedger(2));
EXPECT_FALSE(subscriptionSource_->hasLedger(3));
EXPECT_FALSE(subscriptionSource_.hasLedger(0));
EXPECT_FALSE(subscriptionSource_.hasLedger(1));
EXPECT_FALSE(subscriptionSource_.hasLedger(2));
EXPECT_FALSE(subscriptionSource_.hasLedger(3));
boost::asio::spawn(ioContext_, [this](boost::asio::yield_context yield) {
auto connection =
@@ -406,15 +406,15 @@ TEST_F(SubscriptionSourceReadTests, GotLedgerClosedWithLedgerIndexAndValidatedLe
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
EXPECT_CALL(*networkValidatedLedgers_, push(123));
ioContext_.run();
EXPECT_FALSE(subscriptionSource_->hasLedger(0));
EXPECT_TRUE(subscriptionSource_->hasLedger(1));
EXPECT_TRUE(subscriptionSource_->hasLedger(2));
EXPECT_FALSE(subscriptionSource_->hasLedger(3));
EXPECT_EQ(subscriptionSource_->validatedRange(), "1-2");
EXPECT_FALSE(subscriptionSource_.hasLedger(0));
EXPECT_TRUE(subscriptionSource_.hasLedger(1));
EXPECT_TRUE(subscriptionSource_.hasLedger(2));
EXPECT_FALSE(subscriptionSource_.hasLedger(3));
EXPECT_EQ(subscriptionSource_.validatedRange(), "1-2");
}
TEST_F(SubscriptionSourceReadTests, GotTransactionIsForwardingFalse)
@@ -425,13 +425,13 @@ TEST_F(SubscriptionSourceReadTests, GotTransactionIsForwardingFalse)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
TEST_F(SubscriptionSourceReadTests, GotTransactionIsForwardingTrue)
{
subscriptionSource_->setForwarding(true);
subscriptionSource_.setForwarding(true);
boost::json::object const message = {{"transaction", "some_transaction_data"}};
boost::asio::spawn(ioContext_, [&message, this](boost::asio::yield_context yield) {
@@ -440,7 +440,7 @@ TEST_F(SubscriptionSourceReadTests, GotTransactionIsForwardingTrue)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
EXPECT_CALL(*subscriptionManager_, forwardProposedTransaction(message));
ioContext_.run();
}
@@ -453,13 +453,13 @@ TEST_F(SubscriptionSourceReadTests, GotValidationReceivedIsForwardingFalse)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
TEST_F(SubscriptionSourceReadTests, GotValidationReceivedIsForwardingTrue)
{
subscriptionSource_->setForwarding(true);
subscriptionSource_.setForwarding(true);
boost::json::object const message = {{"type", "validationReceived"}};
boost::asio::spawn(ioContext_, [&message, this](boost::asio::yield_context yield) {
@@ -468,7 +468,7 @@ TEST_F(SubscriptionSourceReadTests, GotValidationReceivedIsForwardingTrue)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
EXPECT_CALL(*subscriptionManager_, forwardValidation(message));
ioContext_.run();
}
@@ -481,13 +481,13 @@ TEST_F(SubscriptionSourceReadTests, GotManiefstReceivedIsForwardingFalse)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
}
TEST_F(SubscriptionSourceReadTests, GotManifestReceivedIsForwardingTrue)
{
subscriptionSource_->setForwarding(true);
subscriptionSource_.setForwarding(true);
boost::json::object const message = {{"type", "manifestReceived"}};
boost::asio::spawn(ioContext_, [&message, this](boost::asio::yield_context yield) {
@@ -496,7 +496,7 @@ TEST_F(SubscriptionSourceReadTests, GotManifestReceivedIsForwardingTrue)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
EXPECT_CALL(*subscriptionManager_, forwardManifest(message));
ioContext_.run();
}
@@ -509,10 +509,10 @@ TEST_F(SubscriptionSourceReadTests, LastMessageTime)
});
EXPECT_CALL(onConnectHook_, Call());
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_->stop(); });
EXPECT_CALL(onDisconnectHook_, Call()).WillOnce([this]() { subscriptionSource_.stop(); });
ioContext_.run();
auto const actualLastTimeMessage = subscriptionSource_->lastMessageTime();
auto const actualLastTimeMessage = subscriptionSource_.lastMessageTime();
auto const now = std::chrono::steady_clock::now();
auto const diff = std::chrono::duration_cast<std::chrono::milliseconds>(now - actualLastTimeMessage);
EXPECT_LT(diff, std::chrono::milliseconds(100));

View File

@@ -67,7 +67,6 @@ struct ETLTransformerTest : util::prometheus::WithPrometheus, MockBackendTest {
void
SetUp() override
{
MockBackendTest::SetUp();
state_.isStopping = false;
state_.writeConflict = false;
state_.isReadOnly = false;
@@ -78,7 +77,6 @@ struct ETLTransformerTest : util::prometheus::WithPrometheus, MockBackendTest {
TearDown() override
{
transformer_.reset();
MockBackendTest::TearDown();
}
};

View File

@@ -64,7 +64,6 @@ protected:
void
SetUp() override
{
MockBackendTest::SetUp();
SyncAsioContextTest::SetUp();
SubscriptionManagerPtr = std::make_shared<SubscriptionManager>(ctx, backend);
session = std::make_shared<MockSession>();
@@ -78,7 +77,6 @@ protected:
session.reset();
SubscriptionManagerPtr.reset();
SyncAsioContextTest::TearDown();
MockBackendTest::TearDown();
}
};

View File

@@ -62,13 +62,11 @@ class RPCHelpersTest : public util::prometheus::WithPrometheus, public MockBacke
void
SetUp() override
{
MockBackendTest::SetUp();
SyncAsioContextTest::SetUp();
}
void
TearDown() override
{
MockBackendTest::TearDown();
SyncAsioContextTest::TearDown();
}
};

View File

@@ -43,23 +43,19 @@ using namespace rpc;
namespace json = boost::json;
using namespace testing;
using TestServerInfoHandler =
BaseServerInfoHandler<MockSubscriptionManager, MockLoadBalancer, MockETLService, MockCounters>;
using TestServerInfoHandler = BaseServerInfoHandler<MockLoadBalancer, MockETLService, MockCounters>;
constexpr static auto LEDGERHASH = "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652";
constexpr static auto CLIENTIP = "1.1.1.1";
class RPCServerInfoHandlerTest : public HandlerBaseTest,
public MockLoadBalancerTest,
public MockSubscriptionManagerTest,
public MockCountersTest {
protected:
struct RPCServerInfoHandlerTest : HandlerBaseTest, MockLoadBalancerTest, MockCountersTest {
StrictMockSubscriptionManagerSharedPtr mockSubscriptionManagerPtr;
void
SetUp() override
{
HandlerBaseTest::SetUp();
MockLoadBalancerTest::SetUp();
MockSubscriptionManagerTest::SetUp();
MockCountersTest::SetUp();
backend->setRange(10, 30);
@@ -69,7 +65,6 @@ protected:
TearDown() override
{
MockCountersTest::TearDown();
MockSubscriptionManagerTest::TearDown();
MockLoadBalancerTest::TearDown();
HandlerBaseTest::TearDown();
}
@@ -341,7 +336,6 @@ TEST_F(RPCServerInfoHandlerTest, AdminSectionPresentWhenAdminFlagIsSet)
{
MockLoadBalancer* rawBalancerPtr = mockLoadBalancerPtr.get();
MockCounters* rawCountersPtr = mockCountersPtr.get();
MockSubscriptionManager* rawSubscriptionManagerPtr = mockSubscriptionManagerPtr.get();
MockETLService* rawETLServicePtr = mockETLServicePtr.get();
auto const empty = json::object{};
@@ -360,7 +354,7 @@ TEST_F(RPCServerInfoHandlerTest, AdminSectionPresentWhenAdminFlagIsSet)
// admin calls
EXPECT_CALL(*rawCountersPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*rawSubscriptionManagerPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*mockSubscriptionManagerPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*rawETLServicePtr, getInfo).WillOnce(Return(empty));
@@ -381,7 +375,6 @@ TEST_F(RPCServerInfoHandlerTest, BackendCountersPresentWhenRequestWithParam)
{
MockLoadBalancer* rawBalancerPtr = mockLoadBalancerPtr.get();
MockCounters* rawCountersPtr = mockCountersPtr.get();
MockSubscriptionManager* rawSubscriptionManagerPtr = mockSubscriptionManagerPtr.get();
MockETLService* rawETLServicePtr = mockETLServicePtr.get();
auto const empty = json::object{};
@@ -400,7 +393,7 @@ TEST_F(RPCServerInfoHandlerTest, BackendCountersPresentWhenRequestWithParam)
// admin calls
EXPECT_CALL(*rawCountersPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*rawSubscriptionManagerPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*mockSubscriptionManagerPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*rawETLServicePtr, getInfo).WillOnce(Return(empty));
@@ -427,7 +420,6 @@ TEST_F(RPCServerInfoHandlerTest, RippledForwardedValuesPresent)
{
MockLoadBalancer* rawBalancerPtr = mockLoadBalancerPtr.get();
MockCounters* rawCountersPtr = mockCountersPtr.get();
MockSubscriptionManager* rawSubscriptionManagerPtr = mockSubscriptionManagerPtr.get();
MockETLService* rawETLServicePtr = mockETLServicePtr.get();
auto const empty = json::object{};
@@ -456,7 +448,7 @@ TEST_F(RPCServerInfoHandlerTest, RippledForwardedValuesPresent)
// admin calls
EXPECT_CALL(*rawCountersPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*rawSubscriptionManagerPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*mockSubscriptionManagerPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*rawETLServicePtr, getInfo).WillOnce(Return(empty));
@@ -478,7 +470,6 @@ TEST_F(RPCServerInfoHandlerTest, RippledForwardedValuesMissingNoExceptionThrown)
{
MockLoadBalancer* rawBalancerPtr = mockLoadBalancerPtr.get();
MockCounters* rawCountersPtr = mockCountersPtr.get();
MockSubscriptionManager* rawSubscriptionManagerPtr = mockSubscriptionManagerPtr.get();
MockETLService* rawETLServicePtr = mockETLServicePtr.get();
auto const empty = json::object{};
@@ -502,7 +493,7 @@ TEST_F(RPCServerInfoHandlerTest, RippledForwardedValuesMissingNoExceptionThrown)
// admin calls
EXPECT_CALL(*rawCountersPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*rawSubscriptionManagerPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*mockSubscriptionManagerPtr, report).WillOnce(Return(empty));
EXPECT_CALL(*rawETLServicePtr, getInfo).WillOnce(Return(empty));

View File

@@ -44,29 +44,25 @@ namespace json = boost::json;
using namespace testing;
using namespace feed;
using TestUnsubscribeHandler = BaseUnsubscribeHandler<MockSubscriptionManager>;
constexpr static auto ACCOUNT = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
constexpr static auto ACCOUNT2 = "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun";
class RPCUnsubscribeTest : public HandlerBaseTest, public MockSubscriptionManagerTest {
protected:
struct RPCUnsubscribeTest : HandlerBaseTest {
void
SetUp() override
{
HandlerBaseTest::SetUp();
MockSubscriptionManagerTest::SetUp();
session_ = std::make_shared<MockSession>();
}
void
TearDown() override
{
MockSubscriptionManagerTest::TearDown();
HandlerBaseTest::TearDown();
}
std::shared_ptr<feed::SubscriptionManager> subManager_;
std::shared_ptr<web::ConnectionBase> session_;
StrictMockSubscriptionManagerSharedPtr mockSubscriptionManagerPtr;
};
struct UnsubscribeParamTestCaseBundle {
@@ -530,7 +526,7 @@ TEST_P(UnsubscribeParameterTest, InvalidParams)
{
auto const testBundle = GetParam();
runSpawn([&, this](auto yield) {
auto const handler = AnyHandler{TestUnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const handler = AnyHandler{UnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const req = json::parse(testBundle.testJson);
auto const output = handler.process(req, Context{yield});
ASSERT_FALSE(output);
@@ -543,7 +539,7 @@ TEST_P(UnsubscribeParameterTest, InvalidParams)
TEST_F(RPCUnsubscribeTest, EmptyResponse)
{
runSpawn([&, this](auto yield) {
auto const handler = AnyHandler{TestUnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const handler = AnyHandler{UnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const output = handler.process(json::parse(R"({})"), Context{yield, session_});
ASSERT_TRUE(output);
EXPECT_TRUE(output.result->as_object().empty());
@@ -558,16 +554,15 @@ TEST_F(RPCUnsubscribeTest, Streams)
})"
);
MockSubscriptionManager* rawSubscriptionManagerPtr = mockSubscriptionManagerPtr.get();
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubLedger).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubTransactions).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubValidation).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubManifest).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubBookChanges).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubProposedTransactions).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubLedger).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubTransactions).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubValidation).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubManifest).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubBookChanges).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubProposedTransactions).Times(1);
runSpawn([&, this](auto yield) {
auto const handler = AnyHandler{TestUnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const handler = AnyHandler{UnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const output = handler.process(input, Context{yield, session_});
ASSERT_TRUE(output);
EXPECT_TRUE(output.result->as_object().empty());
@@ -584,12 +579,11 @@ TEST_F(RPCUnsubscribeTest, Accounts)
ACCOUNT2
));
MockSubscriptionManager* rawSubscriptionManagerPtr = mockSubscriptionManagerPtr.get();
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubAccount(rpc::accountFromStringStrict(ACCOUNT).value(), _)).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubAccount(rpc::accountFromStringStrict(ACCOUNT2).value(), _)).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubAccount(rpc::accountFromStringStrict(ACCOUNT).value(), _)).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubAccount(rpc::accountFromStringStrict(ACCOUNT2).value(), _)).Times(1);
runSpawn([&, this](auto yield) {
auto const handler = AnyHandler{TestUnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const handler = AnyHandler{UnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const output = handler.process(input, Context{yield, session_});
ASSERT_TRUE(output);
EXPECT_TRUE(output.result->as_object().empty());
@@ -606,14 +600,13 @@ TEST_F(RPCUnsubscribeTest, AccountsProposed)
ACCOUNT2
));
MockSubscriptionManager* rawSubscriptionManagerPtr = mockSubscriptionManagerPtr.get();
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubProposedAccount(rpc::accountFromStringStrict(ACCOUNT).value(), _))
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubProposedAccount(rpc::accountFromStringStrict(ACCOUNT).value(), _))
.Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubProposedAccount(rpc::accountFromStringStrict(ACCOUNT2).value(), _))
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubProposedAccount(rpc::accountFromStringStrict(ACCOUNT2).value(), _))
.Times(1);
runSpawn([&, this](auto yield) {
auto const handler = AnyHandler{TestUnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const handler = AnyHandler{UnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const output = handler.process(input, Context{yield, session_});
ASSERT_TRUE(output);
EXPECT_TRUE(output.result->as_object().empty());
@@ -643,12 +636,11 @@ TEST_F(RPCUnsubscribeTest, Books)
auto const parsedBookMaybe = rpc::parseBook(input.as_object().at("books").as_array()[0].as_object());
auto const book = std::get<ripple::Book>(parsedBookMaybe);
MockSubscriptionManager* rawSubscriptionManagerPtr = mockSubscriptionManagerPtr.get();
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubBook(book, _)).Times(1);
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubBook(ripple::reversed(book), _)).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubBook(book, _)).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubBook(ripple::reversed(book), _)).Times(1);
runSpawn([&, this](auto yield) {
auto const handler = AnyHandler{TestUnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const handler = AnyHandler{UnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const output = handler.process(input, Context{yield, session_});
ASSERT_TRUE(output);
EXPECT_TRUE(output.result->as_object().empty());
@@ -677,11 +669,10 @@ TEST_F(RPCUnsubscribeTest, SingleBooks)
auto const parsedBookMaybe = rpc::parseBook(input.as_object().at("books").as_array()[0].as_object());
auto const book = std::get<ripple::Book>(parsedBookMaybe);
MockSubscriptionManager* rawSubscriptionManagerPtr = mockSubscriptionManagerPtr.get();
EXPECT_CALL(*rawSubscriptionManagerPtr, unsubBook(book, _)).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr, unsubBook(book, _)).Times(1);
runSpawn([&, this](auto yield) {
auto const handler = AnyHandler{TestUnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const handler = AnyHandler{UnsubscribeHandler{backend, mockSubscriptionManagerPtr}};
auto const output = handler.process(input, Context{yield, session_});
ASSERT_TRUE(output);
EXPECT_TRUE(output.result->as_object().empty());

View File

@@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2024, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include "util/Random.hpp"
#include <gtest/gtest.h>
#include <algorithm>
#include <cstddef>
#include <iterator>
#include <vector>
using namespace util;
struct RandomTests : public ::testing::Test {
static std::vector<int>
generateRandoms(size_t const numRandoms = 1000)
{
std::vector<int> v;
v.reserve(numRandoms);
std::ranges::generate_n(std::back_inserter(v), numRandoms, []() { return Random::uniform(0, 1000); });
return v;
}
};
TEST_F(RandomTests, Uniform)
{
std::ranges::for_each(generateRandoms(), [](int const& e) {
EXPECT_GE(e, 0);
EXPECT_LE(e, 1000);
});
}
TEST_F(RandomTests, FixedSeed)
{
Random::setSeed(42);
std::vector<int> const v1 = generateRandoms();
Random::setSeed(42);
std::vector<int> const v2 = generateRandoms();
ASSERT_EQ(v1.size(), v2.size());
for (size_t i = 0; i < v1.size(); ++i) {
EXPECT_EQ(v1[i], v2[i]);
};
}

View File

@@ -66,15 +66,10 @@ struct MockWsBase : public web::ConnectionBase {
}
};
class WebRPCServerHandlerTest : public util::prometheus::WithPrometheus,
public MockBackendTest,
public SyncAsioContextTest {
protected:
struct WebRPCServerHandlerTest : util::prometheus::WithPrometheus, MockBackendTest, SyncAsioContextTest {
void
SetUp() override
{
MockBackendTest::SetUp();
etl = std::make_shared<MockETLService>();
rpcEngine = std::make_shared<MockAsyncRPCEngine>();
tagFactory = std::make_shared<util::TagDecoratorFactory>(cfg);
@@ -82,12 +77,6 @@ protected:
handler = std::make_shared<RPCServerHandler<MockAsyncRPCEngine, MockETLService>>(cfg, backend, rpcEngine, etl);
}
void
TearDown() override
{
MockBackendTest::TearDown();
}
std::shared_ptr<MockAsyncRPCEngine> rpcEngine;
std::shared_ptr<MockETLService> etl;
std::shared_ptr<util::TagDecoratorFactory> tagFactory;