rippled
Loading...
Searching...
No Matches
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 <test/shamap/common.h>
21#include <test/unit_test/SuiteJournal.h>
22#include <xrpld/shamap/SHAMap.h>
23#include <xrpld/shamap/SHAMapItem.h>
24#include <xrpl/basics/StringUtilities.h>
25#include <xrpl/basics/random.h>
26#include <xrpl/beast/unit_test.h>
27#include <xrpl/beast/xor_shift_engine.h>
28
29namespace ripple {
30namespace tests {
31
33{
34public:
36
37 boost::intrusive_ptr<SHAMapItem>
39 {
40 Serializer s;
41
42 for (int d = 0; d < 3; ++d)
43 s.add32(rand_int<std::uint32_t>(eng_));
44 return make_shamapitem(s.getSHA512Half(), s.slice());
45 }
46
47 bool
48 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
55
56 for (int i = 0; i < count; ++i)
57 {
58 auto item = makeRandomAS();
59 items.push_back(item->key());
60
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 << "Hashes do not match " << beforeHash << " " << map.getHash()
80 << std::endl;
81 return false;
82 }
83
84 return true;
85 }
86
87 void
88 run() override
89 {
90 using namespace beast::severities;
91 test::SuiteJournal journal("SHAMapSync_test", *this);
92
93 TestNodeFamily 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 {
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) { ++count; });
113 BEAST_EXPECT(count == items);
114
116 source.walkMap(missingNodes, 2048);
117 BEAST_EXPECT(missingNodes.empty());
118
119 std::vector<SHAMapNodeID> nodeIDs, gotNodeIDs;
120 std::vector<Blob> gotNodes;
122
123 destination.setSynching();
124
125 {
127
128 BEAST_EXPECT(source.getNodeFat(
130
131 unexpected(a.size() < 1, "NodeSize");
132
133 BEAST_EXPECT(
134 destination
135 .addRootNode(
136 source.getHash(), makeSlice(a[0].second), nullptr)
137 .isGood());
138 }
139
140 do
141 {
142 f.clock().advance(std::chrono::seconds(1));
143
144 // get the list of nodes we know we need
145 auto nodesMissing = destination.getMissingNodes(2048, nullptr);
146
147 if (nodesMissing.empty())
148 break;
149
150 // get as many nodes as possible based on this information
152
153 for (auto& it : nodesMissing)
154 {
155 // Don't use BEAST_EXPECT here b/c it will be called a
156 // non-deterministic number of times and the number of tests run
157 // should be deterministic
158 if (!source.getNodeFat(
159 it.first, b, rand_bool(eng_), rand_int(eng_, 2)))
160 fail("", __FILE__, __LINE__);
161 }
162
163 // Don't use BEAST_EXPECT here b/c it will be called a
164 // non-deterministic number of times and the number of tests run
165 // should be deterministic
166 if (b.empty())
167 fail("", __FILE__, __LINE__);
168
169 for (std::size_t i = 0; i < b.size(); ++i)
170 {
171 // Don't use BEAST_EXPECT here b/c it will be called a
172 // non-deterministic number of times and the number of tests run
173 // should be deterministic
174 if (!destination
175 .addKnownNode(
176 b[i].first, makeSlice(b[i].second), nullptr)
177 .isUseful())
178 fail("", __FILE__, __LINE__);
179 }
180 } while (true);
181
182 destination.clearSynching();
183
184 BEAST_EXPECT(source.deepCompare(destination));
185
186 destination.invariants();
187 }
188};
189
190BEAST_DEFINE_TESTSUITE(SHAMapSync, shamap, ripple);
191
192} // namespace tests
193} // namespace ripple
A testsuite class.
Definition: suite.h:53
log_os< char > log
Logging output stream.
Definition: suite.h:150
bool unexpected(Condition shouldBeFalse, String const &reason)
Definition: suite.h:497
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition: suite.h:531
Identifies a node inside a SHAMap.
Definition: SHAMapNodeID.h:34
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
Definition: SHAMap.h:96
bool getNodeFat(SHAMapNodeID const &wanted, std::vector< std::pair< SHAMapNodeID, Blob > > &data, bool fatLeaves, std::uint32_t depth) const
Definition: SHAMapSync.cpp:431
void clearSynching()
Definition: SHAMap.h:621
void setImmutable()
Definition: SHAMap.h:600
void invariants() const
Definition: SHAMap.cpp:1242
bool addItem(SHAMapNodeType type, boost::intrusive_ptr< SHAMapItem const > item)
Definition: SHAMap.cpp:880
SHAMapHash getHash() const
Definition: SHAMap.cpp:888
void walkMap(std::vector< SHAMapMissingNode > &missingNodes, int maxMissing) const
std::vector< std::pair< SHAMapNodeID, uint256 > > getMissingNodes(int maxNodes, SHAMapSyncFilter *filter)
Check for nodes in the SHAMap not available.
Definition: SHAMapSync.cpp:315
void setSynching()
Definition: SHAMap.h:615
bool delItem(uint256 const &id)
Definition: SHAMap.cpp:721
void visitLeaves(std::function< void(boost::intrusive_ptr< SHAMapItem const > const &)> const &) const
Visit every leaf node in this SHAMap.
Definition: SHAMapSync.cpp:27
bool deepCompare(SHAMap &other) const
Definition: SHAMapSync.cpp:673
Slice slice() const noexcept
Definition: Serializer.h:66
uint256 getSHA512Half() const
Definition: Serializer.cpp:171
boost::intrusive_ptr< SHAMapItem > makeRandomAS()
bool confuseMap(SHAMap &map, int count)
void run() override
Runs the suite.
beast::xor_shift_engine eng_
T empty(T... args)
T endl(T... args)
A namespace for easy access to logging severity values.
Definition: Journal.h:29
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
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:243
boost::intrusive_ptr< SHAMapItem > make_shamapitem(uint256 const &tag, Slice data)
Definition: SHAMapItem.h:160
T push_back(T... args)
T size(T... args)