rippled
LedgerLoad_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2017 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/beast/unit_test.h>
21 #include <test/jtx.h>
22 #include <test/jtx/Env.h>
23 #include <ripple/beast/utility/temp_dir.h>
24 #include <ripple/protocol/jss.h>
25 #include <ripple/protocol/SField.h>
26 #include <boost/algorithm/string.hpp>
27 #include <boost/filesystem.hpp>
28 #include <fstream>
29 
30 namespace ripple {
31 
32 class LedgerLoad_test : public beast::unit_test::suite
33 {
34  auto static ledgerConfig(
36  std::string const& dbPath,
37  std::string const& ledger,
39  {
40  cfg->START_LEDGER = ledger;
41  cfg->START_UP = type;
42  assert(! dbPath.empty());
43  cfg->legacy("database_path", dbPath);
44  return cfg;
45  }
46 
47  // setup for test cases
48  struct SetupData
49  {
54  };
55 
56  SetupData
58  {
59  using namespace test::jtx;
60  SetupData retval = {td.path()};
61 
62  retval.ledgerFile = td.file("ledgerdata.json");
63 
64  Env env {*this};
65  Account prev;
66 
67  for(auto i = 0; i < 20; ++i)
68  {
69  Account acct {"A" + std::to_string(i)};
70  env.fund(XRP(10000), acct);
71  env.close();
72  if(i > 0)
73  {
74  env.trust(acct["USD"](1000), prev);
75  env(pay(acct, prev, acct["USD"](5)));
76  }
77  env(offer(acct, XRP(100), acct["USD"](1)));
78  env.close();
79  prev = std::move(acct);
80  }
81 
82  retval.ledger = env.rpc ("ledger", "current", "full") [jss::result];
83  BEAST_EXPECT(retval.ledger[jss::ledger][jss::accountState].size() == 101);
84 
85  retval.hashes = [&] {
86  for(auto const& it : retval.ledger[jss::ledger][jss::accountState])
87  {
88  if(it[sfLedgerEntryType.fieldName] == jss::LedgerHashes)
89  return it[sfHashes.fieldName];
90  }
91  return Json::Value {};
92  }();
93 
94  BEAST_EXPECT(retval.hashes.size() == 41);
95 
96  //write this ledger data to a file.
97  std::ofstream o (retval.ledgerFile, std::ios::out | std::ios::trunc);
98  o << to_string(retval.ledger);
99  o.close();
100  return retval;
101  }
102 
103  void
104  testLoad (SetupData const& sd)
105  {
106  testcase ("Load a saved ledger");
107  using namespace test::jtx;
108 
109  // create a new env with the ledger file specified for startup
110  Env env(*this,
111  envconfig( ledgerConfig,
113  auto jrb = env.rpc ( "ledger", "current", "full") [jss::result];
114  BEAST_EXPECT(
115  sd.ledger[jss::ledger][jss::accountState].size() ==
116  jrb[jss::ledger][jss::accountState].size());
117  }
118 
119  void
121  {
122  testcase ("Load ledger: Bad Files");
123  using namespace test::jtx;
124  using namespace boost::filesystem;
125 
126  // empty path
127  except ([&]
128  {
129  Env env(*this,
130  envconfig( ledgerConfig,
131  sd.dbPath, "", Config::LOAD_FILE));
132  });
133 
134  // file does not exist
135  except ([&]
136  {
137  Env env(*this,
138  envconfig( ledgerConfig,
139  sd.dbPath, "badfile.json", Config::LOAD_FILE));
140  });
141 
142  // make a corrupted version of the ledger file (last 10 bytes removed).
143  boost::system::error_code ec;
144  auto ledgerFileCorrupt =
145  boost::filesystem::path{sd.dbPath} / "ledgerdata_bad.json";
146  copy_file(
147  sd.ledgerFile,
148  ledgerFileCorrupt,
149  copy_option::overwrite_if_exists,
150  ec);
151  if(! BEAST_EXPECTS(!ec, ec.message()))
152  return;
153  auto filesize = file_size(ledgerFileCorrupt, ec);
154  if(! BEAST_EXPECTS(!ec, ec.message()))
155  return;
156  resize_file(ledgerFileCorrupt, filesize - 10, ec);
157  if(! BEAST_EXPECTS(!ec, ec.message()))
158  return;
159 
160  except ([&]
161  {
162  Env env(*this,
163  envconfig( ledgerConfig,
164  sd.dbPath, ledgerFileCorrupt.string(), Config::LOAD_FILE));
165  });
166  }
167 
168  void
170  {
171  testcase ("Load by hash");
172  using namespace test::jtx;
173 
174  // create a new env with the ledger hash specified for startup
175  auto ledgerHash = to_string(sd.hashes[sd.hashes.size()-1]);
176  boost::erase_all(ledgerHash, "\"");
177  Env env(*this,
178  envconfig( ledgerConfig,
179  sd.dbPath, ledgerHash, Config::LOAD));
180  auto jrb = env.rpc ( "ledger", "current", "full") [jss::result];
181  BEAST_EXPECT(jrb[jss::ledger][jss::accountState].size() == 97);
182  BEAST_EXPECT(
183  jrb[jss::ledger][jss::accountState].size() <=
184  sd.ledger[jss::ledger][jss::accountState].size());
185  }
186 
187  void
189  {
190  testcase ("Load by keyword");
191  using namespace test::jtx;
192 
193  // create a new env with the ledger "latest" specified for startup
194  Env env(*this,
195  envconfig( ledgerConfig,
196  sd.dbPath, "latest", Config::LOAD));
197  auto jrb = env.rpc ( "ledger", "current", "full") [jss::result];
198  BEAST_EXPECT(
199  sd.ledger[jss::ledger][jss::accountState].size() ==
200  jrb[jss::ledger][jss::accountState].size());
201  }
202 
203  void
205  {
206  testcase ("Load by index");
207  using namespace test::jtx;
208 
209  // create a new env with specific ledger index at startup
210  Env env(*this,
211  envconfig( ledgerConfig,
212  sd.dbPath, "43", Config::LOAD));
213  auto jrb = env.rpc ( "ledger", "current", "full") [jss::result];
214  BEAST_EXPECT(
215  sd.ledger[jss::ledger][jss::accountState].size() ==
216  jrb[jss::ledger][jss::accountState].size());
217  }
218 
219 public:
220  void run () override
221  {
222  beast::temp_dir td;
223  auto sd = setupLedger(td);
224 
225  // test cases
226  testLoad (sd);
227  testBadFiles (sd);
228  testLoadByHash (sd);
229  testLoadLatest (sd);
230  testLoadIndex (sd);
231  }
232 };
233 
234 BEAST_DEFINE_TESTSUITE (LedgerLoad, app, ripple);
235 
236 } // ripple
fstream
std::string
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::sfLedgerEntryType
const SF_U16 sfLedgerEntryType(access, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never)
Definition: SField.h:330
ripple::LedgerLoad_test::SetupData::hashes
Json::Value hashes
Definition: LedgerLoad_test.cpp:53
ripple::SField::fieldName
const std::string fieldName
Definition: SField.h:136
ripple::Config::LOAD
@ LOAD
Definition: Config.h:123
ripple::Config::StartUpType
StartUpType
Definition: Config.h:119
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::LedgerLoad_test::run
void run() override
Definition: LedgerLoad_test.cpp:220
ripple::LedgerLoad_test::SetupData::ledger
Json::Value ledger
Definition: LedgerLoad_test.cpp:52
ripple::LedgerLoad_test::testLoadLatest
void testLoadLatest(SetupData const &sd)
Definition: LedgerLoad_test.cpp:188
ripple::LedgerLoad_test::SetupData
Definition: LedgerLoad_test.cpp:48
std::ofstream
STL class.
std::to_string
T to_string(T... args)
ripple::LedgerLoad_test::setupLedger
SetupData setupLedger(beast::temp_dir const &td)
Definition: LedgerLoad_test.cpp:57
std::ofstream::close
T close(T... args)
Json::Value::size
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:720
ripple::LedgerLoad_test::testLoadByHash
void testLoadByHash(SetupData const &sd)
Definition: LedgerLoad_test.cpp:169
ripple::LedgerLoad_test::ledgerConfig
static auto ledgerConfig(std::unique_ptr< Config > cfg, std::string const &dbPath, std::string const &ledger, Config::StartUpType type)
Definition: LedgerLoad_test.cpp:34
beast::temp_dir::path
std::string path() const
Get the native path for the temporary directory.
Definition: temp_dir.h:68
ripple::LedgerLoad_test::testBadFiles
void testBadFiles(SetupData const &sd)
Definition: LedgerLoad_test.cpp:120
ripple::sfHashes
const SF_Vec256 sfHashes(access, STI_VECTOR256, 2, "Hashes")
Definition: SField.h:474
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LedgerLoad_test::SetupData::dbPath
const std::string dbPath
Definition: LedgerLoad_test.cpp:50
ripple::LedgerLoad_test::SetupData::ledgerFile
std::string ledgerFile
Definition: LedgerLoad_test.cpp:51
std::string::empty
T empty(T... args)
ripple::LedgerLoad_test::testLoad
void testLoad(SetupData const &sd)
Definition: LedgerLoad_test.cpp:104
std::unique_ptr
STL class.
ripple::LedgerLoad_test::testLoadIndex
void testLoadIndex(SetupData const &sd)
Definition: LedgerLoad_test.cpp:204
beast::temp_dir::file
std::string file(std::string const &name) const
Get the native path for the a file.
Definition: temp_dir.h:78
ripple::Config::LOAD_FILE
@ LOAD_FILE
Definition: Config.h:124
beast::temp_dir
RAII temporary directory.
Definition: temp_dir.h:33
ripple::LedgerLoad_test
Definition: LedgerLoad_test.cpp:32
Json::Value
Represents a JSON value.
Definition: json_value.h:141