rippled
Loading...
Searching...
No Matches
SHAMapSync_test.cpp
1#include <test/shamap/common.h>
2#include <test/unit_test/SuiteJournal.h>
3
4#include <xrpl/basics/random.h>
5#include <xrpl/beast/unit_test.h>
6#include <xrpl/beast/xor_shift_engine.h>
7#include <xrpl/shamap/SHAMap.h>
8#include <xrpl/shamap/SHAMapItem.h>
9
10namespace ripple {
11namespace tests {
12
14{
15public:
17
18 boost::intrusive_ptr<SHAMapItem>
20 {
21 Serializer s;
22
23 for (int d = 0; d < 3; ++d)
24 s.add32(rand_int<std::uint32_t>(eng_));
25 return make_shamapitem(s.getSHA512Half(), s.slice());
26 }
27
28 bool
29 confuseMap(SHAMap& map, int count)
30 {
31 // add a bunch of random states to a map, then remove them
32 // map should be the same
33 SHAMapHash beforeHash = map.getHash();
34
36
37 for (int i = 0; i < count; ++i)
38 {
39 auto item = makeRandomAS();
40 items.push_back(item->key());
41
43 {
44 log << "Unable to add item to map\n";
45 return false;
46 }
47 }
48
49 for (auto const& item : items)
50 {
51 if (!map.delItem(item))
52 {
53 log << "Unable to remove item from map\n";
54 return false;
55 }
56 }
57
58 if (beforeHash != map.getHash())
59 {
60 log << "Hashes do not match " << beforeHash << " " << map.getHash()
61 << std::endl;
62 return false;
63 }
64
65 return true;
66 }
67
68 void
69 run() override
70 {
71 using namespace beast::severities;
72 test::SuiteJournal journal("SHAMapSync_test", *this);
73
74 TestNodeFamily f(journal), f2(journal);
75 SHAMap source(SHAMapType::FREE, f);
76 SHAMap destination(SHAMapType::FREE, f2);
77
78 int items = 10000;
79 for (int i = 0; i < items; ++i)
80 {
82 if (i % 100 == 0)
83 source.invariants();
84 }
85
86 source.invariants();
87 BEAST_EXPECT(confuseMap(source, 500));
88 source.invariants();
89
90 source.setImmutable();
91
92 int count = 0;
93 source.visitLeaves([&count](auto const& item) { ++count; });
94 BEAST_EXPECT(count == items);
95
97 source.walkMap(missingNodes, 2048);
98 BEAST_EXPECT(missingNodes.empty());
99
100 std::vector<SHAMapNodeID> nodeIDs, gotNodeIDs;
101 std::vector<Blob> gotNodes;
103
104 destination.setSynching();
105
106 {
108
109 BEAST_EXPECT(source.getNodeFat(
111
112 unexpected(a.size() < 1, "NodeSize");
113
114 BEAST_EXPECT(
115 destination
116 .addRootNode(
117 source.getHash(), makeSlice(a[0].second), nullptr)
118 .isGood());
119 }
120
121 do
122 {
123 f.clock().advance(std::chrono::seconds(1));
124
125 // get the list of nodes we know we need
126 auto nodesMissing = destination.getMissingNodes(2048, nullptr);
127
128 if (nodesMissing.empty())
129 break;
130
131 // get as many nodes as possible based on this information
133
134 for (auto& it : nodesMissing)
135 {
136 // Don't use BEAST_EXPECT here b/c it will be called a
137 // non-deterministic number of times and the number of tests run
138 // should be deterministic
139 if (!source.getNodeFat(
140 it.first, b, rand_bool(eng_), rand_int(eng_, 2)))
141 fail("", __FILE__, __LINE__);
142 }
143
144 // Don't use BEAST_EXPECT here b/c it will be called a
145 // non-deterministic number of times and the number of tests run
146 // should be deterministic
147 if (b.empty())
148 fail("", __FILE__, __LINE__);
149
150 for (std::size_t i = 0; i < b.size(); ++i)
151 {
152 // Don't use BEAST_EXPECT here b/c it will be called a
153 // non-deterministic number of times and the number of tests run
154 // should be deterministic
155 if (!destination
156 .addKnownNode(
157 b[i].first, makeSlice(b[i].second), nullptr)
158 .isUseful())
159 fail("", __FILE__, __LINE__);
160 }
161 } while (true);
162
163 destination.clearSynching();
164
165 BEAST_EXPECT(source.deepCompare(destination));
166
167 destination.invariants();
168 }
169};
170
171BEAST_DEFINE_TESTSUITE(SHAMapSync, shamap, ripple);
172
173} // namespace tests
174} // namespace ripple
A testsuite class.
Definition suite.h:52
log_os< char > log
Logging output stream.
Definition suite.h:149
bool unexpected(Condition shouldBeFalse, String const &reason)
Definition suite.h:496
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition suite.h:530
Identifies a node inside a SHAMap.
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
Definition SHAMap.h:78
bool getNodeFat(SHAMapNodeID const &wanted, std::vector< std::pair< SHAMapNodeID, Blob > > &data, bool fatLeaves, std::uint32_t depth) const
void clearSynching()
Definition SHAMap.h:604
void setImmutable()
Definition SHAMap.h:583
void invariants() const
Definition SHAMap.cpp:1229
bool addItem(SHAMapNodeType type, boost::intrusive_ptr< SHAMapItem const > item)
Definition SHAMap.cpp:863
SHAMapHash getHash() const
Definition SHAMap.cpp:871
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.
void setSynching()
Definition SHAMap.h:598
bool delItem(uint256 const &id)
Definition SHAMap.cpp:702
void visitLeaves(std::function< void(boost::intrusive_ptr< SHAMapItem const > const &)> const &) const
Visit every leaf node in this SHAMap.
Definition SHAMapSync.cpp:9
bool deepCompare(SHAMap &other) const
Slice slice() const noexcept
Definition Serializer.h:47
uint256 getSHA512Half() const
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:11
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
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:225
boost::intrusive_ptr< SHAMapItem > make_shamapitem(uint256 const &tag, Slice data)
Definition SHAMapItem.h:142
T push_back(T... args)
T size(T... args)