rippled
SHAMapStore_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2015 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/app/main/Application.h>
21 #include <ripple/app/misc/SHAMapStore.h>
22 #include <ripple/app/rdb/backend/SQLiteDatabase.h>
23 #include <ripple/core/ConfigSections.h>
24 #include <ripple/protocol/jss.h>
25 #include <test/jtx.h>
26 #include <test/jtx/envconfig.h>
27 
28 namespace ripple {
29 namespace test {
30 
31 class SHAMapStore_test : public beast::unit_test::suite
32 {
33  static auto const deleteInterval = 8;
34 
35  static auto
37  {
38  cfg->LEDGER_HISTORY = deleteInterval;
39  auto& section = cfg->section(ConfigSection::nodeDatabase());
40  section.set("online_delete", std::to_string(deleteInterval));
41  return cfg;
42  }
43 
44  static auto
46  {
47  cfg = onlineDelete(std::move(cfg));
48  cfg->section(ConfigSection::nodeDatabase()).set("advisory_delete", "1");
49  return cfg;
50  }
51 
52  bool
54  jtx::Env& env,
55  Json::Value const& json,
56  std::string ledgerID,
57  bool checkDB = false)
58  {
59  auto good = json.isMember(jss::result) &&
60  !RPC::contains_error(json[jss::result]) &&
61  json[jss::result][jss::ledger][jss::ledger_index] == ledgerID;
62  if (!good || !checkDB)
63  return good;
64 
65  auto const seq = json[jss::result][jss::ledger_index].asUInt();
66 
69  if (!oinfo)
70  return false;
71  const LedgerInfo& info = oinfo.value();
72 
73  const std::string outHash = to_string(info.hash);
74  const LedgerIndex outSeq = info.seq;
75  const std::string outParentHash = to_string(info.parentHash);
76  const std::string outDrops = to_string(info.drops);
77  const std::uint64_t outCloseTime =
78  info.closeTime.time_since_epoch().count();
79  const std::uint64_t outParentCloseTime =
80  info.parentCloseTime.time_since_epoch().count();
81  const std::uint64_t outCloseTimeResolution =
83  const std::uint64_t outCloseFlags = info.closeFlags;
84  const std::string outAccountHash = to_string(info.accountHash);
85  const std::string outTxHash = to_string(info.txHash);
86 
87  auto const& ledger = json[jss::result][jss::ledger];
88  return outHash == ledger[jss::ledger_hash].asString() &&
89  outSeq == seq &&
90  outParentHash == ledger[jss::parent_hash].asString() &&
91  outDrops == ledger[jss::total_coins].asString() &&
92  outCloseTime == ledger[jss::close_time].asUInt() &&
93  outParentCloseTime == ledger[jss::parent_close_time].asUInt() &&
94  outCloseTimeResolution ==
95  ledger[jss::close_time_resolution].asUInt() &&
96  outCloseFlags == ledger[jss::close_flags].asUInt() &&
97  outAccountHash == ledger[jss::account_hash].asString() &&
98  outTxHash == ledger[jss::transaction_hash].asString();
99  }
100 
101  bool
103  {
104  return json.isMember(jss::result) &&
105  RPC::contains_error(json[jss::result]) &&
106  json[jss::result][jss::error_code] == error;
107  }
108 
111  {
112  BEAST_EXPECT(
113  json.isMember(jss::result) &&
114  json[jss::result].isMember(jss::ledger) &&
115  json[jss::result][jss::ledger].isMember(jss::ledger_hash) &&
116  json[jss::result][jss::ledger][jss::ledger_hash].isString());
117  return json[jss::result][jss::ledger][jss::ledger_hash].asString();
118  }
119 
120  void
121  ledgerCheck(jtx::Env& env, int const rows, int const first)
122  {
123  const auto [actualRows, actualFirst, actualLast] =
124  dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())
125  ->getLedgerCountMinMax();
126 
127  BEAST_EXPECT(actualRows == rows);
128  BEAST_EXPECT(actualFirst == first);
129  BEAST_EXPECT(actualLast == first + rows - 1);
130  }
131 
132  void
133  transactionCheck(jtx::Env& env, int const rows)
134  {
135  BEAST_EXPECT(
136  dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())
137  ->getTransactionCount() == rows);
138  }
139 
140  void
141  accountTransactionCheck(jtx::Env& env, int const rows)
142  {
143  BEAST_EXPECT(
144  dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())
145  ->getAccountTransactionCount() == rows);
146  }
147 
148  int
150  {
151  using namespace std::chrono_literals;
152 
153  auto& store = env.app().getSHAMapStore();
154 
155  int ledgerSeq = 3;
156  store.rendezvous();
157  BEAST_EXPECT(!store.getLastRotated());
158 
159  env.close();
160  store.rendezvous();
161 
162  auto ledger = env.rpc("ledger", "validated");
163  BEAST_EXPECT(goodLedger(env, ledger, std::to_string(ledgerSeq++)));
164 
165  BEAST_EXPECT(store.getLastRotated() == ledgerSeq - 1);
166  return ledgerSeq;
167  }
168 
169 public:
170  void
172  {
173  using namespace std::chrono_literals;
174 
175  testcase("clearPrior");
176  using namespace jtx;
177 
178  Env env(*this, envconfig(onlineDelete));
179 
180  auto& store = env.app().getSHAMapStore();
181  env.fund(XRP(10000), noripple("alice"));
182 
183  ledgerCheck(env, 1, 2);
184  transactionCheck(env, 0);
185  accountTransactionCheck(env, 0);
186 
188 
189  auto ledgerTmp = env.rpc("ledger", "0");
190  BEAST_EXPECT(bad(ledgerTmp));
191 
192  ledgers.emplace(std::make_pair(1, env.rpc("ledger", "1")));
193  BEAST_EXPECT(goodLedger(env, ledgers[1], "1"));
194 
195  ledgers.emplace(std::make_pair(2, env.rpc("ledger", "2")));
196  BEAST_EXPECT(goodLedger(env, ledgers[2], "2"));
197 
198  ledgerTmp = env.rpc("ledger", "current");
199  BEAST_EXPECT(goodLedger(env, ledgerTmp, "3"));
200 
201  ledgerTmp = env.rpc("ledger", "4");
202  BEAST_EXPECT(bad(ledgerTmp));
203 
204  ledgerTmp = env.rpc("ledger", "100");
205  BEAST_EXPECT(bad(ledgerTmp));
206 
207  auto const firstSeq = waitForReady(env);
208  auto lastRotated = firstSeq - 1;
209 
210  for (auto i = firstSeq + 1; i < deleteInterval + firstSeq; ++i)
211  {
212  env.fund(XRP(10000), noripple("test" + std::to_string(i)));
213  env.close();
214 
215  ledgerTmp = env.rpc("ledger", "current");
216  BEAST_EXPECT(goodLedger(env, ledgerTmp, std::to_string(i)));
217  }
218  BEAST_EXPECT(store.getLastRotated() == lastRotated);
219 
220  for (auto i = 3; i < deleteInterval + lastRotated; ++i)
221  {
222  ledgers.emplace(
223  std::make_pair(i, env.rpc("ledger", std::to_string(i))));
224  BEAST_EXPECT(
225  goodLedger(env, ledgers[i], std::to_string(i), true) &&
226  getHash(ledgers[i]).length());
227  }
228 
229  ledgerCheck(env, deleteInterval + 1, 2);
232 
233  {
234  // Closing one more ledger triggers a rotate
235  env.close();
236 
237  auto ledger = env.rpc("ledger", "current");
238  BEAST_EXPECT(
239  goodLedger(env, ledger, std::to_string(deleteInterval + 4)));
240  }
241 
242  store.rendezvous();
243 
244  BEAST_EXPECT(store.getLastRotated() == deleteInterval + 3);
245  lastRotated = store.getLastRotated();
246  BEAST_EXPECT(lastRotated == 11);
247 
248  // That took care of the fake hashes
249  ledgerCheck(env, deleteInterval + 1, 3);
252 
253  // The last iteration of this loop should trigger a rotate
254  for (auto i = lastRotated - 1; i < lastRotated + deleteInterval - 1;
255  ++i)
256  {
257  env.close();
258 
259  ledgerTmp = env.rpc("ledger", "current");
260  BEAST_EXPECT(goodLedger(env, ledgerTmp, std::to_string(i + 3)));
261 
262  ledgers.emplace(
263  std::make_pair(i, env.rpc("ledger", std::to_string(i))));
264  BEAST_EXPECT(
265  store.getLastRotated() == lastRotated ||
266  i == lastRotated + deleteInterval - 2);
267  BEAST_EXPECT(
268  goodLedger(env, ledgers[i], std::to_string(i), true) &&
269  getHash(ledgers[i]).length());
270  }
271 
272  store.rendezvous();
273 
274  BEAST_EXPECT(store.getLastRotated() == deleteInterval + lastRotated);
275 
276  ledgerCheck(env, deleteInterval + 1, lastRotated);
277  transactionCheck(env, 0);
278  accountTransactionCheck(env, 0);
279  }
280 
281  void
283  {
284  testcase("automatic online_delete");
285  using namespace jtx;
286  using namespace std::chrono_literals;
287 
288  Env env(*this, envconfig(onlineDelete));
289  auto& store = env.app().getSHAMapStore();
290 
291  auto ledgerSeq = waitForReady(env);
292  auto lastRotated = ledgerSeq - 1;
293  BEAST_EXPECT(store.getLastRotated() == lastRotated);
294  BEAST_EXPECT(lastRotated != 2);
295 
296  // Because advisory_delete is unset,
297  // "can_delete" is disabled.
298  auto const canDelete = env.rpc("can_delete");
299  BEAST_EXPECT(bad(canDelete, rpcNOT_ENABLED));
300 
301  // Close ledgers without triggering a rotate
302  for (; ledgerSeq < lastRotated + deleteInterval; ++ledgerSeq)
303  {
304  env.close();
305 
306  auto ledger = env.rpc("ledger", "validated");
307  BEAST_EXPECT(
308  goodLedger(env, ledger, std::to_string(ledgerSeq), true));
309  }
310 
311  store.rendezvous();
312 
313  // The database will always have back to ledger 2,
314  // regardless of lastRotated.
315  ledgerCheck(env, ledgerSeq - 2, 2);
316  BEAST_EXPECT(lastRotated == store.getLastRotated());
317 
318  {
319  // Closing one more ledger triggers a rotate
320  env.close();
321 
322  auto ledger = env.rpc("ledger", "validated");
323  BEAST_EXPECT(
324  goodLedger(env, ledger, std::to_string(ledgerSeq++), true));
325  }
326 
327  store.rendezvous();
328 
329  ledgerCheck(env, ledgerSeq - lastRotated, lastRotated);
330  BEAST_EXPECT(lastRotated != store.getLastRotated());
331 
332  lastRotated = store.getLastRotated();
333 
334  // Close enough ledgers to trigger another rotate
335  for (; ledgerSeq < lastRotated + deleteInterval + 1; ++ledgerSeq)
336  {
337  env.close();
338 
339  auto ledger = env.rpc("ledger", "validated");
340  BEAST_EXPECT(
341  goodLedger(env, ledger, std::to_string(ledgerSeq), true));
342  }
343 
344  store.rendezvous();
345 
346  ledgerCheck(env, deleteInterval + 1, lastRotated);
347  BEAST_EXPECT(lastRotated != store.getLastRotated());
348  }
349 
350  void
352  {
353  testcase("online_delete with advisory_delete");
354  using namespace jtx;
355  using namespace std::chrono_literals;
356 
357  // Same config with advisory_delete enabled
358  Env env(*this, envconfig(advisoryDelete));
359  auto& store = env.app().getSHAMapStore();
360 
361  auto ledgerSeq = waitForReady(env);
362  auto lastRotated = ledgerSeq - 1;
363  BEAST_EXPECT(store.getLastRotated() == lastRotated);
364  BEAST_EXPECT(lastRotated != 2);
365 
366  auto canDelete = env.rpc("can_delete");
367  BEAST_EXPECT(!RPC::contains_error(canDelete[jss::result]));
368  BEAST_EXPECT(canDelete[jss::result][jss::can_delete] == 0);
369 
370  canDelete = env.rpc("can_delete", "never");
371  BEAST_EXPECT(!RPC::contains_error(canDelete[jss::result]));
372  BEAST_EXPECT(canDelete[jss::result][jss::can_delete] == 0);
373 
374  auto const firstBatch = deleteInterval + ledgerSeq;
375  for (; ledgerSeq < firstBatch; ++ledgerSeq)
376  {
377  env.close();
378 
379  auto ledger = env.rpc("ledger", "validated");
380  BEAST_EXPECT(
381  goodLedger(env, ledger, std::to_string(ledgerSeq), true));
382  }
383 
384  store.rendezvous();
385 
386  ledgerCheck(env, ledgerSeq - 2, 2);
387  BEAST_EXPECT(lastRotated == store.getLastRotated());
388 
389  // This does not kick off a cleanup
390  canDelete = env.rpc(
391  "can_delete", std::to_string(ledgerSeq + deleteInterval / 2));
392  BEAST_EXPECT(!RPC::contains_error(canDelete[jss::result]));
393  BEAST_EXPECT(
394  canDelete[jss::result][jss::can_delete] ==
395  ledgerSeq + deleteInterval / 2);
396 
397  store.rendezvous();
398 
399  ledgerCheck(env, ledgerSeq - 2, 2);
400  BEAST_EXPECT(store.getLastRotated() == lastRotated);
401 
402  {
403  // This kicks off a cleanup, but it stays small.
404  env.close();
405 
406  auto ledger = env.rpc("ledger", "validated");
407  BEAST_EXPECT(
408  goodLedger(env, ledger, std::to_string(ledgerSeq++), true));
409  }
410 
411  store.rendezvous();
412 
413  ledgerCheck(env, ledgerSeq - lastRotated, lastRotated);
414 
415  BEAST_EXPECT(store.getLastRotated() == ledgerSeq - 1);
416  lastRotated = ledgerSeq - 1;
417 
418  for (; ledgerSeq < lastRotated + deleteInterval; ++ledgerSeq)
419  {
420  // No cleanups in this loop.
421  env.close();
422 
423  auto ledger = env.rpc("ledger", "validated");
424  BEAST_EXPECT(
425  goodLedger(env, ledger, std::to_string(ledgerSeq), true));
426  }
427 
428  store.rendezvous();
429 
430  BEAST_EXPECT(store.getLastRotated() == lastRotated);
431 
432  {
433  // This kicks off another cleanup.
434  env.close();
435 
436  auto ledger = env.rpc("ledger", "validated");
437  BEAST_EXPECT(
438  goodLedger(env, ledger, std::to_string(ledgerSeq++), true));
439  }
440 
441  store.rendezvous();
442 
443  ledgerCheck(env, ledgerSeq - firstBatch, firstBatch);
444 
445  BEAST_EXPECT(store.getLastRotated() == ledgerSeq - 1);
446  lastRotated = ledgerSeq - 1;
447 
448  // This does not kick off a cleanup
449  canDelete = env.rpc("can_delete", "always");
450  BEAST_EXPECT(!RPC::contains_error(canDelete[jss::result]));
451  BEAST_EXPECT(
452  canDelete[jss::result][jss::can_delete] ==
454 
455  for (; ledgerSeq < lastRotated + deleteInterval; ++ledgerSeq)
456  {
457  // No cleanups in this loop.
458  env.close();
459 
460  auto ledger = env.rpc("ledger", "validated");
461  BEAST_EXPECT(
462  goodLedger(env, ledger, std::to_string(ledgerSeq), true));
463  }
464 
465  store.rendezvous();
466 
467  BEAST_EXPECT(store.getLastRotated() == lastRotated);
468 
469  {
470  // This kicks off another cleanup.
471  env.close();
472 
473  auto ledger = env.rpc("ledger", "validated");
474  BEAST_EXPECT(
475  goodLedger(env, ledger, std::to_string(ledgerSeq++), true));
476  }
477 
478  store.rendezvous();
479 
480  ledgerCheck(env, ledgerSeq - lastRotated, lastRotated);
481 
482  BEAST_EXPECT(store.getLastRotated() == ledgerSeq - 1);
483  lastRotated = ledgerSeq - 1;
484 
485  // This does not kick off a cleanup
486  canDelete = env.rpc("can_delete", "now");
487  BEAST_EXPECT(!RPC::contains_error(canDelete[jss::result]));
488  BEAST_EXPECT(canDelete[jss::result][jss::can_delete] == ledgerSeq - 1);
489 
490  for (; ledgerSeq < lastRotated + deleteInterval; ++ledgerSeq)
491  {
492  // No cleanups in this loop.
493  env.close();
494 
495  auto ledger = env.rpc("ledger", "validated");
496  BEAST_EXPECT(
497  goodLedger(env, ledger, std::to_string(ledgerSeq), true));
498  }
499 
500  store.rendezvous();
501 
502  BEAST_EXPECT(store.getLastRotated() == lastRotated);
503 
504  {
505  // This kicks off another cleanup.
506  env.close();
507 
508  auto ledger = env.rpc("ledger", "validated");
509  BEAST_EXPECT(
510  goodLedger(env, ledger, std::to_string(ledgerSeq++), true));
511  }
512 
513  store.rendezvous();
514 
515  ledgerCheck(env, ledgerSeq - lastRotated, lastRotated);
516 
517  BEAST_EXPECT(store.getLastRotated() == ledgerSeq - 1);
518  lastRotated = ledgerSeq - 1;
519  }
520 
521  void
522  run() override
523  {
524  testClear();
525  testAutomatic();
526  testCanDelete();
527  }
528 };
529 
530 // VFALCO This test fails because of thread asynchronous issues
532 
533 } // namespace test
534 } // namespace ripple
ripple::SQLiteDatabase
Definition: SQLiteDatabase.h:27
ripple::test::jtx::json
Inject raw JSON.
Definition: jtx_json.h:31
ripple::test::SHAMapStore_test::run
void run() override
Definition: SHAMapStore_test.cpp:522
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
std::string
STL class.
ripple::LedgerHeader::closeFlags
int closeFlags
Definition: LedgerHeader.h:63
ripple::test::SHAMapStore_test::testAutomatic
void testAutomatic()
Definition: SHAMapStore_test.cpp:282
ripple::LedgerHeader::parentHash
uint256 parentHash
Definition: LedgerHeader.h:52
ripple::SHAMapStore
class to create database, launch online delete thread, and related SQLite database
Definition: SHAMapStore.h:36
ripple::test::SHAMapStore_test::deleteInterval
static const auto deleteInterval
Definition: SHAMapStore_test.cpp:33
ripple::LedgerHeader::seq
LedgerIndex seq
Definition: LedgerHeader.h:41
std::map::emplace
T emplace(T... args)
ripple::LedgerHeader::accountHash
uint256 accountHash
Definition: LedgerHeader.h:51
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:242
ripple::test::jtx::envconfig
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:49
ripple::rpcLGR_NOT_FOUND
@ rpcLGR_NOT_FOUND
Definition: ErrorCodes.h:72
ripple::RelationalDatabase::getLedgerInfoByIndex
virtual std::optional< LedgerInfo > getLedgerInfoByIndex(LedgerIndex ledgerSeq)=0
getLedgerInfoByIndex Returns a ledger by its sequence.
ripple::LedgerHeader::txHash
uint256 txHash
Definition: LedgerHeader.h:50
ripple::SHAMapStore::rendezvous
virtual void rendezvous() const =0
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::test::SHAMapStore_test::advisoryDelete
static auto advisoryDelete(std::unique_ptr< Config > cfg)
Definition: SHAMapStore_test.cpp:45
ripple::LedgerHeader::hash
uint256 hash
Definition: LedgerHeader.h:49
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::LedgerHeader::parentCloseTime
NetClock::time_point parentCloseTime
Definition: LedgerHeader.h:42
ripple::RPC::contains_error
bool contains_error(Json::Value const &json)
Returns true if the json contains an rpc error specification.
Definition: ErrorCodes.cpp:195
ripple::SQLiteDatabase::getTransactionCount
virtual std::size_t getTransactionCount()=0
getTransactionCount Returns the number of transactions.
ripple::Application::getRelationalDatabase
virtual RelationalDatabase & getRelationalDatabase()=0
ripple::SQLiteDatabase::getAccountTransactionCount
virtual std::size_t getAccountTransactionCount()=0
getAccountTransactionCount Returns the number of account transactions.
std::to_string
T to_string(T... args)
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:121
ripple::rpcNOT_ENABLED
@ rpcNOT_ENABLED
Definition: ErrorCodes.h:59
std::uint32_t
std::map
STL class.
ripple::test::SHAMapStore_test::transactionCheck
void transactionCheck(jtx::Env &env, int const rows)
Definition: SHAMapStore_test.cpp:133
ripple::LedgerHeader::closeTime
NetClock::time_point closeTime
Definition: LedgerHeader.h:72
ripple::LedgerHeader
Information about the notional ledger backing the view.
Definition: LedgerHeader.h:33
std::optional::value
T value(T... args)
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:33
ripple::test::SHAMapStore_test::testCanDelete
void testCanDelete()
Definition: SHAMapStore_test.cpp:351
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LedgerHeader::drops
XRPAmount drops
Definition: LedgerHeader.h:54
ripple::test::jtx::noripple
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
Definition: Env.h:65
ripple::LedgerHeader::closeTimeResolution
NetClock::duration closeTimeResolution
Definition: LedgerHeader.h:66
ripple::test::SHAMapStore_test::testClear
void testClear()
Definition: SHAMapStore_test.cpp:171
ripple::test::SHAMapStore_test::ledgerCheck
void ledgerCheck(jtx::Env &env, int const rows, int const first)
Definition: SHAMapStore_test.cpp:121
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:228
ripple::test::SHAMapStore_test::accountTransactionCheck
void accountTransactionCheck(jtx::Env &env, int const rows)
Definition: SHAMapStore_test.cpp:141
ripple::test::SHAMapStore_test::waitForReady
int waitForReady(jtx::Env &env)
Definition: SHAMapStore_test.cpp:149
std::chrono::duration::count
T count(T... args)
ripple::test::SHAMapStore_test::goodLedger
bool goodLedger(jtx::Env &env, Json::Value const &json, std::string ledgerID, bool checkDB=false)
Definition: SHAMapStore_test.cpp:53
std::optional
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
std::make_pair
T make_pair(T... args)
ripple::Application::getSHAMapStore
virtual SHAMapStore & getSHAMapStore()=0
ripple::test::SHAMapStore_test
Definition: SHAMapStore_test.cpp:31
ripple::test::SHAMapStore_test::onlineDelete
static auto onlineDelete(std::unique_ptr< Config > cfg)
Definition: SHAMapStore_test.cpp:36
std::unique_ptr
STL class.
std::numeric_limits
ripple::test::SHAMapStore_test::bad
bool bad(Json::Value const &json, error_code_i error=rpcLGR_NOT_FOUND)
Definition: SHAMapStore_test.cpp:102
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
ripple::ConfigSection::nodeDatabase
static std::string nodeDatabase()
Definition: ConfigSections.h:33
ripple::test::jtx::Env::rpc
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:700
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::test::SHAMapStore_test::getHash
std::string getHash(Json::Value const &json)
Definition: SHAMapStore_test.cpp:110
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple)