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

@@ -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_};
}