Simplify backend mock access for unittests (#1062)

This commit is contained in:
Alex Kremer
2024-01-02 13:35:57 +00:00
committed by GitHub
parent 781f3b3c48
commit d077093a8d
38 changed files with 2200 additions and 2926 deletions

View File

@@ -103,39 +103,37 @@ getLatestDiff()
TEST_F(CacheLoaderTest, FromCache)
{
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
CacheLoader loader{cfg, ctx, mockBackendPtr, cache};
CacheLoader loader{cfg, ctx, backend, cache};
auto const diffs = getLatestDiff();
ON_CALL(*rawBackendPtr, fetchLedgerDiff(_, _)).WillByDefault(Return(diffs));
EXPECT_CALL(*rawBackendPtr, fetchLedgerDiff(_, _)).Times(32);
ON_CALL(*backend, fetchLedgerDiff(_, _)).WillByDefault(Return(diffs));
EXPECT_CALL(*backend, fetchLedgerDiff(_, _)).Times(32);
auto const loops = diffs.size() + 1;
auto const keysSize = 14;
std::mutex keysMutex;
std::map<std::thread::id, uint32_t> threadKeysMap;
ON_CALL(*rawBackendPtr, doFetchSuccessorKey(_, SEQ, _))
.WillByDefault(Invoke([&]() -> std::optional<ripple::uint256> {
// mock the result from doFetchSuccessorKey, be aware this function will be called from multiple threads
// for each thread, the last 2 items must be end flag and nullopt, otherwise it will loop forever
std::lock_guard<std::mutex> const guard(keysMutex);
threadKeysMap[std::this_thread::get_id()]++;
ON_CALL(*backend, doFetchSuccessorKey(_, SEQ, _)).WillByDefault(Invoke([&]() -> std::optional<ripple::uint256> {
// mock the result from doFetchSuccessorKey, be aware this function will be called from multiple threads
// for each thread, the last 2 items must be end flag and nullopt, otherwise it will loop forever
std::lock_guard<std::mutex> const guard(keysMutex);
threadKeysMap[std::this_thread::get_id()]++;
if (threadKeysMap[std::this_thread::get_id()] == keysSize - 1) {
return lastKey;
}
if (threadKeysMap[std::this_thread::get_id()] == keysSize) {
threadKeysMap[std::this_thread::get_id()] = 0;
return std::nullopt;
}
return ripple::uint256{INDEX1};
}));
EXPECT_CALL(*rawBackendPtr, doFetchSuccessorKey).Times(keysSize * loops);
if (threadKeysMap[std::this_thread::get_id()] == keysSize - 1) {
return lastKey;
}
if (threadKeysMap[std::this_thread::get_id()] == keysSize) {
threadKeysMap[std::this_thread::get_id()] = 0;
return std::nullopt;
}
return ripple::uint256{INDEX1};
}));
EXPECT_CALL(*backend, doFetchSuccessorKey).Times(keysSize * loops);
ON_CALL(*rawBackendPtr, doFetchLedgerObjects(_, SEQ, _))
ON_CALL(*backend, doFetchLedgerObjects(_, SEQ, _))
.WillByDefault(Return(std::vector<Blob>{keysSize - 1, Blob{'s'}}));
EXPECT_CALL(*rawBackendPtr, doFetchLedgerObjects).Times(loops);
EXPECT_CALL(*backend, doFetchLedgerObjects).Times(loops);
EXPECT_CALL(cache, updateImp).Times(loops);
EXPECT_CALL(cache, isFull).Times(1);

View File

@@ -77,14 +77,11 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoIsWritingFalse)
SystemState dummyState;
dummyState.isWriting = false;
auto const dummyLedgerInfo = CreateLedgerInfo(LEDGERHASH, SEQ, AGE);
detail::LedgerPublisher publisher(ctx, mockBackendPtr, mockCache, mockSubscriptionManagerPtr, dummyState);
detail::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
publisher.publish(dummyLedgerInfo);
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
ASSERT_NE(rawBackendPtr, nullptr);
ON_CALL(*rawBackendPtr, fetchLedgerDiff(SEQ, _)).WillByDefault(Return(std::vector<LedgerObject>{}));
EXPECT_CALL(*rawBackendPtr, fetchLedgerDiff(SEQ, _)).Times(1);
ON_CALL(*backend, fetchLedgerDiff(SEQ, _)).WillByDefault(Return(std::vector<LedgerObject>{}));
EXPECT_CALL(*backend, fetchLedgerDiff(SEQ, _)).Times(1);
// setLastPublishedSequence not in strand, should verify before run
EXPECT_TRUE(publisher.getLastPublishedSequence());
@@ -93,9 +90,9 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoIsWritingFalse)
EXPECT_CALL(mockCache, updateImp).Times(1);
ctx.run();
EXPECT_TRUE(rawBackendPtr->fetchLedgerRange());
EXPECT_EQ(rawBackendPtr->fetchLedgerRange().value().minSequence, SEQ);
EXPECT_EQ(rawBackendPtr->fetchLedgerRange().value().maxSequence, SEQ);
EXPECT_TRUE(backend->fetchLedgerRange());
EXPECT_EQ(backend->fetchLedgerRange().value().minSequence, SEQ);
EXPECT_EQ(backend->fetchLedgerRange().value().maxSequence, SEQ);
}
TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoIsWritingTrue)
@@ -103,18 +100,17 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoIsWritingTrue)
SystemState dummyState;
dummyState.isWriting = true;
auto const dummyLedgerInfo = CreateLedgerInfo(LEDGERHASH, SEQ, AGE);
detail::LedgerPublisher publisher(ctx, mockBackendPtr, mockCache, mockSubscriptionManagerPtr, dummyState);
detail::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
publisher.publish(dummyLedgerInfo);
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
EXPECT_CALL(*rawBackendPtr, fetchLedgerDiff(_, _)).Times(0);
EXPECT_CALL(*backend, fetchLedgerDiff(_, _)).Times(0);
// setLastPublishedSequence not in strand, should verify before run
EXPECT_TRUE(publisher.getLastPublishedSequence());
EXPECT_EQ(publisher.getLastPublishedSequence().value(), SEQ);
ctx.run();
EXPECT_FALSE(rawBackendPtr->fetchLedgerRange());
EXPECT_FALSE(backend->fetchLedgerRange());
}
TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoInRange)
@@ -123,27 +119,25 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoInRange)
dummyState.isWriting = true;
auto const dummyLedgerInfo = CreateLedgerInfo(LEDGERHASH, SEQ, 0); // age is 0
detail::LedgerPublisher publisher(ctx, mockBackendPtr, mockCache, mockSubscriptionManagerPtr, dummyState);
mockBackendPtr->updateRange(SEQ - 1);
mockBackendPtr->updateRange(SEQ);
detail::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
backend->setRange(SEQ - 1, SEQ);
publisher.publish(dummyLedgerInfo);
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
EXPECT_CALL(*rawBackendPtr, fetchLedgerDiff(_, _)).Times(0);
EXPECT_CALL(*backend, fetchLedgerDiff(_, _)).Times(0);
// mock fetch fee
EXPECT_CALL(*rawBackendPtr, doFetchLedgerObject).Times(1);
ON_CALL(*rawBackendPtr, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
.WillByDefault(Return(CreateFeeSettingBlob(1, 2, 3, 4, 0)));
// mock fetch transactions
EXPECT_CALL(*rawBackendPtr, fetchAllTransactionsInLedger).Times(1);
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(*rawBackendPtr, fetchAllTransactionsInLedger(SEQ, _))
ON_CALL(*backend, fetchAllTransactionsInLedger(SEQ, _))
.WillByDefault(Return(std::vector<TransactionAndMetadata>{t1}));
// setLastPublishedSequence not in strand, should verify before run
@@ -173,27 +167,25 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerInfoCloseTimeGreaterThanNow)
auto const closeTime = duration_cast<seconds>(nowPlus10.time_since_epoch()).count() - rippleEpochStart;
dummyLedgerInfo.closeTime = ripple::NetClock::time_point{seconds{closeTime}};
mockBackendPtr->updateRange(SEQ - 1);
mockBackendPtr->updateRange(SEQ);
backend->setRange(SEQ - 1, SEQ);
detail::LedgerPublisher publisher(ctx, mockBackendPtr, mockCache, mockSubscriptionManagerPtr, dummyState);
detail::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
publisher.publish(dummyLedgerInfo);
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
EXPECT_CALL(*rawBackendPtr, fetchLedgerDiff(_, _)).Times(0);
EXPECT_CALL(*backend, fetchLedgerDiff(_, _)).Times(0);
// mock fetch fee
EXPECT_CALL(*rawBackendPtr, doFetchLedgerObject).Times(1);
ON_CALL(*rawBackendPtr, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
.WillByDefault(Return(CreateFeeSettingBlob(1, 2, 3, 4, 0)));
// mock fetch transactions
EXPECT_CALL(*rawBackendPtr, fetchAllTransactionsInLedger).Times(1);
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(*rawBackendPtr, fetchAllTransactionsInLedger(SEQ, _))
ON_CALL(*backend, fetchAllTransactionsInLedger(SEQ, _))
.WillByDefault(Return(std::vector<TransactionAndMetadata>{t1}));
// setLastPublishedSequence not in strand, should verify before run
@@ -217,7 +209,7 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerSeqStopIsTrue)
{
SystemState dummyState;
dummyState.isStopping = true;
detail::LedgerPublisher publisher(ctx, mockBackendPtr, mockCache, mockSubscriptionManagerPtr, dummyState);
detail::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
EXPECT_FALSE(publisher.publish(SEQ, {}));
}
@@ -225,14 +217,14 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerSeqMaxAttampt)
{
SystemState dummyState;
dummyState.isStopping = false;
detail::LedgerPublisher publisher(ctx, mockBackendPtr, mockCache, mockSubscriptionManagerPtr, dummyState);
detail::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
static auto constexpr MAX_ATTEMPT = 2;
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
EXPECT_CALL(*rawBackendPtr, hardFetchLedgerRange).Times(MAX_ATTEMPT);
EXPECT_CALL(*backend, hardFetchLedgerRange).Times(MAX_ATTEMPT);
LedgerRange const range{.minSequence = SEQ - 1, .maxSequence = SEQ - 1};
ON_CALL(*rawBackendPtr, hardFetchLedgerRange(_)).WillByDefault(Return(range));
ON_CALL(*backend, hardFetchLedgerRange(_)).WillByDefault(Return(range));
EXPECT_FALSE(publisher.publish(SEQ, MAX_ATTEMPT));
}
@@ -240,19 +232,18 @@ TEST_F(ETLLedgerPublisherTest, PublishLedgerSeqStopIsFalse)
{
SystemState dummyState;
dummyState.isStopping = false;
detail::LedgerPublisher publisher(ctx, mockBackendPtr, mockCache, mockSubscriptionManagerPtr, dummyState);
detail::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
LedgerRange const range{.minSequence = SEQ, .maxSequence = SEQ};
ON_CALL(*rawBackendPtr, hardFetchLedgerRange(_)).WillByDefault(Return(range));
EXPECT_CALL(*rawBackendPtr, hardFetchLedgerRange).Times(1);
ON_CALL(*backend, hardFetchLedgerRange(_)).WillByDefault(Return(range));
EXPECT_CALL(*backend, hardFetchLedgerRange).Times(1);
auto const dummyLedgerInfo = CreateLedgerInfo(LEDGERHASH, SEQ, AGE);
ON_CALL(*rawBackendPtr, fetchLedgerBySequence(SEQ, _)).WillByDefault(Return(dummyLedgerInfo));
EXPECT_CALL(*rawBackendPtr, fetchLedgerBySequence).Times(1);
ON_CALL(*backend, fetchLedgerBySequence(SEQ, _)).WillByDefault(Return(dummyLedgerInfo));
EXPECT_CALL(*backend, fetchLedgerBySequence).Times(1);
ON_CALL(*rawBackendPtr, fetchLedgerDiff(SEQ, _)).WillByDefault(Return(std::vector<LedgerObject>{}));
EXPECT_CALL(*rawBackendPtr, fetchLedgerDiff(SEQ, _)).Times(1);
ON_CALL(*backend, fetchLedgerDiff(SEQ, _)).WillByDefault(Return(std::vector<LedgerObject>{}));
EXPECT_CALL(*backend, fetchLedgerDiff(SEQ, _)).Times(1);
EXPECT_CALL(mockCache, updateImp).Times(1);
EXPECT_TRUE(publisher.publish(SEQ, {}));
@@ -265,22 +256,20 @@ TEST_F(ETLLedgerPublisherTest, PublishMultipleTxInOrder)
dummyState.isWriting = true;
auto const dummyLedgerInfo = CreateLedgerInfo(LEDGERHASH, SEQ, 0); // age is 0
detail::LedgerPublisher publisher(ctx, mockBackendPtr, mockCache, mockSubscriptionManagerPtr, dummyState);
mockBackendPtr->updateRange(SEQ - 1);
mockBackendPtr->updateRange(SEQ);
detail::LedgerPublisher publisher(ctx, backend, mockCache, mockSubscriptionManagerPtr, dummyState);
backend->setRange(SEQ - 1, SEQ);
publisher.publish(dummyLedgerInfo);
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
EXPECT_CALL(*rawBackendPtr, fetchLedgerDiff(_, _)).Times(0);
EXPECT_CALL(*backend, fetchLedgerDiff(_, _)).Times(0);
// mock fetch fee
EXPECT_CALL(*rawBackendPtr, doFetchLedgerObject).Times(1);
ON_CALL(*rawBackendPtr, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
ON_CALL(*backend, doFetchLedgerObject(ripple::keylet::fees().key, SEQ, _))
.WillByDefault(Return(CreateFeeSettingBlob(1, 2, 3, 4, 0)));
// mock fetch transactions
EXPECT_CALL(*rawBackendPtr, fetchAllTransactionsInLedger).Times(1);
EXPECT_CALL(*backend, fetchAllTransactionsInLedger).Times(1);
// t1 index > t2 index
TransactionAndMetadata t1;
t1.transaction = CreatePaymentTransactionObject(ACCOUNT, ACCOUNT2, 100, 3, SEQ).getSerializer().peekData();
@@ -292,7 +281,7 @@ TEST_F(ETLLedgerPublisherTest, PublishMultipleTxInOrder)
t2.metadata = CreatePaymentTransactionMetaObject(ACCOUNT, ACCOUNT2, 110, 30, 1).getSerializer().peekData();
t2.ledgerSequence = SEQ;
t2.date = 2;
ON_CALL(*rawBackendPtr, fetchAllTransactionsInLedger(SEQ, _))
ON_CALL(*backend, fetchAllTransactionsInLedger(SEQ, _))
.WillByDefault(Return(std::vector<TransactionAndMetadata>{t1, t2}));
// setLastPublishedSequence not in strand, should verify before run

View File

@@ -92,7 +92,7 @@ TEST_F(ETLTransformerTest, StopsOnWriteConflict)
EXPECT_CALL(ledgerPublisher_, publish(_)).Times(0);
transformer_ = std::make_unique<TransformerType>(
dataPipe_, mockBackendPtr, ledgerLoader_, ledgerPublisher_, amendmentBlockHandler_, 0, state_
dataPipe_, backend, ledgerLoader_, ledgerPublisher_, amendmentBlockHandler_, 0, state_
);
transformer_->waitTillFinished(); // explicitly joins the thread
@@ -100,9 +100,7 @@ TEST_F(ETLTransformerTest, StopsOnWriteConflict)
TEST_F(ETLTransformerTest, StopsOnEmptyFetchResponse)
{
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
ASSERT_NE(rawBackendPtr, nullptr);
mockBackendPtr->cache().setFull(); // to avoid throwing exception in updateCache
backend->cache().setFull(); // to avoid throwing exception in updateCache
auto const blob = hexStringToBinaryString(RAW_HEADER);
auto const response = std::make_optional<FakeFetchResponse>(blob);
@@ -112,21 +110,21 @@ TEST_F(ETLTransformerTest, StopsOnEmptyFetchResponse)
return std::nullopt;
return response; // NOLINT (performance-no-automatic-move)
});
ON_CALL(*rawBackendPtr, doFinishWrites).WillByDefault(Return(true));
ON_CALL(*backend, doFinishWrites).WillByDefault(Return(true));
// TODO: most of this should be hidden in a smaller entity that is injected into the transformer thread
EXPECT_CALL(dataPipe_, popNext).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, startWrites).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, writeLedger(_, _)).Times(AtLeast(1));
EXPECT_CALL(*backend, startWrites).Times(AtLeast(1));
EXPECT_CALL(*backend, writeLedger(_, _)).Times(AtLeast(1));
EXPECT_CALL(ledgerLoader_, insertTransactions).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, writeAccountTransactions).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, writeNFTs).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, writeNFTTransactions).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, doFinishWrites).Times(AtLeast(1));
EXPECT_CALL(*backend, writeAccountTransactions).Times(AtLeast(1));
EXPECT_CALL(*backend, writeNFTs).Times(AtLeast(1));
EXPECT_CALL(*backend, writeNFTTransactions).Times(AtLeast(1));
EXPECT_CALL(*backend, doFinishWrites).Times(AtLeast(1));
EXPECT_CALL(ledgerPublisher_, publish(_)).Times(AtLeast(1));
transformer_ = std::make_unique<TransformerType>(
dataPipe_, mockBackendPtr, ledgerLoader_, ledgerPublisher_, amendmentBlockHandler_, 0, state_
dataPipe_, backend, ledgerLoader_, ledgerPublisher_, amendmentBlockHandler_, 0, state_
);
// after 10ms we start spitting out empty responses which means the extractor is finishing up
@@ -137,31 +135,29 @@ TEST_F(ETLTransformerTest, StopsOnEmptyFetchResponse)
TEST_F(ETLTransformerTest, DoesNotPublishIfCanNotBuildNextLedger)
{
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
ASSERT_NE(rawBackendPtr, nullptr);
mockBackendPtr->cache().setFull(); // to avoid throwing exception in updateCache
backend->cache().setFull(); // to avoid throwing exception in updateCache
auto const blob = hexStringToBinaryString(RAW_HEADER);
auto const response = std::make_optional<FakeFetchResponse>(blob);
ON_CALL(dataPipe_, popNext).WillByDefault(Return(response));
ON_CALL(*rawBackendPtr, doFinishWrites).WillByDefault(Return(false)); // emulate write failure
ON_CALL(*backend, doFinishWrites).WillByDefault(Return(false)); // emulate write failure
// TODO: most of this should be hidden in a smaller entity that is injected into the transformer thread
EXPECT_CALL(dataPipe_, popNext).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, startWrites).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, writeLedger(_, _)).Times(AtLeast(1));
EXPECT_CALL(*backend, startWrites).Times(AtLeast(1));
EXPECT_CALL(*backend, writeLedger(_, _)).Times(AtLeast(1));
EXPECT_CALL(ledgerLoader_, insertTransactions).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, writeAccountTransactions).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, writeNFTs).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, writeNFTTransactions).Times(AtLeast(1));
EXPECT_CALL(*rawBackendPtr, doFinishWrites).Times(AtLeast(1));
EXPECT_CALL(*backend, writeAccountTransactions).Times(AtLeast(1));
EXPECT_CALL(*backend, writeNFTs).Times(AtLeast(1));
EXPECT_CALL(*backend, writeNFTTransactions).Times(AtLeast(1));
EXPECT_CALL(*backend, doFinishWrites).Times(AtLeast(1));
// should not call publish
EXPECT_CALL(ledgerPublisher_, publish(_)).Times(0);
transformer_ = std::make_unique<TransformerType>(
dataPipe_, mockBackendPtr, ledgerLoader_, ledgerPublisher_, amendmentBlockHandler_, 0, state_
dataPipe_, backend, ledgerLoader_, ledgerPublisher_, amendmentBlockHandler_, 0, state_
);
}