Skip to content

Commit

Permalink
Simplify backend mock access for unittests (#1062)
Browse files Browse the repository at this point in the history
  • Loading branch information
godexsoft authored Jan 2, 2024
1 parent 781f3b3 commit d077093
Show file tree
Hide file tree
Showing 38 changed files with 2,194 additions and 2,920 deletions.
6 changes: 2 additions & 4 deletions src/data/BackendFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,8 @@ make_Backend(util::Config const& config)
throw std::runtime_error("Invalid database type");

auto const rng = backend->hardFetchLedgerRangeNoThrow();
if (rng) {
backend->updateRange(rng->minSequence);
backend->updateRange(rng->maxSequence);
}
if (rng)
backend->setRange(rng->minSequence, rng->maxSequence);

LOG(log.info()) << "Constructed BackendInterface Successfully";
return backend;
Expand Down
13 changes: 13 additions & 0 deletions src/data/BackendInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,19 @@ BackendInterface::updateRange(uint32_t newMax)
}
}

void
BackendInterface::setRange(uint32_t min, uint32_t max, bool force)
{
std::scoped_lock const lck(rngMtx_);

if (!force) {
ASSERT(min <= max, "Range min must be less than or equal to max");
ASSERT(not range.has_value(), "Range was already set");
}

range = {min, max};
}

LedgerPage
BackendInterface::fetchLedgerPage(
std::optional<ripple::uint256> const& cursor,
Expand Down
10 changes: 10 additions & 0 deletions src/data/BackendInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,16 @@ class BackendInterface {
void
updateRange(uint32_t newMax);

/**
* @brief Sets the range of sequences that are stored in the DB.
*
* @param min The new minimum sequence available
* @param max The new maximum sequence available
* @param force If set to true, the range will be set even if it's already set
*/
void
setRange(uint32_t min, uint32_t max, bool force = false);

/**
* @brief Fetch the fees from a specific ledger sequence.
*
Expand Down
53 changes: 23 additions & 30 deletions unittests/SubscriptionManagerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,15 @@ class SubscriptionManagerSimpleBackendTest : public MockBackendTest {
std::shared_ptr<feed::SubscriptionManager> subManagerPtr;
util::TagDecoratorFactory tagDecoratorFactory{cfg};
std::shared_ptr<web::ConnectionBase> session;

void
SetUp() override
{
MockBackendTest::SetUp();
subManagerPtr = feed::SubscriptionManager::make_SubscriptionManager(cfg, mockBackendPtr);
subManagerPtr = feed::SubscriptionManager::make_SubscriptionManager(cfg, backend);
session = std::make_shared<MockSession>(tagDecoratorFactory);
}

void
TearDown() override
{
Expand Down Expand Up @@ -190,19 +192,16 @@ TEST_F(SubscriptionManagerSimpleBackendTest, ReportCurrentSubscriber)

TEST_F(SubscriptionManagerSimpleBackendTest, SubscriptionManagerLedgerUnSub)
{
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
ASSERT_NE(rawBackendPtr, nullptr);
mockBackendPtr->updateRange(10); // min
mockBackendPtr->updateRange(30); // max
backend->setRange(10, 30);
boost::asio::io_context ctx;
auto ledgerinfo = CreateLedgerInfo(LEDGERHASH, 30);
// mock fetchLedgerBySequence return this ledger
ON_CALL(*rawBackendPtr, fetchLedgerBySequence).WillByDefault(Return(ledgerinfo));
EXPECT_CALL(*rawBackendPtr, fetchLedgerBySequence).Times(1);
ON_CALL(*backend, fetchLedgerBySequence).WillByDefault(Return(ledgerinfo));
EXPECT_CALL(*backend, fetchLedgerBySequence).Times(1);
// mock doFetchLedgerObject return fee setting ledger object
auto feeBlob = CreateFeeSettingBlob(1, 2, 3, 4, 0);
ON_CALL(*rawBackendPtr, doFetchLedgerObject).WillByDefault(Return(feeBlob));
EXPECT_CALL(*rawBackendPtr, doFetchLedgerObject).Times(1);
ON_CALL(*backend, doFetchLedgerObject).WillByDefault(Return(feeBlob));
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
boost::asio::spawn(ctx, [this](boost::asio::yield_context yield) { subManagerPtr->subLedger(yield, session); });
ctx.run();
std::this_thread::sleep_for(milliseconds(20));
Expand Down Expand Up @@ -304,19 +303,16 @@ TEST_F(SubscriptionManagerSimpleBackendTest, SubscriptionManagerAccountProposedT
*/
TEST_F(SubscriptionManagerSimpleBackendTest, SubscriptionManagerLedger)
{
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
ASSERT_NE(rawBackendPtr, nullptr);
mockBackendPtr->updateRange(10); // min
mockBackendPtr->updateRange(30); // max
backend->setRange(10, 30);
boost::asio::io_context ctx;
auto ledgerinfo = CreateLedgerInfo(LEDGERHASH, 30);
// mock fetchLedgerBySequence return this ledger
ON_CALL(*rawBackendPtr, fetchLedgerBySequence).WillByDefault(Return(ledgerinfo));
EXPECT_CALL(*rawBackendPtr, fetchLedgerBySequence).Times(1);
ON_CALL(*backend, fetchLedgerBySequence).WillByDefault(Return(ledgerinfo));
EXPECT_CALL(*backend, fetchLedgerBySequence).Times(1);
// mock doFetchLedgerObject return fee setting ledger object
auto feeBlob = CreateFeeSettingBlob(1, 2, 3, 4, 0);
ON_CALL(*rawBackendPtr, doFetchLedgerObject).WillByDefault(Return(feeBlob));
EXPECT_CALL(*rawBackendPtr, doFetchLedgerObject).Times(1);
ON_CALL(*backend, doFetchLedgerObject).WillByDefault(Return(feeBlob));
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
// check the function response
// Information about the ledgers on hand and current fee schedule. This
// includes the same fields as a ledger stream message, except that it omits
Expand Down Expand Up @@ -479,10 +475,9 @@ TEST_F(SubscriptionManagerSimpleBackendTest, SubscriptionManagerTransactionOffer
line.setFieldU32(ripple::sfFlags, 0);
auto issue2 = GetIssue(CURRENCY, ISSUER);
line.setFieldAmount(ripple::sfBalance, ripple::STAmount(issue2, 100));
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
ASSERT_NE(rawBackendPtr, nullptr);
EXPECT_CALL(*rawBackendPtr, doFetchLedgerObject).Times(3);
ON_CALL(*rawBackendPtr, doFetchLedgerObject).WillByDefault(Return(line.getSerializer().peekData()));

EXPECT_CALL(*backend, doFetchLedgerObject).Times(3);
ON_CALL(*backend, doFetchLedgerObject).WillByDefault(Return(line.getSerializer().peekData()));
subManagerPtr->pubTransaction(trans1, ledgerinfo);
constexpr static auto TransactionForOwnerFund = R"({
"transaction":{
Expand Down Expand Up @@ -581,10 +576,9 @@ TEST_F(SubscriptionManagerSimpleBackendTest, SubscriptionManagerTransactionOffer
line.setFieldU32(ripple::sfPreviousTxnLgrSeq, 3);
line.setFieldU32(ripple::sfFlags, ripple::lsfHighFreeze);
line.setFieldAmount(ripple::sfBalance, ripple::STAmount(GetIssue(CURRENCY, ISSUER), 100));
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
ASSERT_NE(rawBackendPtr, nullptr);
EXPECT_CALL(*rawBackendPtr, doFetchLedgerObject).Times(3);
ON_CALL(*rawBackendPtr, doFetchLedgerObject).WillByDefault(Return(line.getSerializer().peekData()));

EXPECT_CALL(*backend, doFetchLedgerObject).Times(3);
ON_CALL(*backend, doFetchLedgerObject).WillByDefault(Return(line.getSerializer().peekData()));
subManagerPtr->pubTransaction(trans1, ledgerinfo);
CheckSubscriberMessage(TransactionForOwnerFundFrozen, session);
}
Expand Down Expand Up @@ -619,14 +613,13 @@ TEST_F(SubscriptionManagerSimpleBackendTest, SubscriptionManagerTransactionOffer
line.setFieldU32(ripple::sfFlags, ripple::lsfHighFreeze);
auto issueAccount = GetAccountIDWithString(ISSUER);
line.setFieldAmount(ripple::sfBalance, ripple::STAmount(GetIssue(CURRENCY, ISSUER), 100));
MockBackend* rawBackendPtr = dynamic_cast<MockBackend*>(mockBackendPtr.get());
ASSERT_NE(rawBackendPtr, nullptr);
EXPECT_CALL(*rawBackendPtr, doFetchLedgerObject).Times(2);

EXPECT_CALL(*backend, doFetchLedgerObject).Times(2);
auto kk = ripple::keylet::account(issueAccount).key;
ON_CALL(*rawBackendPtr, doFetchLedgerObject(testing::_, testing::_, testing::_))
ON_CALL(*backend, doFetchLedgerObject(testing::_, testing::_, testing::_))
.WillByDefault(Return(line.getSerializer().peekData()));
ripple::STObject const accountRoot = CreateAccountRootObject(ISSUER, ripple::lsfGlobalFreeze, 1, 10, 2, TXNID, 3);
ON_CALL(*rawBackendPtr, doFetchLedgerObject(kk, testing::_, testing::_))
ON_CALL(*backend, doFetchLedgerObject(kk, testing::_, testing::_))
.WillByDefault(Return(accountRoot.getSerializer().peekData()));
subManagerPtr->pubTransaction(trans1, ledgerinfo);
CheckSubscriberMessage(TransactionForOwnerFundFrozen, session);
Expand Down
46 changes: 22 additions & 24 deletions unittests/etl/CacheLoaderTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()]++;

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

ON_CALL(*rawBackendPtr, doFetchLedgerObjects(_, SEQ, _))
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(*backend, doFetchSuccessorKey).Times(keysSize * loops);

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);
Expand Down
Loading

0 comments on commit d077093

Please sign in to comment.