rippled
Loading...
Searching...
No Matches
Livecache_test.cpp
1#include <test/beast/IPEndpointCommon.h>
2#include <test/unit_test/SuiteJournal.h>
3
4#include <xrpld/peerfinder/detail/Livecache.h>
5
6#include <xrpl/basics/chrono.h>
7#include <xrpl/beast/clock/manual_clock.h>
8#include <xrpl/beast/unit_test.h>
9
10#include <boost/algorithm/string.hpp>
11
12namespace xrpl {
13namespace PeerFinder {
14
15bool
16operator==(Endpoint const& a, Endpoint const& b)
17{
18 return (a.hops == b.hops && a.address == b.address);
19}
20
22{
25
26public:
27 Livecache_test() : journal_("Livecache_test", *this)
28 {
29 }
30
31 // Add the address as an endpoint
32 template <class C>
33 inline void
35 {
36 Endpoint cep{ep, hops};
37 c.insert(cep);
38 }
39
40 void
42 {
43 testcase("Basic Insert");
45 BEAST_EXPECT(c.empty());
46
47 for (auto i = 0; i < 10; ++i)
48 add(beast::IP::randomEP(true), c);
49
50 BEAST_EXPECT(!c.empty());
51 BEAST_EXPECT(c.size() == 10);
52
53 for (auto i = 0; i < 10; ++i)
54 add(beast::IP::randomEP(false), c);
55
56 BEAST_EXPECT(!c.empty());
57 BEAST_EXPECT(c.size() == 20);
58 }
59
60 void
62 {
63 testcase("Insert/Update");
65
66 auto ep1 = Endpoint{beast::IP::randomEP(), 2};
67 c.insert(ep1);
68 BEAST_EXPECT(c.size() == 1);
69 // third position list will contain the entry
70 BEAST_EXPECT((c.hops.begin() + 2)->begin()->hops == 2);
71
72 auto ep2 = Endpoint{ep1.address, 4};
73 // this will not change the entry has higher hops
74 c.insert(ep2);
75 BEAST_EXPECT(c.size() == 1);
76 // still in third position list
77 BEAST_EXPECT((c.hops.begin() + 2)->begin()->hops == 2);
78
79 auto ep3 = Endpoint{ep1.address, 2};
80 // this will not change the entry has the same hops as existing
81 c.insert(ep3);
82 BEAST_EXPECT(c.size() == 1);
83 // still in third position list
84 BEAST_EXPECT((c.hops.begin() + 2)->begin()->hops == 2);
85
86 auto ep4 = Endpoint{ep1.address, 1};
87 c.insert(ep4);
88 BEAST_EXPECT(c.size() == 1);
89 // now at second position list
90 BEAST_EXPECT((c.hops.begin() + 1)->begin()->hops == 1);
91 }
92
93 void
95 {
96 testcase("Expire");
97 using namespace std::chrono_literals;
99
100 auto ep1 = Endpoint{beast::IP::randomEP(), 1};
101 c.insert(ep1);
102 BEAST_EXPECT(c.size() == 1);
103 c.expire();
104 BEAST_EXPECT(c.size() == 1);
105 // verify that advancing to 1 sec before expiration
106 // leaves our entry intact
108 c.expire();
109 BEAST_EXPECT(c.size() == 1);
110 // now advance to the point of expiration
111 clock_.advance(1s);
112 c.expire();
113 BEAST_EXPECT(c.empty());
114 }
115
116 void
118 {
119 testcase("Histogram");
120 constexpr auto num_eps = 40;
122 for (auto i = 0; i < num_eps; ++i)
123 add(beast::IP::randomEP(true), c, xrpl::rand_int<std::uint32_t>());
124 auto h = c.hops.histogram();
125 if (!BEAST_EXPECT(!h.empty()))
126 return;
128 boost::split(v, h, boost::algorithm::is_any_of(","));
129 auto sum = 0;
130 for (auto const& n : v)
131 {
132 auto val = boost::lexical_cast<int>(boost::trim_copy(n));
133 sum += val;
134 BEAST_EXPECT(val >= 0);
135 }
136 BEAST_EXPECT(sum == num_eps);
137 }
138
139 void
141 {
142 testcase("Shuffle");
144 for (auto i = 0; i < 100; ++i)
146 c,
148
151
152 auto cmp_EP = [](Endpoint const& a, Endpoint const& b) {
153 return (
154 b.hops < a.hops || (b.hops == a.hops && b.address < a.address));
155 };
156 all_hops before;
157 all_hops before_sorted;
158 for (auto i = std::make_pair(0, c.hops.begin());
159 i.second != c.hops.end();
160 ++i.first, ++i.second)
161 {
162 std::copy(
163 (*i.second).begin(),
164 (*i.second).end(),
165 std::back_inserter(before[i.first]));
166 std::copy(
167 (*i.second).begin(),
168 (*i.second).end(),
169 std::back_inserter(before_sorted[i.first]));
170 std::sort(
171 before_sorted[i.first].begin(),
172 before_sorted[i.first].end(),
173 cmp_EP);
174 }
175
176 c.hops.shuffle();
177
178 all_hops after;
179 all_hops after_sorted;
180 for (auto i = std::make_pair(0, c.hops.begin());
181 i.second != c.hops.end();
182 ++i.first, ++i.second)
183 {
184 std::copy(
185 (*i.second).begin(),
186 (*i.second).end(),
187 std::back_inserter(after[i.first]));
188 std::copy(
189 (*i.second).begin(),
190 (*i.second).end(),
191 std::back_inserter(after_sorted[i.first]));
192 std::sort(
193 after_sorted[i.first].begin(),
194 after_sorted[i.first].end(),
195 cmp_EP);
196 }
197
198 // each hop bucket should contain the same items
199 // before and after sort, albeit in different order
200 bool all_match = true;
201 for (auto i = 0; i < before.size(); ++i)
202 {
203 BEAST_EXPECT(before[i].size() == after[i].size());
204 all_match = all_match && (before[i] == after[i]);
205 BEAST_EXPECT(before_sorted[i] == after_sorted[i]);
206 }
207 BEAST_EXPECT(!all_match);
208 }
209
210 void
211 run() override
212 {
215 testExpire();
217 testShuffle();
218 }
219};
220
221BEAST_DEFINE_TESTSUITE(Livecache, peerfinder, xrpl);
222
223} // namespace PeerFinder
224} // namespace xrpl
T back_inserter(T... args)
A version-independent IP address and port combination.
Definition IPEndpoint.h:19
void advance(std::chrono::duration< Rep, Period > const &elapsed)
Advance the clock by a duration.
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
void shuffle()
Shuffle each hop list.
Definition Livecache.h:480
void add(beast::IP::Endpoint ep, C &c, std::uint32_t hops=0)
void run() override
Runs the suite.
The Livecache holds the short-lived relayed Endpoint messages.
Definition Livecache.h:179
cache_type::size_type size() const
Returns the number of entries in the cache.
Definition Livecache.h:357
class xrpl::PeerFinder::Livecache::hops_t hops
void expire()
Erase entries whose time has expired.
Definition Livecache.h:388
void insert(Endpoint const &ep)
Creates or updates an existing Element based on a new message.
Definition Livecache.h:410
bool empty() const
Returns true if the cache is empty.
Definition Livecache.h:350
T copy(T... args)
T make_pair(T... args)
Endpoint randomEP(bool v4=true)
std::chrono::seconds constexpr liveCacheSecondsToLive(30)
bool operator==(Endpoint const &a, Endpoint const &b)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
static auto sum(TCollection const &col)
Definition BookStep.cpp:976
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:3922
T sort(T... args)
Describes a connectable peer address along with some metadata.