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