rippled
SHAMapSync_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 <ripple/shamap/SHAMap.h>
21 #include <ripple/shamap/SHAMapItem.h>
22 #include <ripple/basics/random.h>
23 #include <ripple/basics/StringUtilities.h>
24 #include <ripple/beast/unit_test.h>
25 #include <ripple/beast/xor_shift_engine.h>
26 #include <test/shamap/common.h>
27 #include <test/unit_test/SuiteJournal.h>
28 
29 namespace ripple {
30 namespace tests {
31 
32 class SHAMapSync_test : public beast::unit_test::suite
33 {
34 public:
36 
38  {
39  Serializer s;
40 
41  for (int d = 0; d < 3; ++d)
42  s.add32 (rand_int<std::uint32_t>(eng_));
43 
44  return std::make_shared<SHAMapItem>(
45  s.getSHA512Half(), s.peekData ());
46  }
47 
48  bool confuseMap (SHAMap& map, int count)
49  {
50  // add a bunch of random states to a map, then remove them
51  // map should be the same
52  SHAMapHash beforeHash = map.getHash ();
53 
54  std::list<uint256> items;
55 
56  for (int i = 0; i < count; ++i)
57  {
59  items.push_back (item->key());
60 
61  if (!map.addItem (std::move(*item), false, false))
62  {
63  log << "Unable to add item to map\n";
64  return false;
65  }
66  }
67 
68  for (auto const& item : items)
69  {
70  if (!map.delItem (item))
71  {
72  log << "Unable to remove item from map\n";
73  return false;
74  }
75  }
76 
77  if (beforeHash != map.getHash ())
78  {
79  log <<
80  "Hashes do not match " << beforeHash <<
81  " " << map.getHash () << std::endl;
82  return false;
83  }
84 
85  return true;
86  }
87 
88  void run() override
89  {
90  using namespace beast::severities;
91  test::SuiteJournal journal ("SHAMapSync_test", *this);
92 
93  TestFamily f(journal), f2(journal);
94  SHAMap source (SHAMapType::FREE, f);
95  SHAMap destination (SHAMapType::FREE, f2);
96 
97  int items = 10000;
98  for (int i = 0; i < items; ++i)
99  {
100  source.addItem (std::move(*makeRandomAS ()), false, false);
101  if (i % 100 == 0)
102  source.invariants();
103  }
104 
105  source.invariants();
106  BEAST_EXPECT(confuseMap (source, 500));
107  source.invariants();
108 
109  source.setImmutable ();
110 
111  int count = 0;
112  source.visitLeaves([&count](auto const& item)
113  {
114  ++count;
115  });
116  BEAST_EXPECT(count == items);
117 
118  std::vector<SHAMapMissingNode> missingNodes;
119  source.walkMap(missingNodes, 2048);
120  BEAST_EXPECT(missingNodes.empty());
121 
122  std::vector<SHAMapNodeID> nodeIDs, gotNodeIDs;
123  std::vector< Blob > gotNodes;
124  std::vector<uint256> hashes;
125 
126  destination.setSynching ();
127 
128  {
129  std::vector<SHAMapNodeID> gotNodeIDs_a;
130  std::vector<Blob> gotNodes_a;
131 
132  BEAST_EXPECT(source.getNodeFat (
133  SHAMapNodeID (),
134  gotNodeIDs_a,
135  gotNodes_a,
136  rand_bool(eng_),
137  rand_int(eng_, 2)));
138 
139  unexpected (gotNodes_a.size () < 1, "NodeSize");
140 
141  BEAST_EXPECT(destination.addRootNode (
142  source.getHash(),
143  makeSlice(*gotNodes_a.begin ()),
144  snfWIRE,
145  nullptr).isGood());
146  }
147 
148  do
149  {
150  f.clock().advance(std::chrono::seconds(1));
151 
152  // get the list of nodes we know we need
153  auto nodesMissing = destination.getMissingNodes (2048, nullptr);
154 
155  if (nodesMissing.empty ())
156  break;
157 
158  // get as many nodes as possible based on this information
159  std::vector<SHAMapNodeID> gotNodeIDs_b;
160  std::vector<Blob> gotNodes_b;
161 
162  for (auto& it : nodesMissing)
163  {
164  // Don't use BEAST_EXPECT here b/c it will be called a non-deterministic number of times
165  // and the number of tests run should be deterministic
166  if (!source.getNodeFat(
167  it.first,
168  gotNodeIDs_b,
169  gotNodes_b,
170  rand_bool(eng_),
171  rand_int(eng_, 2)))
172  fail("", __FILE__, __LINE__);
173  }
174 
175  // Don't use BEAST_EXPECT here b/c it will be called a non-deterministic number of times
176  // and the number of tests run should be deterministic
177  if (gotNodeIDs_b.size() != gotNodes_b.size() ||
178  gotNodeIDs_b.empty())
179  fail("", __FILE__, __LINE__);
180 
181  for (std::size_t i = 0; i < gotNodeIDs_b.size(); ++i)
182  {
183  // Don't use BEAST_EXPECT here b/c it will be called a non-deterministic number of times
184  // and the number of tests run should be deterministic
185  if (!destination
186  .addKnownNode(
187  gotNodeIDs_b[i], makeSlice(gotNodes_b[i]), nullptr)
188  .isUseful())
189  fail("", __FILE__, __LINE__);
190  }
191  }
192  while (true);
193 
194  destination.clearSynching ();
195 
196  BEAST_EXPECT(source.deepCompare (destination));
197 
198  log << "Checking destination invariants..." << std::endl;
199  destination.invariants();
200  }
201 
202 };
203 
204 BEAST_DEFINE_TESTSUITE(SHAMapSync,shamap,ripple);
205 
206 } // tests
207 } // ripple
ripple::SHAMap::invariants
void invariants() const
Definition: SHAMap.cpp:1079
ripple::SHAMap::clearSynching
void clearSynching()
Definition: SHAMap.h:429
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:199
std::shared_ptr
STL class.
ripple::SHAMap::getHash
SHAMapHash getHash() const
Definition: SHAMap.cpp:751
ripple::tests::SHAMapSync_test::run
void run() override
Definition: SHAMapSync_test.cpp:88
std::list
STL class.
ripple::SHAMap::deepCompare
bool deepCompare(SHAMap &other) const
Definition: SHAMapSync.cpp:647
ripple::tests::TestFamily
Definition: common.h:32
ripple::SHAMap::getNodeFat
bool getNodeFat(SHAMapNodeID node, std::vector< SHAMapNodeID > &nodeIDs, std::vector< Blob > &rawNode, bool fatLeaves, std::uint32_t depth) const
Definition: SHAMapSync.cpp:428
std::vector
STL class.
std::vector::size
T size(T... args)
std::chrono::seconds
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:121
beast::severities
A namespace for easy access to logging severity values.
Definition: Journal.h:29
ripple::Serializer::add32
int add32(std::uint32_t)
Definition: Serializer.cpp:46
ripple::tests::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(cluster, overlay, ripple)
ripple::SHAMapNodeID
Definition: SHAMapNodeID.h:33
ripple::tests::SHAMapSync_test::makeRandomAS
std::shared_ptr< SHAMapItem > makeRandomAS()
Definition: SHAMapSync_test.cpp:37
ripple::Serializer::getSHA512Half
uint256 getSHA512Half() const
Definition: Serializer.cpp:203
ripple::SHAMapHash
Definition: SHAMapTreeNode.h:44
std::list::push_back
T push_back(T... args)
ripple::SHAMap::visitLeaves
void visitLeaves(std::function< void(std::shared_ptr< SHAMapItem const > const &)> const &) const
Visit every leaf node in this SHAMap.
Definition: SHAMapSync.cpp:27
ripple::SHAMapAddNode::isGood
bool isGood() const
Definition: SHAMapAddNode.h:135
ripple::SHAMap
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
Definition: SHAMap.h:79
ripple::tests::SHAMapSync_test
Definition: SHAMapSync_test.cpp:32
ripple::tests::SHAMapSync_test::eng_
beast::xor_shift_engine eng_
Definition: SHAMapSync_test.cpp:35
ripple::SHAMap::addRootNode
SHAMapAddNode addRootNode(SHAMapHash const &hash, Slice const &rootNode, SHANodeFormat format, SHAMapSyncFilter *filter)
Definition: SHAMapSync.cpp:525
ripple::SHAMap::getMissingNodes
std::vector< std::pair< SHAMapNodeID, uint256 > > getMissingNodes(int maxNodes, SHAMapSyncFilter *filter)
Check for nodes in the SHAMap not available.
Definition: SHAMapSync.cpp:307
ripple::test::SuiteJournal
Definition: SuiteJournal.h:81
ripple::SHAMap::walkMap
void walkMap(std::vector< SHAMapMissingNode > &missingNodes, int maxMissing) const
Definition: SHAMapDelta.cpp:228
ripple::Serializer
Definition: Serializer.h:43
ripple::SHAMap::setImmutable
void setImmutable()
Definition: SHAMap.h:407
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::endl
T endl(T... args)
std::vector::begin
T begin(T... args)
ripple::Serializer::peekData
Blob const & peekData() const
Definition: Serializer.h:173
ripple::snfWIRE
@ snfWIRE
Definition: SHAMapTreeNode.h:38
ripple::tests::SHAMapSync_test::confuseMap
bool confuseMap(SHAMap &map, int count)
Definition: SHAMapSync_test.cpp:48
std::vector::empty
T empty(T... args)
ripple::SHAMap::addItem
bool addItem(SHAMapItem &&i, bool isTransaction, bool hasMeta)
Definition: SHAMap.cpp:744
ripple::SHAMapType::FREE
@ FREE
std::size_t
beast::detail::xor_shift_engine
Definition: xor_shift_engine.h:32
ripple::rand_bool
bool rand_bool(Engine &engine)
Return a random boolean value.
Definition: ripple/basics/random.h:190
ripple::SHAMap::delItem
bool delItem(uint256 const &id)
Definition: SHAMap.cpp:593
ripple::SHAMap::setSynching
void setSynching()
Definition: SHAMap.h:422