rippled
Loading...
Searching...
No Matches
Livecache_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/beast/IPEndpointCommon.h>
21#include <test/unit_test/SuiteJournal.h>
22
23#include <xrpld/peerfinder/detail/Livecache.h>
24
25#include <xrpl/basics/chrono.h>
26#include <xrpl/beast/clock/manual_clock.h>
27#include <xrpl/beast/unit_test.h>
28
29#include <boost/algorithm/string.hpp>
30
31namespace ripple {
32namespace PeerFinder {
33
34bool
35operator==(Endpoint const& a, Endpoint const& b)
36{
37 return (a.hops == b.hops && a.address == b.address);
38}
39
41{
44
45public:
46 Livecache_test() : journal_("Livecache_test", *this)
47 {
48 }
49
50 // Add the address as an endpoint
51 template <class C>
52 inline void
54 {
55 Endpoint cep{ep, hops};
56 c.insert(cep);
57 }
58
59 void
61 {
62 testcase("Basic Insert");
64 BEAST_EXPECT(c.empty());
65
66 for (auto i = 0; i < 10; ++i)
67 add(beast::IP::randomEP(true), c);
68
69 BEAST_EXPECT(!c.empty());
70 BEAST_EXPECT(c.size() == 10);
71
72 for (auto i = 0; i < 10; ++i)
73 add(beast::IP::randomEP(false), c);
74
75 BEAST_EXPECT(!c.empty());
76 BEAST_EXPECT(c.size() == 20);
77 }
78
79 void
81 {
82 testcase("Insert/Update");
84
85 auto ep1 = Endpoint{beast::IP::randomEP(), 2};
86 c.insert(ep1);
87 BEAST_EXPECT(c.size() == 1);
88 // third position list will contain the entry
89 BEAST_EXPECT((c.hops.begin() + 2)->begin()->hops == 2);
90
91 auto ep2 = Endpoint{ep1.address, 4};
92 // this will not change the entry has higher hops
93 c.insert(ep2);
94 BEAST_EXPECT(c.size() == 1);
95 // still in third position list
96 BEAST_EXPECT((c.hops.begin() + 2)->begin()->hops == 2);
97
98 auto ep3 = Endpoint{ep1.address, 2};
99 // this will not change the entry has the same hops as existing
100 c.insert(ep3);
101 BEAST_EXPECT(c.size() == 1);
102 // still in third position list
103 BEAST_EXPECT((c.hops.begin() + 2)->begin()->hops == 2);
104
105 auto ep4 = Endpoint{ep1.address, 1};
106 c.insert(ep4);
107 BEAST_EXPECT(c.size() == 1);
108 // now at second position list
109 BEAST_EXPECT((c.hops.begin() + 1)->begin()->hops == 1);
110 }
111
112 void
114 {
115 testcase("Expire");
116 using namespace std::chrono_literals;
118
119 auto ep1 = Endpoint{beast::IP::randomEP(), 1};
120 c.insert(ep1);
121 BEAST_EXPECT(c.size() == 1);
122 c.expire();
123 BEAST_EXPECT(c.size() == 1);
124 // verify that advancing to 1 sec before expiration
125 // leaves our entry intact
127 c.expire();
128 BEAST_EXPECT(c.size() == 1);
129 // now advance to the point of expiration
130 clock_.advance(1s);
131 c.expire();
132 BEAST_EXPECT(c.empty());
133 }
134
135 void
137 {
138 testcase("Histogram");
139 constexpr auto num_eps = 40;
141 for (auto i = 0; i < num_eps; ++i)
143 c,
144 ripple::rand_int<std::uint32_t>());
145 auto h = c.hops.histogram();
146 if (!BEAST_EXPECT(!h.empty()))
147 return;
149 boost::split(v, h, boost::algorithm::is_any_of(","));
150 auto sum = 0;
151 for (auto const& n : v)
152 {
153 auto val = boost::lexical_cast<int>(boost::trim_copy(n));
154 sum += val;
155 BEAST_EXPECT(val >= 0);
156 }
157 BEAST_EXPECT(sum == num_eps);
158 }
159
160 void
162 {
163 testcase("Shuffle");
165 for (auto i = 0; i < 100; ++i)
167 c,
169
172
173 auto cmp_EP = [](Endpoint const& a, Endpoint const& b) {
174 return (
175 b.hops < a.hops || (b.hops == a.hops && b.address < a.address));
176 };
177 all_hops before;
178 all_hops before_sorted;
179 for (auto i = std::make_pair(0, c.hops.begin());
180 i.second != c.hops.end();
181 ++i.first, ++i.second)
182 {
183 std::copy(
184 (*i.second).begin(),
185 (*i.second).end(),
186 std::back_inserter(before[i.first]));
187 std::copy(
188 (*i.second).begin(),
189 (*i.second).end(),
190 std::back_inserter(before_sorted[i.first]));
191 std::sort(
192 before_sorted[i.first].begin(),
193 before_sorted[i.first].end(),
194 cmp_EP);
195 }
196
197 c.hops.shuffle();
198
199 all_hops after;
200 all_hops after_sorted;
201 for (auto i = std::make_pair(0, c.hops.begin());
202 i.second != c.hops.end();
203 ++i.first, ++i.second)
204 {
205 std::copy(
206 (*i.second).begin(),
207 (*i.second).end(),
208 std::back_inserter(after[i.first]));
209 std::copy(
210 (*i.second).begin(),
211 (*i.second).end(),
212 std::back_inserter(after_sorted[i.first]));
213 std::sort(
214 after_sorted[i.first].begin(),
215 after_sorted[i.first].end(),
216 cmp_EP);
217 }
218
219 // each hop bucket should contain the same items
220 // before and after sort, albeit in different order
221 bool all_match = true;
222 for (auto i = 0; i < before.size(); ++i)
223 {
224 BEAST_EXPECT(before[i].size() == after[i].size());
225 all_match = all_match && (before[i] == after[i]);
226 BEAST_EXPECT(before_sorted[i] == after_sorted[i]);
227 }
228 BEAST_EXPECT(!all_match);
229 }
230
231 void
232 run() override
233 {
236 testExpire();
238 testShuffle();
239 }
240};
241
242BEAST_DEFINE_TESTSUITE(Livecache, peerfinder, ripple);
243
244} // namespace PeerFinder
245} // namespace ripple
T back_inserter(T... args)
A version-independent IP address and port combination.
Definition IPEndpoint.h:38
void advance(std::chrono::duration< Rep, Period > const &elapsed)
Advance the clock by a duration.
A testsuite class.
Definition suite.h:55
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:155
void shuffle()
Shuffle each hop list.
Definition Livecache.h:499
void run() override
Runs the suite.
void add(beast::IP::Endpoint ep, C &c, std::uint32_t hops=0)
The Livecache holds the short-lived relayed Endpoint messages.
Definition Livecache.h:198
cache_type::size_type size() const
Returns the number of entries in the cache.
Definition Livecache.h:376
void expire()
Erase entries whose time has expired.
Definition Livecache.h:407
void insert(Endpoint const &ep)
Creates or updates an existing Element based on a new message.
Definition Livecache.h:429
class ripple::PeerFinder::Livecache::hops_t hops
bool empty() const
Returns true if the cache is empty.
Definition Livecache.h:369
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:25
static auto sum(TCollection const &col)
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:3239
T sort(T... args)
Describes a connectible peer address along with some metadata.