mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Isolate Application object in Env:
This change causes each instance of Env to construct its own isolated Application object for testing. Also included is part of a framework to create multiple Application objects in the same unit test and connect them together.
This commit is contained in:
@@ -3760,6 +3760,16 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\utility.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\test\mao\impl\Net.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\test\mao\impl\Net_test.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\test\mao\Net.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\unity\app_ledger.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
|
||||
|
||||
@@ -421,6 +421,12 @@
|
||||
<Filter Include="ripple\test\jtx\impl">
|
||||
<UniqueIdentifier>{27D70888-7145-691C-0E0A-E511EB3A80A2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\test\mao">
|
||||
<UniqueIdentifier>{94B5035A-6D4A-E4FC-DB50-E7E804DC9F13}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\test\mao\impl">
|
||||
<UniqueIdentifier>{23DE6C05-81D2-7471-D9BB-3AA1D49DE429}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\unity">
|
||||
<UniqueIdentifier>{5DB3CD0B-B361-B301-9562-697CA8A52B68}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -4437,6 +4443,15 @@
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\utility.h">
|
||||
<Filter>ripple\test\jtx</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\test\mao\impl\Net.cpp">
|
||||
<Filter>ripple\test\mao\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\test\mao\impl\Net_test.cpp">
|
||||
<Filter>ripple\test\mao\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\test\mao\Net.h">
|
||||
<Filter>ripple\test\mao</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\unity\app_ledger.cpp">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -79,33 +79,6 @@ namespace ripple {
|
||||
// 204/256 about 80%
|
||||
static int const MAJORITY_FRACTION (204);
|
||||
|
||||
// This hack lets the s_instance variable remain set during
|
||||
// the call to ~Application
|
||||
class ApplicationImpBase : public Application
|
||||
{
|
||||
public:
|
||||
ApplicationImpBase ()
|
||||
{
|
||||
assert (s_instance == nullptr);
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
~ApplicationImpBase ()
|
||||
{
|
||||
s_instance = nullptr;
|
||||
}
|
||||
|
||||
static Application* s_instance;
|
||||
|
||||
static Application& getInstance ()
|
||||
{
|
||||
bassert (s_instance != nullptr);
|
||||
return *s_instance;
|
||||
}
|
||||
};
|
||||
|
||||
Application* ApplicationImpBase::s_instance;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
@@ -239,7 +212,7 @@ public:
|
||||
|
||||
// VFALCO TODO Move the function definitions into the class declaration
|
||||
class ApplicationImp
|
||||
: public ApplicationImpBase
|
||||
: public Application
|
||||
, public beast::RootStoppable
|
||||
, public beast::DeadlineTimer::Listener
|
||||
, public BasicApp
|
||||
@@ -523,6 +496,25 @@ public:
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void setup() override;
|
||||
void run() override;
|
||||
bool isShutdown() override;
|
||||
void signalStop() override;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
Logs&
|
||||
logs() override
|
||||
{
|
||||
return *logs_;
|
||||
}
|
||||
|
||||
Config const&
|
||||
config() const override
|
||||
{
|
||||
return *config_;
|
||||
}
|
||||
|
||||
CollectorManager& getCollectorManager () override
|
||||
{
|
||||
return *m_collectorManager;
|
||||
@@ -555,18 +547,6 @@ public:
|
||||
return *m_networkOPs;
|
||||
}
|
||||
|
||||
Config const&
|
||||
config() const override
|
||||
{
|
||||
return *config_;
|
||||
}
|
||||
|
||||
Logs&
|
||||
logs() override
|
||||
{
|
||||
return *logs_;
|
||||
}
|
||||
|
||||
boost::asio::io_service& getIOService () override
|
||||
{
|
||||
return get_io_service();
|
||||
@@ -702,12 +682,6 @@ public:
|
||||
return *m_overlay;
|
||||
}
|
||||
|
||||
// VFALCO TODO Move these to the .cpp
|
||||
bool running () override
|
||||
{
|
||||
return mTxnDB != nullptr;
|
||||
}
|
||||
|
||||
DatabaseCon& getTxnDB () override
|
||||
{
|
||||
assert (mTxnDB.get() != nullptr);
|
||||
@@ -724,12 +698,6 @@ public:
|
||||
return *mWalletDB;
|
||||
}
|
||||
|
||||
bool isShutdown () override
|
||||
{
|
||||
// from Stoppable mixin
|
||||
return isStopped();
|
||||
}
|
||||
|
||||
bool serverOkay (std::string& reason) override;
|
||||
|
||||
beast::Journal journal (std::string const& name) override;
|
||||
@@ -774,12 +742,145 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// VFALCO TODO Break this function up into many small initialization segments.
|
||||
// Or better yet refactor these initializations into RAII classes
|
||||
// which are members of the Application object.
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
void setup () override
|
||||
// Stoppable
|
||||
//
|
||||
|
||||
void onPrepare() override
|
||||
{
|
||||
}
|
||||
|
||||
void onStart () override
|
||||
{
|
||||
m_journal.info << "Application starting. Build is " << gitCommitID();
|
||||
|
||||
m_sweepTimer.setExpiration (10);
|
||||
m_entropyTimer.setRecurringExpiration (300);
|
||||
|
||||
m_io_latency_sampler.start();
|
||||
|
||||
m_resolver->start ();
|
||||
}
|
||||
|
||||
// Called to indicate shutdown.
|
||||
void onStop () override
|
||||
{
|
||||
m_journal.debug << "Application stopping";
|
||||
|
||||
m_io_latency_sampler.cancel_async ();
|
||||
|
||||
// VFALCO Enormous hack, we have to force the probe to cancel
|
||||
// before we stop the io_service queue or else it never
|
||||
// unblocks in its destructor. The fix is to make all
|
||||
// io_objects gracefully handle exit so that we can
|
||||
// naturally return from io_service::run() instead of
|
||||
// forcing a call to io_service::stop()
|
||||
m_io_latency_sampler.cancel ();
|
||||
|
||||
m_resolver->stop_async ();
|
||||
|
||||
// NIKB This is a hack - we need to wait for the resolver to
|
||||
// stop. before we stop the io_server_queue or weird
|
||||
// things will happen.
|
||||
m_resolver->stop ();
|
||||
|
||||
m_sweepTimer.cancel ();
|
||||
|
||||
m_entropyTimer.cancel ();
|
||||
|
||||
mValidations->flush ();
|
||||
|
||||
m_overlay->saveValidatorKeyManifests (getWalletDB ());
|
||||
|
||||
stopped ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// PropertyStream
|
||||
//
|
||||
|
||||
void onWrite (beast::PropertyStream::Map& stream) override
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void exitWithCode(int code)
|
||||
{
|
||||
StopSustain();
|
||||
// VFALCO This breaks invariants: automatic objects
|
||||
// will not have destructors called.
|
||||
std::exit(code);
|
||||
}
|
||||
|
||||
void onDeadlineTimer (beast::DeadlineTimer& timer) override
|
||||
{
|
||||
if (timer == m_entropyTimer)
|
||||
{
|
||||
add_entropy (nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer == m_sweepTimer)
|
||||
{
|
||||
// VFALCO TODO Move all this into doSweep
|
||||
|
||||
boost::filesystem::space_info space =
|
||||
boost::filesystem::space (config_->legacy ("database_path"));
|
||||
|
||||
// VFALCO TODO Give this magic constant a name and move it into a well documented header
|
||||
//
|
||||
if (space.available < (512 * 1024 * 1024))
|
||||
{
|
||||
m_journal.fatal << "Remaining free disk space is less than 512MB";
|
||||
signalStop ();
|
||||
}
|
||||
|
||||
m_jobQueue->addJob(jtSWEEP, "sweep", [this] (Job&) { doSweep(); });
|
||||
}
|
||||
}
|
||||
|
||||
void doSweep ()
|
||||
{
|
||||
// VFALCO NOTE Does the order of calls matter?
|
||||
// VFALCO TODO fix the dependency inversion using an observer,
|
||||
// have listeners register for "onSweep ()" notification.
|
||||
|
||||
family().fullbelow().sweep ();
|
||||
getMasterTransaction().sweep();
|
||||
getNodeStore().sweep();
|
||||
getLedgerMaster().sweep();
|
||||
getTempNodeCache().sweep();
|
||||
getValidations().sweep();
|
||||
getInboundLedgers().sweep();
|
||||
m_acceptedLedgerCache.sweep();
|
||||
family().treecache().sweep();
|
||||
cachedSLEs_.expire();
|
||||
|
||||
// VFALCO NOTE does the call to sweep() happen on another thread?
|
||||
m_sweepTimer.setExpiration (config_->getSize (siSweepInterval));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void addTxnSeqField();
|
||||
void updateTables ();
|
||||
void startGenesisLedger ();
|
||||
Ledger::pointer getLastFullLedger();
|
||||
bool loadOldLedger (
|
||||
std::string const& ledgerID, bool replay, bool isFilename);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// VFALCO TODO Break this function up into many small initialization segments.
|
||||
// Or better yet refactor these initializations into RAII classes
|
||||
// which are members of the Application object.
|
||||
//
|
||||
void ApplicationImp::setup()
|
||||
{
|
||||
// VFALCO NOTE: 0 means use heuristics to determine the thread count.
|
||||
m_jobQueue->setThreadCount (0, config_->RUN_STANDALONE);
|
||||
|
||||
@@ -951,75 +1052,11 @@ public:
|
||||
|
||||
m_networkOPs->setStandAlone ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Stoppable
|
||||
//
|
||||
|
||||
void onPrepare() override
|
||||
{
|
||||
}
|
||||
|
||||
void onStart () override
|
||||
{
|
||||
m_journal.info << "Application starting. Build is " << gitCommitID();
|
||||
|
||||
m_sweepTimer.setExpiration (10);
|
||||
m_entropyTimer.setRecurringExpiration (300);
|
||||
|
||||
m_io_latency_sampler.start();
|
||||
|
||||
m_resolver->start ();
|
||||
}
|
||||
|
||||
// Called to indicate shutdown.
|
||||
void onStop () override
|
||||
{
|
||||
m_journal.debug << "Application stopping";
|
||||
|
||||
m_io_latency_sampler.cancel_async ();
|
||||
|
||||
// VFALCO Enormous hack, we have to force the probe to cancel
|
||||
// before we stop the io_service queue or else it never
|
||||
// unblocks in its destructor. The fix is to make all
|
||||
// io_objects gracefully handle exit so that we can
|
||||
// naturally return from io_service::run() instead of
|
||||
// forcing a call to io_service::stop()
|
||||
m_io_latency_sampler.cancel ();
|
||||
|
||||
m_resolver->stop_async ();
|
||||
|
||||
// NIKB This is a hack - we need to wait for the resolver to
|
||||
// stop. before we stop the io_server_queue or weird
|
||||
// things will happen.
|
||||
m_resolver->stop ();
|
||||
|
||||
m_sweepTimer.cancel ();
|
||||
|
||||
m_entropyTimer.cancel ();
|
||||
|
||||
mValidations->flush ();
|
||||
|
||||
m_overlay->saveValidatorKeyManifests (getWalletDB ());
|
||||
|
||||
stopped ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// PropertyStream
|
||||
//
|
||||
|
||||
void onWrite (beast::PropertyStream::Map& stream) override
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void run () override
|
||||
{
|
||||
void
|
||||
ApplicationImp::run()
|
||||
{
|
||||
// VFALCO NOTE I put this here in the hopes that when unit tests run (which
|
||||
// tragically require an Application object to exist or else they
|
||||
// crash), the run() function will not get called and we will
|
||||
@@ -1047,84 +1084,27 @@ public:
|
||||
stop (m_journal);
|
||||
m_journal.info << "Done.";
|
||||
StopSustain();
|
||||
}
|
||||
}
|
||||
|
||||
void exitWithCode(int code)
|
||||
{
|
||||
StopSustain();
|
||||
// VFALCO This breaks invariants: automatic objects
|
||||
// will not have destructors called.
|
||||
std::exit(code);
|
||||
}
|
||||
|
||||
void signalStop () override
|
||||
{
|
||||
void
|
||||
ApplicationImp::signalStop()
|
||||
{
|
||||
// Unblock the main thread (which is sitting in run()).
|
||||
//
|
||||
m_stop.signal();
|
||||
}
|
||||
}
|
||||
|
||||
void onDeadlineTimer (beast::DeadlineTimer& timer) override
|
||||
{
|
||||
if (timer == m_entropyTimer)
|
||||
{
|
||||
add_entropy (nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timer == m_sweepTimer)
|
||||
{
|
||||
// VFALCO TODO Move all this into doSweep
|
||||
|
||||
boost::filesystem::space_info space =
|
||||
boost::filesystem::space (config_->legacy ("database_path"));
|
||||
|
||||
// VFALCO TODO Give this magic constant a name and move it into a well documented header
|
||||
//
|
||||
if (space.available < (512 * 1024 * 1024))
|
||||
{
|
||||
m_journal.fatal << "Remaining free disk space is less than 512MB";
|
||||
signalStop ();
|
||||
}
|
||||
|
||||
m_jobQueue->addJob(jtSWEEP, "sweep", [this] (Job&) { doSweep(); });
|
||||
}
|
||||
}
|
||||
|
||||
void doSweep ()
|
||||
{
|
||||
// VFALCO NOTE Does the order of calls matter?
|
||||
// VFALCO TODO fix the dependency inversion using an observer,
|
||||
// have listeners register for "onSweep ()" notification.
|
||||
|
||||
family().fullbelow().sweep ();
|
||||
getMasterTransaction().sweep();
|
||||
getNodeStore().sweep();
|
||||
getLedgerMaster().sweep();
|
||||
getTempNodeCache().sweep();
|
||||
getValidations().sweep();
|
||||
getInboundLedgers().sweep();
|
||||
m_acceptedLedgerCache.sweep();
|
||||
family().treecache().sweep();
|
||||
cachedSLEs_.expire();
|
||||
|
||||
// VFALCO NOTE does the call to sweep() happen on another thread?
|
||||
m_sweepTimer.setExpiration (config_->getSize (siSweepInterval));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void addTxnSeqField();
|
||||
void updateTables ();
|
||||
void startGenesisLedger ();
|
||||
Ledger::pointer getLastFullLedger();
|
||||
bool loadOldLedger (
|
||||
std::string const& ledgerID, bool replay, bool isFilename);
|
||||
};
|
||||
bool
|
||||
ApplicationImp::isShutdown()
|
||||
{
|
||||
// from Stoppable mixin
|
||||
return isStopped();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ApplicationImp::startGenesisLedger ()
|
||||
void
|
||||
ApplicationImp::startGenesisLedger()
|
||||
{
|
||||
std::shared_ptr<Ledger> const genesis =
|
||||
std::make_shared<Ledger>(
|
||||
@@ -1485,14 +1465,17 @@ bool ApplicationImp::serverOkay (std::string& reason)
|
||||
return true;
|
||||
}
|
||||
|
||||
beast::Journal ApplicationImp::journal (std::string const& name)
|
||||
beast::Journal
|
||||
ApplicationImp::journal (std::string const& name)
|
||||
{
|
||||
return logs_->journal (name);
|
||||
}
|
||||
|
||||
//VFALCO TODO clean this up since it is just a file holding a single member function definition
|
||||
|
||||
static std::vector<std::string> getSchema (DatabaseCon& dbc, std::string const& dbName)
|
||||
static
|
||||
std::vector<std::string>
|
||||
getSchema (DatabaseCon& dbc, std::string const& dbName)
|
||||
{
|
||||
std::vector<std::string> schema;
|
||||
schema.reserve(32);
|
||||
@@ -1653,6 +1636,8 @@ Application::Application ()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<Application>
|
||||
make_Application (
|
||||
std::unique_ptr<Config const> config,
|
||||
@@ -1662,9 +1647,14 @@ make_Application (
|
||||
std::move(config), std::move(logs));
|
||||
}
|
||||
|
||||
Application& getApp ()
|
||||
void
|
||||
setupConfigForUnitTests (Config& config)
|
||||
{
|
||||
return ApplicationImpBase::getInstance ();
|
||||
config.overwrite (ConfigSection::nodeDatabase (), "type", "memory");
|
||||
config.overwrite (ConfigSection::nodeDatabase (), "path", "main");
|
||||
|
||||
config.deprecatedClearSection (ConfigSection::importNodeDatabase ());
|
||||
config.legacy("database_path", "DummyForUnitTests");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -90,8 +90,18 @@ public:
|
||||
Application ();
|
||||
|
||||
virtual ~Application () = default;
|
||||
virtual Config const& config() const = 0;
|
||||
|
||||
virtual void setup() = 0;
|
||||
virtual void run() = 0;
|
||||
virtual bool isShutdown () = 0;
|
||||
virtual void signalStop () = 0;
|
||||
|
||||
//
|
||||
// ---
|
||||
//
|
||||
|
||||
virtual Logs& logs() = 0;
|
||||
virtual Config const& config() const = 0;
|
||||
virtual boost::asio::io_service& getIOService () = 0;
|
||||
virtual CollectorManager& getCollectorManager () = 0;
|
||||
virtual Family& family() = 0;
|
||||
@@ -138,12 +148,6 @@ public:
|
||||
// NOTE This will be replaced by class Validators
|
||||
//
|
||||
virtual DatabaseCon& getWalletDB () = 0;
|
||||
|
||||
virtual bool isShutdown () = 0;
|
||||
virtual bool running () = 0;
|
||||
virtual void setup () = 0;
|
||||
virtual void run () = 0;
|
||||
virtual void signalStop () = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr <Application>
|
||||
@@ -151,8 +155,9 @@ make_Application(
|
||||
std::unique_ptr<Config const> config,
|
||||
std::unique_ptr<Logs> logs);
|
||||
|
||||
// DEPRECATED
|
||||
extern Application& getApp ();
|
||||
extern
|
||||
void
|
||||
setupConfigForUnitTests (Config& config);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -162,17 +162,6 @@ void printHelp (const po::options_description& desc)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static
|
||||
void
|
||||
setupConfigForUnitTests (Config& config)
|
||||
{
|
||||
config.overwrite (ConfigSection::nodeDatabase (), "type", "memory");
|
||||
config.overwrite (ConfigSection::nodeDatabase (), "path", "main");
|
||||
|
||||
config.deprecatedClearSection (ConfigSection::importNodeDatabase ());
|
||||
config.legacy("database_path", "DummyForUnitTests");
|
||||
}
|
||||
|
||||
static int runShutdownTests (std::unique_ptr<Config> config)
|
||||
{
|
||||
// Shutdown tests can not be part of the normal unit tests in 'runUnitTests'
|
||||
@@ -204,18 +193,10 @@ static int runShutdownTests (std::unique_ptr<Config> config)
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int runUnitTests (
|
||||
std::unique_ptr<Config> config,
|
||||
static int runUnitTests(
|
||||
std::string const& pattern,
|
||||
std::string const& argument)
|
||||
{
|
||||
// Config needs to be set up before creating Application
|
||||
setupConfigForUnitTests (*config);
|
||||
|
||||
auto app = make_Application (
|
||||
std::move(config),
|
||||
std::make_unique<Logs>());
|
||||
|
||||
using namespace beast::unit_test;
|
||||
beast::debug_ostream stream;
|
||||
reporter r (stream);
|
||||
@@ -363,9 +344,7 @@ int run (int argc, char** argv)
|
||||
argument = vm["unittest-arg"].as<std::string>();
|
||||
|
||||
return runUnitTests(
|
||||
std::make_unique<Config> (),
|
||||
vm["unittest"].as<std::string>(),
|
||||
argument);
|
||||
vm["unittest"].as<std::string>(), argument);
|
||||
}
|
||||
|
||||
auto config = std::make_unique<Config>();
|
||||
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
env.require (owners (alice, 4));
|
||||
|
||||
// This should work.
|
||||
auto const baseFee = env.config.FEE_DEFAULT;
|
||||
auto const baseFee = env.app().config().FEE_DEFAULT;
|
||||
std::uint32_t aliceSeq = env.seq (alice);
|
||||
env(noop(alice), msig(bogie, demon), fee(3 * baseFee));
|
||||
env.close();
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
|
||||
// alice multisigns a transaction. Should succeed.
|
||||
std::uint32_t aliceSeq = env.seq (alice);
|
||||
auto const baseFee = env.config.FEE_DEFAULT;
|
||||
auto const baseFee = env.app().config().FEE_DEFAULT;
|
||||
env(noop(alice), msig(bogie), fee(2 * baseFee));
|
||||
env.close();
|
||||
expect (env.seq(alice) == aliceSeq + 1);
|
||||
@@ -265,7 +265,7 @@ public:
|
||||
env.require (owners (alice, 10));
|
||||
|
||||
// This should work.
|
||||
auto const baseFee = env.config.FEE_DEFAULT;
|
||||
auto const baseFee = env.app().config().FEE_DEFAULT;
|
||||
std::uint32_t aliceSeq = env.seq (alice);
|
||||
env(noop(alice), msig(bogie), fee(2 * baseFee));
|
||||
env.close();
|
||||
@@ -348,7 +348,7 @@ public:
|
||||
env.require (owners (alice, 4));
|
||||
|
||||
// Attempt a multisigned transaction that meets the quorum.
|
||||
auto const baseFee = env.config.FEE_DEFAULT;
|
||||
auto const baseFee = env.app().config().FEE_DEFAULT;
|
||||
aliceSeq = env.seq (alice);
|
||||
env(noop(alice), msig(cheri), fee(2 * baseFee));
|
||||
env.close();
|
||||
@@ -401,7 +401,7 @@ public:
|
||||
env.close();
|
||||
|
||||
// Attempt a multisigned transaction that meets the quorum.
|
||||
auto const baseFee = env.config.FEE_DEFAULT;
|
||||
auto const baseFee = env.app().config().FEE_DEFAULT;
|
||||
std::uint32_t aliceSeq = env.seq (alice);
|
||||
env(noop(alice), msig(msig::Reg{cheri, cher}), fee(2 * baseFee));
|
||||
env.close();
|
||||
@@ -468,7 +468,7 @@ public:
|
||||
env.require (owners (alice, 6));
|
||||
|
||||
// Each type of signer should succeed individually.
|
||||
auto const baseFee = env.config.FEE_DEFAULT;
|
||||
auto const baseFee = env.app().config().FEE_DEFAULT;
|
||||
std::uint32_t aliceSeq = env.seq (alice);
|
||||
env(noop(alice), msig(becky), fee(2 * baseFee));
|
||||
env.close();
|
||||
@@ -592,7 +592,7 @@ public:
|
||||
env(regkey (alice, disabled), sig(alie));
|
||||
|
||||
// L0; A lone signer list cannot be removed.
|
||||
auto const baseFee = env.config.FEE_DEFAULT;
|
||||
auto const baseFee = env.app().config().FEE_DEFAULT;
|
||||
env(signers(alice, jtx::none), msig(bogie),
|
||||
fee(2 * baseFee), ter(tecNO_ALTERNATIVE_KEY));
|
||||
|
||||
@@ -645,7 +645,7 @@ public:
|
||||
env.require (owners (alice, 4));
|
||||
|
||||
// Multisign a ttPAYMENT.
|
||||
auto const baseFee = env.config.FEE_DEFAULT;
|
||||
auto const baseFee = env.app().config().FEE_DEFAULT;
|
||||
std::uint32_t aliceSeq = env.seq (alice);
|
||||
env(pay(alice, env.master, XRP(1)),
|
||||
msig(becky, bogie), fee(3 * baseFee));
|
||||
|
||||
@@ -49,7 +49,7 @@ struct Regression_test : public beast::unit_test::suite
|
||||
// be reproduced against an open ledger. Make a local
|
||||
// closed ledger and work with it directly.
|
||||
auto closed = std::make_shared<Ledger>(
|
||||
create_genesis, env.config, env.app().family());
|
||||
create_genesis, env.app().config(), env.app().family());
|
||||
auto expectedDrops = SYSTEM_CURRENCY_START;
|
||||
expect(closed->info().drops == expectedDrops);
|
||||
|
||||
@@ -67,7 +67,7 @@ struct Regression_test : public beast::unit_test::suite
|
||||
|
||||
auto const result = ripple::apply(env.app(),
|
||||
accum, *jt.stx, tapENABLE_TESTING,
|
||||
directSigVerify, env.config,
|
||||
directSigVerify, env.app().config(),
|
||||
env.journal);
|
||||
expect(result.first == tesSUCCESS);
|
||||
expect(result.second);
|
||||
@@ -95,7 +95,7 @@ struct Regression_test : public beast::unit_test::suite
|
||||
|
||||
auto const result = ripple::apply(env.app(),
|
||||
accum, *jt.stx, tapENABLE_TESTING,
|
||||
directSigVerify, env.config,
|
||||
directSigVerify, env.app().config(),
|
||||
env.journal);
|
||||
expect(result.first == tecINSUFF_FEE);
|
||||
expect(result.second);
|
||||
|
||||
@@ -175,6 +175,9 @@ public:
|
||||
If the section does not exist, an empty section is returned.
|
||||
*/
|
||||
/** @{ */
|
||||
Section&
|
||||
section (std::string const& name);
|
||||
|
||||
Section const&
|
||||
section (std::string const& name) const;
|
||||
|
||||
@@ -183,6 +186,12 @@ public:
|
||||
{
|
||||
return section(name);
|
||||
}
|
||||
|
||||
Section&
|
||||
operator[] (std::string const& name)
|
||||
{
|
||||
return section(name);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Overwrite a key/value pair with a command line argument
|
||||
|
||||
@@ -96,6 +96,12 @@ BasicConfig::exists (std::string const& name) const
|
||||
return map_.find(name) != map_.end();
|
||||
}
|
||||
|
||||
Section&
|
||||
BasicConfig::section (std::string const& name)
|
||||
{
|
||||
return map_[name];
|
||||
}
|
||||
|
||||
Section const&
|
||||
BasicConfig::section (std::string const& name) const
|
||||
{
|
||||
|
||||
@@ -162,9 +162,7 @@ public:
|
||||
beast::File getModuleDatabasePath () const;
|
||||
|
||||
bool doImport = false;
|
||||
|
||||
bool QUIET = false;
|
||||
|
||||
bool ELB_SUPPORT = false;
|
||||
|
||||
std::string VALIDATORS_SITE; // Where to find validators.txt on the Internet.
|
||||
|
||||
@@ -47,13 +47,8 @@ public:
|
||||
Account (Account const&) = default;
|
||||
Account& operator= (Account const&) = default;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
Account (Account&&);
|
||||
Account& operator= (Account&&);
|
||||
#else
|
||||
Account (Account&&) = default;
|
||||
Account& operator= (Account&&) = default;
|
||||
#endif
|
||||
|
||||
/** Create an account from a key pair. */
|
||||
Account (std::string name,
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/ledger/OpenLedger.h>
|
||||
#include <ripple/basics/chrono.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
@@ -126,13 +127,21 @@ public:
|
||||
|
||||
beast::Journal const journal;
|
||||
|
||||
/** Configuration used. */
|
||||
Config const config;
|
||||
|
||||
/** The master account. */
|
||||
Account const master;
|
||||
|
||||
private:
|
||||
struct AppBundle
|
||||
{
|
||||
Application* app;
|
||||
std::unique_ptr<Logs> logs;
|
||||
std::unique_ptr<Application> owned;
|
||||
|
||||
AppBundle (std::unique_ptr<Config const> config);
|
||||
AppBundle (Application* app_);
|
||||
};
|
||||
|
||||
AppBundle bundle_;
|
||||
std::shared_ptr<Ledger const> closed_;
|
||||
CachedSLEs cachedSLEs_;
|
||||
LogSquelcher logSquelcher_;
|
||||
@@ -150,7 +159,7 @@ public:
|
||||
Application&
|
||||
app()
|
||||
{
|
||||
return getApp();
|
||||
return *bundle_.app;
|
||||
}
|
||||
|
||||
/** Returns the open ledger.
|
||||
|
||||
@@ -26,28 +26,6 @@ namespace ripple {
|
||||
namespace test {
|
||||
namespace jtx {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
Account::Account (Account&& other)
|
||||
: name_(std::move(other.name_))
|
||||
, pk_(std::move(other.pk_))
|
||||
, sk_(std::move(other.sk_))
|
||||
, id_(std::move(other.id_))
|
||||
, human_(std::move(other.human_))
|
||||
{
|
||||
}
|
||||
|
||||
Account&
|
||||
Account::operator= (Account&& rhs)
|
||||
{
|
||||
name_ = std::move(rhs.name_);
|
||||
pk_ = std::move(rhs.pk_);
|
||||
sk_ = std::move(rhs.sk_);
|
||||
id_ = std::move(rhs.id_);
|
||||
human_ = std::move(rhs.human_);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
Account::Account(std::string name,
|
||||
std::pair<PublicKey, SecretKey> const& keys)
|
||||
: name_(std::move(name))
|
||||
@@ -58,16 +36,15 @@ Account::Account(std::string name,
|
||||
{
|
||||
}
|
||||
|
||||
Account::Account (std::string name,
|
||||
KeyType type)
|
||||
#ifndef _MSC_VER
|
||||
: Account(name,
|
||||
#else
|
||||
// Fails on Clang and possibly gcc
|
||||
: Account(std::move(name),
|
||||
#endif
|
||||
generateKeyPair(type, generateSeed(name)))
|
||||
Account::Account (std::string name, KeyType type)
|
||||
: name_(std::move(name))
|
||||
{
|
||||
auto const keys = generateKeyPair(
|
||||
type, generateSeed(name_));
|
||||
pk_ = keys.first;
|
||||
sk_ = keys.second;
|
||||
id_ = calcAccountID(pk_);
|
||||
human_ = toBase58(id_);
|
||||
}
|
||||
|
||||
IOU
|
||||
|
||||
@@ -50,17 +50,41 @@ namespace test {
|
||||
|
||||
namespace jtx {
|
||||
|
||||
Env::AppBundle::AppBundle(Application* app_)
|
||||
: app (app_)
|
||||
{
|
||||
}
|
||||
|
||||
Env::AppBundle::AppBundle(std::unique_ptr<Config const> config)
|
||||
{
|
||||
auto logs = std::make_unique<Logs>();
|
||||
owned = make_Application(
|
||||
std::move(config), std::move(logs));
|
||||
app = owned.get();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static
|
||||
std::unique_ptr<Config const>
|
||||
makeConfig()
|
||||
{
|
||||
auto p = std::make_unique<Config>();
|
||||
setupConfigForUnitTests(*p);
|
||||
return std::unique_ptr<Config const>(p.release());
|
||||
}
|
||||
|
||||
// VFALCO Could wrap the log in a Journal here
|
||||
Env::Env (beast::unit_test::suite& test_)
|
||||
: test(test_)
|
||||
, config()
|
||||
, master("master", generateKeyPair(
|
||||
: test (test_)
|
||||
, master ("master", generateKeyPair(
|
||||
KeyType::secp256k1,
|
||||
generateSeed("masterpassphrase")))
|
||||
, bundle_ (makeConfig())
|
||||
, closed_ (std::make_shared<Ledger>(
|
||||
create_genesis, config, app().family()))
|
||||
create_genesis, app().config(), app().family()))
|
||||
, cachedSLEs_ (std::chrono::seconds(5), stopwatch_)
|
||||
, openLedger (closed_, config, cachedSLEs_, journal)
|
||||
, openLedger (closed_, app().config(), cachedSLEs_, journal)
|
||||
{
|
||||
memoize(master);
|
||||
initializePathfinding();
|
||||
@@ -98,7 +122,7 @@ Env::close(NetClock::time_point const& closeTime)
|
||||
OpenView accum(&*next);
|
||||
OpenLedger::apply(app(), accum, *closed_,
|
||||
txs, retries, applyFlags(), *router,
|
||||
config, journal);
|
||||
app().config(), journal);
|
||||
accum.apply(*next);
|
||||
}
|
||||
// To ensure that the close time is exact and not rounded, we don't
|
||||
@@ -254,7 +278,7 @@ Env::submit (JTx const& jt)
|
||||
{
|
||||
std::tie(ter_, didApply) = ripple::apply(
|
||||
app(), view, *stx, applyFlags(),
|
||||
directSigVerify, config,
|
||||
directSigVerify, app().config(),
|
||||
beast::Journal{});
|
||||
return didApply;
|
||||
});
|
||||
|
||||
@@ -360,7 +360,7 @@ public:
|
||||
{ { "bob", 1 }, { "carol", 2 } }));
|
||||
env(noop("alice"));
|
||||
|
||||
auto const baseFee = env.config.FEE_DEFAULT;
|
||||
auto const baseFee = env.app().config().FEE_DEFAULT;
|
||||
env(noop("alice"), msig("bob"), fee(2 * baseFee));
|
||||
env(noop("alice"), msig("carol"), fee(2 * baseFee));
|
||||
env(noop("alice"), msig("bob", "carol"), fee(3 * baseFee));
|
||||
|
||||
27
src/ripple/test/mao.h
Normal file
27
src/ripple/test/mao.h
Normal file
@@ -0,0 +1,27 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TEST_MAO_H_INCLUDED
|
||||
#define RIPPLE_TEST_MAO_H_INCLUDED
|
||||
|
||||
// Convenience header that includes everything
|
||||
|
||||
#include <ripple/test/mao/Net.h>
|
||||
|
||||
#endif
|
||||
39
src/ripple/test/mao/Net.h
Normal file
39
src/ripple/test/mao/Net.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TEST_MAO_H_INCLUDED
|
||||
#define RIPPLE_TEST_MAO_H_INCLUDED
|
||||
|
||||
#include <ripple/app/main/Application.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
namespace mao {
|
||||
|
||||
class Net
|
||||
{
|
||||
private:
|
||||
public:
|
||||
};
|
||||
|
||||
} // mao
|
||||
} // test
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
31
src/ripple/test/mao/impl/Net.cpp
Normal file
31
src/ripple/test/mao/impl/Net.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/test/mao/Net.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
namespace mao {
|
||||
|
||||
|
||||
|
||||
} // mao
|
||||
} // test
|
||||
} // ripple
|
||||
145
src/ripple/test/mao/impl/Net_test.cpp
Normal file
145
src/ripple/test/mao/impl/Net_test.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/test/mao/Net.h>
|
||||
#include <ripple/net/HTTPClient.h>
|
||||
#include <ripple/net/RPCCall.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
namespace mao {
|
||||
|
||||
struct TestApp
|
||||
{
|
||||
TestApp()
|
||||
{
|
||||
auto config = std::make_unique<Config>();
|
||||
setupConfigForUnitTests(*config);
|
||||
config->RUN_STANDALONE = true;
|
||||
(*config)["server"].append("port_peer");
|
||||
(*config)["port_peer"].set("ip", "127.0.0.1");
|
||||
(*config)["port_peer"].set("port", "8080");
|
||||
(*config)["port_peer"].set("protocol", "peer");
|
||||
(*config)["server"].append("port_admin");
|
||||
(*config)["port_admin"].set("ip", "127.0.0.1");
|
||||
(*config)["port_admin"].set("port", "8081");
|
||||
(*config)["port_admin"].set("protocol", "http");
|
||||
(*config)["port_admin"].set("admin", "127.0.0.1");
|
||||
// Hack so we dont have to call Config::setup
|
||||
HTTPClient::initializeSSLContext(*config);
|
||||
auto logs = std::make_unique<Logs>();
|
||||
instance = make_Application(
|
||||
std::move(config), std::move(logs));
|
||||
instance->setup();
|
||||
thread_ = std::thread(
|
||||
[&]() { instance->run(); });
|
||||
}
|
||||
|
||||
~TestApp()
|
||||
{
|
||||
if (thread_.joinable())
|
||||
{
|
||||
instance->signalStop();
|
||||
thread_.join();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
join()
|
||||
{
|
||||
thread_.join();
|
||||
}
|
||||
|
||||
Application*
|
||||
operator->()
|
||||
{
|
||||
return instance.get();
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
void
|
||||
rpc (T const& t, Args const&... args)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
collect(v, t, args...);
|
||||
RPCCall::fromCommandLine(
|
||||
instance->config(), v,
|
||||
instance->logs());
|
||||
}
|
||||
|
||||
private:
|
||||
inline
|
||||
void
|
||||
collect (std::vector<std::string>& v)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
void
|
||||
collect (std::vector<std::string>& v,
|
||||
T const& t, Args const&... args)
|
||||
{
|
||||
v.emplace_back(t);
|
||||
collect(v, args...);
|
||||
}
|
||||
|
||||
std::unique_ptr<Application> instance;
|
||||
std::thread thread_;
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
||||
class Net_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testStartStop()
|
||||
{
|
||||
TestApp app;
|
||||
pass();
|
||||
}
|
||||
|
||||
void
|
||||
testRPC()
|
||||
{
|
||||
TestApp app;
|
||||
app.rpc("stop");
|
||||
app.join();
|
||||
pass();
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testStartStop();
|
||||
testRPC();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(Net,mao,ripple)
|
||||
|
||||
} // mao
|
||||
} // test
|
||||
} // ripple
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <ripple/test/jtx/impl/balance.cpp>
|
||||
#include <ripple/test/jtx/impl/delivermin.cpp>
|
||||
#include <ripple/test/jtx/impl/Env.cpp>
|
||||
#include <ripple/test/jtx/impl/Env_test.cpp>
|
||||
#include <ripple/test/jtx/impl/fee.cpp>
|
||||
#include <ripple/test/jtx/impl/flags.cpp>
|
||||
#include <ripple/test/jtx/impl/jtx_json.cpp>
|
||||
@@ -44,4 +45,6 @@
|
||||
#include <ripple/test/jtx/impl/txflags.cpp>
|
||||
#include <ripple/test/jtx/impl/utility.cpp>
|
||||
|
||||
#include <ripple/test/jtx/impl/Env_test.cpp>
|
||||
#include <ripple/test/mao/impl/Net.cpp>
|
||||
#include <ripple/test/mao/impl/Net_test.cpp>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user