test: network_topology: add test_topology_compare_endpoints

Add a regression unit test for topology::compare_endpoint
before it's optimized in the following patches.

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
This commit is contained in:
Benny Halevy
2023-02-07 14:05:08 +02:00
parent df497a5a94
commit e7af35a64d
2 changed files with 96 additions and 0 deletions

View File

@@ -100,6 +100,11 @@ private:
/**
* compares two endpoints in relation to the target endpoint, returning as
* Comparator.compare would
*
* The closest nodes to a given node are:
* 1. The node itself
* 2. Nodes in the same RACK as the reference node
* 3. Nodes in the same DC as the reference node
*/
int compare_endpoints(const inet_address& address, const inet_address& a1, const inet_address& a2) const;
@@ -123,6 +128,9 @@ private:
std::unordered_set<sstring> _datacenters;
void calculate_datacenters();
public:
void test_compare_endpoints(const inet_address& address, const inet_address& a1, const inet_address& a2) const;
};
} // namespace locator

View File

@@ -631,3 +631,91 @@ SEASTAR_TEST_CASE(test_invalid_dcs) {
});
}
namespace locator {
void topology::test_compare_endpoints(const inet_address& address, const inet_address& a1, const inet_address& a2) const {
std::optional<int> expected;
const auto& loc = get_location(address);
const auto& loc1 = get_location(a1);
const auto& loc2 = get_location(a2);
if (a1 == a2) {
expected = 0;
} else {
if (a1 == address) {
expected = -1;
} else if (a2 == address) {
expected = 1;
} else {
if (loc1.dc == loc.dc) {
if (loc2.dc != loc.dc) {
expected = -1;
} else {
if (loc1.rack == loc.rack) {
if (loc2.rack != loc.rack) {
expected = -1;
}
} else if (loc2.rack == loc.rack) {
expected = 1;
}
}
} else if (loc2.dc == loc.dc) {
expected = 1;
}
}
}
auto res = compare_endpoints(address, a1, a2);
testlog.debug("compare_endpoint: address={} [{}/{}] a1={} [{}/{}] a2={} [{}/{}]: res={} expected={} expected_value={}",
address, loc.dc, loc.rack,
a1, loc1.dc, loc1.rack,
a2, loc2.dc, loc2.rack,
res, bool(expected), expected.value_or(0));
if (expected) {
BOOST_REQUIRE_EQUAL(res, *expected);
}
}
} // namespace locator
SEASTAR_THREAD_TEST_CASE(test_topology_compare_endpoints) {
utils::fb_utilities::set_broadcast_address(gms::inet_address("localhost"));
utils::fb_utilities::set_broadcast_rpc_address(gms::inet_address("localhost"));
constexpr size_t NODES = 10;
std::unordered_map<sstring, size_t> datacenters = {
{ "rf1", 1 },
{ "rf2", 2 },
{ "rf3", 3 },
};
std::vector<inet_address> nodes;
nodes.reserve(NODES);
auto make_address = [] (unsigned i) {
return inet_address((127u << 24) | i);
};
std::generate_n(std::back_inserter(nodes), NODES, [&, i = 0u]() mutable {
return make_address(++i);
});
auto bogus_address = make_address(NODES + 1);
semaphore sem(1);
shared_token_metadata stm([&sem] () noexcept { return get_units(sem, 1); }, locator::token_metadata::config{});
auto topo = generate_topology(datacenters, nodes);
const auto& address = nodes[tests::random::get_int<size_t>(0, NODES-1)];
const auto& a1 = nodes[tests::random::get_int<size_t>(0, NODES-1)];
const auto& a2 = nodes[tests::random::get_int<size_t>(0, NODES-1)];
topo->test_compare_endpoints(address, address, address);
topo->test_compare_endpoints(address, address, a1);
topo->test_compare_endpoints(address, a1, address);
topo->test_compare_endpoints(address, a1, a1);
topo->test_compare_endpoints(address, a1, a2);
topo->test_compare_endpoints(address, a2, a1);
topo->test_compare_endpoints(bogus_address, bogus_address, bogus_address);
topo->test_compare_endpoints(address, bogus_address, bogus_address);
topo->test_compare_endpoints(address, a1, bogus_address);
topo->test_compare_endpoints(address, bogus_address, a2);
}