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#include <set>
24#include <vector>
25
26namespace ripple {
27namespace test {
28
30{
31public:
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();
144 }
145};
146
147BEAST_DEFINE_TESTSUITE(BasicNetwork, test, ripple);
148
149} // namespace test
150} // namespace ripple
A testsuite class.
Definition: suite.h:53
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:316
void start(csf::Scheduler &scheduler, Net &net)
void receive(Net &net, Peer *from, int m)