diff --git a/src/etl/ETLService.hpp b/src/etl/ETLService.hpp index 5eb6fd78..2a983c83 100644 --- a/src/etl/ETLService.hpp +++ b/src/etl/ETLService.hpp @@ -181,6 +181,10 @@ public: ret = std::make_shared(config, ioc, backend, subscriptions, balancer, ledgers); } + // inject networkID into subscriptions, as transaction feed require it to inject CTID in response + if (auto const state = ret->getETLState(); state) + subscriptions->setNetworkID(state->networkID); + ret->run(); return ret; } diff --git a/src/feed/SubscriptionManager.cpp b/src/feed/SubscriptionManager.cpp index 7db63718..af7bd574 100644 --- a/src/feed/SubscriptionManager.cpp +++ b/src/feed/SubscriptionManager.cpp @@ -191,7 +191,7 @@ SubscriptionManager::unsubBook(ripple::Book const& book, SubscriberSharedPtr con void SubscriptionManager::pubTransaction(data::TransactionAndMetadata const& txMeta, ripple::LedgerHeader const& lgrInfo) { - transactionFeed_.pub(txMeta, lgrInfo, backend_, amendmentCenter_); + transactionFeed_.pub(txMeta, lgrInfo, backend_, amendmentCenter_, networkID_); } boost::json::object @@ -210,4 +210,16 @@ SubscriptionManager::report() const }; } +void +SubscriptionManager::setNetworkID(uint32_t const networkID) +{ + networkID_ = networkID; +} + +uint32_t +SubscriptionManager::getNetworkID() const +{ + return networkID_; +} + } // namespace feed diff --git a/src/feed/SubscriptionManager.hpp b/src/feed/SubscriptionManager.hpp index 09c004a5..0108ef0c 100644 --- a/src/feed/SubscriptionManager.hpp +++ b/src/feed/SubscriptionManager.hpp @@ -69,6 +69,7 @@ class SubscriptionManager : public SubscriptionManagerInterface { impl::BookChangesFeed bookChangesFeed_; impl::TransactionFeed transactionFeed_; impl::ProposedTransactionFeed proposedTransactionFeed_; + uint32_t networkID_{0}; public: /** @@ -332,6 +333,21 @@ public: */ boost::json::object report() const final; + + /** + * @brief Set the networkID. + * @param networkID The network id to set. + */ + void + setNetworkID(uint32_t networkID) final; + + /** + * @brief Get the networkID. + * + * @return The network id. + */ + uint32_t + getNetworkID() const final; }; } // namespace feed diff --git a/src/feed/SubscriptionManagerInterface.hpp b/src/feed/SubscriptionManagerInterface.hpp index 4339e595..8303fb69 100644 --- a/src/feed/SubscriptionManagerInterface.hpp +++ b/src/feed/SubscriptionManagerInterface.hpp @@ -244,10 +244,25 @@ public: /** * @brief Get the number of subscribers. * - * @return The report of the number of subscribers + * @return The report of the number of subscribers. */ virtual boost::json::object report() const = 0; + + /** + * @brief Set the networkID. + * @param networkID The network id to set. + */ + virtual void + setNetworkID(uint32_t networkID) = 0; + + /** + * @brief Get the networkID. + * + * @return The network id. + */ + virtual uint32_t + getNetworkID() const = 0; }; } // namespace feed diff --git a/src/feed/impl/TransactionFeed.cpp b/src/feed/impl/TransactionFeed.cpp index ac65cca6..b2b85db4 100644 --- a/src/feed/impl/TransactionFeed.cpp +++ b/src/feed/impl/TransactionFeed.cpp @@ -25,6 +25,7 @@ #include "feed/Types.hpp" #include "rpc/JS.hpp" #include "rpc/RPCHelpers.hpp" +#include "util/Assert.hpp" #include "util/log/Logger.hpp" #include @@ -176,7 +177,8 @@ TransactionFeed::pub( data::TransactionAndMetadata const& txMeta, ripple::LedgerHeader const& lgrInfo, std::shared_ptr const& backend, - std::shared_ptr const& amendmentCenter + std::shared_ptr const& amendmentCenter, + uint32_t const networkID ) { auto [tx, meta] = rpc::deserializeTxPlusMeta(txMeta, lgrInfo.seq); @@ -205,6 +207,15 @@ TransactionFeed::pub( rpc::insertDeliverMaxAlias(pubObj[txKey].as_object(), version); rpc::insertMPTIssuanceID(pubObj[JS(meta)].as_object(), tx, meta); + auto const& metaObj = pubObj[JS(meta)]; + ASSERT(metaObj.is_object(), "meta must be an obj in rippled and clio"); + if (metaObj.as_object().contains("TransactionIndex") && metaObj.as_object().at("TransactionIndex").is_int64()) { + if (auto const& ctid = + rpc::encodeCTID(lgrInfo.seq, metaObj.as_object().at("TransactionIndex").as_int64(), networkID); + ctid) + pubObj[JS(ctid)] = ctid.value(); + } + pubObj[JS(type)] = "transaction"; pubObj[JS(validated)] = true; pubObj[JS(status)] = "closed"; diff --git a/src/feed/impl/TransactionFeed.hpp b/src/feed/impl/TransactionFeed.hpp index 4500575d..ac16ca79 100644 --- a/src/feed/impl/TransactionFeed.hpp +++ b/src/feed/impl/TransactionFeed.hpp @@ -182,12 +182,14 @@ public: * @param txMeta The transaction and metadata. * @param lgrInfo The ledger header. * @param backend The backend. + * @param networkID The network ID. */ void pub(data::TransactionAndMetadata const& txMeta, ripple::LedgerHeader const& lgrInfo, std::shared_ptr const& backend, - std::shared_ptr const& amendmentCenter); + std::shared_ptr const& amendmentCenter, + uint32_t networkID); /** * @brief Get the number of subscribers of the transaction feed. diff --git a/src/rpc/RPCHelpers.cpp b/src/rpc/RPCHelpers.cpp index 651b8412..6d1ec350 100644 --- a/src/rpc/RPCHelpers.cpp +++ b/src/rpc/RPCHelpers.cpp @@ -290,7 +290,10 @@ std::optional encodeCTID(uint32_t ledgerSeq, uint16_t txnIndex, uint16_t networkId) noexcept { static constexpr uint32_t kMAX_LEDGER_SEQ = 0x0FFF'FFFF; - if (ledgerSeq > kMAX_LEDGER_SEQ) + static constexpr uint32_t kMAX_TXN_INDEX = 0xFFFF; + static constexpr uint32_t kMAX_NETWORK_ID = 0xFFFF; + + if (ledgerSeq > kMAX_LEDGER_SEQ || txnIndex > kMAX_TXN_INDEX || networkId > kMAX_NETWORK_ID) return {}; static constexpr uint64_t kCTID_PREFIX = 0xC000'0000; diff --git a/src/rpc/common/impl/HandlerProvider.cpp b/src/rpc/common/impl/HandlerProvider.cpp index 6707cca0..c05e5cd5 100644 --- a/src/rpc/common/impl/HandlerProvider.cpp +++ b/src/rpc/common/impl/HandlerProvider.cpp @@ -86,7 +86,7 @@ ProductionHandlerProvider::ProductionHandlerProvider( {"account_nfts", {.handler = AccountNFTsHandler{backend}}}, {"account_objects", {.handler = AccountObjectsHandler{backend}}}, {"account_offers", {.handler = AccountOffersHandler{backend}}}, - {"account_tx", {.handler = AccountTxHandler{backend}}}, + {"account_tx", {.handler = AccountTxHandler{backend, etl}}}, {"amm_info", {.handler = AMMInfoHandler{backend, amendmentCenter}}}, {"book_changes", {.handler = BookChangesHandler{backend}}}, {"book_offers", {.handler = BookOffersHandler{backend, amendmentCenter}}}, diff --git a/src/rpc/handlers/AccountTx.cpp b/src/rpc/handlers/AccountTx.cpp index 9b9c68ad..882d5a98 100644 --- a/src/rpc/handlers/AccountTx.cpp +++ b/src/rpc/handlers/AccountTx.cpp @@ -161,6 +161,18 @@ AccountTxHandler::process(AccountTxHandler::Input input, Context const& ctx) con auto const txKey = ctx.apiVersion < 2u ? JS(tx) : JS(tx_json); obj[JS(meta)] = std::move(meta); obj[txKey] = std::move(txn); + + // Put CTID into tx or tx_json + if (obj[JS(meta)].as_object().contains("TransactionIndex")) { + auto networkID = 0u; + if (auto const& etlState = etl_->getETLState(); etlState.has_value()) + networkID = etlState->networkID; + + auto const txnIdx = obj[JS(meta)].as_object().at("TransactionIndex").as_int64(); + if (auto const& ctid = rpc::encodeCTID(txnPlusMeta.ledgerSequence, txnIdx, networkID); ctid) + obj[txKey].as_object()[JS(ctid)] = ctid.value(); + } + obj[txKey].as_object()[JS(date)] = txnPlusMeta.date; obj[txKey].as_object()[JS(ledger_index)] = txnPlusMeta.ledgerSequence; diff --git a/src/rpc/handlers/AccountTx.hpp b/src/rpc/handlers/AccountTx.hpp index 0e620a8c..14551c42 100644 --- a/src/rpc/handlers/AccountTx.hpp +++ b/src/rpc/handlers/AccountTx.hpp @@ -20,6 +20,7 @@ #pragma once #include "data/BackendInterface.hpp" +#include "etlng/ETLServiceInterface.hpp" #include "rpc/Errors.hpp" #include "rpc/JS.hpp" #include "rpc/common/JsonBool.hpp" @@ -55,6 +56,7 @@ namespace rpc { class AccountTxHandler { util::Logger log_{"RPC"}; std::shared_ptr sharedPtrBackend_; + std::shared_ptr etl_; public: static constexpr auto kLIMIT_MIN = 1; @@ -109,8 +111,13 @@ public: * @brief Construct a new AccountTxHandler object * * @param sharedPtrBackend The backend to use + * @param etl The ETL service to use */ - AccountTxHandler(std::shared_ptr const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) + AccountTxHandler( + std::shared_ptr const& sharedPtrBackend, + std::shared_ptr const& etl + ) + : sharedPtrBackend_(sharedPtrBackend), etl_{etl} { } @@ -130,6 +137,7 @@ public: {JS(ledger_index), validation::CustomValidators::ledgerIndexValidator}, {JS(ledger_index_min), validation::Type{}}, {JS(ledger_index_max), validation::Type{}}, + {JS(ctid), validation::Type{}}, {JS(limit), validation::Type{}, validation::Min(1u), diff --git a/src/rpc/handlers/Tx.hpp b/src/rpc/handlers/Tx.hpp index fe15929c..26da69a1 100644 --- a/src/rpc/handlers/Tx.hpp +++ b/src/rpc/handlers/Tx.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include diff --git a/tests/common/util/MockSubscriptionManager.hpp b/tests/common/util/MockSubscriptionManager.hpp index 304168c0..9c8c0353 100644 --- a/tests/common/util/MockSubscriptionManager.hpp +++ b/tests/common/util/MockSubscriptionManager.hpp @@ -103,6 +103,10 @@ struct MockSubscriptionManager : feed::SubscriptionManagerInterface { MOCK_METHOD(boost::json::object, report, (), (const, override)); + MOCK_METHOD(void, setNetworkID, (uint32_t), (override)); + + MOCK_METHOD(uint32_t, getNetworkID, (), (const, override)); + MOCK_METHOD(void, stop, (), (override)); }; diff --git a/tests/unit/feed/SubscriptionManagerTests.cpp b/tests/unit/feed/SubscriptionManagerTests.cpp index 5384614a..f5d1fd0d 100644 --- a/tests/unit/feed/SubscriptionManagerTests.cpp +++ b/tests/unit/feed/SubscriptionManagerTests.cpp @@ -79,6 +79,12 @@ using SubscriptionManagerTest = SubscriptionManagerBaseTest; +TEST_F(SubscriptionManagerAsyncTest, SetAndGetNetworkID) +{ + subscriptionManagerPtr_->setNetworkID(32u); + EXPECT_EQ(subscriptionManagerPtr_->getNetworkID(), 32u); +} + TEST_F(SubscriptionManagerAsyncTest, MultipleThreadCtx) { EXPECT_CALL(*sessionPtr_, onDisconnect); @@ -388,6 +394,7 @@ TEST_F(SubscriptionManagerTest, TransactionTest) "TransactionResult":"tesSUCCESS", "delivered_amount":"unavailable" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -477,6 +484,7 @@ TEST_F(SubscriptionManagerTest, ProposedTransactionTest) "TransactionResult":"tesSUCCESS", "delivered_amount":"unavailable" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", diff --git a/tests/unit/feed/TransactionFeedTests.cpp b/tests/unit/feed/TransactionFeedTests.cpp index 9dafe153..89ad1c08 100644 --- a/tests/unit/feed/TransactionFeedTests.cpp +++ b/tests/unit/feed/TransactionFeedTests.cpp @@ -57,6 +57,7 @@ constexpr auto kISSUER = "rK9DrarGKnVEo2nYp5MfVRXRYf5yRX3mwD"; constexpr auto kTXN_ID = "E6DBAFC99223B42257915A63DFC6B0C032D4070F9A574B255AD97466726FC321"; constexpr auto kAMM_ACCOUNT = "rnW8FAPgpQgA6VoESnVrUVJHBdq9QAtRZs"; constexpr auto kLPTOKEN_CURRENCY = "037C35306B24AAB7FF90848206E003279AA47090"; +constexpr auto kNETWORK_ID = 0u; constexpr auto kTRAN_V1 = R"({ @@ -104,6 +105,7 @@ constexpr auto kTRAN_V1 = "TransactionResult":"tesSUCCESS", "delivered_amount":"unavailable" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -155,6 +157,7 @@ constexpr auto kTRAN_V2 = "TransactionResult":"tesSUCCESS", "delivered_amount":"unavailable" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -189,10 +192,10 @@ TEST_F(FeedTransactionTest, SubTransactionV1) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V1))); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(sessionPtr); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); EXPECT_EQ(testFeedPtr->transactionSubCount(), 0); } @@ -211,10 +214,10 @@ TEST_F(FeedTransactionTest, SubTransactionForProposedTx) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V1))); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsubProposed(sessionPtr); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubTransactionV2) @@ -232,12 +235,12 @@ TEST_F(FeedTransactionTest, SubTransactionV2) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(2)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V2))); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(sessionPtr); EXPECT_EQ(testFeedPtr->transactionSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubAccountV1) @@ -258,12 +261,12 @@ TEST_F(FeedTransactionTest, SubAccountV1) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V1))); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(account, sessionPtr); EXPECT_EQ(testFeedPtr->accountSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubForProposedAccount) @@ -284,10 +287,10 @@ TEST_F(FeedTransactionTest, SubForProposedAccount) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V1))); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsubProposed(account, sessionPtr); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubAccountV2) @@ -307,12 +310,12 @@ TEST_F(FeedTransactionTest, SubAccountV2) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(2)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V2))); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(account, sessionPtr); EXPECT_EQ(testFeedPtr->accountSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubBothTransactionAndAccount) @@ -334,14 +337,14 @@ TEST_F(FeedTransactionTest, SubBothTransactionAndAccount) EXPECT_CALL(*mockSessionPtr, apiSubversion).Times(2).WillRepeatedly(testing::Return(2)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V2))).Times(2); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(account, sessionPtr); EXPECT_EQ(testFeedPtr->accountSubCount(), 0); testFeedPtr->unsub(sessionPtr); EXPECT_EQ(testFeedPtr->transactionSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubBookV1) @@ -411,6 +414,7 @@ TEST_F(FeedTransactionTest, SubBookV1) "TransactionResult":"tesSUCCESS", "delivered_amount":"unavailable" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -424,7 +428,7 @@ TEST_F(FeedTransactionTest, SubBookV1) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kORDERBOOK_PUBLISH))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); // trigger by offer cancel meta data metaObj = createMetaDataForCancelOffer(kCURRENCY, kISSUER, 22, 3, 1); @@ -467,6 +471,7 @@ TEST_F(FeedTransactionTest, SubBookV1) "TransactionResult":"tesSUCCESS", "delivered_amount":"unavailable" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -480,7 +485,7 @@ TEST_F(FeedTransactionTest, SubBookV1) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kORDERBOOK_CANCEL_PUBLISH))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); // trigger by offer create meta data static constexpr auto kORDERBOOK_CREATE_PUBLISH = @@ -522,6 +527,7 @@ TEST_F(FeedTransactionTest, SubBookV1) "TransactionResult":"tesSUCCESS", "delivered_amount":"unavailable" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -537,12 +543,12 @@ TEST_F(FeedTransactionTest, SubBookV1) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kORDERBOOK_CREATE_PUBLISH))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(book, sessionPtr); EXPECT_EQ(testFeedPtr->bookSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubBookV2) @@ -611,6 +617,7 @@ TEST_F(FeedTransactionTest, SubBookV2) "TransactionResult":"tesSUCCESS", "delivered_amount":"unavailable" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -625,12 +632,12 @@ TEST_F(FeedTransactionTest, SubBookV2) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(2)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kORDERBOOK_PUBLISH))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(book, sessionPtr); EXPECT_EQ(testFeedPtr->bookSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, TransactionContainsBothAccountsSubed) @@ -655,18 +662,18 @@ TEST_F(FeedTransactionTest, TransactionContainsBothAccountsSubed) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(2)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V2))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(account, sessionPtr); EXPECT_EQ(testFeedPtr->accountSubCount(), 1); EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(2)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V2))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(account2, sessionPtr); EXPECT_EQ(testFeedPtr->accountSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubAccountRepeatWithDifferentVersion) @@ -692,19 +699,19 @@ TEST_F(FeedTransactionTest, SubAccountRepeatWithDifferentVersion) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(2)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V2))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(account, sessionPtr); EXPECT_EQ(testFeedPtr->accountSubCount(), 1); EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(2)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V2))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(account2, sessionPtr); EXPECT_EQ(testFeedPtr->accountSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubTransactionRepeatWithDifferentVersion) @@ -726,12 +733,12 @@ TEST_F(FeedTransactionTest, SubTransactionRepeatWithDifferentVersion) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(2)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V2))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(sessionPtr); EXPECT_EQ(testFeedPtr->transactionSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubRepeat) @@ -858,6 +865,7 @@ TEST_F(FeedTransactionTest, PubTransactionWithOwnerFund) "TransactionIndex":22, "TransactionResult":"tesSUCCESS" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -874,7 +882,7 @@ TEST_F(FeedTransactionTest, PubTransactionWithOwnerFund) EXPECT_CALL(*mockAmendmentCenterPtr_, isEnabled(testing::_, Amendments::fixFrozenLPTokenTransfer, testing::_)); ON_CALL(*mockAmendmentCenterPtr_, isEnabled(testing::_, Amendments::fixFrozenLPTokenTransfer, testing::_)) .WillByDefault(testing::Return(false)); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } static constexpr auto kTRAN_FROZEN = @@ -902,6 +910,7 @@ static constexpr auto kTRAN_FROZEN = "TransactionIndex":22, "TransactionResult":"tesSUCCESS" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -950,7 +959,7 @@ TEST_F(FeedTransactionTest, PubTransactionOfferCreationFrozenLine) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_FROZEN))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubTransactionOfferCreationGlobalFrozen) @@ -991,7 +1000,7 @@ TEST_F(FeedTransactionTest, SubTransactionOfferCreationGlobalFrozen) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_FROZEN))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubBothProposedAndValidatedAccount) @@ -1014,13 +1023,13 @@ TEST_F(FeedTransactionTest, SubBothProposedAndValidatedAccount) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V1))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(account, sessionPtr); testFeedPtr->unsubProposed(account, sessionPtr); EXPECT_EQ(testFeedPtr->accountSubCount(), 0); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubBothProposedAndValidated) @@ -1041,11 +1050,11 @@ TEST_F(FeedTransactionTest, SubBothProposedAndValidated) EXPECT_CALL(*mockSessionPtr, apiSubversion).Times(2).WillRepeatedly(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V1))).Times(2); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); testFeedPtr->unsub(sessionPtr); testFeedPtr->unsubProposed(sessionPtr); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubProposedDisconnect) @@ -1063,10 +1072,10 @@ TEST_F(FeedTransactionTest, SubProposedDisconnect) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V1))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); sessionPtr.reset(); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } TEST_F(FeedTransactionTest, SubProposedAccountDisconnect) @@ -1086,10 +1095,10 @@ TEST_F(FeedTransactionTest, SubProposedAccountDisconnect) EXPECT_CALL(*mockSessionPtr, apiSubversion).WillOnce(testing::Return(1)); EXPECT_CALL(*mockSessionPtr, send(sharedStringJsonEq(kTRAN_V1))).Times(1); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); sessionPtr.reset(); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } // This test exercises `accountHold` for amendment fixFrozenLPTokenTransfer, so that the output shows "owner_funds: 0" @@ -1162,6 +1171,7 @@ TEST_F(FeedTransactionTest, PubTransactionWithOwnerFundFrozenLPToken) "TransactionIndex":22, "TransactionResult":"tesSUCCESS" }, + "ctid":"C000002100160000", "type":"transaction", "validated":true, "status":"closed", @@ -1190,7 +1200,7 @@ TEST_F(FeedTransactionTest, PubTransactionWithOwnerFundFrozenLPToken) EXPECT_CALL(*backend_, doFetchLedgerObject(ripple::keylet::account(issuerAccount).key, testing::_, testing::_)) .WillOnce(testing::Return(issuerAccountRoot.getSerializer().peekData())); - testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_); + testFeedPtr->pub(trans1, ledgerHeader, backend_, mockAmendmentCenterPtr_, kNETWORK_ID); } struct TransactionFeedMockPrometheusTest : WithMockPrometheus, SyncExecutionCtxFixture { diff --git a/tests/unit/rpc/RPCHelpersTests.cpp b/tests/unit/rpc/RPCHelpersTests.cpp index fd8df9dd..f687f47e 100644 --- a/tests/unit/rpc/RPCHelpersTests.cpp +++ b/tests/unit/rpc/RPCHelpersTests.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/tests/unit/rpc/handlers/AccountTxTests.cpp b/tests/unit/rpc/handlers/AccountTxTests.cpp index d61a9122..6958a276 100644 --- a/tests/unit/rpc/handlers/AccountTxTests.cpp +++ b/tests/unit/rpc/handlers/AccountTxTests.cpp @@ -18,6 +18,7 @@ //============================================================================== #include "data/Types.hpp" +#include "etl/ETLState.hpp" #include "rpc/Errors.hpp" #include "rpc/common/AnyHandler.hpp" #include "rpc/common/Types.hpp" @@ -419,7 +420,7 @@ TEST_P(AccountTxParameterTest, CheckParams) ASSERT_TRUE(testBundle.expectedErrorMessage.has_value()); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto const output = handler.process(req, Context{.yield = yield, .apiVersion = testBundle.apiVersion}); ASSERT_FALSE(output); auto const err = rpc::makeError(output.result.error()); @@ -430,7 +431,7 @@ TEST_P(AccountTxParameterTest, CheckParams) EXPECT_CALL(*backend_, fetchAccountTransactions); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto const output = handler.process(req, Context{.yield = yield, .apiVersion = testBundle.apiVersion}); EXPECT_TRUE(output); }); @@ -505,11 +506,12 @@ TEST_F(RPCAccountTxHandlerTest, IndexSpecificForwardTrue) testing::Optional(testing::Eq(TransactionsCursor{kMIN_SEQ, INT32_MAX})), testing::_ ) - ) - .Times(1); + ); + + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -546,11 +548,12 @@ TEST_F(RPCAccountTxHandlerTest, IndexSpecificForwardFalse) testing::Optional(testing::Eq(TransactionsCursor{kMAX_SEQ - 1, INT32_MAX})), testing::_ ) - ) - .Times(1); + ); + + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -587,11 +590,12 @@ TEST_F(RPCAccountTxHandlerTest, IndexNotSpecificForwardTrue) testing::Optional(testing::Eq(TransactionsCursor{kMIN_SEQ - 1, INT32_MAX})), testing::_ ) - ) - .Times(1); + ); + + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -628,11 +632,12 @@ TEST_F(RPCAccountTxHandlerTest, IndexNotSpecificForwardFalse) testing::Optional(testing::Eq(TransactionsCursor{kMAX_SEQ, INT32_MAX})), testing::_ ) - ) - .Times(1); + ); + + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -669,11 +674,10 @@ TEST_F(RPCAccountTxHandlerTest, BinaryTrue) testing::Optional(testing::Eq(TransactionsCursor{kMAX_SEQ, INT32_MAX})), testing::_ ) - ) - .Times(1); + ); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -727,7 +731,7 @@ TEST_F(RPCAccountTxHandlerTest, BinaryTrueV2) .WillOnce(Return(transCursor)); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -776,8 +780,10 @@ TEST_F(RPCAccountTxHandlerTest, LimitAndMarker) ) .WillOnce(Return(transCursor)); + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); + runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -808,9 +814,10 @@ TEST_F(RPCAccountTxHandlerTest, LimitIsCapped) auto const transCursor = TransactionsAndCursor{.txns = transactions, .cursor = TransactionsCursor{12, 34}}; EXPECT_CALL(*backend_, fetchAccountTransactions(testing::_, testing::_, false, testing::_, testing::_)) .WillOnce(Return(transCursor)); + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -839,9 +846,10 @@ TEST_F(RPCAccountTxHandlerTest, LimitAllowedUpToCap) auto const transCursor = TransactionsAndCursor{.txns = transactions, .cursor = TransactionsCursor{12, 34}}; EXPECT_CALL(*backend_, fetchAccountTransactions(testing::_, testing::_, false, testing::_, testing::_)) .WillOnce(Return(transCursor)); + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -880,15 +888,16 @@ TEST_F(RPCAccountTxHandlerTest, SpecificLedgerIndex) testing::Optional(testing::Eq(TransactionsCursor{kMAX_SEQ - 1, INT32_MAX})), testing::_ ) - ) - .Times(1); + ); auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, kMAX_SEQ - 1); EXPECT_CALL(*backend_, fetchLedgerBySequence).Times(1); ON_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ - 1, _)).WillByDefault(Return(ledgerHeader)); + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); + runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -914,7 +923,7 @@ TEST_F(RPCAccountTxHandlerTest, SpecificNonexistLedgerIntIndex) ON_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ - 1, _)).WillByDefault(Return(std::nullopt)); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -937,7 +946,7 @@ TEST_F(RPCAccountTxHandlerTest, SpecificNonexistLedgerStringIndex) ON_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ - 1, _)).WillByDefault(Return(std::nullopt)); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -976,8 +985,10 @@ TEST_F(RPCAccountTxHandlerTest, SpecificLedgerHash) EXPECT_CALL(*backend_, fetchLedgerByHash).Times(1); ON_CALL(*backend_, fetchLedgerByHash(ripple::uint256{kLEDGER_HASH}, _)).WillByDefault(Return(ledgerHeader)); + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); + runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -1012,15 +1023,16 @@ TEST_F(RPCAccountTxHandlerTest, SpecificLedgerIndexValidated) testing::Optional(testing::Eq(TransactionsCursor{kMAX_SEQ, INT32_MAX})), testing::_ ) - ) - .Times(1); + ); auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, kMAX_SEQ); EXPECT_CALL(*backend_, fetchLedgerBySequence).Times(1); ON_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ, _)).WillByDefault(Return(ledgerHeader)); + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); + runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -1053,11 +1065,12 @@ TEST_F(RPCAccountTxHandlerTest, TxLessThanMinSeq) testing::Optional(testing::Eq(TransactionsCursor{kMAX_SEQ - 1, INT32_MAX})), testing::_ ) - ) - .Times(1); + ); + + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -1094,11 +1107,12 @@ TEST_F(RPCAccountTxHandlerTest, TxLargerThanMaxSeq) testing::Optional(testing::Eq(TransactionsCursor{kMAX_SEQ - 2, INT32_MAX})), testing::_ ) - ) - .Times(1); + ); + + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -1187,6 +1201,7 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v1) "hash": "C74463F49CFDCBEF3E9902672719918CDE5042DC7E7660BEBD1D1105C4B6DFF4", "ledger_index": 11, "inLedger": 11, + "ctid": "C000000B00000000", "date": 1 }, "validated": true @@ -1225,6 +1240,7 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v1) "hash": "C85E486EE308C68D7E601FCEB4FC961BFA914C80ABBF7ECC7E6277B06692B490", "ledger_index": 11, "inLedger": 11, + "ctid": "C000000B00000000", "date": 2 }, "validated": true @@ -1277,6 +1293,7 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v1) "hash": "9F82743EEB30065FB9CB92C61F0F064B5859C5A590FA811FAAAD9C988E5B47DB", "ledger_index": 11, "inLedger": 11, + "ctid": "C000000B00000000", "date": 3 }, "validated": true @@ -1310,6 +1327,7 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v1) "hash": "ECB1837EB7C7C0AC22ECDCCE59FDD4795C70E0B9D8F4E1C9A9408BB7EC75DA5C", "ledger_index": 11, "inLedger": 11, + "ctid": "C000000B00000000", "date": 4 }, "validated": true @@ -1331,11 +1349,12 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v1) fetchAccountTransactions( testing::_, testing::_, false, testing::Optional(testing::Eq(TransactionsCursor{10, 11})), testing::_ ) - ) - .Times(1); + ); + + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -1422,6 +1441,7 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v2) "SigningPubKey": "74657374", "TransactionType": "NFTokenMint", "ledger_index": 11, + "ctid": "C000000B00000000", "date": 1 }, "validated": true @@ -1461,6 +1481,7 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v2) "SigningPubKey": "74657374", "TransactionType": "NFTokenAcceptOffer", "ledger_index": 11, + "ctid": "C000000B00000000", "date": 2 }, "validated": true @@ -1515,6 +1536,7 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v2) "SigningPubKey": "74657374", "TransactionType": "NFTokenCancelOffer", "ledger_index": 11, + "ctid": "C000000B00000000", "date": 3 }, "validated": true @@ -1550,6 +1572,7 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v2) "SigningPubKey": "74657374", "TransactionType": "NFTokenCreateOffer", "ledger_index": 11, + "ctid": "C000000B00000000", "date": 4 }, "validated": true @@ -1571,14 +1594,15 @@ TEST_F(RPCAccountTxHandlerTest, NFTTxs_API_v2) fetchAccountTransactions( testing::_, testing::_, false, testing::Optional(testing::Eq(TransactionsCursor{10, 11})), testing::_ ) - ) - .Times(1); + ); + + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, 11); EXPECT_CALL(*backend_, fetchLedgerBySequence).Times(transactions.size()).WillRepeatedly(Return(ledgerHeader)); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto static const kINPUT = json::parse(fmt::format( R"({{ "account": "{}", @@ -1873,6 +1897,7 @@ generateTransactionTypeTestValues() "hash": "51D2AAA6B8E4E16EF22F6424854283D8391B56875858A711B8CE4D5B9A422CC2", "ledger_index": 30, "inLedger": 30, + "ctid": "C000001E00000000", "date": 1 }, "validated": true @@ -1925,6 +1950,7 @@ generateTransactionTypeTestValues() "hash": "51D2AAA6B8E4E16EF22F6424854283D8391B56875858A711B8CE4D5B9A422CC2", "ledger_index": 30, "inLedger": 30, + "ctid": "C000001E00000000", "date": 1 }, "validated": true @@ -1978,6 +2004,7 @@ generateTransactionTypeTestValues() "SigningPubKey": "74657374", "TransactionType": "Payment", "ledger_index": 30, + "ctid": "C000001E00000000", "date": 1 }, "validated": true @@ -2091,16 +2118,17 @@ TEST_P(AccountTxTransactionTypeTest, SpecificTransactionType) ON_CALL(*backend_, fetchAccountTransactions).WillByDefault(Return(transCursor)); EXPECT_CALL( *backend_, fetchAccountTransactions(_, _, false, Optional(Eq(TransactionsCursor{kMAX_SEQ, INT32_MAX})), _) - ) - .Times(1); + ); auto const ledgerHeader = createLedgerHeader(kLEDGER_HASH, kMAX_SEQ); ON_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ, _)).WillByDefault(Return(ledgerHeader)); EXPECT_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ, _)).Times(Between(1, 2)); + ON_CALL(*mockETLServicePtr_, getETLState).WillByDefault(Return(etl::ETLState{})); + auto const testBundle = GetParam(); runSpawn([&, this](auto yield) { - auto const handler = AnyHandler{AccountTxHandler{backend_}}; + auto const handler = AnyHandler{AccountTxHandler{backend_, mockETLServicePtr_}}; auto const req = json::parse(testBundle.testJson); auto const output = handler.process(req, Context{.yield = yield, .apiVersion = testBundle.apiVersion}); EXPECT_TRUE(output); diff --git a/tests/unit/rpc/handlers/AllHandlerTests.cpp b/tests/unit/rpc/handlers/AllHandlerTests.cpp index 310a858e..41f04669 100644 --- a/tests/unit/rpc/handlers/AllHandlerTests.cpp +++ b/tests/unit/rpc/handlers/AllHandlerTests.cpp @@ -142,6 +142,8 @@ private: return HandlerType{this->backend_, this->mockAmendmentCenterPtr_}; } else if constexpr (std::is_same_v) { return HandlerType{this->backend_, this->mockAmendmentCenterPtr_, this->mockSubscriptionManagerPtr_}; + } else if constexpr (std::is_same_v) { + return HandlerType{this->backend_, mockETLServicePtr_}; } else if constexpr (std::is_same_v) { return HandlerType{ this->backend_, @@ -174,6 +176,15 @@ createInput() return input; } +template <> +AccountTxHandler::Input +createInput() +{ + AccountTxHandler::Input input{}; + input.account = kACCOUNT; + return input; +} + template <> AMMInfoHandler::Input createInput()