rippled
Database_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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 <test/nodestore/TestBase.h>
21 #include <ripple/nodestore/DummyScheduler.h>
22 #include <ripple/nodestore/Manager.h>
23 #include <ripple/beast/utility/temp_dir.h>
24 #include <test/unit_test/SuiteJournal.h>
25 
26 namespace ripple {
27 namespace NodeStore {
28 
29 class Database_test : public TestBase
30 {
32 
33 public:
35  : journal_ ("Database_test", *this)
36  { }
37 
38  void testImport (std::string const& destBackendType,
39  std::string const& srcBackendType, std::int64_t seedValue)
40  {
41  DummyScheduler scheduler;
42  RootStoppable parent ("TestRootStoppable");
43 
44  beast::temp_dir node_db;
45  Section srcParams;
46  srcParams.set ("type", srcBackendType);
47  srcParams.set ("path", node_db.path());
48 
49  // Create a batch
50  auto batch = createPredictableBatch (
51  numObjectsToTest, seedValue);
52 
53  // Write to source db
54  {
56  "test", scheduler, 2, parent, srcParams, journal_);
57  storeBatch (*src, batch);
58  }
59 
60  Batch copy;
61 
62  {
63  // Re-open the db
65  "test", scheduler, 2, parent, srcParams, journal_);
66 
67  // Set up the destination database
68  beast::temp_dir dest_db;
69  Section destParams;
70  destParams.set ("type", destBackendType);
71  destParams.set ("path", dest_db.path());
72 
74  "test", scheduler, 2, parent, destParams, journal_);
75 
76  testcase ("import into '" + destBackendType +
77  "' from '" + srcBackendType + "'");
78 
79  // Do the import
80  dest->import (*src);
81 
82  // Get the results of the import
83  fetchCopyOfBatch (*dest, &copy, batch);
84  }
85 
86  // Canonicalize the source and destination batches
87  std::sort (batch.begin (), batch.end (), LessThan{});
88  std::sort (copy.begin (), copy.end (), LessThan{});
89  BEAST_EXPECT(areBatchesEqual (batch, copy));
90  }
91 
92  //--------------------------------------------------------------------------
93 
94  void testNodeStore (std::string const& type,
95  bool const testPersistence,
96  std::int64_t const seedValue,
97  int numObjsToTest = 2000)
98  {
99  DummyScheduler scheduler;
100  RootStoppable parent ("TestRootStoppable");
101 
102  std::string s = "NodeStore backend '" + type + "'";
103 
104  testcase (s);
105 
106  beast::temp_dir node_db;
107  Section nodeParams;
108  nodeParams.set ("type", type);
109  nodeParams.set ("path", node_db.path());
110 
111  beast::xor_shift_engine rng (seedValue);
112 
113  // Create a batch
114  auto batch = createPredictableBatch (
115  numObjsToTest, rng());
116 
117  {
118  // Open the database
120  "test", scheduler, 2, parent, nodeParams, journal_);
121 
122  // Write the batch
123  storeBatch (*db, batch);
124 
125  {
126  // Read it back in
127  Batch copy;
128  fetchCopyOfBatch (*db, &copy, batch);
129  BEAST_EXPECT(areBatchesEqual (batch, copy));
130  }
131 
132  {
133  // Reorder and read the copy again
134  std::shuffle (
135  batch.begin(),
136  batch.end(),
137  rng);
138  Batch copy;
139  fetchCopyOfBatch (*db, &copy, batch);
140  BEAST_EXPECT(areBatchesEqual (batch, copy));
141  }
142  }
143 
144  if (testPersistence)
145  {
146  // Re-open the database without the ephemeral DB
148  "test", scheduler, 2, parent, nodeParams, journal_);
149 
150  // Read it back in
151  Batch copy;
152  fetchCopyOfBatch (*db, &copy, batch);
153 
154  // Canonicalize the source and destination batches
155  std::sort (batch.begin (), batch.end (), LessThan{});
156  std::sort (copy.begin (), copy.end (), LessThan{});
157  BEAST_EXPECT(areBatchesEqual (batch, copy));
158  }
159 
160  if (type == "memory")
161  {
162  // Earliest ledger sequence tests
163  {
164  // Verify default earliest ledger sequence
167  "test", scheduler, 2, parent, nodeParams, journal_);
168  BEAST_EXPECT(db->earliestLedgerSeq() == XRP_LEDGER_EARLIEST_SEQ);
169  }
170 
171  // Set an invalid earliest ledger sequence
172  try
173  {
174  nodeParams.set("earliest_seq", "0");
177  "test", scheduler, 2, parent, nodeParams, journal_);
178  }
179  catch (std::runtime_error const& e)
180  {
181  BEAST_EXPECT(std::strcmp(e.what(),
182  "Invalid earliest_seq") == 0);
183  }
184 
185  {
186  // Set a valid earliest ledger sequence
187  nodeParams.set("earliest_seq", "1");
190  "test", scheduler, 2, parent, nodeParams, journal_);
191 
192  // Verify database uses the earliest ledger sequence setting
193  BEAST_EXPECT(db->earliestLedgerSeq() == 1);
194  }
195 
196 
197  // Create another database that attempts to set the value again
198  try
199  {
200  // Set to default earliest ledger sequence
201  nodeParams.set("earliest_seq",
205  "test", scheduler, 2, parent, nodeParams, journal_);
206  }
207  catch (std::runtime_error const& e)
208  {
209  BEAST_EXPECT(std::strcmp(e.what(),
210  "earliest_seq set more than once") == 0);
211  }
212  }
213  }
214 
215  //--------------------------------------------------------------------------
216 
217  void run () override
218  {
219  std::int64_t const seedValue = 50;
220 
221  testNodeStore ("memory", false, seedValue);
222 
223  // Persistent backend tests
224  {
225  testNodeStore ("nudb", true, seedValue);
226 
227  #if RIPPLE_ROCKSDB_AVAILABLE
228  testNodeStore ("rocksdb", true, seedValue);
229  #endif
230  }
231 
232  // Import tests
233  {
234  testImport ("nudb", "nudb", seedValue);
235 
236  #if RIPPLE_ROCKSDB_AVAILABLE
237  testImport ("rocksdb", "rocksdb", seedValue);
238  #endif
239 
240  #if RIPPLE_ENABLE_SQLITE_BACKEND_TESTS
241  testImport ("sqlite", "sqlite", seedValue);
242  #endif
243  }
244  }
245 };
246 
247 BEAST_DEFINE_TESTSUITE(Database,NodeStore,ripple);
248 
249 }
250 }
ripple::NodeStore::DummyScheduler
Simple NodeStore Scheduler that just peforms the tasks synchronously.
Definition: DummyScheduler.h:29
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:43
std::strcmp
T strcmp(T... args)
ripple::NodeStore::TestBase
Definition: TestBase.h:68
std::string
STL class.
ripple::NodeStore::Database_test::Database_test
Database_test()
Definition: Database_test.cpp:34
std::vector< std::shared_ptr< NodeObject > >
ripple::NodeStore::LessThan
Binary function that satisfies the strict-weak-ordering requirement.
Definition: TestBase.h:44
ripple::NodeStore::Database_test::testNodeStore
void testNodeStore(std::string const &type, bool const testPersistence, std::int64_t const seedValue, int numObjsToTest=2000)
Definition: Database_test.cpp:94
ripple::NodeStore::Database_test::testImport
void testImport(std::string const &destBackendType, std::string const &srcBackendType, std::int64_t seedValue)
Definition: Database_test.cpp:38
ripple::NodeStore::Database_test::run
void run() override
Definition: Database_test.cpp:217
std::sort
T sort(T... args)
ripple::NodeStore::TestBase::areBatchesEqual
static bool areBatchesEqual(Batch const &lhs, Batch const &rhs)
Definition: TestBase.h:117
ripple::NodeStore::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(Backend, ripple_core, ripple)
ripple::RootStoppable
Definition: Stoppable.h:336
ripple::NodeStore::TestBase::fetchCopyOfBatch
void fetchCopyOfBatch(Backend &backend, Batch *pCopy, Batch const &batch)
Definition: TestBase.h:150
std::to_string
T to_string(T... args)
std::runtime_error
STL class.
std::int64_t
ripple::test::SuiteJournal
Definition: SuiteJournal.h:81
beast::temp_dir::path
std::string path() const
Get the native path for the temporary directory.
Definition: temp_dir.h:68
ripple::NodeStore::TestBase::numObjectsToTest
static const int numObjectsToTest
Definition: TestBase.h:75
ripple::NodeStore::TestBase::createPredictableBatch
static Batch createPredictableBatch(int numObjects, std::uint64_t seed)
Definition: TestBase.h:80
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::NodeStore::Database_test::journal_
test::SuiteJournal journal_
Definition: Database_test.cpp:31
ripple::Section::set
void set(std::string const &key, std::string const &value)
Set a key/value pair.
Definition: BasicConfig.cpp:33
ripple::XRP_LEDGER_EARLIEST_SEQ
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_SEQ
The XRP ledger network's earliest allowed sequence.
Definition: SystemParameters.h:66
beast::detail::xor_shift_engine
Definition: xor_shift_engine.h:32
ripple::NodeStore::TestBase::storeBatch
void storeBatch(Backend &backend, Batch const &batch)
Definition: TestBase.h:141
ripple::NodeStore::Manager::make_Database
virtual std::unique_ptr< Database > make_Database(std::string const &name, Scheduler &scheduler, int readThreads, Stoppable &parent, Section const &backendParameters, beast::Journal journal)=0
Construct a NodeStore database.
ripple::NodeStore::Manager::instance
static Manager & instance()
Returns the instance of the manager singleton.
Definition: ManagerImp.cpp:117
std::unique_ptr
STL class.
std::shuffle
T shuffle(T... args)
beast::temp_dir
RAII temporary directory.
Definition: temp_dir.h:33
std::runtime_error::what
T what(T... args)
ripple::NodeStore::Database_test
Definition: Database_test.cpp:29