rippled
TestBase.h
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 #ifndef RIPPLE_NODESTORE_BASE_H_INCLUDED
21 #define RIPPLE_NODESTORE_BASE_H_INCLUDED
22 
23 #include <ripple/basics/StringUtilities.h>
24 #include <ripple/basics/random.h>
25 #include <ripple/beast/unit_test.h>
26 #include <ripple/beast/utility/rngfill.h>
27 #include <ripple/beast/xor_shift_engine.h>
28 #include <ripple/nodestore/Backend.h>
29 #include <ripple/nodestore/Database.h>
30 #include <ripple/nodestore/Types.h>
31 #include <boost/algorithm/string.hpp>
32 #include <iomanip>
33 
34 namespace ripple {
35 namespace NodeStore {
36 
44 struct LessThan
45 {
46  bool
48  std::shared_ptr<NodeObject> const& lhs,
49  std::shared_ptr<NodeObject> const& rhs) const noexcept
50  {
51  return lhs->getHash() < rhs->getHash();
52  }
53 };
54 
56 inline bool
58  std::shared_ptr<NodeObject> const& lhs,
59  std::shared_ptr<NodeObject> const& rhs)
60 {
61  return (lhs->getType() == rhs->getType()) &&
62  (lhs->getHash() == rhs->getHash()) &&
63  (lhs->getData() == rhs->getData());
64 }
65 
66 // Some common code for the unit tests
67 //
68 class TestBase : public beast::unit_test::suite
69 {
70 public:
71  // Tunable parameters
72  //
73  static std::size_t const minPayloadBytes = 1;
74  static std::size_t const maxPayloadBytes = 2000;
75  static int const numObjectsToTest = 2000;
76 
77 public:
78  // Create a predictable batch of objects
79  static Batch
80  createPredictableBatch(int numObjects, std::uint64_t seed)
81  {
82  Batch batch;
83  batch.reserve(numObjects);
84 
85  beast::xor_shift_engine rng(seed);
86 
87  for (int i = 0; i < numObjects; ++i)
88  {
89  NodeObjectType const type = [&] {
90  switch (rand_int(rng, 3))
91  {
92  case 0:
93  return hotLEDGER;
94  case 1:
95  return hotACCOUNT_NODE;
96  case 2:
97  return hotTRANSACTION_NODE;
98  case 3:
99  return hotUNKNOWN;
100  }
101  // will never happen, but make static analysys tool happy.
102  return hotUNKNOWN;
103  }();
104 
105  uint256 hash;
106  beast::rngfill(hash.begin(), hash.size(), rng);
107 
109  beast::rngfill(blob.data(), blob.size(), rng);
110 
111  batch.push_back(
112  NodeObject::createObject(type, std::move(blob), hash));
113  }
114 
115  return batch;
116  }
117 
118  // Compare two batches for equality
119  static bool
120  areBatchesEqual(Batch const& lhs, Batch const& rhs)
121  {
122  bool result = true;
123 
124  if (lhs.size() == rhs.size())
125  {
126  for (int i = 0; i < lhs.size(); ++i)
127  {
128  if (!isSame(lhs[i], rhs[i]))
129  {
130  result = false;
131  break;
132  }
133  }
134  }
135  else
136  {
137  result = false;
138  }
139 
140  return result;
141  }
142 
143  // Store a batch in a backend
144  void
145  storeBatch(Backend& backend, Batch const& batch)
146  {
147  for (int i = 0; i < batch.size(); ++i)
148  {
149  backend.store(batch[i]);
150  }
151  }
152 
153  // Get a copy of a batch in a backend
154  void
155  fetchCopyOfBatch(Backend& backend, Batch* pCopy, Batch const& batch)
156  {
157  pCopy->clear();
158  pCopy->reserve(batch.size());
159 
160  for (int i = 0; i < batch.size(); ++i)
161  {
163 
164  Status const status =
165  backend.fetch(batch[i]->getHash().cbegin(), &object);
166 
167  BEAST_EXPECT(status == ok);
168 
169  if (status == ok)
170  {
171  BEAST_EXPECT(object != nullptr);
172 
173  pCopy->push_back(object);
174  }
175  }
176  }
177 
178  void
179  fetchMissing(Backend& backend, Batch const& batch)
180  {
181  for (int i = 0; i < batch.size(); ++i)
182  {
184 
185  Status const status =
186  backend.fetch(batch[i]->getHash().cbegin(), &object);
187 
188  BEAST_EXPECT(status == notFound);
189  }
190  }
191 
192  // Store all objects in a batch
193  static void
194  storeBatch(Database& db, Batch const& batch)
195  {
196  for (int i = 0; i < batch.size(); ++i)
197  {
198  std::shared_ptr<NodeObject> const object(batch[i]);
199 
200  Blob data(object->getData());
201 
202  db.store(
203  object->getType(),
204  std::move(data),
205  object->getHash(),
206  db.earliestLedgerSeq());
207  }
208  }
209 
210  // Fetch all the hashes in one batch, into another batch.
211  static void
212  fetchCopyOfBatch(Database& db, Batch* pCopy, Batch const& batch)
213  {
214  pCopy->clear();
215  pCopy->reserve(batch.size());
216 
217  for (int i = 0; i < batch.size(); ++i)
218  {
220  db.fetchNodeObject(batch[i]->getHash(), 0);
221 
222  if (object != nullptr)
223  pCopy->push_back(object);
224  }
225  }
226 };
227 
228 } // namespace NodeStore
229 } // namespace ripple
230 
231 #endif
ripple::hotUNKNOWN
@ hotUNKNOWN
Definition: NodeObject.h:33
ripple::NodeStore::Database
Persistency layer for NodeObject.
Definition: Database.h:51
ripple::NodeStore::TestBase
Definition: TestBase.h:68
std::shared_ptr< NodeObject >
ripple::NodeStore::ok
@ ok
Definition: nodestore/Types.h:45
ripple::NodeStore::TestBase::maxPayloadBytes
static const std::size_t maxPayloadBytes
Definition: TestBase.h:74
std::vector::reserve
T reserve(T... args)
ripple::hotACCOUNT_NODE
@ hotACCOUNT_NODE
Definition: NodeObject.h:35
std::vector< std::shared_ptr< NodeObject > >
std::vector::size
T size(T... args)
ripple::NodeObjectType
NodeObjectType
The types of node objects.
Definition: NodeObject.h:32
ripple::NodeStore::LessThan
Binary function that satisfies the strict-weak-ordering requirement.
Definition: TestBase.h:44
ripple::NodeObject::createObject
static std::shared_ptr< NodeObject > createObject(NodeObjectType type, Blob &&data, uint256 const &hash)
Create an object from fields.
Definition: NodeObject.cpp:37
ripple::NodeStore::Database::store
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t ledgerSeq)=0
Store the object.
ripple::hotTRANSACTION_NODE
@ hotTRANSACTION_NODE
Definition: NodeObject.h:36
ripple::NodeStore::Backend::store
virtual void store(std::shared_ptr< NodeObject > const &object)=0
Store a single object.
std::vector::clear
T clear(T... args)
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:519
ripple::NodeStore::TestBase::areBatchesEqual
static bool areBatchesEqual(Batch const &lhs, Batch const &rhs)
Definition: TestBase.h:120
std::vector::push_back
T push_back(T... args)
ripple::NodeStore::notFound
@ notFound
Definition: nodestore/Types.h:46
ripple::base_uint< 256 >
ripple::rand_int
std::enable_if_t< std::is_integral< Integral >::value &&detail::is_engine< Engine >::value, Integral > rand_int(Engine &engine, Integral min, Integral max)
Return a uniformly distributed random integer.
Definition: ripple/basics/random.h:115
ripple::NodeStore::TestBase::storeBatch
static void storeBatch(Database &db, Batch const &batch)
Definition: TestBase.h:194
ripple::NodeStore::TestBase::fetchMissing
void fetchMissing(Backend &backend, Batch const &batch)
Definition: TestBase.h:179
ripple::NodeStore::TestBase::fetchCopyOfBatch
void fetchCopyOfBatch(Backend &backend, Batch *pCopy, Batch const &batch)
Definition: TestBase.h:155
std::uint64_t
ripple::NodeStore::Status
Status
Return codes from Backend operations.
Definition: nodestore/Types.h:44
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::LessThan::operator()
bool operator()(std::shared_ptr< NodeObject > const &lhs, std::shared_ptr< NodeObject > const &rhs) const noexcept
Definition: TestBase.h:47
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:133
ripple::NodeStore::TestBase::minPayloadBytes
static const std::size_t minPayloadBytes
Definition: TestBase.h:73
iomanip
beast::rngfill
void rngfill(void *buffer, std::size_t bytes, Generator &g)
Definition: rngfill.h:33
ripple::NodeStore::TestBase::fetchCopyOfBatch
static void fetchCopyOfBatch(Database &db, Batch *pCopy, Batch const &batch)
Definition: TestBase.h:212
ripple::NodeStore::isSame
bool isSame(std::shared_ptr< NodeObject > const &lhs, std::shared_ptr< NodeObject > const &rhs)
Returns true if objects are identical.
Definition: TestBase.h:57
std::size_t
ripple::hotLEDGER
@ hotLEDGER
Definition: NodeObject.h:34
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:145
ripple::NodeStore::Database::fetchNodeObject
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, std::uint32_t ledgerSeq=0, FetchType fetchType=FetchType::synchronous, bool duplicate=false)
Fetch a node object.
Definition: Database.cpp:252
ripple::NodeStore::Database::earliestLedgerSeq
std::uint32_t earliestLedgerSeq() const noexcept
Definition: Database.h:238
std::vector::data
T data(T... args)
ripple::NodeStore::Backend::fetch
virtual Status fetch(void const *key, std::shared_ptr< NodeObject > *pObject)=0
Fetch a single object.
ripple::NodeStore::Backend
A backend used for the NodeStore.
Definition: Backend.h:39