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