diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj index e5fbd1eceb..40b4967b0b 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj +++ b/Builds/VisualStudio2015/RippleD.vcxproj @@ -3760,6 +3760,16 @@ + + True + True + + + True + True + + + True True diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters index dbe9081d3d..a7d3c809de 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters @@ -421,6 +421,12 @@ {27D70888-7145-691C-0E0A-E511EB3A80A2} + + {94B5035A-6D4A-E4FC-DB50-E7E804DC9F13} + + + {23DE6C05-81D2-7471-D9BB-3AA1D49DE429} + {5DB3CD0B-B361-B301-9562-697CA8A52B68} @@ -4437,6 +4443,15 @@ ripple\test\jtx + + ripple\test\mao\impl + + + ripple\test\mao\impl + + + ripple\test\mao + ripple\unity diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index 899a2bd30d..24bf557b7a 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -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,185 +742,6 @@ 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 - { - // VFALCO NOTE: 0 means use heuristics to determine the thread count. - m_jobQueue->setThreadCount (0, config_->RUN_STANDALONE); - - // We want to intercept and wait for CTRL-C to terminate the process - m_signals.add (SIGINT); - - m_signals.async_wait(std::bind(&ApplicationImp::signalled, this, - std::placeholders::_1, std::placeholders::_2)); - - assert (mTxnDB == nullptr); - - auto debug_log = config_->getDebugLogFile (); - - if (!debug_log.empty ()) - { - // Let debug messages go to the file but only WARNING or higher to - // regular output (unless verbose) - - if (!logs_->open(debug_log)) - std::cerr << "Can't open log file " << debug_log << '\n'; - - if (logs_->severity() > beast::Journal::kDebug) - logs_->severity (beast::Journal::kDebug); - } - - if (!config_->RUN_STANDALONE) - timeKeeper_->run(config_->SNTP_SERVERS); - - if (!initSqliteDbs ()) - { - m_journal.fatal << "Can not create database connections!"; - exitWithCode(3); - } - - getLedgerDB ().getSession () - << boost::str (boost::format ("PRAGMA cache_size=-%d;") % - (config_->getSize (siLgrDBCache) * 1024)); - - getTxnDB ().getSession () - << boost::str (boost::format ("PRAGMA cache_size=-%d;") % - (config_->getSize (siTxnDBCache) * 1024)); - - mTxnDB->setupCheckpointing (m_jobQueue.get(), logs()); - mLedgerDB->setupCheckpointing (m_jobQueue.get(), logs()); - - if (!config_->RUN_STANDALONE) - updateTables (); - - m_amendmentTable->addInitial ( - config_->section (SECTION_AMENDMENTS)); - initializePathfinding (); - - m_ledgerMaster->setMinValidations ( - config_->VALIDATION_QUORUM, config_->LOCK_QUORUM); - - auto const startUp = config_->START_UP; - if (startUp == Config::FRESH) - { - m_journal.info << "Starting new Ledger"; - - startGenesisLedger (); - } - else if (startUp == Config::LOAD || - startUp == Config::LOAD_FILE || - startUp == Config::REPLAY) - { - m_journal.info << "Loading specified Ledger"; - - if (!loadOldLedger (config_->START_LEDGER, - startUp == Config::REPLAY, - startUp == Config::LOAD_FILE)) - { - exitWithCode(-1); - } - } - else if (startUp == Config::NETWORK) - { - // This should probably become the default once we have a stable network. - if (!config_->RUN_STANDALONE) - m_networkOPs->needNetworkLedger (); - - startGenesisLedger (); - } - else - { - startGenesisLedger (); - } - - m_orderBookDB.setup (getLedgerMaster ().getCurrentLedger ()); - - // Begin validation and ip maintenance. - // - // - LocalCredentials maintains local information: including identity - // - and network connection persistence information. - // - // VFALCO NOTE this starts the UNL - m_localCredentials.start (); - - // - // Set up UNL. - // - if (!config_->RUN_STANDALONE) - getUNL ().nodeBootstrap (); - - mValidations->tune (config_->getSize (siValidationsSize), config_->getSize (siValidationsAge)); - m_nodeStore->tune (config_->getSize (siNodeCacheSize), config_->getSize (siNodeCacheAge)); - m_ledgerMaster->tune (config_->getSize (siLedgerSize), config_->getSize (siLedgerAge)); - family().treecache().setTargetSize (config_->getSize (siTreeCacheSize)); - family().treecache().setTargetAge (config_->getSize (siTreeCacheAge)); - - //---------------------------------------------------------------------- - // - // Server - // - //---------------------------------------------------------------------- - - // VFALCO NOTE Unfortunately, in stand-alone mode some code still - // foolishly calls overlay(). When this is fixed we can - // move the instantiation inside a conditional: - // - // if (!config_.RUN_STANDALONE) - m_overlay = make_Overlay (*this, setup_Overlay(*config_), *m_jobQueue, - *serverHandler_, *m_resourceManager, *m_resolver, get_io_service(), - *config_); - add (*m_overlay); // add to PropertyStream - - m_overlay->setupValidatorKeyManifests (*config_, getWalletDB ()); - - { - auto setup = setup_ServerHandler(*config_, std::cerr); - setup.makeContexts(); - serverHandler_->setup (setup, m_journal); - } - - // Create websocket servers. - for (auto const& port : serverHandler_->setup().ports) - { - if (! port.websockets()) - continue; - auto server = websocket::makeServer ( - {*this, port, *m_resourceManager, getOPs(), m_journal, *config_, - *m_collectorManager}); - if (!server) - { - m_journal.fatal << "Could not create Websocket for [" << - port.name << "]"; - throw std::exception(); - } - websocketServers_.emplace_back (std::move (server)); - } - - //---------------------------------------------------------------------- - - // Begin connecting to network. - if (!config_->RUN_STANDALONE) - { - // Should this message be here, conceptually? In theory this sort - // of message, if displayed, should be displayed from PeerFinder. - if (config_->PEER_PRIVATE && config_->IPS.empty ()) - m_journal.warning << "No outbound peer connections will be made"; - - // VFALCO NOTE the state timer resets the deadlock detector. - // - m_networkOPs->setStateTimer (); - } - else - { - m_journal.warning << "Running in standalone mode"; - - m_networkOPs->setStandAlone (); - } - } - //-------------------------------------------------------------------------- // // Stoppable @@ -1018,37 +807,6 @@ public: //------------------------------------------------------------------------------ - void run () override - { - // 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 - // avoid doing silly things like contacting the SNTP server, or - // running the various logic threads like Validators, PeerFinder, etc. - prepare (); - start (); - - - { - if (!config_->RUN_STANDALONE) - { - // VFALCO NOTE This seems unnecessary. If we properly refactor the load - // manager then the deadlock detector can just always be "armed" - // - getLoadManager ().activateDeadlockDetector (); - } - } - - m_stop.wait (); - - // Stop the server. When this returns, all - // Stoppable objects should be stopped. - m_journal.info << "Received shutdown request"; - stop (m_journal); - m_journal.info << "Done."; - StopSustain(); - } - void exitWithCode(int code) { StopSustain(); @@ -1057,13 +815,6 @@ public: std::exit(code); } - void signalStop () override - { - // Unblock the main thread (which is sitting in run()). - // - m_stop.signal(); - } - void onDeadlineTimer (beast::DeadlineTimer& timer) override { if (timer == m_entropyTimer) @@ -1124,7 +875,236 @@ private: //------------------------------------------------------------------------------ -void ApplicationImp::startGenesisLedger () +// 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); + + // We want to intercept and wait for CTRL-C to terminate the process + m_signals.add (SIGINT); + + m_signals.async_wait(std::bind(&ApplicationImp::signalled, this, + std::placeholders::_1, std::placeholders::_2)); + + assert (mTxnDB == nullptr); + + auto debug_log = config_->getDebugLogFile (); + + if (!debug_log.empty ()) + { + // Let debug messages go to the file but only WARNING or higher to + // regular output (unless verbose) + + if (!logs_->open(debug_log)) + std::cerr << "Can't open log file " << debug_log << '\n'; + + if (logs_->severity() > beast::Journal::kDebug) + logs_->severity (beast::Journal::kDebug); + } + + if (!config_->RUN_STANDALONE) + timeKeeper_->run(config_->SNTP_SERVERS); + + if (!initSqliteDbs ()) + { + m_journal.fatal << "Can not create database connections!"; + exitWithCode(3); + } + + getLedgerDB ().getSession () + << boost::str (boost::format ("PRAGMA cache_size=-%d;") % + (config_->getSize (siLgrDBCache) * 1024)); + + getTxnDB ().getSession () + << boost::str (boost::format ("PRAGMA cache_size=-%d;") % + (config_->getSize (siTxnDBCache) * 1024)); + + mTxnDB->setupCheckpointing (m_jobQueue.get(), logs()); + mLedgerDB->setupCheckpointing (m_jobQueue.get(), logs()); + + if (!config_->RUN_STANDALONE) + updateTables (); + + m_amendmentTable->addInitial ( + config_->section (SECTION_AMENDMENTS)); + initializePathfinding (); + + m_ledgerMaster->setMinValidations ( + config_->VALIDATION_QUORUM, config_->LOCK_QUORUM); + + auto const startUp = config_->START_UP; + if (startUp == Config::FRESH) + { + m_journal.info << "Starting new Ledger"; + + startGenesisLedger (); + } + else if (startUp == Config::LOAD || + startUp == Config::LOAD_FILE || + startUp == Config::REPLAY) + { + m_journal.info << "Loading specified Ledger"; + + if (!loadOldLedger (config_->START_LEDGER, + startUp == Config::REPLAY, + startUp == Config::LOAD_FILE)) + { + exitWithCode(-1); + } + } + else if (startUp == Config::NETWORK) + { + // This should probably become the default once we have a stable network. + if (!config_->RUN_STANDALONE) + m_networkOPs->needNetworkLedger (); + + startGenesisLedger (); + } + else + { + startGenesisLedger (); + } + + m_orderBookDB.setup (getLedgerMaster ().getCurrentLedger ()); + + // Begin validation and ip maintenance. + // + // - LocalCredentials maintains local information: including identity + // - and network connection persistence information. + // + // VFALCO NOTE this starts the UNL + m_localCredentials.start (); + + // + // Set up UNL. + // + if (!config_->RUN_STANDALONE) + getUNL ().nodeBootstrap (); + + mValidations->tune (config_->getSize (siValidationsSize), config_->getSize (siValidationsAge)); + m_nodeStore->tune (config_->getSize (siNodeCacheSize), config_->getSize (siNodeCacheAge)); + m_ledgerMaster->tune (config_->getSize (siLedgerSize), config_->getSize (siLedgerAge)); + family().treecache().setTargetSize (config_->getSize (siTreeCacheSize)); + family().treecache().setTargetAge (config_->getSize (siTreeCacheAge)); + + //---------------------------------------------------------------------- + // + // Server + // + //---------------------------------------------------------------------- + + // VFALCO NOTE Unfortunately, in stand-alone mode some code still + // foolishly calls overlay(). When this is fixed we can + // move the instantiation inside a conditional: + // + // if (!config_.RUN_STANDALONE) + m_overlay = make_Overlay (*this, setup_Overlay(*config_), *m_jobQueue, + *serverHandler_, *m_resourceManager, *m_resolver, get_io_service(), + *config_); + add (*m_overlay); // add to PropertyStream + + m_overlay->setupValidatorKeyManifests (*config_, getWalletDB ()); + + { + auto setup = setup_ServerHandler(*config_, std::cerr); + setup.makeContexts(); + serverHandler_->setup (setup, m_journal); + } + + // Create websocket servers. + for (auto const& port : serverHandler_->setup().ports) + { + if (! port.websockets()) + continue; + auto server = websocket::makeServer ( + {*this, port, *m_resourceManager, getOPs(), m_journal, *config_, + *m_collectorManager}); + if (!server) + { + m_journal.fatal << "Could not create Websocket for [" << + port.name << "]"; + throw std::exception(); + } + websocketServers_.emplace_back (std::move (server)); + } + + //---------------------------------------------------------------------- + + // Begin connecting to network. + if (!config_->RUN_STANDALONE) + { + // Should this message be here, conceptually? In theory this sort + // of message, if displayed, should be displayed from PeerFinder. + if (config_->PEER_PRIVATE && config_->IPS.empty ()) + m_journal.warning << "No outbound peer connections will be made"; + + // VFALCO NOTE the state timer resets the deadlock detector. + // + m_networkOPs->setStateTimer (); + } + else + { + m_journal.warning << "Running in standalone mode"; + + m_networkOPs->setStandAlone (); + } +} + +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 + // avoid doing silly things like contacting the SNTP server, or + // running the various logic threads like Validators, PeerFinder, etc. + prepare (); + start (); + + + { + if (!config_->RUN_STANDALONE) + { + // VFALCO NOTE This seems unnecessary. If we properly refactor the load + // manager then the deadlock detector can just always be "armed" + // + getLoadManager ().activateDeadlockDetector (); + } + } + + m_stop.wait (); + + // Stop the server. When this returns, all + // Stoppable objects should be stopped. + m_journal.info << "Received shutdown request"; + stop (m_journal); + m_journal.info << "Done."; + StopSustain(); +} + +void +ApplicationImp::signalStop() +{ + // Unblock the main thread (which is sitting in run()). + // + m_stop.signal(); +} + +bool +ApplicationImp::isShutdown() +{ + // from Stoppable mixin + return isStopped(); +} + +//------------------------------------------------------------------------------ + +void +ApplicationImp::startGenesisLedger() { std::shared_ptr const genesis = std::make_shared( @@ -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 getSchema (DatabaseCon& dbc, std::string const& dbName) +static +std::vector +getSchema (DatabaseCon& dbc, std::string const& dbName) { std::vector schema; schema.reserve(32); @@ -1653,6 +1636,8 @@ Application::Application () { } +//------------------------------------------------------------------------------ + std::unique_ptr make_Application ( std::unique_ptr 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"); } } diff --git a/src/ripple/app/main/Application.h b/src/ripple/app/main/Application.h index c459a50f78..367ebcdbb4 100644 --- a/src/ripple/app/main/Application.h +++ b/src/ripple/app/main/Application.h @@ -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 @@ -151,8 +155,9 @@ make_Application( std::unique_ptr config, std::unique_ptr logs); -// DEPRECATED -extern Application& getApp (); +extern +void +setupConfigForUnitTests (Config& config); } diff --git a/src/ripple/app/main/Main.cpp b/src/ripple/app/main/Main.cpp index fdc0a3d82a..d4b6bfe757 100644 --- a/src/ripple/app/main/Main.cpp +++ b/src/ripple/app/main/Main.cpp @@ -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) { // Shutdown tests can not be part of the normal unit tests in 'runUnitTests' @@ -204,18 +193,10 @@ static int runShutdownTests (std::unique_ptr config) return EXIT_SUCCESS; } -static int runUnitTests ( - std::unique_ptr 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()); - 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(); return runUnitTests( - std::make_unique (), - vm["unittest"].as(), - argument); + vm["unittest"].as(), argument); } auto config = std::make_unique(); diff --git a/src/ripple/app/tests/MultiSign.test.cpp b/src/ripple/app/tests/MultiSign.test.cpp index db01fc9056..d172ea0917 100644 --- a/src/ripple/app/tests/MultiSign.test.cpp +++ b/src/ripple/app/tests/MultiSign.test.cpp @@ -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)); diff --git a/src/ripple/app/tests/Regression_test.cpp b/src/ripple/app/tests/Regression_test.cpp index ac82d573c4..eb9042a992 100644 --- a/src/ripple/app/tests/Regression_test.cpp +++ b/src/ripple/app/tests/Regression_test.cpp @@ -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( - 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); diff --git a/src/ripple/basics/BasicConfig.h b/src/ripple/basics/BasicConfig.h index 666475891c..c99668618c 100644 --- a/src/ripple/basics/BasicConfig.h +++ b/src/ripple/basics/BasicConfig.h @@ -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 diff --git a/src/ripple/basics/impl/BasicConfig.cpp b/src/ripple/basics/impl/BasicConfig.cpp index 02ddb0ef31..f0a58d7fe4 100644 --- a/src/ripple/basics/impl/BasicConfig.cpp +++ b/src/ripple/basics/impl/BasicConfig.cpp @@ -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 { diff --git a/src/ripple/core/Config.h b/src/ripple/core/Config.h index d97d9828f5..f71868e944 100644 --- a/src/ripple/core/Config.h +++ b/src/ripple/core/Config.h @@ -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. diff --git a/src/ripple/test/jtx/Account.h b/src/ripple/test/jtx/Account.h index 36781e1567..a95d1d43e7 100644 --- a/src/ripple/test/jtx/Account.h +++ b/src/ripple/test/jtx/Account.h @@ -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, diff --git a/src/ripple/test/jtx/Env.h b/src/ripple/test/jtx/Env.h index c1a38fb774..f8fb3e6467 100644 --- a/src/ripple/test/jtx/Env.h +++ b/src/ripple/test/jtx/Env.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -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; + std::unique_ptr owned; + + AppBundle (std::unique_ptr config); + AppBundle (Application* app_); + }; + + AppBundle bundle_; std::shared_ptr closed_; CachedSLEs cachedSLEs_; LogSquelcher logSquelcher_; @@ -150,7 +159,7 @@ public: Application& app() { - return getApp(); + return *bundle_.app; } /** Returns the open ledger. diff --git a/src/ripple/test/jtx/impl/Account.cpp b/src/ripple/test/jtx/impl/Account.cpp index 6b9eb31a86..6985d4f4ea 100644 --- a/src/ripple/test/jtx/impl/Account.cpp +++ b/src/ripple/test/jtx/impl/Account.cpp @@ -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 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 diff --git a/src/ripple/test/jtx/impl/Env.cpp b/src/ripple/test/jtx/impl/Env.cpp index e190427d98..254c7178b8 100644 --- a/src/ripple/test/jtx/impl/Env.cpp +++ b/src/ripple/test/jtx/impl/Env.cpp @@ -50,17 +50,41 @@ namespace test { namespace jtx { +Env::AppBundle::AppBundle(Application* app_) + : app (app_) +{ +} + +Env::AppBundle::AppBundle(std::unique_ptr config) +{ + auto logs = std::make_unique(); + owned = make_Application( + std::move(config), std::move(logs)); + app = owned.get(); +} + +//------------------------------------------------------------------------------ + +static +std::unique_ptr +makeConfig() +{ + auto p = std::make_unique(); + setupConfigForUnitTests(*p); + return std::unique_ptr(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( - 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; }); diff --git a/src/ripple/test/jtx/impl/Env_test.cpp b/src/ripple/test/jtx/impl/Env_test.cpp index fa6a42e629..8c8127d308 100644 --- a/src/ripple/test/jtx/impl/Env_test.cpp +++ b/src/ripple/test/jtx/impl/Env_test.cpp @@ -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)); diff --git a/src/ripple/test/mao.h b/src/ripple/test/mao.h new file mode 100644 index 0000000000..c344baab1d --- /dev/null +++ b/src/ripple/test/mao.h @@ -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 + +#endif diff --git a/src/ripple/test/mao/Net.h b/src/ripple/test/mao/Net.h new file mode 100644 index 0000000000..d1406679a3 --- /dev/null +++ b/src/ripple/test/mao/Net.h @@ -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 + +namespace ripple { +namespace test { +namespace mao { + +class Net +{ +private: +public: +}; + +} // mao +} // test +} // ripple + +#endif diff --git a/src/ripple/test/mao/impl/Net.cpp b/src/ripple/test/mao/impl/Net.cpp new file mode 100644 index 0000000000..957266ded7 --- /dev/null +++ b/src/ripple/test/mao/impl/Net.cpp @@ -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 +#include + +namespace ripple { +namespace test { +namespace mao { + + + +} // mao +} // test +} // ripple diff --git a/src/ripple/test/mao/impl/Net_test.cpp b/src/ripple/test/mao/impl/Net_test.cpp new file mode 100644 index 0000000000..ededdaa9a2 --- /dev/null +++ b/src/ripple/test/mao/impl/Net_test.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ripple { +namespace test { +namespace mao { + +struct TestApp +{ + TestApp() + { + auto config = std::make_unique(); + 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(); + 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 + void + rpc (T const& t, Args const&... args) + { + std::vector v; + collect(v, t, args...); + RPCCall::fromCommandLine( + instance->config(), v, + instance->logs()); + } + +private: + inline + void + collect (std::vector& v) + { + } + + template + void + collect (std::vector& v, + T const& t, Args const&... args) + { + v.emplace_back(t); + collect(v, args...); + } + + std::unique_ptr 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 diff --git a/src/ripple/unity/test.cpp b/src/ripple/unity/test.cpp index d766d54757..9a53617f41 100644 --- a/src/ripple/unity/test.cpp +++ b/src/ripple/unity/test.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -44,4 +45,6 @@ #include #include -#include +#include +#include +