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 type;
90 
91  switch (rand_int(rng, 3))
92  {
93  case 0:
94  type = hotLEDGER;
95  break;
96  case 1:
97  type = hotACCOUNT_NODE;
98  break;
99  case 2:
100  type = hotTRANSACTION_NODE;
101  break;
102  case 3:
103  type = hotUNKNOWN;
104  break;
105  }
106 
107  uint256 hash;
108  beast::rngfill(hash.begin(), hash.size(), rng);
109 
111  beast::rngfill(blob.data(), blob.size(), rng);
112 
113  batch.push_back(
114  NodeObject::createObject(type, std::move(blob), hash));
115  }
116 
117  return batch;
118  }
119 
120  // Compare two batches for equality
121  static bool
122  areBatchesEqual(Batch const& lhs, Batch const& rhs)
123  {
124  bool result = true;
125 
126  if (lhs.size() == rhs.size())
127  {
128  for (int i = 0; i < lhs.size(); ++i)
129  {
130  if (!isSame(lhs[i], rhs[i]))
131  {
132  result = false;
133  break;
134  }
135  }
136  }
137  else
138  {
139  result = false;
140  }
141 
142  return result;
143  }
144 
145  // Store a batch in a backend
146  void
147  storeBatch(Backend& backend, Batch const& batch)
148  {
149  for (int i = 0; i < batch.size(); ++i)
150  {
151  backend.store(batch[i]);
152  }
153  }
154 
155  // Get a copy of a batch in a backend
156  void
157  fetchCopyOfBatch(Backend& backend, Batch* pCopy, Batch const& batch)
158  {
159  pCopy->clear();
160  pCopy->reserve(batch.size());
161 
162  for (int i = 0; i < batch.size(); ++i)
163  {
165 
166  Status const status =
167  backend.fetch(batch[i]->getHash().cbegin(), &object);
168 
169  BEAST_EXPECT(status == ok);
170 
171  if (status == ok)
172  {
173  BEAST_EXPECT(object != nullptr);
174 
175  pCopy->push_back(object);
176  }
177  }
178  }
179 
180  void
181  fetchMissing(Backend& backend, Batch const& batch)
182  {
183  for (int i = 0; i < batch.size(); ++i)
184  {
186 
187  Status const status =
188  backend.fetch(batch[i]->getHash().cbegin(), &object);
189 
190  BEAST_EXPECT(status == notFound);
191  }
192  }
193 
194  // Store all objects in a batch
195  static void
196  storeBatch(Database& db, Batch const& batch)
197  {
198  for (int i = 0; i < batch.size(); ++i)
199  {
200  std::shared_ptr<NodeObject> const object(batch[i]);
201 
202  Blob data(object->getData());
203 
204  db.store(
205  object->getType(),
206  std::move(data),
207  object->getHash(),
208  db.earliestLedgerSeq());
209  }
210  }
211 
212  // Fetch all the hashes in one batch, into another batch.
213  static void
214  fetchCopyOfBatch(Database& db, Batch* pCopy, Batch const& batch)
215  {
216  pCopy->clear();
217  pCopy->reserve(batch.size());
218 
219  for (int i = 0; i < batch.size(); ++i)
220  {
222  db.fetch(batch[i]->getHash(), 0);
223 
224  if (object != nullptr)
225  pCopy->push_back(object);
226  }
227  }
228 };
229 
230 } // namespace NodeStore
231 } // namespace ripple
232 
233 #endif
ripple::hotUNKNOWN
@ hotUNKNOWN
Definition: NodeObject.h:33
ripple::NodeStore::Database
Persistency layer for NodeObject.
Definition: Database.h:53
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::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:462
ripple::NodeStore::TestBase::areBatchesEqual
static bool areBatchesEqual(Batch const &lhs, Batch const &rhs)
Definition: TestBase.h:122
std::vector::push_back
T push_back(T... args)
ripple::NodeStore::notFound
@ notFound
Definition: nodestore/Types.h:46
ripple::base_uint< 256 >
ripple::NodeStore::Database::store
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t seq)=0
Store the object.
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:196
ripple::NodeStore::TestBase::fetchMissing
void fetchMissing(Backend &backend, Batch const &batch)
Definition: TestBase.h:181
ripple::NodeStore::Database::fetch
virtual std::shared_ptr< NodeObject > fetch(uint256 const &hash, std::uint32_t seq)=0
Fetch an object.
ripple::NodeStore::TestBase::fetchCopyOfBatch
void fetchCopyOfBatch(Backend &backend, Batch *pCopy, Batch const &batch)
Definition: TestBase.h:157
std::uint64_t
ripple::NodeStore::Database::earliestLedgerSeq
std::uint32_t earliestLedgerSeq() const
Definition: Database.h:236
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:114
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:32
ripple::NodeStore::TestBase::fetchCopyOfBatch
static void fetchCopyOfBatch(Database &db, Batch *pCopy, Batch const &batch)
Definition: TestBase.h:214
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:147
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:37