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