xrpld
Loading...
Searching...
No Matches
BasicNetwork.cpp
1#include <csf/BasicNetwork.h>
2
3#include <csf/Scheduler.h>
4#include <gtest/gtest.h>
5
6#include <set>
7#include <vector>
8
9namespace xrpl::test {
10
11namespace {
12
13struct Peer
14{
15 int id;
16 std::set<int> set;
17
18 Peer(Peer const&) = default;
19 Peer(Peer&&) = default;
20
21 explicit Peer(int id) : id(id)
22 {
23 }
24
25 template <class Net>
26 void
27 start(csf::Scheduler& scheduler, Net& net)
28 {
29 using namespace std::chrono_literals;
30 auto t = scheduler.in(1s, [&] { set.insert(0); });
31 if (id == 0)
32 {
33 for (auto const link : net.links(this))
34 {
35 net.send(this, link.target, [&, to = link.target] { to->receive(net, this, 1); });
36 }
37 }
38 else
39 {
40 scheduler.cancel(t);
41 }
42 }
43
44 template <class Net>
45 void
46 receive(Net& net, Peer* from, int m)
47 {
48 set.insert(m);
49 ++m;
50 if (m < 5)
51 {
52 for (auto const link : net.links(this))
53 {
54 net.send(this, link.target, [&, mm = m, to = link.target] {
55 to->receive(net, this, mm);
56 });
57 }
58 }
59 }
60};
61
62} // namespace
63
64TEST(BasicNetworkTest, network)
65{
66 using namespace std::chrono_literals;
68 pv.emplace_back(0);
69 pv.emplace_back(1);
70 pv.emplace_back(2);
71 csf::Scheduler scheduler;
72 csf::BasicNetwork<Peer*> net(scheduler);
73 EXPECT_TRUE(!net.connect(&pv[0], &pv[0]));
74 EXPECT_TRUE(net.connect(&pv[0], &pv[1], 1s));
75 EXPECT_TRUE(net.connect(&pv[1], &pv[2], 1s));
76 EXPECT_TRUE(!net.connect(&pv[0], &pv[1]));
77 for (auto& peer : pv)
78 peer.start(scheduler, net);
79 EXPECT_TRUE(scheduler.stepFor(0s));
80 EXPECT_TRUE(scheduler.stepFor(1s));
81 EXPECT_TRUE(scheduler.step());
82 EXPECT_TRUE(!scheduler.step());
83 EXPECT_TRUE(!scheduler.stepFor(1s));
84 net.send(&pv[0], &pv[1], [] {});
85 net.send(&pv[1], &pv[0], [] {});
86 EXPECT_TRUE(net.disconnect(&pv[0], &pv[1]));
87 EXPECT_TRUE(!net.disconnect(&pv[0], &pv[1]));
88 for (;;)
89 {
90 auto const links = net.links(&pv[1]);
91 if (links.empty())
92 break;
93 EXPECT_TRUE(net.disconnect(&pv[1], links[0].target));
94 }
95 EXPECT_TRUE(pv[0].set == std::set<int>({0, 2, 4}));
96 EXPECT_TRUE(pv[1].set == std::set<int>({1, 3}));
97 EXPECT_TRUE(pv[2].set == std::set<int>({2, 4}));
98}
99
100TEST(BasicNetworkTest, disconnect)
101{
102 using namespace std::chrono_literals;
103 csf::Scheduler scheduler;
104 csf::BasicNetwork<int> net(scheduler);
105 EXPECT_TRUE(net.connect(0, 1, 1s));
106 EXPECT_TRUE(net.connect(0, 2, 2s));
107
108 std::set<int> delivered;
109 net.send(0, 1, [&]() { delivered.insert(1); });
110 net.send(0, 2, [&]() { delivered.insert(2); });
111
112 scheduler.in(1000ms, [&]() { EXPECT_TRUE(net.disconnect(0, 2)); });
113 scheduler.in(1100ms, [&]() { EXPECT_TRUE(net.connect(0, 2)); });
114
115 scheduler.step();
116
117 // only the first message is delivered because the disconnect at 1 s
118 // purges all pending messages from 0 to 2
119 EXPECT_TRUE(delivered == std::set<int>({1}));
120}
121
122} // namespace xrpl::test
Peer to peer network simulator.
bool connect(Peer const &from, Peer const &to, duration const &delay=std::chrono::seconds{0})
Connect two peers.
auto links(Peer const &from)
Return the range of active links.
bool disconnect(Peer const &peer1, Peer const &peer2)
Break a link.
void send(Peer const &from, Peer const &to, Function &&f)
Send a message to a peer.
Simulated discrete-event scheduler.
bool step()
Run the scheduler until no events remain.
CancelToken in(duration const &delay, Function &&f)
Schedule an event after a specified duration passes.
bool stepFor(std::chrono::duration< Period, Rep > const &amount)
Run the scheduler until time has elapsed.
T emplace_back(T... args)
T insert(T... args)
TEST(UnitsTest, types)
Definition Units.cpp:16
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,...