/* * Copyright (C) 2021-present ScyllaDB */ /* * SPDX-License-Identifier: AGPL-3.0-or-later */ #define BOOST_TEST_MODULE raft #include "test/raft/helpers.hh" #include "service/raft/discovery.hh" using namespace raft; using discovery_network = std::unordered_map; using service::discovery; void run_discovery_impl(discovery_network& network) { while (true) { for (auto e : network) { discovery& from = *e.second; auto output = from.tick(); if (std::holds_alternative(output)) { return; } else if (std::holds_alternative(output)) { continue; } auto& msgs = std::get(output); for (auto&& m : msgs) { auto it = network.find(m.first.id); if (it == network.end()) { // The node is not available, drop the message continue; } discovery& to = *(it->second); if (auto peer_list = to.request(m.second)) { from.response(m.first, std::move(*peer_list)); } } } } } template void run_discovery(Args&&... args) { discovery_network network; auto add_node = [&network](discovery& node) -> void { network.emplace(node.id(), &node); }; (add_node(args), ...); run_discovery_impl(network); } BOOST_AUTO_TEST_CASE(test_basic) { server_address addr1 = {.id = id()}; // Must supply an Internet address for self BOOST_CHECK_THROW(discovery(addr1, {}), std::logic_error); server_address addr2 = {.id = id(), .info = "192.168.1.2"}; BOOST_CHECK_NO_THROW(discovery(addr2, {})); // Must supply an Internet address for each peer BOOST_CHECK_THROW(discovery(addr2, {addr1}), std::logic_error); // OK to include self into peers BOOST_CHECK_NO_THROW(discovery(addr2, {addr2})); // With a single peer, discovery immediately finds a leader discovery d(addr2, {}); BOOST_CHECK(d.is_leader()); d = discovery(addr2, {addr2}); BOOST_CHECK(d.is_leader()); } BOOST_AUTO_TEST_CASE(test_discovery) { server_address addr1 = {.id = id(), .info = "192.168.1.1"}; server_address addr2 = {.id = id(), .info = "192.168.1.2"}; discovery d1(addr1, {addr2}); discovery d2(addr2, {addr1}); run_discovery(d1, d2); BOOST_CHECK(d1.is_leader() ^ d2.is_leader()); } BOOST_AUTO_TEST_CASE(test_discovery_fullmesh) { server_address addr1 = {.id = id(), .info = "127.0.0.13"}; server_address addr2 = {.id = id(), .info = "127.0.0.19"}; server_address addr3 = {.id = id(), .info = "127.0.0.21"}; auto seeds = std::vector({addr1, addr2, addr3}); discovery d1(addr1, seeds); discovery d2(addr2, seeds); discovery d3(addr3, seeds); run_discovery(d1, d2, d3); BOOST_CHECK(d1.is_leader() ^ d2.is_leader() ^ d3.is_leader()); }