mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-04 11:55:51 +00:00
@@ -52,9 +52,6 @@
|
||||
struct AccountTransactionsData;
|
||||
struct NFTTransactionsData;
|
||||
struct NFTsData;
|
||||
namespace feed {
|
||||
class SubscriptionManager;
|
||||
} // namespace feed
|
||||
|
||||
/**
|
||||
* @brief This namespace contains everything to do with the ETL and ETL sources.
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "feed/impl/LedgerFeed.hpp"
|
||||
#include "feed/impl/ProposedTransactionFeed.hpp"
|
||||
#include "feed/impl/TransactionFeed.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
#include "util/async/context/BasicExecutionContext.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
@@ -40,10 +42,8 @@
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
@@ -57,9 +57,8 @@ namespace feed {
|
||||
* @brief A subscription manager is responsible for managing the subscriptions and publishing the feeds
|
||||
*/
|
||||
class SubscriptionManager : public SubscriptionManagerInterface {
|
||||
std::reference_wrapper<boost::asio::io_context> ioContext_;
|
||||
std::shared_ptr<data::BackendInterface const> backend_;
|
||||
|
||||
util::async::AnyExecutionContext ctx_;
|
||||
impl::ForwardFeed manifestFeed_;
|
||||
impl::ForwardFeed validationsFeed_;
|
||||
impl::LedgerFeed ledgerFeed_;
|
||||
@@ -71,24 +70,31 @@ public:
|
||||
/**
|
||||
* @brief Construct a new Subscription Manager object
|
||||
*
|
||||
* @param ioContext The io context to use
|
||||
* @param executor The executor to use to publish the feeds
|
||||
* @param backend The backend to use
|
||||
*/
|
||||
SubscriptionManager(
|
||||
boost::asio::io_context& ioContext,
|
||||
std::shared_ptr<data::BackendInterface const> const& backend
|
||||
)
|
||||
: ioContext_(ioContext)
|
||||
, backend_(backend)
|
||||
, manifestFeed_(ioContext, "manifest")
|
||||
, validationsFeed_(ioContext, "validations")
|
||||
, ledgerFeed_(ioContext)
|
||||
, bookChangesFeed_(ioContext)
|
||||
, transactionFeed_(ioContext)
|
||||
, proposedTransactionFeed_(ioContext)
|
||||
template <class ExecutorCtx>
|
||||
SubscriptionManager(ExecutorCtx& executor, std::shared_ptr<data::BackendInterface const> const& backend)
|
||||
: backend_(backend)
|
||||
, ctx_(executor)
|
||||
, manifestFeed_(ctx_, "manifest")
|
||||
, validationsFeed_(ctx_, "validations")
|
||||
, ledgerFeed_(ctx_)
|
||||
, bookChangesFeed_(ctx_)
|
||||
, transactionFeed_(ctx_)
|
||||
, proposedTransactionFeed_(ctx_)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor of the SubscriptionManager object. It will block until all running jobs finished.
|
||||
*/
|
||||
~SubscriptionManager() override
|
||||
{
|
||||
ctx_.stop();
|
||||
ctx_.join();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subscribe to the book changes feed.
|
||||
* @param subscriber
|
||||
@@ -286,16 +292,15 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The help class to run the subscription manager. The container of io_context which is used to publish the
|
||||
* feeds.
|
||||
* @brief The help class to run the subscription manager. The container of PoolExecutionContext which is used to publish
|
||||
* the feeds.
|
||||
*/
|
||||
class SubscriptionManagerRunner {
|
||||
boost::asio::io_context ioContext_;
|
||||
std::uint64_t workersNum_;
|
||||
using ActualExecutionCtx = util::async::PoolExecutionContext;
|
||||
ActualExecutionCtx ctx_;
|
||||
std::shared_ptr<SubscriptionManager> subscriptionManager_;
|
||||
util::Logger logger_{"Subscriptions"};
|
||||
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work_ =
|
||||
boost::asio::make_work_guard(ioContext_);
|
||||
std::vector<std::thread> workers_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -305,13 +310,11 @@ public:
|
||||
* @param backend The backend to use
|
||||
*/
|
||||
SubscriptionManagerRunner(util::Config const& config, std::shared_ptr<data::BackendInterface> const& backend)
|
||||
: subscriptionManager_(std::make_shared<SubscriptionManager>(ioContext_, backend))
|
||||
: workersNum_(config.valueOr<std::uint64_t>("subscription_workers", 1))
|
||||
, ctx_(workersNum_)
|
||||
, subscriptionManager_(std::make_shared<SubscriptionManager>(ctx_, backend))
|
||||
{
|
||||
auto numThreads = config.valueOr<uint64_t>("subscription_workers", 1);
|
||||
LOG(logger_.info()) << "Starting subscription manager with " << numThreads << " workers";
|
||||
workers_.reserve(numThreads);
|
||||
for (auto i = numThreads; i > 0; --i)
|
||||
workers_.emplace_back([&] { ioContext_.run(); });
|
||||
LOG(logger_.info()) << "Starting subscription manager with " << workersNum_ << " workers";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,12 +327,5 @@ public:
|
||||
{
|
||||
return subscriptionManager_;
|
||||
}
|
||||
|
||||
~SubscriptionManagerRunner()
|
||||
{
|
||||
work_.reset();
|
||||
for (auto& worker : workers_)
|
||||
worker.join();
|
||||
}
|
||||
};
|
||||
} // namespace feed
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "data/Types.hpp"
|
||||
#include "feed/impl/SingleFeedBase.hpp"
|
||||
#include "rpc/BookChangesHelper.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/json/serialize.hpp>
|
||||
@@ -37,7 +38,7 @@ namespace feed::impl {
|
||||
* '0A5010342D8AAFABDCA58A68F6F588E1C6E58C21B63ED6CA8DB2478F58F3ECD5', 'ledger_time': 756395682, 'changes': []}
|
||||
*/
|
||||
struct BookChangesFeed : public SingleFeedBase {
|
||||
BookChangesFeed(boost::asio::io_context& ioContext) : SingleFeedBase(ioContext, "book_changes")
|
||||
BookChangesFeed(util::async::AnyExecutionContext& executionCtx) : SingleFeedBase(executionCtx, "book_changes")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "feed/Types.hpp"
|
||||
#include "feed/impl/SingleFeedBase.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
@@ -46,9 +47,9 @@ class LedgerFeed : public SingleFeedBase {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Ledger Feed object
|
||||
* @param ioContext The actual publish will be called in the strand of this.
|
||||
* @param executionCtx The actual publish will be called in the strand of this.
|
||||
*/
|
||||
LedgerFeed(boost::asio::io_context& ioContext) : SingleFeedBase(ioContext, "ledger")
|
||||
LedgerFeed(util::async::AnyExecutionContext& executionCtx) : SingleFeedBase(executionCtx, "ledger")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -101,17 +101,18 @@ ProposedTransactionFeed::pub(boost::json::object const& receivedTxJson)
|
||||
auto const accounts = rpc::getAccountsFromTransaction(transaction);
|
||||
auto affectedAccounts = std::unordered_set<ripple::AccountID>(accounts.cbegin(), accounts.cend());
|
||||
|
||||
boost::asio::post(strand_, [this, pubMsg = std::move(pubMsg), affectedAccounts = std::move(affectedAccounts)]() {
|
||||
notified_.clear();
|
||||
signal_.emit(pubMsg);
|
||||
// Prevent the same connection from receiving the same message twice if it is subscribed to multiple accounts
|
||||
// However, if the same connection subscribe both stream and account, it will still receive the message twice.
|
||||
// notified_ can be cleared before signal_ emit to improve this, but let's keep it as is for now, since rippled
|
||||
// acts like this.
|
||||
notified_.clear();
|
||||
for (auto const& account : affectedAccounts)
|
||||
accountSignal_.emit(account, pubMsg);
|
||||
});
|
||||
[[maybe_unused]] auto task =
|
||||
strand_.execute([this, pubMsg = std::move(pubMsg), affectedAccounts = std::move(affectedAccounts)]() {
|
||||
notified_.clear();
|
||||
signal_.emit(pubMsg);
|
||||
// Prevent the same connection from receiving the same message twice if it is subscribed to multiple
|
||||
// accounts However, if the same connection subscribe both stream and account, it will still receive the
|
||||
// message twice. notified_ can be cleared before signal_ emit to improve this, but let's keep it as is for
|
||||
// now, since rippled acts like this.
|
||||
notified_.clear();
|
||||
for (auto const& account : affectedAccounts)
|
||||
accountSignal_.emit(account, pubMsg);
|
||||
});
|
||||
}
|
||||
|
||||
std::uint64_t
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "feed/impl/TrackableSignal.hpp"
|
||||
#include "feed/impl/TrackableSignalMap.hpp"
|
||||
#include "feed/impl/Util.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
#include "util/async/AnyStrand.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "util/prometheus/Gauge.hpp"
|
||||
|
||||
@@ -51,7 +53,7 @@ class ProposedTransactionFeed {
|
||||
|
||||
std::unordered_set<SubscriberPtr>
|
||||
notified_; // Used by slots to prevent double notifications if tx contains multiple subscribed accounts
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||
util::async::AnyStrand strand_;
|
||||
std::reference_wrapper<util::prometheus::GaugeInt> subAllCount_;
|
||||
std::reference_wrapper<util::prometheus::GaugeInt> subAccountCount_;
|
||||
|
||||
@@ -61,10 +63,10 @@ class ProposedTransactionFeed {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a Proposed Transaction Feed object.
|
||||
* @param ioContext The actual publish will be called in the strand of this.
|
||||
* @param executionCtx The actual publish will be called in the strand of this.
|
||||
*/
|
||||
ProposedTransactionFeed(boost::asio::io_context& ioContext)
|
||||
: strand_(boost::asio::make_strand(ioContext))
|
||||
ProposedTransactionFeed(util::async::AnyExecutionContext& executionCtx)
|
||||
: strand_(executionCtx.makeStrand())
|
||||
, subAllCount_(getSubscriptionsGaugeInt("tx_proposed"))
|
||||
, subAccountCount_(getSubscriptionsGaugeInt("account_proposed"))
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "feed/Types.hpp"
|
||||
#include "feed/impl/TrackableSignal.hpp"
|
||||
#include "feed/impl/Util.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
@@ -35,8 +36,8 @@
|
||||
|
||||
namespace feed::impl {
|
||||
|
||||
SingleFeedBase::SingleFeedBase(boost::asio::io_context& ioContext, std::string const& name)
|
||||
: strand_(boost::asio::make_strand(ioContext)), subCount_(getSubscriptionsGaugeInt(name)), name_(name)
|
||||
SingleFeedBase::SingleFeedBase(util::async::AnyExecutionContext& executionCtx, std::string const& name)
|
||||
: strand_(executionCtx.makeStrand()), subCount_(getSubscriptionsGaugeInt(name)), name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -67,8 +68,8 @@ SingleFeedBase::unsub(SubscriberSharedPtr const& subscriber)
|
||||
void
|
||||
SingleFeedBase::pub(std::string msg) const
|
||||
{
|
||||
boost::asio::post(strand_, [this, msg = std::move(msg)]() mutable {
|
||||
auto const msgPtr = std::make_shared<std::string>(std::move(msg));
|
||||
[[maybe_unused]] auto task = strand_.execute([this, msg = std::move(msg)]() {
|
||||
auto const msgPtr = std::make_shared<std::string>(msg);
|
||||
signal_.emit(msgPtr);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "feed/Types.hpp"
|
||||
#include "feed/impl/TrackableSignal.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
#include "util/async/AnyStrand.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "util/prometheus/Gauge.hpp"
|
||||
|
||||
@@ -38,7 +40,7 @@ namespace feed::impl {
|
||||
* @brief Base class for single feed.
|
||||
*/
|
||||
class SingleFeedBase {
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||
util::async::AnyStrand strand_;
|
||||
std::reference_wrapper<util::prometheus::GaugeInt> subCount_;
|
||||
TrackableSignal<Subscriber, std::shared_ptr<std::string> const&> signal_;
|
||||
util::Logger logger_{"Subscriptions"};
|
||||
@@ -47,10 +49,10 @@ class SingleFeedBase {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Single Feed Base object
|
||||
* @param ioContext The actual publish will be called in the strand of this.
|
||||
* @param executionCtx The actual publish will be called in the strand of this.
|
||||
* @param name The promethues counter name of the feed.
|
||||
*/
|
||||
SingleFeedBase(boost::asio::io_context& ioContext, std::string const& name);
|
||||
SingleFeedBase(util::async::AnyExecutionContext& executionCtx, std::string const& name);
|
||||
|
||||
/**
|
||||
* @brief Subscribe the feed.
|
||||
|
||||
@@ -276,33 +276,30 @@ TransactionFeed::pub(
|
||||
}
|
||||
}
|
||||
|
||||
boost::asio::post(
|
||||
strand_,
|
||||
[this,
|
||||
allVersionsMsgs = std::move(allVersionsMsgs),
|
||||
affectedAccounts = std::move(affectedAccounts),
|
||||
affectedBooks = std::move(affectedBooks)]() {
|
||||
notified_.clear();
|
||||
signal_.emit(allVersionsMsgs);
|
||||
// clear the notified set. If the same connection subscribes both transactions + proposed_transactions,
|
||||
// rippled SENDS the same message twice
|
||||
notified_.clear();
|
||||
txProposedsignal_.emit(allVersionsMsgs);
|
||||
notified_.clear();
|
||||
// check duplicate for account and proposed_account, this prevents sending the same message multiple times
|
||||
// if it affects multiple accounts watched by the same connection
|
||||
for (auto const& account : affectedAccounts) {
|
||||
accountSignal_.emit(account, allVersionsMsgs);
|
||||
accountProposedSignal_.emit(account, allVersionsMsgs);
|
||||
}
|
||||
notified_.clear();
|
||||
// check duplicate for books, this prevents sending the same message multiple times if it affects multiple
|
||||
// books watched by the same connection
|
||||
for (auto const& book : affectedBooks) {
|
||||
bookSignal_.emit(book, allVersionsMsgs);
|
||||
}
|
||||
[[maybe_unused]] auto task = strand_.execute([this,
|
||||
allVersionsMsgs = std::move(allVersionsMsgs),
|
||||
affectedAccounts = std::move(affectedAccounts),
|
||||
affectedBooks = std::move(affectedBooks)]() {
|
||||
notified_.clear();
|
||||
signal_.emit(allVersionsMsgs);
|
||||
// clear the notified set. If the same connection subscribes both transactions + proposed_transactions,
|
||||
// rippled SENDS the same message twice
|
||||
notified_.clear();
|
||||
txProposedsignal_.emit(allVersionsMsgs);
|
||||
notified_.clear();
|
||||
// check duplicate for account and proposed_account, this prevents sending the same message multiple times
|
||||
// if it affects multiple accounts watched by the same connection
|
||||
for (auto const& account : affectedAccounts) {
|
||||
accountSignal_.emit(account, allVersionsMsgs);
|
||||
accountProposedSignal_.emit(account, allVersionsMsgs);
|
||||
}
|
||||
);
|
||||
notified_.clear();
|
||||
// check duplicate for books, this prevents sending the same message multiple times if it affects multiple
|
||||
// books watched by the same connection
|
||||
for (auto const& book : affectedBooks) {
|
||||
bookSignal_.emit(book, allVersionsMsgs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "feed/impl/TrackableSignal.hpp"
|
||||
#include "feed/impl/TrackableSignalMap.hpp"
|
||||
#include "feed/impl/Util.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
#include "util/async/AnyStrand.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "util/prometheus/Gauge.hpp"
|
||||
|
||||
@@ -63,7 +65,7 @@ class TransactionFeed {
|
||||
|
||||
util::Logger logger_{"Subscriptions"};
|
||||
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||
util::async::AnyStrand strand_;
|
||||
std::reference_wrapper<util::prometheus::GaugeInt> subAllCount_;
|
||||
std::reference_wrapper<util::prometheus::GaugeInt> subAccountCount_;
|
||||
std::reference_wrapper<util::prometheus::GaugeInt> subBookCount_;
|
||||
@@ -82,10 +84,10 @@ class TransactionFeed {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Transaction Feed object.
|
||||
* @param ioContext The actual publish will be called in the strand of this.
|
||||
* @param executionCtx The actual publish will be called in the strand of this.
|
||||
*/
|
||||
TransactionFeed(boost::asio::io_context& ioContext)
|
||||
: strand_(boost::asio::make_strand(ioContext))
|
||||
TransactionFeed(util::async::AnyExecutionContext& executionCtx)
|
||||
: strand_(executionCtx.makeStrand())
|
||||
, subAllCount_(getSubscriptionsGaugeInt("tx"))
|
||||
, subAccountCount_(getSubscriptionsGaugeInt("account"))
|
||||
, subBookCount_(getSubscriptionsGaugeInt("book"))
|
||||
|
||||
@@ -44,9 +44,6 @@
|
||||
#include <utility>
|
||||
|
||||
// forward declarations
|
||||
namespace feed {
|
||||
class SubscriptionManager;
|
||||
} // namespace feed
|
||||
namespace etl {
|
||||
class LoadBalancer;
|
||||
class ETLService;
|
||||
|
||||
@@ -43,9 +43,6 @@ class LoadBalancer;
|
||||
namespace web {
|
||||
struct ConnectionBase;
|
||||
} // namespace web
|
||||
namespace feed {
|
||||
class SubscriptionManager;
|
||||
} // namespace feed
|
||||
|
||||
namespace rpc {
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "data/AmendmentCenterInterface.hpp"
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "etl/ETLService.hpp"
|
||||
#include "feed/SubscriptionManager.hpp"
|
||||
#include "feed/SubscriptionManagerInterface.hpp"
|
||||
#include "rpc/Counters.hpp"
|
||||
#include "rpc/common/AnyHandler.hpp"
|
||||
#include "rpc/handlers/AMMInfo.hpp"
|
||||
@@ -70,7 +70,7 @@ namespace rpc::impl {
|
||||
ProductionHandlerProvider::ProductionHandlerProvider(
|
||||
util::Config const& config,
|
||||
std::shared_ptr<BackendInterface> const& backend,
|
||||
std::shared_ptr<feed::SubscriptionManager> const& subscriptionManager,
|
||||
std::shared_ptr<feed::SubscriptionManagerInterface> const& subscriptionManager,
|
||||
std::shared_ptr<etl::LoadBalancer> const& balancer,
|
||||
std::shared_ptr<etl::ETLService const> const& etl,
|
||||
std::shared_ptr<data::AmendmentCenterInterface const> const& amendmentCenter,
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "data/AmendmentCenterInterface.hpp"
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "feed/SubscriptionManager.hpp"
|
||||
#include "feed/SubscriptionManagerInterface.hpp"
|
||||
#include "rpc/common/AnyHandler.hpp"
|
||||
#include "rpc/common/HandlerProvider.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
@@ -39,9 +39,6 @@ class LoadBalancer;
|
||||
namespace rpc {
|
||||
class Counters;
|
||||
} // namespace rpc
|
||||
namespace feed {
|
||||
class SubscriptionManager;
|
||||
} // namespace feed
|
||||
|
||||
namespace rpc::impl {
|
||||
|
||||
@@ -57,7 +54,7 @@ public:
|
||||
ProductionHandlerProvider(
|
||||
util::Config const& config,
|
||||
std::shared_ptr<BackendInterface> const& backend,
|
||||
std::shared_ptr<feed::SubscriptionManager> const& subscriptionManager,
|
||||
std::shared_ptr<feed::SubscriptionManagerInterface> const& subscriptionManager,
|
||||
std::shared_ptr<etl::LoadBalancer> const& balancer,
|
||||
std::shared_ptr<etl::ETLService const> const& etl,
|
||||
std::shared_ptr<data::AmendmentCenterInterface const> const& amendmentCenter,
|
||||
|
||||
@@ -37,10 +37,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace feed {
|
||||
class SubscriptionManager;
|
||||
} // namespace feed
|
||||
|
||||
namespace rpc {
|
||||
|
||||
/**
|
||||
|
||||
@@ -202,6 +202,24 @@ public:
|
||||
return pimpl_->makeStrand();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the execution context
|
||||
*/
|
||||
void
|
||||
stop()
|
||||
{
|
||||
pimpl_->stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Join the execution context
|
||||
*/
|
||||
void
|
||||
join()
|
||||
{
|
||||
pimpl_->join();
|
||||
}
|
||||
|
||||
private:
|
||||
struct Concept {
|
||||
virtual ~Concept() = default;
|
||||
@@ -218,6 +236,10 @@ private:
|
||||
scheduleAfter(std::chrono::milliseconds, std::function<std::any(AnyStopToken, bool)>) = 0;
|
||||
virtual AnyStrand
|
||||
makeStrand() = 0;
|
||||
virtual void
|
||||
stop() = 0;
|
||||
virtual void
|
||||
join() = 0;
|
||||
};
|
||||
|
||||
template <typename CtxType>
|
||||
@@ -257,6 +279,18 @@ private:
|
||||
{
|
||||
return ctx.get().makeStrand();
|
||||
}
|
||||
|
||||
void
|
||||
stop() override
|
||||
{
|
||||
ctx.get().stop();
|
||||
}
|
||||
|
||||
void
|
||||
join() override
|
||||
{
|
||||
ctx.get().join();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/async/AnyStopToken.hpp"
|
||||
#include "util/async/Concepts.hpp"
|
||||
#include "util/async/impl/ErasedOperation.hpp"
|
||||
|
||||
#include <any>
|
||||
@@ -60,7 +59,7 @@ public:
|
||||
* @return The type-erased operation
|
||||
*/
|
||||
[[nodiscard]] auto
|
||||
execute(SomeHandlerWithoutStopToken auto&& fn)
|
||||
execute(SomeHandlerWithoutStopToken auto&& fn) const
|
||||
{
|
||||
using RetType = std::decay_t<decltype(fn())>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
@@ -84,7 +83,7 @@ public:
|
||||
* @return The type-erased operation
|
||||
*/
|
||||
[[nodiscard]] auto
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn)
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn) const
|
||||
{
|
||||
using RetType = std::decay_t<decltype(fn(std::declval<AnyStopToken>()))>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
@@ -109,7 +108,7 @@ public:
|
||||
* @return The type-erased operation
|
||||
*/
|
||||
[[nodiscard]] auto
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn, SomeStdDuration auto timeout)
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn, SomeStdDuration auto timeout) const
|
||||
{
|
||||
using RetType = std::decay_t<decltype(fn(std::declval<AnyStopToken>()))>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
@@ -134,11 +133,9 @@ private:
|
||||
virtual ~Concept() = default;
|
||||
|
||||
[[nodiscard]] virtual impl::ErasedOperation
|
||||
execute(
|
||||
std::function<std::any(AnyStopToken)>,
|
||||
std::optional<std::chrono::milliseconds> timeout = std::nullopt
|
||||
) = 0;
|
||||
[[nodiscard]] virtual impl::ErasedOperation execute(std::function<std::any()>) = 0;
|
||||
execute(std::function<std::any(AnyStopToken)>, std::optional<std::chrono::milliseconds> timeout = std::nullopt)
|
||||
const = 0;
|
||||
[[nodiscard]] virtual impl::ErasedOperation execute(std::function<std::any()>) const = 0;
|
||||
};
|
||||
|
||||
template <typename StrandType>
|
||||
@@ -152,13 +149,14 @@ private:
|
||||
}
|
||||
|
||||
[[nodiscard]] impl::ErasedOperation
|
||||
execute(std::function<std::any(AnyStopToken)> fn, std::optional<std::chrono::milliseconds> timeout) override
|
||||
execute(std::function<std::any(AnyStopToken)> fn, std::optional<std::chrono::milliseconds> timeout)
|
||||
const override
|
||||
{
|
||||
return strand.execute(std::move(fn), timeout);
|
||||
}
|
||||
|
||||
[[nodiscard]] impl::ErasedOperation
|
||||
execute(std::function<std::any()> fn) override
|
||||
execute(std::function<std::any()> fn) const override
|
||||
{
|
||||
return strand.execute(std::move(fn));
|
||||
}
|
||||
|
||||
@@ -327,6 +327,15 @@ public:
|
||||
{
|
||||
context_.executor.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Block until all operations are completed
|
||||
*/
|
||||
void
|
||||
join() noexcept
|
||||
{
|
||||
context_.executor.join();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,6 +40,11 @@ struct SameThreadContext {
|
||||
stop() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
join() noexcept
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Note: these types are not actually used but needed for compilation
|
||||
|
||||
@@ -64,10 +64,8 @@ public:
|
||||
BasicStrand(BasicStrand const&) = delete;
|
||||
|
||||
[[nodiscard]] auto
|
||||
execute(
|
||||
SomeHandlerWith<StopToken> auto&& fn,
|
||||
std::optional<std::chrono::milliseconds> timeout = std::nullopt
|
||||
) noexcept(isNoexcept)
|
||||
execute(SomeHandlerWith<StopToken> auto&& fn, std::optional<std::chrono::milliseconds> timeout = std::nullopt) const
|
||||
noexcept(isNoexcept)
|
||||
{
|
||||
return DispatcherType::dispatch(
|
||||
context_,
|
||||
@@ -91,7 +89,7 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] auto
|
||||
execute(SomeHandlerWith<StopToken> auto&& fn, SomeStdDuration auto timeout) noexcept(isNoexcept)
|
||||
execute(SomeHandlerWith<StopToken> auto&& fn, SomeStdDuration auto timeout) const noexcept(isNoexcept)
|
||||
{
|
||||
return execute(
|
||||
std::forward<decltype(fn)>(fn),
|
||||
@@ -100,7 +98,7 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] auto
|
||||
execute(SomeHandlerWithoutStopToken auto&& fn) noexcept(isNoexcept)
|
||||
execute(SomeHandlerWithoutStopToken auto&& fn) const noexcept(isNoexcept)
|
||||
{
|
||||
return DispatcherType::dispatch(
|
||||
context_,
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/AsioContextTestFixture.hpp"
|
||||
#include "util/MockBackendTestFixture.hpp"
|
||||
#include "util/MockPrometheus.hpp"
|
||||
#include "util/MockWsBase.hpp"
|
||||
#include "util/SyncExecutionCtxFixture.hpp"
|
||||
#include "web/interface/ConnectionBase.hpp"
|
||||
|
||||
#include <boost/json/parse.hpp>
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
// Base class for feed tests, providing easy way to access the received feed
|
||||
template <typename TestedFeed>
|
||||
struct FeedBaseTest : util::prometheus::WithPrometheus, SyncAsioContextTest, MockBackendTest {
|
||||
struct FeedBaseTest : util::prometheus::WithPrometheus, MockBackendTest, SyncExecutionCtxFixture {
|
||||
protected:
|
||||
std::shared_ptr<web::ConnectionBase> sessionPtr;
|
||||
std::shared_ptr<TestedFeed> testFeedPtr;
|
||||
@@ -44,7 +44,6 @@ protected:
|
||||
void
|
||||
SetUp() override
|
||||
{
|
||||
SyncAsioContextTest::SetUp();
|
||||
testFeedPtr = std::make_shared<TestedFeed>(ctx);
|
||||
sessionPtr = std::make_shared<MockSession>();
|
||||
sessionPtr->apiSubVersion = 1;
|
||||
@@ -56,7 +55,6 @@ protected:
|
||||
{
|
||||
sessionPtr.reset();
|
||||
testFeedPtr.reset();
|
||||
SyncAsioContextTest::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -77,4 +77,5 @@ struct MockExecutionContext {
|
||||
);
|
||||
MOCK_METHOD(MockStrand const&, makeStrand, (), (const));
|
||||
MOCK_METHOD(void, stop, (), (const));
|
||||
MOCK_METHOD(void, join, (), (const));
|
||||
};
|
||||
|
||||
37
tests/common/util/SyncExecutionCtxFixture.hpp
Normal file
37
tests/common/util/SyncExecutionCtxFixture.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/LoggerFixtures.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
#include "util/async/context/SyncExecutionContext.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
/**
|
||||
* @brief Fixture with an embedded AnyExecutionContext wrapping a SyncExecutionContext
|
||||
*
|
||||
*/
|
||||
struct SyncExecutionCtxFixture : virtual public NoLoggerFixture {
|
||||
protected:
|
||||
util::async::SyncExecutionContext syncCtx;
|
||||
util::async::AnyExecutionContext ctx{syncCtx};
|
||||
};
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "feed/impl/ForwardFeed.hpp"
|
||||
#include "util/TestObject.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
@@ -55,7 +54,6 @@ TEST_F(FeedBookChangeTest, Pub)
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
transactions.push_back(trans1);
|
||||
|
||||
testFeedPtr->pub(ledgerHeader, transactions);
|
||||
constexpr static auto bookChangePublish =
|
||||
R"({
|
||||
"type":"bookChanges",
|
||||
@@ -78,11 +76,9 @@ TEST_F(FeedBookChangeTest, Pub)
|
||||
})";
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(bookChangePublish))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(ledgerHeader, transactions);
|
||||
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->count(), 0);
|
||||
testFeedPtr->pub(ledgerHeader, transactions);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "feed/FeedTestUtil.hpp"
|
||||
#include "feed/impl/ForwardFeed.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
@@ -35,7 +36,7 @@ constexpr static auto FEED = R"({"test":"test"})";
|
||||
|
||||
class NamedForwardFeedTest : public ForwardFeed {
|
||||
public:
|
||||
NamedForwardFeedTest(boost::asio::io_context& ioContext) : ForwardFeed(ioContext, "test")
|
||||
NamedForwardFeedTest(util::async::AnyExecutionContext& executionCtx) : ForwardFeed(executionCtx, "test")
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -47,15 +48,11 @@ TEST_F(FeedForwardTest, Pub)
|
||||
testFeedPtr->sub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->count(), 1);
|
||||
auto const json = json::parse(FEED).as_object();
|
||||
testFeedPtr->pub(json);
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(FEED))).Times(1);
|
||||
ctx.run();
|
||||
|
||||
testFeedPtr->pub(json);
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->count(), 0);
|
||||
testFeedPtr->pub(json);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedForwardTest, AutoDisconnect)
|
||||
@@ -63,9 +60,8 @@ TEST_F(FeedForwardTest, AutoDisconnect)
|
||||
testFeedPtr->sub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->count(), 1);
|
||||
auto const json = json::parse(FEED).as_object();
|
||||
testFeedPtr->pub(json);
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(FEED))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(json);
|
||||
sessionPtr.reset();
|
||||
EXPECT_EQ(testFeedPtr->count(), 0);
|
||||
testFeedPtr->pub(json);
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "feed/impl/LedgerFeed.hpp"
|
||||
#include "util/TestObject.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <gmock/gmock.h>
|
||||
@@ -63,7 +62,6 @@ TEST_F(FeedLedgerTest, SubPub)
|
||||
// check the response
|
||||
EXPECT_EQ(res, json::parse(LedgerResponse));
|
||||
});
|
||||
ctx.run();
|
||||
EXPECT_EQ(testFeedPtr->count(), 1);
|
||||
|
||||
constexpr static auto ledgerPub =
|
||||
@@ -85,16 +83,12 @@ TEST_F(FeedLedgerTest, SubPub)
|
||||
auto fee2 = ripple::Fees();
|
||||
fee2.reserve = 10;
|
||||
testFeedPtr->pub(ledgerHeader2, fee2, "10-31", 8);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
|
||||
// test unsub, after unsub the send should not be called
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->count(), 0);
|
||||
EXPECT_CALL(*mockSessionPtr, send(_)).Times(0);
|
||||
testFeedPtr->pub(ledgerHeader2, fee2, "10-31", 8);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedLedgerTest, AutoDisconnect)
|
||||
@@ -120,7 +114,6 @@ TEST_F(FeedLedgerTest, AutoDisconnect)
|
||||
// check the response
|
||||
EXPECT_EQ(res, json::parse(LedgerResponse));
|
||||
});
|
||||
ctx.run();
|
||||
EXPECT_EQ(testFeedPtr->count(), 1);
|
||||
EXPECT_CALL(*mockSessionPtr, send(_)).Times(0);
|
||||
|
||||
@@ -132,6 +125,4 @@ TEST_F(FeedLedgerTest, AutoDisconnect)
|
||||
fee2.reserve = 10;
|
||||
// no error
|
||||
testFeedPtr->pub(ledgerHeader2, fee2, "10-31", 8);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
@@ -19,14 +19,13 @@
|
||||
|
||||
#include "feed/FeedTestUtil.hpp"
|
||||
#include "feed/impl/ProposedTransactionFeed.hpp"
|
||||
#include "util/AsioContextTestFixture.hpp"
|
||||
#include "util/MockPrometheus.hpp"
|
||||
#include "util/MockWsBase.hpp"
|
||||
#include "util/SyncExecutionCtxFixture.hpp"
|
||||
#include "util/TestObject.hpp"
|
||||
#include "util/prometheus/Gauge.hpp"
|
||||
#include "web/interface/ConnectionBase.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
@@ -66,14 +65,11 @@ TEST_F(FeedProposedTransactionTest, ProposedTransaction)
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(DUMMY_TRANSACTION))).Times(1);
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.run();
|
||||
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->transactionSubcount(), 0);
|
||||
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedProposedTransactionTest, AccountProposedTransaction)
|
||||
@@ -90,15 +86,12 @@ TEST_F(FeedProposedTransactionTest, AccountProposedTransaction)
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(DUMMY_TRANSACTION))).Times(1);
|
||||
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.run();
|
||||
|
||||
// unsub
|
||||
testFeedPtr->unsub(account, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 1);
|
||||
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedProposedTransactionTest, SubStreamAndAccount)
|
||||
@@ -111,7 +104,6 @@ TEST_F(FeedProposedTransactionTest, SubStreamAndAccount)
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(DUMMY_TRANSACTION))).Times(2);
|
||||
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.run();
|
||||
|
||||
// unsub
|
||||
testFeedPtr->unsub(account, sessionPtr);
|
||||
@@ -119,16 +111,12 @@ TEST_F(FeedProposedTransactionTest, SubStreamAndAccount)
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(DUMMY_TRANSACTION))).Times(1);
|
||||
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
|
||||
// unsub transaction
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->transactionSubcount(), 0);
|
||||
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedProposedTransactionTest, AccountProposedTransactionDuplicate)
|
||||
@@ -142,23 +130,18 @@ TEST_F(FeedProposedTransactionTest, AccountProposedTransactionDuplicate)
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(DUMMY_TRANSACTION))).Times(1);
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.run();
|
||||
|
||||
// unsub account1
|
||||
testFeedPtr->unsub(account, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 1);
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(DUMMY_TRANSACTION))).Times(1);
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
|
||||
// unsub account2
|
||||
testFeedPtr->unsub(account2, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(json::parse(DUMMY_TRANSACTION).get_object());
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedProposedTransactionTest, Count)
|
||||
@@ -231,7 +214,7 @@ TEST_F(FeedProposedTransactionTest, AutoDisconnect)
|
||||
EXPECT_EQ(testFeedPtr->transactionSubcount(), 0);
|
||||
}
|
||||
|
||||
struct ProposedTransactionFeedMockPrometheusTest : WithMockPrometheus, SyncAsioContextTest {
|
||||
struct ProposedTransactionFeedMockPrometheusTest : WithMockPrometheus, SyncExecutionCtxFixture {
|
||||
protected:
|
||||
std::shared_ptr<web::ConnectionBase> sessionPtr;
|
||||
std::shared_ptr<ProposedTransactionFeed> testFeedPtr;
|
||||
@@ -239,7 +222,6 @@ protected:
|
||||
void
|
||||
SetUp() override
|
||||
{
|
||||
SyncAsioContextTest::SetUp();
|
||||
testFeedPtr = std::make_shared<ProposedTransactionFeed>(ctx);
|
||||
sessionPtr = std::make_shared<MockSession>();
|
||||
}
|
||||
@@ -248,7 +230,6 @@ protected:
|
||||
{
|
||||
sessionPtr.reset();
|
||||
testFeedPtr.reset();
|
||||
SyncAsioContextTest::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
#include "feed/FeedTestUtil.hpp"
|
||||
#include "feed/impl/SingleFeedBase.hpp"
|
||||
#include "util/AsioContextTestFixture.hpp"
|
||||
#include "util/MockPrometheus.hpp"
|
||||
#include "util/MockWsBase.hpp"
|
||||
#include "util/SyncExecutionCtxFixture.hpp"
|
||||
#include "util/async/AnyExecutionContext.hpp"
|
||||
#include "util/prometheus/Gauge.hpp"
|
||||
#include "web/interface/ConnectionBase.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -36,7 +36,7 @@ constexpr static auto FEED = R"({"test":"test"})";
|
||||
using namespace feed::impl;
|
||||
using namespace util::prometheus;
|
||||
|
||||
struct FeedBaseMockPrometheusTest : WithMockPrometheus, SyncAsioContextTest {
|
||||
struct FeedBaseMockPrometheusTest : WithMockPrometheus, SyncExecutionCtxFixture {
|
||||
protected:
|
||||
std::shared_ptr<web::ConnectionBase> sessionPtr;
|
||||
std::shared_ptr<SingleFeedBase> testFeedPtr;
|
||||
@@ -45,7 +45,6 @@ protected:
|
||||
void
|
||||
SetUp() override
|
||||
{
|
||||
SyncAsioContextTest::SetUp();
|
||||
testFeedPtr = std::make_shared<SingleFeedBase>(ctx, "testFeed");
|
||||
sessionPtr = std::make_shared<MockSession>();
|
||||
mockSessionPtr = dynamic_cast<MockSession*>(sessionPtr.get());
|
||||
@@ -55,7 +54,6 @@ protected:
|
||||
{
|
||||
sessionPtr.reset();
|
||||
testFeedPtr.reset();
|
||||
SyncAsioContextTest::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -81,7 +79,7 @@ TEST_F(FeedBaseMockPrometheusTest, AutoUnsub)
|
||||
|
||||
class NamedSingleFeedTest : public SingleFeedBase {
|
||||
public:
|
||||
NamedSingleFeedTest(boost::asio::io_context& ioContext) : SingleFeedBase(ioContext, "forTest")
|
||||
NamedSingleFeedTest(util::async::AnyExecutionContext& executionCtx) : SingleFeedBase(executionCtx, "forTest")
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -94,13 +92,10 @@ TEST_F(SingleFeedBaseTest, Test)
|
||||
testFeedPtr->sub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->count(), 1);
|
||||
testFeedPtr->pub(FEED);
|
||||
ctx.run();
|
||||
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->count(), 0);
|
||||
testFeedPtr->pub(FEED);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(SingleFeedBaseTest, TestAutoDisconnect)
|
||||
@@ -109,7 +104,6 @@ TEST_F(SingleFeedBaseTest, TestAutoDisconnect)
|
||||
testFeedPtr->sub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->count(), 1);
|
||||
testFeedPtr->pub(FEED);
|
||||
ctx.run();
|
||||
|
||||
sessionPtr.reset();
|
||||
EXPECT_EQ(testFeedPtr->count(), 0);
|
||||
|
||||
@@ -20,15 +20,15 @@
|
||||
#include "data/Types.hpp"
|
||||
#include "feed/FeedTestUtil.hpp"
|
||||
#include "feed/SubscriptionManager.hpp"
|
||||
#include "util/AsioContextTestFixture.hpp"
|
||||
#include "util/MockBackendTestFixture.hpp"
|
||||
#include "util/MockPrometheus.hpp"
|
||||
#include "util/MockWsBase.hpp"
|
||||
#include "util/TestObject.hpp"
|
||||
#include "util/async/context/BasicExecutionContext.hpp"
|
||||
#include "util/async/context/SyncExecutionContext.hpp"
|
||||
#include "web/interface/ConnectionBase.hpp"
|
||||
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
@@ -41,7 +41,6 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
constexpr static auto ACCOUNT1 = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
|
||||
@@ -54,19 +53,18 @@ namespace json = boost::json;
|
||||
using namespace feed;
|
||||
using namespace feed::impl;
|
||||
|
||||
class SubscriptionManagerTest : public util::prometheus::WithPrometheus,
|
||||
public MockBackendTest,
|
||||
public SyncAsioContextTest {
|
||||
template <class Execution>
|
||||
class SubscriptionManagerBaseTest : public util::prometheus::WithPrometheus, public MockBackendTest {
|
||||
protected:
|
||||
std::shared_ptr<SubscriptionManager> SubscriptionManagerPtr;
|
||||
std::shared_ptr<SubscriptionManager> subscriptionManagerPtr;
|
||||
std::shared_ptr<web::ConnectionBase> session;
|
||||
Execution ctx{2};
|
||||
MockSession* sessionPtr = nullptr;
|
||||
|
||||
void
|
||||
SetUp() override
|
||||
{
|
||||
SyncAsioContextTest::SetUp();
|
||||
SubscriptionManagerPtr = std::make_shared<SubscriptionManager>(ctx, backend);
|
||||
subscriptionManagerPtr = std::make_shared<SubscriptionManager>(ctx, backend);
|
||||
session = std::make_shared<MockSession>();
|
||||
session->apiSubVersion = 1;
|
||||
sessionPtr = dynamic_cast<MockSession*>(session.get());
|
||||
@@ -76,65 +74,38 @@ protected:
|
||||
TearDown() override
|
||||
{
|
||||
session.reset();
|
||||
SubscriptionManagerPtr.reset();
|
||||
SyncAsioContextTest::TearDown();
|
||||
subscriptionManagerPtr.reset();
|
||||
}
|
||||
};
|
||||
|
||||
// TODO enable when fixed :/
|
||||
/*
|
||||
TEST_F(SubscriptionManagerTest, MultipleThreadCtx)
|
||||
{
|
||||
std::vector<std::thread> workers;
|
||||
workers.reserve(2);
|
||||
using SubscriptionManagerTest = SubscriptionManagerBaseTest<util::async::SyncExecutionContext>;
|
||||
|
||||
SubscriptionManagerPtr->subManifest(session);
|
||||
SubscriptionManagerPtr->subValidation(session);
|
||||
using SubscriptionManagerAsyncTest = SubscriptionManagerBaseTest<util::async::PoolExecutionContext>;
|
||||
|
||||
TEST_F(SubscriptionManagerAsyncTest, MultipleThreadCtx)
|
||||
{
|
||||
subscriptionManagerPtr->subManifest(session);
|
||||
subscriptionManagerPtr->subValidation(session);
|
||||
|
||||
constexpr static auto jsonManifest = R"({"manifest":"test"})";
|
||||
constexpr static auto jsonValidation = R"({"validation":"test"})";
|
||||
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(jsonManifest))).Times(1);
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(jsonValidation))).Times(1);
|
||||
EXPECT_CALL(*sessionPtr, send(testing::_)).Times(testing::AtMost(2));
|
||||
|
||||
SubscriptionManagerPtr->forwardManifest(json::parse(jsonManifest).get_object());
|
||||
SubscriptionManagerPtr->forwardValidation(json::parse(jsonValidation).get_object());
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
workers.emplace_back([this]() { ctx.run(); });
|
||||
|
||||
// wait for all jobs in ctx to finish
|
||||
for (auto& worker : workers)
|
||||
worker.join();
|
||||
|
||||
session.reset();
|
||||
SubscriptionManagerPtr.reset();
|
||||
subscriptionManagerPtr->forwardManifest(json::parse(jsonManifest).get_object());
|
||||
subscriptionManagerPtr->forwardValidation(json::parse(jsonValidation).get_object());
|
||||
}
|
||||
*/
|
||||
|
||||
TEST_F(SubscriptionManagerTest, MultipleThreadCtxSessionDieEarly)
|
||||
TEST_F(SubscriptionManagerAsyncTest, MultipleThreadCtxSessionDieEarly)
|
||||
{
|
||||
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work_ = boost::asio::make_work_guard(ctx);
|
||||
|
||||
std::vector<std::thread> workers;
|
||||
workers.reserve(2);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
workers.emplace_back([this]() { ctx.run(); });
|
||||
|
||||
SubscriptionManagerPtr->subManifest(session);
|
||||
SubscriptionManagerPtr->subValidation(session);
|
||||
|
||||
SubscriptionManagerPtr->forwardManifest(json::parse(R"({"manifest":"test"})").get_object());
|
||||
SubscriptionManagerPtr->forwardValidation(json::parse(R"({"validation":"test"})").get_object());
|
||||
subscriptionManagerPtr->subManifest(session);
|
||||
subscriptionManagerPtr->subValidation(session);
|
||||
|
||||
EXPECT_CALL(*sessionPtr, send(testing::_)).Times(0);
|
||||
session.reset();
|
||||
|
||||
work_.reset();
|
||||
for (auto& worker : workers)
|
||||
worker.join();
|
||||
// SubscriptionManager's pub job is running in thread pool, so we let thread pool run out of work, otherwise
|
||||
// SubscriptionManager will die before the job is called
|
||||
SubscriptionManagerPtr.reset();
|
||||
subscriptionManagerPtr->forwardManifest(json::parse(R"({"manifest":"test"})").get_object());
|
||||
subscriptionManagerPtr->forwardValidation(json::parse(R"({"validation":"test"})").get_object());
|
||||
}
|
||||
|
||||
TEST_F(SubscriptionManagerTest, ReportCurrentSubscriber)
|
||||
@@ -153,42 +124,42 @@ TEST_F(SubscriptionManagerTest, ReportCurrentSubscriber)
|
||||
})";
|
||||
std::shared_ptr<web::ConnectionBase> const session1 = std::make_shared<MockSession>();
|
||||
std::shared_ptr<web::ConnectionBase> session2 = std::make_shared<MockSession>();
|
||||
SubscriptionManagerPtr->subBookChanges(session1);
|
||||
SubscriptionManagerPtr->subBookChanges(session2);
|
||||
SubscriptionManagerPtr->subManifest(session1);
|
||||
SubscriptionManagerPtr->subManifest(session2);
|
||||
SubscriptionManagerPtr->subProposedTransactions(session1);
|
||||
SubscriptionManagerPtr->subProposedTransactions(session2);
|
||||
SubscriptionManagerPtr->subTransactions(session1);
|
||||
subscriptionManagerPtr->subBookChanges(session1);
|
||||
subscriptionManagerPtr->subBookChanges(session2);
|
||||
subscriptionManagerPtr->subManifest(session1);
|
||||
subscriptionManagerPtr->subManifest(session2);
|
||||
subscriptionManagerPtr->subProposedTransactions(session1);
|
||||
subscriptionManagerPtr->subProposedTransactions(session2);
|
||||
subscriptionManagerPtr->subTransactions(session1);
|
||||
session2->apiSubVersion = 2;
|
||||
SubscriptionManagerPtr->subTransactions(session2);
|
||||
SubscriptionManagerPtr->subValidation(session1);
|
||||
SubscriptionManagerPtr->subValidation(session2);
|
||||
subscriptionManagerPtr->subTransactions(session2);
|
||||
subscriptionManagerPtr->subValidation(session1);
|
||||
subscriptionManagerPtr->subValidation(session2);
|
||||
auto const account = GetAccountIDWithString(ACCOUNT1);
|
||||
SubscriptionManagerPtr->subAccount(account, session1);
|
||||
SubscriptionManagerPtr->subAccount(account, session2);
|
||||
SubscriptionManagerPtr->subProposedAccount(account, session1);
|
||||
SubscriptionManagerPtr->subProposedAccount(account, session2);
|
||||
subscriptionManagerPtr->subAccount(account, session1);
|
||||
subscriptionManagerPtr->subAccount(account, session2);
|
||||
subscriptionManagerPtr->subProposedAccount(account, session1);
|
||||
subscriptionManagerPtr->subProposedAccount(account, session2);
|
||||
auto const issue1 = GetIssue(CURRENCY, ISSUER);
|
||||
ripple::Book const book{ripple::xrpIssue(), issue1};
|
||||
SubscriptionManagerPtr->subBook(book, session1);
|
||||
SubscriptionManagerPtr->subBook(book, session2);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report(), json::parse(ReportReturn));
|
||||
subscriptionManagerPtr->subBook(book, session1);
|
||||
subscriptionManagerPtr->subBook(book, session2);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report(), json::parse(ReportReturn));
|
||||
|
||||
// count down when unsub manually
|
||||
SubscriptionManagerPtr->unsubBookChanges(session1);
|
||||
SubscriptionManagerPtr->unsubManifest(session1);
|
||||
SubscriptionManagerPtr->unsubProposedTransactions(session1);
|
||||
SubscriptionManagerPtr->unsubTransactions(session1);
|
||||
SubscriptionManagerPtr->unsubValidation(session1);
|
||||
SubscriptionManagerPtr->unsubAccount(account, session1);
|
||||
SubscriptionManagerPtr->unsubProposedAccount(account, session1);
|
||||
SubscriptionManagerPtr->unsubBook(book, session1);
|
||||
subscriptionManagerPtr->unsubBookChanges(session1);
|
||||
subscriptionManagerPtr->unsubManifest(session1);
|
||||
subscriptionManagerPtr->unsubProposedTransactions(session1);
|
||||
subscriptionManagerPtr->unsubTransactions(session1);
|
||||
subscriptionManagerPtr->unsubValidation(session1);
|
||||
subscriptionManagerPtr->unsubAccount(account, session1);
|
||||
subscriptionManagerPtr->unsubProposedAccount(account, session1);
|
||||
subscriptionManagerPtr->unsubBook(book, session1);
|
||||
|
||||
// try to unsub an account which is not subscribed
|
||||
auto const account2 = GetAccountIDWithString(ACCOUNT2);
|
||||
SubscriptionManagerPtr->unsubAccount(account2, session1);
|
||||
SubscriptionManagerPtr->unsubProposedAccount(account2, session1);
|
||||
subscriptionManagerPtr->unsubAccount(account2, session1);
|
||||
subscriptionManagerPtr->unsubProposedAccount(account2, session1);
|
||||
auto checkResult = [](json::object reportReturn, int result) {
|
||||
EXPECT_EQ(reportReturn["book_changes"], result);
|
||||
EXPECT_EQ(reportReturn["validations"], result);
|
||||
@@ -199,46 +170,41 @@ TEST_F(SubscriptionManagerTest, ReportCurrentSubscriber)
|
||||
EXPECT_EQ(reportReturn["account"], result);
|
||||
EXPECT_EQ(reportReturn["books"], result);
|
||||
};
|
||||
checkResult(SubscriptionManagerPtr->report(), 1);
|
||||
checkResult(subscriptionManagerPtr->report(), 1);
|
||||
|
||||
// count down when session disconnect
|
||||
session2.reset();
|
||||
checkResult(SubscriptionManagerPtr->report(), 0);
|
||||
checkResult(subscriptionManagerPtr->report(), 0);
|
||||
}
|
||||
|
||||
TEST_F(SubscriptionManagerTest, ManifestTest)
|
||||
{
|
||||
constexpr static auto dummyManifest = R"({"manifest":"test"})";
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(dummyManifest))).Times(1);
|
||||
SubscriptionManagerPtr->subManifest(session);
|
||||
SubscriptionManagerPtr->forwardManifest(json::parse(dummyManifest).get_object());
|
||||
ctx.run();
|
||||
subscriptionManagerPtr->subManifest(session);
|
||||
subscriptionManagerPtr->forwardManifest(json::parse(dummyManifest).get_object());
|
||||
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(dummyManifest))).Times(0);
|
||||
SubscriptionManagerPtr->unsubManifest(session);
|
||||
SubscriptionManagerPtr->forwardManifest(json::parse(dummyManifest).get_object());
|
||||
ctx.run();
|
||||
subscriptionManagerPtr->unsubManifest(session);
|
||||
subscriptionManagerPtr->forwardManifest(json::parse(dummyManifest).get_object());
|
||||
}
|
||||
|
||||
TEST_F(SubscriptionManagerTest, ValidationTest)
|
||||
{
|
||||
constexpr static auto dummy = R"({"validation":"test"})";
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(dummy))).Times(1);
|
||||
SubscriptionManagerPtr->subValidation(session);
|
||||
SubscriptionManagerPtr->forwardValidation(json::parse(dummy).get_object());
|
||||
ctx.run();
|
||||
subscriptionManagerPtr->subValidation(session);
|
||||
subscriptionManagerPtr->forwardValidation(json::parse(dummy).get_object());
|
||||
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(dummy))).Times(0);
|
||||
SubscriptionManagerPtr->unsubValidation(session);
|
||||
SubscriptionManagerPtr->forwardValidation(json::parse(dummy).get_object());
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
subscriptionManagerPtr->unsubValidation(session);
|
||||
subscriptionManagerPtr->forwardValidation(json::parse(dummy).get_object());
|
||||
}
|
||||
|
||||
TEST_F(SubscriptionManagerTest, BookChangesTest)
|
||||
{
|
||||
SubscriptionManagerPtr->subBookChanges(session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["book_changes"], 1);
|
||||
subscriptionManagerPtr->subBookChanges(session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["book_changes"], 1);
|
||||
|
||||
auto const ledgerHeader = CreateLedgerHeader(LEDGERHASH, 32);
|
||||
auto transactions = std::vector<TransactionAndMetadata>{};
|
||||
@@ -249,8 +215,6 @@ TEST_F(SubscriptionManagerTest, BookChangesTest)
|
||||
ripple::STObject const metaObj = CreateMetaDataForBookChange(CURRENCY, ISSUER, 22, 1, 3, 3, 1);
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
transactions.push_back(trans1);
|
||||
|
||||
SubscriptionManagerPtr->pubBookChanges(ledgerHeader, transactions);
|
||||
constexpr static auto bookChangePublish =
|
||||
R"({
|
||||
"type":"bookChanges",
|
||||
@@ -272,10 +236,11 @@ TEST_F(SubscriptionManagerTest, BookChangesTest)
|
||||
]
|
||||
})";
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(bookChangePublish))).Times(1);
|
||||
ctx.run();
|
||||
|
||||
SubscriptionManagerPtr->unsubBookChanges(session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["book_changes"], 0);
|
||||
subscriptionManagerPtr->pubBookChanges(ledgerHeader, transactions);
|
||||
|
||||
subscriptionManagerPtr->unsubBookChanges(session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["book_changes"], 0);
|
||||
}
|
||||
|
||||
TEST_F(SubscriptionManagerTest, LedgerTest)
|
||||
@@ -301,18 +266,16 @@ TEST_F(SubscriptionManagerTest, LedgerTest)
|
||||
"reserve_inc":2
|
||||
})";
|
||||
boost::asio::spawn(ctx, [this](boost::asio::yield_context yield) {
|
||||
auto const res = SubscriptionManagerPtr->subLedger(yield, session);
|
||||
auto const res = subscriptionManagerPtr->subLedger(yield, session);
|
||||
// check the response
|
||||
EXPECT_EQ(res, json::parse(LedgerResponse));
|
||||
});
|
||||
ctx.run();
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["ledger"], 1);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["ledger"], 1);
|
||||
|
||||
// test publish
|
||||
auto const ledgerHeader2 = CreateLedgerHeader(LEDGERHASH, 31);
|
||||
auto fee2 = ripple::Fees();
|
||||
fee2.reserve = 10;
|
||||
SubscriptionManagerPtr->pubLedger(ledgerHeader2, fee2, "10-31", 8);
|
||||
constexpr static auto ledgerPub =
|
||||
R"({
|
||||
"type":"ledgerClosed",
|
||||
@@ -326,12 +289,11 @@ TEST_F(SubscriptionManagerTest, LedgerTest)
|
||||
"txn_count":8
|
||||
})";
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(ledgerPub))).Times(1);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
subscriptionManagerPtr->pubLedger(ledgerHeader2, fee2, "10-31", 8);
|
||||
|
||||
// test unsub
|
||||
SubscriptionManagerPtr->unsubLedger(session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["ledger"], 0);
|
||||
subscriptionManagerPtr->unsubLedger(session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["ledger"], 0);
|
||||
}
|
||||
|
||||
TEST_F(SubscriptionManagerTest, TransactionTest)
|
||||
@@ -339,12 +301,12 @@ TEST_F(SubscriptionManagerTest, TransactionTest)
|
||||
auto const issue1 = GetIssue(CURRENCY, ISSUER);
|
||||
auto const account = GetAccountIDWithString(ISSUER);
|
||||
ripple::Book const book{ripple::xrpIssue(), issue1};
|
||||
SubscriptionManagerPtr->subBook(book, session);
|
||||
SubscriptionManagerPtr->subTransactions(session);
|
||||
SubscriptionManagerPtr->subAccount(account, session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["account"], 1);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["transactions"], 1);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["books"], 1);
|
||||
subscriptionManagerPtr->subBook(book, session);
|
||||
subscriptionManagerPtr->subTransactions(session);
|
||||
subscriptionManagerPtr->subAccount(account, session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["account"], 1);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["transactions"], 1);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["books"], 1);
|
||||
|
||||
auto const ledgerHeader = CreateLedgerHeader(LEDGERHASH, 33);
|
||||
auto trans1 = TransactionAndMetadata();
|
||||
@@ -354,8 +316,6 @@ TEST_F(SubscriptionManagerTest, TransactionTest)
|
||||
|
||||
auto const metaObj = CreateMetaDataForBookChange(CURRENCY, ISSUER, 22, 3, 1, 1, 3);
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
SubscriptionManagerPtr->pubTransaction(trans1, ledgerHeader);
|
||||
|
||||
constexpr static auto OrderbookPublish =
|
||||
R"({
|
||||
"transaction":
|
||||
@@ -417,23 +377,23 @@ TEST_F(SubscriptionManagerTest, TransactionTest)
|
||||
"engine_result_message":"The transaction was applied. Only final in a validated ledger."
|
||||
})";
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(OrderbookPublish))).Times(3);
|
||||
ctx.run();
|
||||
subscriptionManagerPtr->pubTransaction(trans1, ledgerHeader);
|
||||
|
||||
SubscriptionManagerPtr->unsubBook(book, session);
|
||||
SubscriptionManagerPtr->unsubTransactions(session);
|
||||
SubscriptionManagerPtr->unsubAccount(account, session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["account"], 0);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["transactions"], 0);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["books"], 0);
|
||||
subscriptionManagerPtr->unsubBook(book, session);
|
||||
subscriptionManagerPtr->unsubTransactions(session);
|
||||
subscriptionManagerPtr->unsubAccount(account, session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["account"], 0);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["transactions"], 0);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["books"], 0);
|
||||
}
|
||||
|
||||
TEST_F(SubscriptionManagerTest, ProposedTransactionTest)
|
||||
{
|
||||
auto const account = GetAccountIDWithString(ACCOUNT1);
|
||||
SubscriptionManagerPtr->subProposedAccount(account, session);
|
||||
SubscriptionManagerPtr->subProposedTransactions(session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["accounts_proposed"], 1);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["transactions_proposed"], 1);
|
||||
subscriptionManagerPtr->subProposedAccount(account, session);
|
||||
subscriptionManagerPtr->subProposedTransactions(session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["accounts_proposed"], 1);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["transactions_proposed"], 1);
|
||||
|
||||
constexpr static auto dummyTransaction =
|
||||
R"({
|
||||
@@ -505,7 +465,7 @@ TEST_F(SubscriptionManagerTest, ProposedTransactionTest)
|
||||
})";
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(dummyTransaction))).Times(2);
|
||||
EXPECT_CALL(*sessionPtr, send(SharedStringJsonEq(OrderbookPublish))).Times(2);
|
||||
SubscriptionManagerPtr->forwardProposedTransaction(json::parse(dummyTransaction).get_object());
|
||||
subscriptionManagerPtr->forwardProposedTransaction(json::parse(dummyTransaction).get_object());
|
||||
|
||||
auto const ledgerHeader = CreateLedgerHeader(LEDGERHASH, 33);
|
||||
auto trans1 = TransactionAndMetadata();
|
||||
@@ -515,22 +475,21 @@ TEST_F(SubscriptionManagerTest, ProposedTransactionTest)
|
||||
|
||||
auto const metaObj = CreateMetaDataForBookChange(CURRENCY, ACCOUNT1, 22, 3, 1, 1, 3);
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
SubscriptionManagerPtr->pubTransaction(trans1, ledgerHeader);
|
||||
ctx.run();
|
||||
subscriptionManagerPtr->pubTransaction(trans1, ledgerHeader);
|
||||
|
||||
// unsub account1
|
||||
SubscriptionManagerPtr->unsubProposedAccount(account, session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["accounts_proposed"], 0);
|
||||
SubscriptionManagerPtr->unsubProposedTransactions(session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["transactions_proposed"], 0);
|
||||
subscriptionManagerPtr->unsubProposedAccount(account, session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["accounts_proposed"], 0);
|
||||
subscriptionManagerPtr->unsubProposedTransactions(session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["transactions_proposed"], 0);
|
||||
}
|
||||
|
||||
TEST_F(SubscriptionManagerTest, DuplicateResponseSubTxAndProposedTx)
|
||||
{
|
||||
SubscriptionManagerPtr->subProposedTransactions(session);
|
||||
SubscriptionManagerPtr->subTransactions(session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["transactions"], 1);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["transactions_proposed"], 1);
|
||||
subscriptionManagerPtr->subProposedTransactions(session);
|
||||
subscriptionManagerPtr->subTransactions(session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["transactions"], 1);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["transactions_proposed"], 1);
|
||||
|
||||
EXPECT_CALL(*sessionPtr, send(testing::_)).Times(2);
|
||||
|
||||
@@ -542,22 +501,21 @@ TEST_F(SubscriptionManagerTest, DuplicateResponseSubTxAndProposedTx)
|
||||
|
||||
auto const metaObj = CreateMetaDataForBookChange(CURRENCY, ACCOUNT1, 22, 3, 1, 1, 3);
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
SubscriptionManagerPtr->pubTransaction(trans1, ledgerHeader);
|
||||
ctx.run();
|
||||
subscriptionManagerPtr->pubTransaction(trans1, ledgerHeader);
|
||||
|
||||
SubscriptionManagerPtr->unsubTransactions(session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["transactions"], 0);
|
||||
SubscriptionManagerPtr->unsubProposedTransactions(session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["transactions_proposed"], 0);
|
||||
subscriptionManagerPtr->unsubTransactions(session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["transactions"], 0);
|
||||
subscriptionManagerPtr->unsubProposedTransactions(session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["transactions_proposed"], 0);
|
||||
}
|
||||
|
||||
TEST_F(SubscriptionManagerTest, NoDuplicateResponseSubAccountAndProposedAccount)
|
||||
{
|
||||
auto const account = GetAccountIDWithString(ACCOUNT1);
|
||||
SubscriptionManagerPtr->subProposedAccount(account, session);
|
||||
SubscriptionManagerPtr->subAccount(account, session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["accounts_proposed"], 1);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["account"], 1);
|
||||
subscriptionManagerPtr->subProposedAccount(account, session);
|
||||
subscriptionManagerPtr->subAccount(account, session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["accounts_proposed"], 1);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["account"], 1);
|
||||
|
||||
EXPECT_CALL(*sessionPtr, send(testing::_)).Times(1);
|
||||
|
||||
@@ -569,12 +527,11 @@ TEST_F(SubscriptionManagerTest, NoDuplicateResponseSubAccountAndProposedAccount)
|
||||
|
||||
auto const metaObj = CreateMetaDataForBookChange(CURRENCY, ACCOUNT1, 22, 3, 1, 1, 3);
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
SubscriptionManagerPtr->pubTransaction(trans1, ledgerHeader);
|
||||
ctx.run();
|
||||
subscriptionManagerPtr->pubTransaction(trans1, ledgerHeader);
|
||||
|
||||
// unsub account1
|
||||
SubscriptionManagerPtr->unsubProposedAccount(account, session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["accounts_proposed"], 0);
|
||||
SubscriptionManagerPtr->unsubAccount(account, session);
|
||||
EXPECT_EQ(SubscriptionManagerPtr->report()["account"], 0);
|
||||
subscriptionManagerPtr->unsubProposedAccount(account, session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["accounts_proposed"], 0);
|
||||
subscriptionManagerPtr->unsubAccount(account, session);
|
||||
EXPECT_EQ(subscriptionManagerPtr->report()["account"], 0);
|
||||
}
|
||||
|
||||
@@ -20,14 +20,13 @@
|
||||
#include "data/Types.hpp"
|
||||
#include "feed/FeedTestUtil.hpp"
|
||||
#include "feed/impl/TransactionFeed.hpp"
|
||||
#include "util/AsioContextTestFixture.hpp"
|
||||
#include "util/MockPrometheus.hpp"
|
||||
#include "util/MockWsBase.hpp"
|
||||
#include "util/SyncExecutionCtxFixture.hpp"
|
||||
#include "util/TestObject.hpp"
|
||||
#include "util/prometheus/Gauge.hpp"
|
||||
#include "web/interface/ConnectionBase.hpp"
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
@@ -174,17 +173,12 @@ TEST_F(FeedTransactionTest, SubTransactionV1)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V1))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->transactionSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
EXPECT_EQ(testFeedPtr->transactionSubCount(), 0);
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubTransactionForProposedTx)
|
||||
@@ -198,15 +192,12 @@ TEST_F(FeedTransactionTest, SubTransactionForProposedTx)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V1))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsubProposed(sessionPtr);
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubTransactionV2)
|
||||
@@ -221,17 +212,14 @@ TEST_F(FeedTransactionTest, SubTransactionV2)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V2))).Times(1);
|
||||
|
||||
ctx.run();
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V2))).Times(1);
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->transactionSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubAccountV1)
|
||||
@@ -247,16 +235,14 @@ TEST_F(FeedTransactionTest, SubAccountV1)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V1))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(account, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubForProposedAccount)
|
||||
@@ -272,14 +258,12 @@ TEST_F(FeedTransactionTest, SubForProposedAccount)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V1))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsubProposed(account, sessionPtr);
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubAccountV2)
|
||||
@@ -297,16 +281,13 @@ TEST_F(FeedTransactionTest, SubAccountV2)
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V2))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(account, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubBothTransactionAndAccount)
|
||||
@@ -326,10 +307,8 @@ TEST_F(FeedTransactionTest, SubBothTransactionAndAccount)
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V2))).Times(2);
|
||||
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(account, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 0);
|
||||
@@ -337,8 +316,6 @@ TEST_F(FeedTransactionTest, SubBothTransactionAndAccount)
|
||||
EXPECT_EQ(testFeedPtr->transactionSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubBookV1)
|
||||
@@ -356,7 +333,6 @@ TEST_F(FeedTransactionTest, SubBookV1)
|
||||
|
||||
auto metaObj = CreateMetaDataForBookChange(CURRENCY, ISSUER, 22, 3, 1, 1, 3);
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
constexpr static auto OrderbookPublish =
|
||||
R"({
|
||||
@@ -419,12 +395,11 @@ TEST_F(FeedTransactionTest, SubBookV1)
|
||||
})";
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(OrderbookPublish))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
// trigger by offer cancel meta data
|
||||
metaObj = CreateMetaDataForCancelOffer(CURRENCY, ISSUER, 22, 3, 1);
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
constexpr static auto OrderbookCancelPublish =
|
||||
R"({
|
||||
@@ -473,9 +448,8 @@ TEST_F(FeedTransactionTest, SubBookV1)
|
||||
"close_time_iso": "2000-01-01T00:00:00Z",
|
||||
"engine_result_message":"The transaction was applied. Only final in a validated ledger."
|
||||
})";
|
||||
ctx.restart();
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(OrderbookCancelPublish))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
// trigger by offer create meta data
|
||||
constexpr static auto OrderbookCreatePublish =
|
||||
@@ -529,17 +503,14 @@ TEST_F(FeedTransactionTest, SubBookV1)
|
||||
})";
|
||||
metaObj = CreateMetaDataForCreateOffer(CURRENCY, ISSUER, 22, 3, 1);
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(OrderbookCreatePublish))).Times(1);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(book, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->bookSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubBookV2)
|
||||
@@ -558,7 +529,6 @@ TEST_F(FeedTransactionTest, SubBookV2)
|
||||
|
||||
auto const metaObj = CreateMetaDataForBookChange(CURRENCY, ISSUER, 22, 3, 1, 1, 3);
|
||||
trans1.metadata = metaObj.getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
constexpr static auto OrderbookPublish =
|
||||
R"({
|
||||
@@ -621,14 +591,12 @@ TEST_F(FeedTransactionTest, SubBookV2)
|
||||
})";
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(OrderbookPublish))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(book, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->bookSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, TransactionContainsBothAccountsSubed)
|
||||
@@ -648,23 +616,19 @@ TEST_F(FeedTransactionTest, TransactionContainsBothAccountsSubed)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V2))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(account, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 1);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V2))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(account2, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 0);
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubAccountRepeatWithDifferentVersion)
|
||||
@@ -684,24 +648,20 @@ TEST_F(FeedTransactionTest, SubAccountRepeatWithDifferentVersion)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V2))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(account, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 1);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V2))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(account2, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubTransactionRepeatWithDifferentVersion)
|
||||
@@ -721,16 +681,13 @@ TEST_F(FeedTransactionTest, SubTransactionRepeatWithDifferentVersion)
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V2))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->transactionSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubRepeat)
|
||||
@@ -820,7 +777,6 @@ TEST_F(FeedTransactionTest, PubTransactionWithOwnerFund)
|
||||
ON_CALL(*backend, doFetchLedgerObject(kk, testing::_, testing::_))
|
||||
.WillByDefault(testing::Return(accountRoot.getSerializer().peekData()));
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
constexpr static auto TransactionForOwnerFund =
|
||||
R"({
|
||||
"transaction":
|
||||
@@ -859,7 +815,7 @@ TEST_F(FeedTransactionTest, PubTransactionWithOwnerFund)
|
||||
})";
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TransactionForOwnerFund))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
}
|
||||
|
||||
constexpr static auto TRAN_FROZEN =
|
||||
@@ -931,9 +887,9 @@ TEST_F(FeedTransactionTest, PubTransactionOfferCreationFrozenLine)
|
||||
ripple::STObject const accountRoot = CreateAccountRootObject(ISSUER, 0, 1, 10, 2, TXNID, 3);
|
||||
ON_CALL(*backend, doFetchLedgerObject(kk, testing::_, testing::_))
|
||||
.WillByDefault(testing::Return(accountRoot.getSerializer().peekData()));
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_FROZEN))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubTransactionOfferCreationGlobalFrozen)
|
||||
@@ -969,10 +925,9 @@ TEST_F(FeedTransactionTest, SubTransactionOfferCreationGlobalFrozen)
|
||||
ripple::STObject const accountRoot = CreateAccountRootObject(ISSUER, ripple::lsfGlobalFreeze, 1, 10, 2, TXNID, 3);
|
||||
ON_CALL(*backend, doFetchLedgerObject(kk, testing::_, testing::_))
|
||||
.WillByDefault(testing::Return(accountRoot.getSerializer().peekData()));
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_FROZEN))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubBothProposedAndValidatedAccount)
|
||||
@@ -988,17 +943,14 @@ TEST_F(FeedTransactionTest, SubBothProposedAndValidatedAccount)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V1))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(account, sessionPtr);
|
||||
testFeedPtr->unsubProposed(account, sessionPtr);
|
||||
EXPECT_EQ(testFeedPtr->accountSubCount(), 0);
|
||||
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubBothProposedAndValidated)
|
||||
@@ -1013,15 +965,13 @@ TEST_F(FeedTransactionTest, SubBothProposedAndValidated)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V1))).Times(2);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
testFeedPtr->unsub(sessionPtr);
|
||||
testFeedPtr->unsubProposed(sessionPtr);
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubProposedDisconnect)
|
||||
@@ -1035,14 +985,12 @@ TEST_F(FeedTransactionTest, SubProposedDisconnect)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V1))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
sessionPtr.reset();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
TEST_F(FeedTransactionTest, SubProposedAccountDisconnect)
|
||||
@@ -1057,17 +1005,15 @@ TEST_F(FeedTransactionTest, SubProposedAccountDisconnect)
|
||||
trans1.transaction = obj.getSerializer().peekData();
|
||||
trans1.ledgerSequence = 32;
|
||||
trans1.metadata = CreatePaymentTransactionMetaObject(ACCOUNT1, ACCOUNT2, 110, 30, 22).getSerializer().peekData();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
EXPECT_CALL(*mockSessionPtr, send(SharedStringJsonEq(TRAN_V1))).Times(1);
|
||||
ctx.run();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
|
||||
sessionPtr.reset();
|
||||
testFeedPtr->pub(trans1, ledgerHeader, backend);
|
||||
ctx.restart();
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
struct TransactionFeedMockPrometheusTest : WithMockPrometheus, SyncAsioContextTest {
|
||||
struct TransactionFeedMockPrometheusTest : WithMockPrometheus, SyncExecutionCtxFixture {
|
||||
protected:
|
||||
std::shared_ptr<web::ConnectionBase> sessionPtr;
|
||||
std::shared_ptr<TransactionFeed> testFeedPtr;
|
||||
@@ -1075,7 +1021,6 @@ protected:
|
||||
void
|
||||
SetUp() override
|
||||
{
|
||||
SyncAsioContextTest::SetUp();
|
||||
testFeedPtr = std::make_shared<TransactionFeed>(ctx);
|
||||
sessionPtr = std::make_shared<MockSession>();
|
||||
}
|
||||
@@ -1084,7 +1029,6 @@ protected:
|
||||
{
|
||||
sessionPtr.reset();
|
||||
testFeedPtr.reset();
|
||||
SyncAsioContextTest::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -18,18 +18,19 @@
|
||||
//==============================================================================
|
||||
|
||||
#include "data/Types.hpp"
|
||||
#include "feed/SubscriptionManager.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/RPCHelpers.hpp"
|
||||
#include "rpc/common/AnyHandler.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "rpc/handlers/Subscribe.hpp"
|
||||
#include "util/HandlerBaseTestFixture.hpp"
|
||||
#include "util/MockSubscriptionManager.hpp"
|
||||
#include "util/MockWsBase.hpp"
|
||||
#include "util/NameGenerator.hpp"
|
||||
#include "util/TestObject.hpp"
|
||||
#include "web/interface/ConnectionBase.hpp"
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <fmt/core.h>
|
||||
@@ -57,7 +58,6 @@ constexpr static auto MINSEQ = 10;
|
||||
constexpr static auto MAXSEQ = 30;
|
||||
constexpr static auto ACCOUNT = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
|
||||
constexpr static auto ACCOUNT2 = "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun";
|
||||
constexpr static auto LEDGERHASH = "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652";
|
||||
constexpr static auto PAYS20USDGETS10XRPBOOKDIR = "43B83ADC452B85FCBADA6CAEAC5181C255A213630D58FFD455071AFD498D0000";
|
||||
constexpr static auto PAYS20XRPGETS10USDBOOKDIR = "7B1767D41DBCE79D9585CF9D0262A5FEC45E5206FF524F8B55071AFD498D0000";
|
||||
constexpr static auto INDEX1 = "1B8590C01B0006EDFA9ED60296DD052DC5E90F99659B25014D08E1BC983515BC";
|
||||
@@ -69,8 +69,6 @@ protected:
|
||||
SetUp() override
|
||||
{
|
||||
HandlerBaseTest::SetUp();
|
||||
|
||||
subManager_ = std::make_shared<feed::SubscriptionManager>(ctx, backend);
|
||||
session_ = std::make_shared<MockSession>();
|
||||
}
|
||||
void
|
||||
@@ -79,8 +77,8 @@ protected:
|
||||
HandlerBaseTest::TearDown();
|
||||
}
|
||||
|
||||
std::shared_ptr<feed::SubscriptionManager> subManager_;
|
||||
std::shared_ptr<web::ConnectionBase> session_;
|
||||
StrictMockSubscriptionManagerSharedPtr mockSubscriptionManagerPtr;
|
||||
};
|
||||
|
||||
struct SubscribeParamTestCaseBundle {
|
||||
@@ -575,7 +573,7 @@ TEST_P(SubscribeParameterTest, InvalidParams)
|
||||
{
|
||||
auto const testBundle = GetParam();
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
auto const req = json::parse(testBundle.testJson);
|
||||
auto const output = handler.process(req, Context{yield});
|
||||
ASSERT_FALSE(output);
|
||||
@@ -588,7 +586,7 @@ TEST_P(SubscribeParameterTest, InvalidParams)
|
||||
TEST_F(RPCSubscribeHandlerTest, EmptyResponse)
|
||||
{
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
auto const output = handler.process(json::parse(R"({})"), Context{yield, session_});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_TRUE(output.result->as_object().empty());
|
||||
@@ -604,16 +602,16 @@ TEST_F(RPCSubscribeHandlerTest, StreamsWithoutLedger)
|
||||
})"
|
||||
);
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subTransactions).Times(1);
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subValidation).Times(1);
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subManifest).Times(1);
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subBookChanges).Times(1);
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subProposedTransactions).Times(1);
|
||||
|
||||
auto const output = handler.process(input, Context{yield, session_});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_TRUE(output.result->as_object().empty());
|
||||
auto const report = subManager_->report();
|
||||
EXPECT_EQ(report.at("transactions_proposed").as_uint64(), 1);
|
||||
EXPECT_EQ(report.at("transactions").as_uint64(), 1);
|
||||
EXPECT_EQ(report.at("validations").as_uint64(), 1);
|
||||
EXPECT_EQ(report.at("manifests").as_uint64(), 1);
|
||||
EXPECT_EQ(report.at("book_changes").as_uint64(), 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -629,31 +627,21 @@ TEST_F(RPCSubscribeHandlerTest, StreamsLedger)
|
||||
"reserve_base":3,
|
||||
"reserve_inc":2
|
||||
})";
|
||||
backend->setRange(MINSEQ, MAXSEQ);
|
||||
|
||||
EXPECT_CALL(*backend, fetchLedgerBySequence).Times(1);
|
||||
// return valid ledgerHeader
|
||||
auto const ledgerHeader = CreateLedgerHeader(LEDGERHASH, MAXSEQ);
|
||||
ON_CALL(*backend, fetchLedgerBySequence(MAXSEQ, _)).WillByDefault(Return(ledgerHeader));
|
||||
// fee
|
||||
auto feeBlob = CreateLegacyFeeSettingBlob(1, 2, 3, 4, 0);
|
||||
ON_CALL(*backend, doFetchLedgerObject).WillByDefault(Return(feeBlob));
|
||||
EXPECT_CALL(*backend, doFetchLedgerObject).Times(1);
|
||||
|
||||
// ledger stream returns information about the ledgers on hand and current
|
||||
// fee schedule.
|
||||
auto const input = json::parse(
|
||||
R"({
|
||||
"streams": ["ledger"]
|
||||
})"
|
||||
);
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subLedger)
|
||||
.WillOnce(testing::Return(boost::json::parse(expectedOutput).as_object()));
|
||||
|
||||
auto const output = handler.process(input, Context{yield, session_});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(output.result->as_object(), json::parse(expectedOutput));
|
||||
auto const report = subManager_->report();
|
||||
EXPECT_EQ(report.at("ledger").as_uint64(), 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -668,13 +656,13 @@ TEST_F(RPCSubscribeHandlerTest, Accounts)
|
||||
ACCOUNT2
|
||||
));
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subAccount(GetAccountIDWithString(ACCOUNT), session_)).Times(1);
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subAccount(GetAccountIDWithString(ACCOUNT2), session_)).Times(2);
|
||||
auto const output = handler.process(input, Context{yield, session_});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_TRUE(output.result->as_object().empty());
|
||||
auto const report = subManager_->report();
|
||||
// filter the duplicates
|
||||
EXPECT_EQ(report.at("account").as_uint64(), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -689,13 +677,15 @@ TEST_F(RPCSubscribeHandlerTest, AccountsProposed)
|
||||
ACCOUNT2
|
||||
));
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subProposedAccount(GetAccountIDWithString(ACCOUNT), session_))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subProposedAccount(GetAccountIDWithString(ACCOUNT2), session_))
|
||||
.Times(2);
|
||||
auto const output = handler.process(input, Context{yield, session_});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_TRUE(output.result->as_object().empty());
|
||||
auto const report = subManager_->report();
|
||||
// filter the duplicates
|
||||
EXPECT_EQ(report.at("accounts_proposed").as_uint64(), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -721,12 +711,11 @@ TEST_F(RPCSubscribeHandlerTest, JustBooks)
|
||||
ACCOUNT
|
||||
));
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subBook).Times(1);
|
||||
auto const output = handler.process(input, Context{yield, session_});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_TRUE(output.result->as_object().empty());
|
||||
auto const report = subManager_->report();
|
||||
EXPECT_EQ(report.at("books").as_uint64(), 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -753,13 +742,11 @@ TEST_F(RPCSubscribeHandlerTest, BooksBothSet)
|
||||
ACCOUNT
|
||||
));
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subBook).Times(2);
|
||||
auto const output = handler.process(input, Context{yield, session_});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_TRUE(output.result->as_object().empty());
|
||||
auto const report = subManager_->report();
|
||||
// original book + reverse book
|
||||
EXPECT_EQ(report.at("books").as_uint64(), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -919,16 +906,14 @@ TEST_F(RPCSubscribeHandlerTest, BooksBothSnapshotSet)
|
||||
ACCOUNT
|
||||
);
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subBook).Times(2);
|
||||
auto const output = handler.process(input, Context{yield, session_});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(output.result->as_object().at("bids").as_array().size(), 10);
|
||||
EXPECT_EQ(output.result->as_object().at("asks").as_array().size(), 10);
|
||||
EXPECT_EQ(output.result->as_object().at("bids").as_array()[0].as_object(), json::parse(expectedOffer));
|
||||
EXPECT_EQ(output.result->as_object().at("asks").as_array()[0].as_object(), json::parse(expectedReversedOffer));
|
||||
auto const report = subManager_->report();
|
||||
// original book + reverse book
|
||||
EXPECT_EQ(report.at("books").as_uint64(), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1061,14 +1046,12 @@ TEST_F(RPCSubscribeHandlerTest, BooksBothUnsetSnapshotSet)
|
||||
);
|
||||
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subBook).Times(1);
|
||||
auto const output = handler.process(input, Context{yield, session_});
|
||||
ASSERT_TRUE(output);
|
||||
EXPECT_EQ(output.result->as_object().at("offers").as_array().size(), 10);
|
||||
EXPECT_EQ(output.result->as_object().at("offers").as_array()[0].as_object(), json::parse(expectedOffer));
|
||||
auto const report = subManager_->report();
|
||||
// original book + reverse book
|
||||
EXPECT_EQ(report.at("books").as_uint64(), 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1081,7 +1064,8 @@ TEST_F(RPCSubscribeHandlerTest, APIVersion)
|
||||
);
|
||||
auto const apiVersion = 2;
|
||||
runSpawn([&, this](auto yield) {
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, subManager_}};
|
||||
auto const handler = AnyHandler{SubscribeHandler{backend, mockSubscriptionManagerPtr}};
|
||||
EXPECT_CALL(*mockSubscriptionManagerPtr, subProposedTransactions).Times(1);
|
||||
auto const output =
|
||||
handler.process(input, Context{.yield = yield, .session = session_, .apiVersion = apiVersion});
|
||||
ASSERT_TRUE(output);
|
||||
|
||||
@@ -61,7 +61,6 @@ struct RPCUnsubscribeTest : HandlerBaseTest {
|
||||
HandlerBaseTest::TearDown();
|
||||
}
|
||||
|
||||
std::shared_ptr<feed::SubscriptionManager> subManager_;
|
||||
std::shared_ptr<web::ConnectionBase> session_;
|
||||
StrictMockSubscriptionManagerSharedPtr mockSubscriptionManagerPtr;
|
||||
};
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
using namespace feed;
|
||||
using namespace web;
|
||||
|
||||
constexpr static auto MINSEQ = 10;
|
||||
|
||||
Reference in New Issue
Block a user