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 xrpl {
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() << std::endl;
61 return false;
62 }
63
64 return true;
65 }
66
67 void
68 run() override
69 {
70 using namespace beast::severities;
71 test::SuiteJournal journal("SHAMapSync_test", *this);
72
73 TestNodeFamily f(journal), f2(journal);
74 SHAMap source(SHAMapType::FREE, f);
75 SHAMap destination(SHAMapType::FREE, f2);
76
77 int items = 10000;
78 for (int i = 0; i < items; ++i)
79 {
81 if (i % 100 == 0)
82 source.invariants();
83 }
84
85 source.invariants();
86 BEAST_EXPECT(confuseMap(source, 500));
87 source.invariants();
88
89 source.setImmutable();
90
91 int count = 0;
92 source.visitLeaves([&count](auto const& item) { ++count; });
93 BEAST_EXPECT(count == items);
94
96 source.walkMap(missingNodes, 2048);
97 BEAST_EXPECT(missingNodes.empty());
98
99 std::vector<SHAMapNodeID> nodeIDs, gotNodeIDs;
100 std::vector<Blob> gotNodes;
102
103 destination.setSynching();
104
105 {
107
108 BEAST_EXPECT(source.getNodeFat(SHAMapNodeID(), a, rand_bool(eng_), rand_int(eng_, 2)));
109
110 unexpected(a.size() < 1, "NodeSize");
111
112 BEAST_EXPECT(destination.addRootNode(source.getHash(), makeSlice(a[0].second), nullptr).isGood());
113 }
114
115 do
116 {
117 f.clock().advance(std::chrono::seconds(1));
118
119 // get the list of nodes we know we need
120 auto nodesMissing = destination.getMissingNodes(2048, nullptr);
121
122 if (nodesMissing.empty())
123 break;
124
125 // get as many nodes as possible based on this information
127
128 for (auto& it : nodesMissing)
129 {
130 // Don't use BEAST_EXPECT here b/c it will be called a
131 // non-deterministic number of times and the number of tests run
132 // should be deterministic
133 if (!source.getNodeFat(it.first, b, rand_bool(eng_), rand_int(eng_, 2)))
134 fail("", __FILE__, __LINE__);
135 }
136
137 // Don't use BEAST_EXPECT here b/c it will be called a
138 // non-deterministic number of times and the number of tests run
139 // should be deterministic
140 if (b.empty())
141 fail("", __FILE__, __LINE__);
142
143 for (std::size_t i = 0; i < b.size(); ++i)
144 {
145 // Don't use BEAST_EXPECT here b/c it will be called a
146 // non-deterministic number of times and the number of tests run
147 // should be deterministic
148 if (!destination.addKnownNode(b[i].first, makeSlice(b[i].second), nullptr).isUseful())
149 fail("", __FILE__, __LINE__);
150 }
151 } while (true);
152
153 destination.clearSynching();
154
155 BEAST_EXPECT(source.deepCompare(destination));
156
157 destination.invariants();
158 }
159};
160
161BEAST_DEFINE_TESTSUITE(SHAMapSync, shamap, xrpl);
162
163} // namespace tests
164} // namespace xrpl
A testsuite class.
Definition suite.h:51
log_os< char > log
Logging output stream.
Definition suite.h:144
bool unexpected(Condition shouldBeFalse, String const &reason)
Definition suite.h:482
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition suite.h:516
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:77
bool addItem(SHAMapNodeType type, boost::intrusive_ptr< SHAMapItem const > item)
Definition SHAMap.cpp:775
void walkMap(std::vector< SHAMapMissingNode > &missingNodes, int maxMissing) const
bool deepCompare(SHAMap &other) const
void visitLeaves(std::function< void(boost::intrusive_ptr< SHAMapItem const > const &)> const &) const
Visit every leaf node in this SHAMap.
Definition SHAMapSync.cpp:9
void setImmutable()
Definition SHAMap.h:523
bool getNodeFat(SHAMapNodeID const &wanted, std::vector< std::pair< SHAMapNodeID, Blob > > &data, bool fatLeaves, std::uint32_t depth) const
void invariants() const
Definition SHAMap.cpp:1115
SHAMapHash getHash() const
Definition SHAMap.cpp:781
bool delItem(uint256 const &id)
Definition SHAMap.cpp:631
uint256 getSHA512Half() const
Slice slice() const noexcept
Definition Serializer.h:44
bool confuseMap(SHAMap &map, int count)
boost::intrusive_ptr< SHAMapItem > makeRandomAS()
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:10
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
boost::intrusive_ptr< SHAMapItem > make_shamapitem(uint256 const &tag, Slice data)
Definition SHAMapItem.h:137
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:213
T push_back(T... args)
T size(T... args)