rippled
Loading...
Searching...
No Matches
BasicNetwork_test.cpp
1#include <test/csf/BasicNetwork.h>
2#include <test/csf/Scheduler.h>
3
4#include <xrpl/beast/unit_test.h>
5
6#include <set>
7#include <vector>
8
9namespace xrpl {
10namespace test {
11
13{
14public:
15 struct Peer
16 {
17 int id;
19
20 Peer(Peer const&) = default;
21 Peer(Peer&&) = default;
22
23 explicit Peer(int id_) : id(id_)
24 {
25 }
26
27 template <class Net>
28 void
29 start(csf::Scheduler& scheduler, Net& net)
30 {
31 using namespace std::chrono_literals;
32 auto t = scheduler.in(1s, [&] { set.insert(0); });
33 if (id == 0)
34 {
35 for (auto const link : net.links(this))
36 {
37 net.send(
38 this, link.target, [&, to = link.target] { to->receive(net, this, 1); });
39 }
40 }
41 else
42 {
43 scheduler.cancel(t);
44 }
45 }
46
47 template <class Net>
48 void
49 receive(Net& net, Peer* from, int m)
50 {
51 set.insert(m);
52 ++m;
53 if (m < 5)
54 {
55 for (auto const link : net.links(this))
56 {
57 net.send(this, link.target, [&, mm = m, to = link.target] {
58 to->receive(net, this, mm);
59 });
60 }
61 }
62 }
63 };
64
65 void
67 {
68 using namespace std::chrono_literals;
70 pv.emplace_back(0);
71 pv.emplace_back(1);
72 pv.emplace_back(2);
73 csf::Scheduler scheduler;
74 csf::BasicNetwork<Peer*> net(scheduler);
75 BEAST_EXPECT(!net.connect(&pv[0], &pv[0]));
76 BEAST_EXPECT(net.connect(&pv[0], &pv[1], 1s));
77 BEAST_EXPECT(net.connect(&pv[1], &pv[2], 1s));
78 BEAST_EXPECT(!net.connect(&pv[0], &pv[1]));
79 for (auto& peer : pv)
80 peer.start(scheduler, net);
81 BEAST_EXPECT(scheduler.step_for(0s));
82 BEAST_EXPECT(scheduler.step_for(1s));
83 BEAST_EXPECT(scheduler.step());
84 BEAST_EXPECT(!scheduler.step());
85 BEAST_EXPECT(!scheduler.step_for(1s));
86 net.send(&pv[0], &pv[1], [] {});
87 net.send(&pv[1], &pv[0], [] {});
88 BEAST_EXPECT(net.disconnect(&pv[0], &pv[1]));
89 BEAST_EXPECT(!net.disconnect(&pv[0], &pv[1]));
90 for (;;)
91 {
92 auto const links = net.links(&pv[1]);
93 if (links.empty())
94 break;
95 BEAST_EXPECT(net.disconnect(&pv[1], links[0].target));
96 }
97 BEAST_EXPECT(pv[0].set == std::set<int>({0, 2, 4}));
98 BEAST_EXPECT(pv[1].set == std::set<int>({1, 3}));
99 BEAST_EXPECT(pv[2].set == std::set<int>({2, 4}));
100 }
101
102 void
104 {
105 using namespace std::chrono_literals;
106 csf::Scheduler scheduler;
107 csf::BasicNetwork<int> net(scheduler);
108 BEAST_EXPECT(net.connect(0, 1, 1s));
109 BEAST_EXPECT(net.connect(0, 2, 2s));
110
111 std::set<int> delivered;
112 net.send(0, 1, [&]() { delivered.insert(1); });
113 net.send(0, 2, [&]() { delivered.insert(2); });
114
115 scheduler.in(1000ms, [&]() { BEAST_EXPECT(net.disconnect(0, 2)); });
116 scheduler.in(1100ms, [&]() { BEAST_EXPECT(net.connect(0, 2)); });
117
118 scheduler.step();
119
120 // only the first message is delivered because the disconnect at 1 s
121 // purges all pending messages from 0 to 2
122 BEAST_EXPECT(delivered == std::set<int>({1}));
123 }
124
125 void
126 run() override
127 {
128 testNetwork();
129 testDisconnect();
130 }
131};
132
133BEAST_DEFINE_TESTSUITE(BasicNetwork, csf, xrpl);
134
135} // namespace test
136} // namespace xrpl
A testsuite class.
Definition suite.h:51
void run() override
Runs the suite.
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.
cancel_token in(duration const &delay, Function &&f)
Schedule an event after a specified duration passes.
bool step()
Run the scheduler until no events remain.
bool step_for(std::chrono::duration< Period, Rep > const &amount)
Run the scheduler until time has elapsed.
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:5
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 receive(Net &net, Peer *from, int m)
void start(csf::Scheduler &scheduler, Net &net)