From be0fb67d8d44830e5235a2a84513802cd7c9beba Mon Sep 17 00:00:00 2001 From: Mike Ellery Date: Wed, 4 Jan 2017 09:59:07 -0800 Subject: [PATCH] Add ledger save/load test (RIPD-1378) Provide unit test to invoke ledger load at startup. --- Builds/VisualStudio2015/RippleD.vcxproj | 4 + .../VisualStudio2015/RippleD.vcxproj.filters | 3 + src/test/app/LedgerLoad_test.cpp | 229 ++++++++++++++++++ src/test/jtx/impl/Env.cpp | 3 +- src/test/unity/app_test_unity.cpp | 1 + 5 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 src/test/app/LedgerLoad_test.cpp diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj index 105ad17915..c35972e969 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj +++ b/Builds/VisualStudio2015/RippleD.vcxproj @@ -4168,6 +4168,10 @@ True True + + True + True + True True diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters index 564d37882c..8cd6e8f9ed 100644 --- a/Builds/VisualStudio2015/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters @@ -4917,6 +4917,9 @@ test\app + + test\app + test\app diff --git a/src/test/app/LedgerLoad_test.cpp b/src/test/app/LedgerLoad_test.cpp new file mode 100644 index 0000000000..e74dbfaecd --- /dev/null +++ b/src/test/app/LedgerLoad_test.cpp @@ -0,0 +1,229 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012-2017 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 { + +class LedgerLoad_test : public beast::unit_test::suite +{ + Json::Value jvLedger_; + Json::Value jvHashes_; + boost::filesystem::path ledgerFile_; + boost::filesystem::path dbPath_; + + auto ledgerConfig(std::string const& ledger, Config::StartUpType type) + { + assert(! dbPath_.empty()); + auto p = std::make_unique(); + test::setupConfigForUnitTests(*p); + p->START_LEDGER = ledger; + p->START_UP = type; + p->legacy("database_path", dbPath_.string()); + return p; + } + + // setup for test cases + void + setupLedger() + { + using namespace test::jtx; + + boost::system::error_code ec; + // create a temporary path to write ledger files in + dbPath_ = boost::filesystem::temp_directory_path(ec); + if(! BEAST_EXPECTS(!ec, ec.message())) + return; + dbPath_ /= boost::filesystem::unique_path("%%%%-%%%%-%%%%-%%%%", ec); + if(! BEAST_EXPECTS(!ec, ec.message())) + return; + boost::filesystem::create_directories(dbPath_, ec); + if(! BEAST_EXPECTS(!ec, ec.message())) + return; + + ledgerFile_ = dbPath_ / "ledgerdata.json"; + + Env env {*this}; + Account prev; + + for(auto i = 0; i < 20; ++i) + { + Account acct {"A" + std::to_string(i)}; + env.fund(XRP(10000), acct); + env.close(); + if(i > 0) + { + env.trust(acct["USD"](1000), prev); + env(pay(acct, prev, acct["USD"](5))); + } + env(offer(acct, XRP(100), acct["USD"](1))); + env.close(); + prev = std::move(acct); + } + + jvLedger_ = env.rpc ("ledger", "current", "full") [jss::result]; + BEAST_EXPECT(jvLedger_[jss::ledger][jss::accountState].size() == 101); + + for(auto const& it : jvLedger_[jss::ledger][jss::accountState]) + { + if(it[sfLedgerEntryType.fieldName] == "LedgerHashes") + { + jvHashes_ = it[sfHashes.fieldName]; + } + } + BEAST_EXPECT(jvHashes_.size() == 41); + + //write this ledger data to a file. + std::ofstream o (ledgerFile_.string(), std::ios::out | std::ios::trunc); + o << to_string(jvLedger_); + o.close(); + } + + void + testLoad () + { + testcase ("Load a saved ledger"); + using namespace test::jtx; + + // create a new env with the ledger file specified for startup + Env env(*this, ledgerConfig(ledgerFile_.string(), Config::LOAD_FILE)); + auto jrb = env.rpc ( "ledger", "current", "full") [jss::result]; + BEAST_EXPECT( + jvLedger_[jss::ledger][jss::accountState].size() == + jrb[jss::ledger][jss::accountState].size()); + } + + void + testBadFiles () + { + testcase ("Load ledger: Bad Files"); + using namespace test::jtx; + using namespace boost::filesystem; + + // empty path + except ([this] + { + Env env(*this, ledgerConfig("", Config::LOAD_FILE)); + }); + + // file does not exist + except ([this] + { + Env env(*this, ledgerConfig("badfile.json", Config::LOAD_FILE)); + }); + + // make a corrupted version of the ledger file (last 10 bytes removed). + boost::system::error_code ec; + auto ledgerFileCorrupt = dbPath_ / "ledgerdata_bad.json"; + copy_file( + ledgerFile_, + ledgerFileCorrupt, + copy_option::overwrite_if_exists, + ec); + if(! BEAST_EXPECTS(!ec, ec.message())) + return; + auto filesize = file_size(ledgerFileCorrupt, ec); + if(! BEAST_EXPECTS(!ec, ec.message())) + return; + resize_file(ledgerFileCorrupt, filesize - 10, ec); + if(! BEAST_EXPECTS(!ec, ec.message())) + return; + + except ([this, &ledgerFileCorrupt] + { + Env env(*this, ledgerConfig(ledgerFileCorrupt.string(), Config::LOAD_FILE)); + }); + } + + void + testLoadByHash () + { + testcase ("Load by hash"); + using namespace test::jtx; + + // create a new env with the ledger hash specified for startup + auto ledgerHash = to_string(jvHashes_[jvHashes_.size()-1]); + boost::erase_all(ledgerHash, "\""); + Env env(*this, ledgerConfig(ledgerHash, Config::LOAD)); + auto jrb = env.rpc ( "ledger", "current", "full") [jss::result]; + BEAST_EXPECT(jrb[jss::ledger][jss::accountState].size() == 97); + BEAST_EXPECT( + jrb[jss::ledger][jss::accountState].size() <= + jvLedger_[jss::ledger][jss::accountState].size()); + } + + void + testLoadLatest () + { + testcase ("Load by keyword"); + using namespace test::jtx; + + // create a new env with the ledger "latest" specified for startup + Env env(*this, ledgerConfig("latest", Config::LOAD)); + auto jrb = env.rpc ( "ledger", "current", "full") [jss::result]; + BEAST_EXPECT( + jvLedger_[jss::ledger][jss::accountState].size() == + jrb[jss::ledger][jss::accountState].size()); + } + + void + testLoadIndex () + { + testcase ("Load by index"); + using namespace test::jtx; + + // create a new env with specific ledger index at startup + Env env(*this, ledgerConfig("43", Config::LOAD)); + auto jrb = env.rpc ( "ledger", "current", "full") [jss::result]; + BEAST_EXPECT( + jvLedger_[jss::ledger][jss::accountState].size() == + jrb[jss::ledger][jss::accountState].size()); + } + +public: + void run () + { + setupLedger(); + BOOST_SCOPE_EXIT( this_ ) { + boost::system::error_code ec; + boost::filesystem::remove_all(this_->dbPath_, ec); + this_->expect(!ec, ec.message(), __FILE__, __LINE__); + } BOOST_SCOPE_EXIT_END + + // test cases + testLoad (); + testBadFiles (); + testLoadByHash (); + testLoadLatest (); + testLoadIndex (); + } +}; + +BEAST_DEFINE_TESTSUITE (LedgerLoad, app, ripple); + +} // ripple diff --git a/src/test/jtx/impl/Env.cpp b/src/test/jtx/impl/Env.cpp index 9b76f3cfec..056114d229 100644 --- a/src/test/jtx/impl/Env.cpp +++ b/src/test/jtx/impl/Env.cpp @@ -170,7 +170,8 @@ Env::AppBundle::AppBundle(beast::unit_test::suite& suite, std::move(logs), std::move(timeKeeper_)); app = owned.get(); app->logs().threshold(beast::severities::kError); - app->setup(); + if(! app->setup()) + Throw ("Env::AppBundle: setup failed"); timeKeeper->set( app->getLedgerMaster().getClosedLedger()->info().closeTime); app->doStart(); diff --git a/src/test/unity/app_test_unity.cpp b/src/test/unity/app_test_unity.cpp index 050479e70d..314218f684 100644 --- a/src/test/unity/app_test_unity.cpp +++ b/src/test/unity/app_test_unity.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include