rippled
BasicNetwork_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2015 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/beast/unit_test.h>
21 #include <set>
22 #include <test/csf/BasicNetwork.h>
23 #include <test/csf/Scheduler.h>
24 #include <vector>
25 
26 namespace ripple {
27 namespace test {
28 
29 class BasicNetwork_test : public beast::unit_test::suite
30 {
31 public:
32  struct Peer
33  {
34  int id;
36 
37  Peer(Peer const&) = default;
38  Peer(Peer&&) = default;
39 
40  explicit Peer(int id_) : id(id_)
41  {
42  }
43 
44  template <class Net>
45  void
46  start(csf::Scheduler& scheduler, Net& net)
47  {
48  using namespace std::chrono_literals;
49  auto t = scheduler.in(1s, [&] { set.insert(0); });
50  if (id == 0)
51  {
52  for (auto const link : net.links(this))
53  net.send(this, link.target, [&, to = link.target] {
54  to->receive(net, this, 1);
55  });
56  }
57  else
58  {
59  scheduler.cancel(t);
60  }
61  }
62 
63  template <class Net>
64  void
65  receive(Net& net, Peer* from, int m)
66  {
67  set.insert(m);
68  ++m;
69  if (m < 5)
70  {
71  for (auto const link : net.links(this))
72  net.send(this, link.target, [&, mm = m, to = link.target] {
73  to->receive(net, this, mm);
74  });
75  }
76  }
77  };
78 
79  void
81  {
82  using namespace std::chrono_literals;
84  pv.emplace_back(0);
85  pv.emplace_back(1);
86  pv.emplace_back(2);
87  csf::Scheduler scheduler;
88  csf::BasicNetwork<Peer*> net(scheduler);
89  BEAST_EXPECT(!net.connect(&pv[0], &pv[0]));
90  BEAST_EXPECT(net.connect(&pv[0], &pv[1], 1s));
91  BEAST_EXPECT(net.connect(&pv[1], &pv[2], 1s));
92  BEAST_EXPECT(!net.connect(&pv[0], &pv[1]));
93  for (auto& peer : pv)
94  peer.start(scheduler, net);
95  BEAST_EXPECT(scheduler.step_for(0s));
96  BEAST_EXPECT(scheduler.step_for(1s));
97  BEAST_EXPECT(scheduler.step());
98  BEAST_EXPECT(!scheduler.step());
99  BEAST_EXPECT(!scheduler.step_for(1s));
100  net.send(&pv[0], &pv[1], [] {});
101  net.send(&pv[1], &pv[0], [] {});
102  BEAST_EXPECT(net.disconnect(&pv[0], &pv[1]));
103  BEAST_EXPECT(!net.disconnect(&pv[0], &pv[1]));
104  for (;;)
105  {
106  auto const links = net.links(&pv[1]);
107  if (links.empty())
108  break;
109  BEAST_EXPECT(net.disconnect(&pv[1], links[0].target));
110  }
111  BEAST_EXPECT(pv[0].set == std::set<int>({0, 2, 4}));
112  BEAST_EXPECT(pv[1].set == std::set<int>({1, 3}));
113  BEAST_EXPECT(pv[2].set == std::set<int>({2, 4}));
114  }
115 
116  void
118  {
119  using namespace std::chrono_literals;
120  csf::Scheduler scheduler;
121  csf::BasicNetwork<int> net(scheduler);
122  BEAST_EXPECT(net.connect(0, 1, 1s));
123  BEAST_EXPECT(net.connect(0, 2, 2s));
124 
125  std::set<int> delivered;
126  net.send(0, 1, [&]() { delivered.insert(1); });
127  net.send(0, 2, [&]() { delivered.insert(2); });
128 
129  scheduler.in(1000ms, [&]() { BEAST_EXPECT(net.disconnect(0, 2)); });
130  scheduler.in(1100ms, [&]() { BEAST_EXPECT(net.connect(0, 2)); });
131 
132  scheduler.step();
133 
134  // only the first message is delivered because the disconnect at 1 s
135  // purges all pending messages from 0 to 2
136  BEAST_EXPECT(delivered == std::set<int>({1}));
137  }
138 
139  void
140  run() override
141  {
142  testNetwork();
143  testDisconnect();
144  }
145 };
146 
147 BEAST_DEFINE_TESTSUITE(BasicNetwork, test, ripple);
148 
149 } // namespace test
150 } // namespace ripple
ripple::test::BasicNetwork_test::Peer::Peer
Peer(int id_)
Definition: BasicNetwork_test.cpp:40
ripple::test::BasicNetwork_test::run
void run() override
Definition: BasicNetwork_test.cpp:140
ripple::test::csf::Scheduler::cancel
void cancel(cancel_token const &token)
Cancel a timer.
Definition: test/csf/Scheduler.h:385
ripple::test::csf::BasicNetwork::disconnect
bool disconnect(Peer const &peer1, Peer const &peer2)
Break a link.
Definition: BasicNetwork.h:224
vector
ripple::test::csf::Scheduler
Simulated discrete-event scheduler.
Definition: test/csf/Scheduler.h:47
ripple::test::BasicNetwork_test::Peer::Peer
Peer(Peer const &)=default
ripple::test::BasicNetwork_test::Peer::id
int id
Definition: BasicNetwork_test.cpp:34
ripple::test::BasicNetwork_test::testNetwork
void testNetwork()
Definition: BasicNetwork_test.cpp:80
ripple::test::BasicNetwork_test
Definition: BasicNetwork_test.cpp:29
ripple::test::csf::Scheduler::in
cancel_token in(duration const &delay, Function &&f)
Schedule an event after a specified duration passes.
ripple::test::BasicNetwork_test::Peer::set
std::set< int > set
Definition: BasicNetwork_test.cpp:35
ripple::test::BasicNetwork_test::Peer::start
void start(csf::Scheduler &scheduler, Net &net)
Definition: BasicNetwork_test.cpp:46
ripple::test::BasicNetwork_test::Peer
Definition: BasicNetwork_test.cpp:32
ripple::test::csf::BasicNetwork::connect
bool connect(Peer const &from, Peer const &to, duration const &delay=std::chrono::seconds{0})
Connect two peers.
Definition: BasicNetwork.h:206
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::csf::Scheduler::step
bool step()
Run the scheduler until no events remain.
Definition: test/csf/Scheduler.h:403
std::set::insert
T insert(T... args)
ripple::test::BasicNetwork_test::testDisconnect
void testDisconnect()
Definition: BasicNetwork_test.cpp:117
ripple::test::csf::BasicNetwork::send
void send(Peer const &from, Peer const &to, Function &&f)
Send a message to a peer.
Definition: BasicNetwork.h:237
ripple::test::csf::BasicNetwork::links
auto links(Peer const &from)
Return the range of active links.
Definition: BasicNetwork.h:185
ripple::test::csf::Scheduler::step_for
bool step_for(std::chrono::duration< Period, Rep > const &amount)
Run the scheduler until time has elapsed.
Definition: test/csf/Scheduler.h:449
ripple::test::BasicNetwork_test::Peer::receive
void receive(Net &net, Peer *from, int m)
Definition: BasicNetwork_test.cpp:65
ripple::test::csf::BasicNetwork
Peer to peer network simulator.
Definition: BasicNetwork.h:83
set
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple)