rippled
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 <ripple/basics/chrono.h>
21 #include <ripple/basics/safe_cast.h>
22 #include <ripple/beast/clock/manual_clock.h>
23 #include <ripple/beast/unit_test.h>
24 #include <ripple/peerfinder/impl/Livecache.h>
25 #include <boost/algorithm/string.hpp>
26 #include <test/beast/IPEndpointCommon.h>
27 #include <test/unit_test/SuiteJournal.h>
28 
29 namespace ripple {
30 namespace PeerFinder {
31 
32 bool
33 operator==(Endpoint const& a, Endpoint const& b)
34 {
35  return (a.hops == b.hops && a.address == b.address);
36 }
37 
38 class Livecache_test : public beast::unit_test::suite
39 {
42 
43 public:
44  Livecache_test() : journal_("Livecache_test", *this)
45  {
46  }
47 
48  // Add the address as an endpoint
49  template <class C>
50  inline void
52  {
53  Endpoint cep{ep, hops};
54  c.insert(cep);
55  }
56 
57  void
59  {
60  testcase("Basic Insert");
62  BEAST_EXPECT(c.empty());
63 
64  for (auto i = 0; i < 10; ++i)
65  add(beast::IP::randomEP(true), c);
66 
67  BEAST_EXPECT(!c.empty());
68  BEAST_EXPECT(c.size() == 10);
69 
70  for (auto i = 0; i < 10; ++i)
71  add(beast::IP::randomEP(false), c);
72 
73  BEAST_EXPECT(!c.empty());
74  BEAST_EXPECT(c.size() == 20);
75  }
76 
77  void
79  {
80  testcase("Insert/Update");
82 
83  auto ep1 = Endpoint{beast::IP::randomEP(), 2};
84  c.insert(ep1);
85  BEAST_EXPECT(c.size() == 1);
86  // third position list will contain the entry
87  BEAST_EXPECT((c.hops.begin() + 2)->begin()->hops == 2);
88 
89  auto ep2 = Endpoint{ep1.address, 4};
90  // this will not change the entry has higher hops
91  c.insert(ep2);
92  BEAST_EXPECT(c.size() == 1);
93  // still in third position list
94  BEAST_EXPECT((c.hops.begin() + 2)->begin()->hops == 2);
95 
96  auto ep3 = Endpoint{ep1.address, 2};
97  // this will not change the entry has the same hops as existing
98  c.insert(ep3);
99  BEAST_EXPECT(c.size() == 1);
100  // still in third position list
101  BEAST_EXPECT((c.hops.begin() + 2)->begin()->hops == 2);
102 
103  auto ep4 = Endpoint{ep1.address, 1};
104  c.insert(ep4);
105  BEAST_EXPECT(c.size() == 1);
106  // now at second position list
107  BEAST_EXPECT((c.hops.begin() + 1)->begin()->hops == 1);
108  }
109 
110  void
112  {
113  testcase("Expire");
114  using namespace std::chrono_literals;
116 
117  auto ep1 = Endpoint{beast::IP::randomEP(), 1};
118  c.insert(ep1);
119  BEAST_EXPECT(c.size() == 1);
120  c.expire();
121  BEAST_EXPECT(c.size() == 1);
122  // verify that advancing to 1 sec before expiration
123  // leaves our entry intact
125  c.expire();
126  BEAST_EXPECT(c.size() == 1);
127  // now advance to the point of expiration
128  clock_.advance(1s);
129  c.expire();
130  BEAST_EXPECT(c.empty());
131  }
132 
133  void
135  {
136  testcase("Histogram");
137  constexpr auto num_eps = 40;
139  for (auto i = 0; i < num_eps; ++i)
140  add(beast::IP::randomEP(true),
141  c,
142  ripple::rand_int<std::uint32_t>());
143  auto h = c.hops.histogram();
144  if (!BEAST_EXPECT(!h.empty()))
145  return;
147  boost::split(v, h, boost::algorithm::is_any_of(","));
148  auto sum = 0;
149  for (auto const& n : v)
150  {
151  auto val = boost::lexical_cast<int>(boost::trim_copy(n));
152  sum += val;
153  BEAST_EXPECT(val >= 0);
154  }
155  BEAST_EXPECT(sum == num_eps);
156  }
157 
158  void
160  {
161  testcase("Shuffle");
163  for (auto i = 0; i < 100; ++i)
164  add(beast::IP::randomEP(true),
165  c,
167 
170 
171  auto cmp_EP = [](Endpoint const& a, Endpoint const& b) {
172  return (
173  b.hops < a.hops || (b.hops == a.hops && b.address < a.address));
174  };
175  all_hops before;
176  all_hops before_sorted;
177  for (auto i = std::make_pair(0, c.hops.begin());
178  i.second != c.hops.end();
179  ++i.first, ++i.second)
180  {
181  std::copy(
182  (*i.second).begin(),
183  (*i.second).end(),
184  std::back_inserter(before[i.first]));
185  std::copy(
186  (*i.second).begin(),
187  (*i.second).end(),
188  std::back_inserter(before_sorted[i.first]));
189  std::sort(
190  before_sorted[i.first].begin(),
191  before_sorted[i.first].end(),
192  cmp_EP);
193  }
194 
195  c.hops.shuffle();
196 
197  all_hops after;
198  all_hops after_sorted;
199  for (auto i = std::make_pair(0, c.hops.begin());
200  i.second != c.hops.end();
201  ++i.first, ++i.second)
202  {
203  std::copy(
204  (*i.second).begin(),
205  (*i.second).end(),
206  std::back_inserter(after[i.first]));
207  std::copy(
208  (*i.second).begin(),
209  (*i.second).end(),
210  std::back_inserter(after_sorted[i.first]));
211  std::sort(
212  after_sorted[i.first].begin(),
213  after_sorted[i.first].end(),
214  cmp_EP);
215  }
216 
217  // each hop bucket should contain the same items
218  // before and after sort, albeit in different order
219  bool all_match = true;
220  for (auto i = 0; i < before.size(); ++i)
221  {
222  BEAST_EXPECT(before[i].size() == after[i].size());
223  all_match = all_match && (before[i] == after[i]);
224  BEAST_EXPECT(before_sorted[i] == after_sorted[i]);
225  }
226  BEAST_EXPECT(!all_match);
227  }
228 
229  void
230  run() override
231  {
232  testBasicInsert();
234  testExpire();
235  testHistogram();
236  testShuffle();
237  }
238 };
239 
240 BEAST_DEFINE_TESTSUITE(Livecache, peerfinder, ripple);
241 
242 } // namespace PeerFinder
243 } // namespace ripple
ripple::PeerFinder::Livecache::hops_t::histogram
std::string histogram() const
Definition: Livecache.h:511
ripple::PeerFinder::Livecache_test::testHistogram
void testHistogram()
Definition: Livecache_test.cpp:134
beast::manual_clock::advance
void advance(std::chrono::duration< Rep, Period > const &elapsed)
Advance the clock by a duration.
Definition: manual_clock.h:79
ripple::PeerFinder::Livecache_test
Definition: Livecache_test.cpp:38
ripple::PeerFinder::Livecache_test::testBasicInsert
void testBasicInsert()
Definition: Livecache_test.cpp:58
ripple::PeerFinder::Livecache_test::add
void add(beast::IP::Endpoint ep, C &c, std::uint32_t hops=0)
Definition: Livecache_test.cpp:51
std::vector< std::string >
std::back_inserter
T back_inserter(T... args)
ripple::PeerFinder::Livecache_test::clock_
TestStopwatch clock_
Definition: Livecache_test.cpp:40
ripple::PeerFinder::Livecache_test::Livecache_test
Livecache_test()
Definition: Livecache_test.cpp:44
ripple::PeerFinder::Tuning::liveCacheSecondsToLive
constexpr std::chrono::seconds liveCacheSecondsToLive(30)
std::sort
T sort(T... args)
ripple::PeerFinder::Livecache::size
cache_type::size_type size() const
Returns the number of entries in the cache.
Definition: Livecache.h:374
ripple::PeerFinder::Livecache_test::testInsertUpdate
void testInsertUpdate()
Definition: Livecache_test.cpp:78
ripple::PeerFinder::Livecache::insert
void insert(Endpoint const &ep)
Creates or updates an existing Element based on a new message.
Definition: Livecache.h:427
ripple::rand_int
std::enable_if_t< std::is_integral< Integral >::value &&detail::is_engine< Engine >::value, Integral > rand_int(Engine &engine, Integral min, Integral max)
Return a uniformly distributed random integer.
Definition: ripple/basics/random.h:115
ripple::PeerFinder::Livecache::hops_t::shuffle
void shuffle()
Shuffle each hop list.
Definition: Livecache.h:495
std::array
STL class.
ripple::PeerFinder::Endpoint::hops
std::uint32_t hops
Definition: PeerfinderManager.h:119
ripple::PeerFinder::Livecache_test::run
void run() override
Definition: Livecache_test.cpp:230
ripple::PeerFinder::Livecache
The Livecache holds the short-lived relayed Endpoint messages.
Definition: Livecache.h:39
std::copy
T copy(T... args)
std::uint32_t
ripple::PeerFinder::Livecache_test::testShuffle
void testShuffle()
Definition: Livecache_test.cpp:159
ripple::test::SuiteJournal
Definition: SuiteJournal.h:88
ripple::PeerFinder::Livecache::hops
class ripple::PeerFinder::Livecache::hops_t hops
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::PeerFinder::Livecache::hops_t::end
iterator end()
Definition: Livecache.h:287
ripple::PeerFinder::operator==
bool operator==(Endpoint const &a, Endpoint const &b)
Definition: Livecache_test.cpp:33
ripple::PeerFinder::Livecache::expire
void expire()
Erase entries whose time has expired.
Definition: Livecache.h:405
ripple::PeerFinder::Livecache_test::journal_
test::SuiteJournal journal_
Definition: Livecache_test.cpp:41
ripple::PeerFinder::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(Livecache, peerfinder, ripple)
ripple::PeerFinder::Livecache::empty
bool empty() const
Returns true if the cache is empty.
Definition: Livecache.h:367
beast::IP::randomEP
Endpoint randomEP(bool v4=true)
Definition: IPEndpointCommon.h:27
ripple::after
static bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition: Escrow.cpp:88
std::make_pair
T make_pair(T... args)
beast::IP::Endpoint
A version-independent IP address and port combination.
Definition: IPEndpoint.h:38
ripple::PeerFinder::Tuning::maxHops
constexpr std::uint32_t maxHops
Definition: peerfinder/impl/Tuning.h:110
beast::manual_clock< std::chrono::steady_clock >
ripple::PeerFinder::Endpoint
Describes a connectible peer address along with some metadata.
Definition: PeerfinderManager.h:113
ripple::sum
static auto sum(TCollection const &col)
Definition: BookStep.cpp:710
ripple::PeerFinder::Endpoint::address
beast::IP::Endpoint address
Definition: PeerfinderManager.h:120
ripple::PeerFinder::Livecache_test::testExpire
void testExpire()
Definition: Livecache_test.cpp:111
ripple::PeerFinder::Livecache::hops_t::begin
iterator begin()
Definition: Livecache.h:269