#include #include #include #include #include namespace xrpl { namespace test { class BasicNetwork_test : public beast::unit_test::suite { public: struct Peer { int id; std::set set; Peer(Peer const&) = default; Peer(Peer&&) = default; explicit Peer(int id_) : id(id_) { } template void start(csf::Scheduler& scheduler, Net& net) { using namespace std::chrono_literals; auto t = scheduler.in(1s, [&] { set.insert(0); }); if (id == 0) { for (auto const link : net.links(this)) net.send(this, link.target, [&, to = link.target] { to->receive(net, this, 1); }); } else { scheduler.cancel(t); } } template void receive(Net& net, Peer* from, int m) { set.insert(m); ++m; if (m < 5) { for (auto const link : net.links(this)) net.send(this, link.target, [&, mm = m, to = link.target] { to->receive(net, this, mm); }); } } }; void testNetwork() { using namespace std::chrono_literals; std::vector pv; pv.emplace_back(0); pv.emplace_back(1); pv.emplace_back(2); csf::Scheduler scheduler; csf::BasicNetwork net(scheduler); BEAST_EXPECT(!net.connect(&pv[0], &pv[0])); BEAST_EXPECT(net.connect(&pv[0], &pv[1], 1s)); BEAST_EXPECT(net.connect(&pv[1], &pv[2], 1s)); BEAST_EXPECT(!net.connect(&pv[0], &pv[1])); for (auto& peer : pv) peer.start(scheduler, net); BEAST_EXPECT(scheduler.step_for(0s)); BEAST_EXPECT(scheduler.step_for(1s)); BEAST_EXPECT(scheduler.step()); BEAST_EXPECT(!scheduler.step()); BEAST_EXPECT(!scheduler.step_for(1s)); net.send(&pv[0], &pv[1], [] {}); net.send(&pv[1], &pv[0], [] {}); BEAST_EXPECT(net.disconnect(&pv[0], &pv[1])); BEAST_EXPECT(!net.disconnect(&pv[0], &pv[1])); for (;;) { auto const links = net.links(&pv[1]); if (links.empty()) break; BEAST_EXPECT(net.disconnect(&pv[1], links[0].target)); } BEAST_EXPECT(pv[0].set == std::set({0, 2, 4})); BEAST_EXPECT(pv[1].set == std::set({1, 3})); BEAST_EXPECT(pv[2].set == std::set({2, 4})); } void testDisconnect() { using namespace std::chrono_literals; csf::Scheduler scheduler; csf::BasicNetwork net(scheduler); BEAST_EXPECT(net.connect(0, 1, 1s)); BEAST_EXPECT(net.connect(0, 2, 2s)); std::set delivered; net.send(0, 1, [&]() { delivered.insert(1); }); net.send(0, 2, [&]() { delivered.insert(2); }); scheduler.in(1000ms, [&]() { BEAST_EXPECT(net.disconnect(0, 2)); }); scheduler.in(1100ms, [&]() { BEAST_EXPECT(net.connect(0, 2)); }); scheduler.step(); // only the first message is delivered because the disconnect at 1 s // purges all pending messages from 0 to 2 BEAST_EXPECT(delivered == std::set({1})); } void run() override { testNetwork(); testDisconnect(); } }; BEAST_DEFINE_TESTSUITE(BasicNetwork, csf, xrpl); } // namespace test } // namespace xrpl