mirror of
https://github.com/transmission/transmission.git
synced 2025-12-20 02:18:42 +00:00
refactor: overhaul tr_address special address checks (#7818)
* refactor: rewrite is_martian_addr() with tr_address methods - Fix broken check for IPv4 multicast address in is_martian_address() * refactor: rewrite is_global_unicast_address() - Rewrite using new tr_address methods - Add missing IPv4 loopback check - Follow RFC 4291 IPv6 global unicast definition - Fix and update existing tests * chore: reorganise methods and add comments * fix: check for teredo and 6to4 * test: tests for new methods
This commit is contained in:
@@ -141,7 +141,7 @@ TEST_F(IPCacheTest, setGlobalAddr)
|
||||
static auto constexpr AddrStr = std::array{
|
||||
"8.8.8.8"sv, "192.168.133.133"sv, "172.16.241.133"sv, "2001:1890:1112:1::20"sv, "fd12:3456:789a:1::1"sv,
|
||||
};
|
||||
static auto constexpr AddrTests = std::array{ true, false, false, true, false };
|
||||
static auto constexpr AddrTests = std::array{ true, false, false, true, true };
|
||||
static_assert(TR_AF_INET == 0);
|
||||
static_assert(TR_AF_INET6 == 1);
|
||||
static_assert(NUM_TR_AF_INET_TYPES == 2);
|
||||
@@ -154,7 +154,7 @@ TEST_F(IPCacheTest, setGlobalAddr)
|
||||
{
|
||||
auto const addr = tr_address::from_string(AddrStr[i]);
|
||||
ASSERT_TRUE(addr.has_value());
|
||||
EXPECT_EQ(ip_cache_->set_global_addr(*addr), AddrTests[i]);
|
||||
EXPECT_EQ(ip_cache_->set_global_addr(*addr), AddrTests[i]) << AddrStr[i];
|
||||
if (auto const val = ip_cache_->global_addr(addr->type); val && AddrTests[i])
|
||||
{
|
||||
EXPECT_EQ(val->display_name(), AddrStr[i]);
|
||||
@@ -213,11 +213,13 @@ TEST_F(IPCacheTest, globalSourceIPv6)
|
||||
TEST_F(IPCacheTest, onResponseIPQuery)
|
||||
{
|
||||
static auto constexpr AddrStr = std::array{
|
||||
"8.8.8.8"sv, "192.168.133.133"sv, "172.16.241.133"sv, "2001:1890:1112:1::20"sv, "fd12:3456:789a:1::1"sv,
|
||||
"91.121.74.28"sv, "2001:1890:1112:1::20"sv
|
||||
"8.8.8.8"sv, "192.168.133.133"sv, "172.16.241.133"sv, "2001:1890:1112:1::20"sv, "fd12:3456:789a:1::1"sv,
|
||||
"91.121.74.28"sv, "2001:1890:1112:1::20"sv,
|
||||
};
|
||||
static auto constexpr AddrTests = std::array{
|
||||
std::array{ true, false, false, false, false, true, false /* IPv4 */ },
|
||||
std::array{ false, false, false, true, true, false, true /* IPv6 */ },
|
||||
};
|
||||
static auto constexpr AddrTests = std::array{ std::array{ true, false, false, false, false, true, false /* IPv4 */ },
|
||||
std::array{ false, false, false, true, false, false, true /* IPv6 */ } };
|
||||
static_assert(TR_AF_INET == 0);
|
||||
static_assert(TR_AF_INET6 == 1);
|
||||
static_assert(NUM_TR_AF_INET_TYPES == 2);
|
||||
@@ -228,8 +230,9 @@ TEST_F(IPCacheTest, onResponseIPQuery)
|
||||
{
|
||||
void fetch(tr_web::FetchOptions&& options) override // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
|
||||
{
|
||||
auto response = tr_web::FetchResponse{ http_code, std::string{ AddrStr[k_] }, std::string{}, true,
|
||||
false, options.done_func_user_data };
|
||||
auto response = tr_web::FetchResponse{
|
||||
http_code, std::string{ AddrStr[k_] }, std::string{}, true, false, options.done_func_user_data,
|
||||
};
|
||||
options.done_func(response);
|
||||
}
|
||||
|
||||
@@ -256,7 +259,8 @@ TEST_F(IPCacheTest, onResponseIPQuery)
|
||||
ip_cache_->update_global_addr(type);
|
||||
|
||||
auto const global_addr = ip_cache_->global_addr(type);
|
||||
EXPECT_EQ(!!global_addr, j == 200 /* HTTP_OK */ && AddrTests[i][k]);
|
||||
EXPECT_EQ(!!global_addr, j == 200 /* HTTP_OK */ && AddrTests[i][k])
|
||||
<< "i = " << i << ", j = "sv << j << ", addr = "sv << AddrStr[k];
|
||||
if (global_addr)
|
||||
{
|
||||
EXPECT_EQ(global_addr->display_name(), AddrStr[k]);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstddef> // std::byte, size_t
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
@@ -32,8 +31,7 @@ TEST_F(NetTest, conversionsIPv4)
|
||||
static auto constexpr AddrStr = "127.0.0.1"sv;
|
||||
|
||||
auto addr = tr_address::from_string(AddrStr);
|
||||
EXPECT_TRUE(addr.has_value());
|
||||
assert(addr.has_value());
|
||||
ASSERT_TRUE(addr.has_value());
|
||||
EXPECT_EQ(AddrStr, addr->display_name());
|
||||
|
||||
auto [ss, sslen] = tr_socket_address::to_sockaddr(*addr, Port);
|
||||
@@ -191,23 +189,729 @@ TEST_F(NetTest, isGlobalUnicastAddress)
|
||||
{ "100.64.0.0"sv, false },
|
||||
{ "100.128.0.0"sv, true },
|
||||
{ "126.0.0.0"sv, true },
|
||||
{ "127.0.0.0"sv, true },
|
||||
{ "127.0.0.0"sv, false },
|
||||
{ "169.253.255.255"sv, true },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "169.254.255.255"sv, false },
|
||||
{ "169.255.0.0"sv, true },
|
||||
{ "223.0.0.0"sv, true },
|
||||
{ "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1", false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e", true },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, true },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
EXPECT_TRUE(address.has_value());
|
||||
assert(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_global_unicast_address()) << presentation;
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_global_unicast()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4CurrentNetwork)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 19>{ {
|
||||
{ "0.0.0.0"sv, true },
|
||||
{ "0.25.37.132"sv, true },
|
||||
{ "0.255.255.255"sv, true },
|
||||
{ "1.0.0.0"sv, false },
|
||||
{ "10.0.0.0"sv, false },
|
||||
{ "10.255.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false },
|
||||
{ "100.64.0.0"sv, false },
|
||||
{ "100.128.0.0"sv, false },
|
||||
{ "126.0.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false },
|
||||
{ "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "169.254.255.255"sv, false },
|
||||
{ "169.255.0.0"sv, false },
|
||||
{ "223.0.0.0"sv, false },
|
||||
{ "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_current_network()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4And10Private)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 18>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "9.255.255.255"sv, false },
|
||||
{ "10.0.0.0"sv, true },
|
||||
{ "10.255.0.0"sv, true },
|
||||
{ "10.255.0.255"sv, true },
|
||||
{ "10.255.255.255"sv, true },
|
||||
{ "11.0.0.0"sv, false },
|
||||
{ "100.128.0.0"sv, false },
|
||||
{ "126.0.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false },
|
||||
{ "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "169.254.255.255"sv, false },
|
||||
{ "169.255.0.0"sv, false },
|
||||
{ "223.0.0.0"sv, false },
|
||||
{ "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_10_private()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4CarrierGradeNAT)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 19>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "1.0.0.0"sv, false },
|
||||
{ "10.0.0.0"sv, false },
|
||||
{ "10.255.0.0"sv, false },
|
||||
{ "100.63.255.255"sv, false },
|
||||
{ "100.64.0.0"sv, true },
|
||||
{ "100.100.32.0"sv, true },
|
||||
{ "100.127.255.255"sv, true },
|
||||
{ "100.128.0.0"sv, false },
|
||||
{ "126.0.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false },
|
||||
{ "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "169.254.255.255"sv, false },
|
||||
{ "169.255.0.0"sv, false },
|
||||
{ "223.0.0.0"sv, false },
|
||||
{ "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_carrier_grade_nat()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4Loopback)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 19>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "1.0.0.0"sv, false },
|
||||
{ "10.0.0.0"sv, false },
|
||||
{ "10.255.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false },
|
||||
{ "100.64.0.0"sv, false },
|
||||
{ "100.128.0.0"sv, false },
|
||||
{ "126.255.255.255"sv, false },
|
||||
{ "127.0.0.0"sv, true },
|
||||
{ "127.12.12.57"sv, true },
|
||||
{ "127.255.255.255"sv, true },
|
||||
{ "128.0.0.0"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "169.254.255.255"sv, false },
|
||||
{ "169.255.0.0"sv, false },
|
||||
{ "223.0.0.0"sv, false },
|
||||
{ "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_loopback()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4LinkLocal)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 18>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "1.0.0.0"sv, false },
|
||||
{ "10.0.0.0"sv, false },
|
||||
{ "10.255.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false },
|
||||
{ "100.64.0.0"sv, false },
|
||||
{ "100.128.0.0"sv, false },
|
||||
{ "126.0.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false },
|
||||
{ "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, true },
|
||||
{ "169.254.235.12"sv, true },
|
||||
{ "169.254.255.255"sv, true },
|
||||
{ "169.255.0.0"sv, false },
|
||||
{ "223.0.0.0"sv, false },
|
||||
{ "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_link_local()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4And172Private)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.0"sv, false }, { "10.255.0.255"sv, false },
|
||||
{ "100.64.0.0"sv, false }, { "100.128.0.0"sv, false },
|
||||
{ "126.0.0.0"sv, false }, { "127.0.0.0"sv, false },
|
||||
{ "169.253.255.255"sv, false }, { "169.254.0.0"sv, false },
|
||||
{ "169.254.255.255"sv, false }, { "172.15.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, true }, { "172.17.78.245"sv, true },
|
||||
{ "172.31.255.255"sv, true }, { "172.32.0.0"sv, false },
|
||||
{ "223.0.0.0"sv, false }, { "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_172_private()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4IetfProtocolAssignment)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "191.255.255.255"sv, false },
|
||||
{ "192.0.0.0"sv, true }, { "192.0.0.14"sv, true },
|
||||
{ "192.0.0.255"sv, true }, { "192.0.1.0"sv, false },
|
||||
{ "223.0.0.0"sv, false }, { "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_ietf_protocol_assignment()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4TestNet1)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "192.0.1.255"sv, false },
|
||||
{ "192.0.2.0"sv, true }, { "192.0.2.14"sv, true },
|
||||
{ "192.0.2.225"sv, true }, { "192.0.3.0"sv, false },
|
||||
{ "223.0.0.0"sv, false }, { "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_test_net_1()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4And6to4Relay)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "192.88.98.255"sv, false },
|
||||
{ "192.88.99.0"sv, true }, { "192.88.99.14"sv, true },
|
||||
{ "192.88.99.225"sv, true }, { "192.88.100.0"sv, false },
|
||||
{ "223.0.0.0"sv, false }, { "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_6to4_relay()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4And192Private)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "192.167.255.255"sv, false },
|
||||
{ "192.168.0.0"sv, true }, { "192.168.99.14"sv, true },
|
||||
{ "192.168.255.225"sv, true }, { "192.169.0.0"sv, false },
|
||||
{ "223.0.0.0"sv, false }, { "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_192_168_private()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4Benchmark)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "198.17.255.255"sv, false },
|
||||
{ "198.18.0.0"sv, true }, { "198.19.99.14"sv, true },
|
||||
{ "198.19.255.225"sv, true }, { "198.20.0.0"sv, false },
|
||||
{ "223.0.0.0"sv, false }, { "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_benchmark()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4TestNet2)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "198.51.99.255"sv, false },
|
||||
{ "198.51.100.0"sv, true }, { "198.51.100.45"sv, true },
|
||||
{ "198.51.100.255"sv, true }, { "198.51.101.0"sv, false },
|
||||
{ "223.0.0.0"sv, false }, { "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_test_net_2()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4TestNet3)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "203.0.112.255"sv, false },
|
||||
{ "203.0.113.0"sv, true }, { "203.0.113.45"sv, true },
|
||||
{ "203.0.113.255"sv, true }, { "203.0.114.0"sv, false },
|
||||
{ "223.0.0.0"sv, false }, { "224.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_test_net_3()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4Multicast)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "203.0.113.255"sv, false },
|
||||
{ "203.0.114.0"sv, false }, { "223.255.255.255"sv, false },
|
||||
{ "224.0.0.0"sv, true }, { "230.124.45.18"sv, true },
|
||||
{ "239.255.255.255"sv, true }, { "240.0.0.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_multicast()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4McastTestNet)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "203.0.113.255"sv, false },
|
||||
{ "203.0.114.0"sv, false }, { "233.251.255.255"sv, false },
|
||||
{ "233.252.0.0"sv, true }, { "233.252.0.18"sv, true },
|
||||
{ "233.252.0.255"sv, true }, { "233.252.1.0"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_mcast_test_net()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4ReservedClassE)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "203.0.113.255"sv, false },
|
||||
{ "203.0.114.0"sv, false }, { "239.255.255.255"sv, false },
|
||||
{ "240.0.0.0"sv, true }, { "247.252.0.18"sv, true },
|
||||
{ "255.255.255.254"sv, true }, { "255.255.255.255"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_reserved_class_e()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv4LimitedBroadcast)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 20>{ {
|
||||
{ "0.0.0.0"sv, false }, { "10.0.0.0"sv, false },
|
||||
{ "10.255.0.255"sv, false }, { "100.64.0.0"sv, false },
|
||||
{ "127.0.0.0"sv, false }, { "169.253.255.255"sv, false },
|
||||
{ "169.254.0.0"sv, false }, { "169.254.255.255"sv, false },
|
||||
{ "172.16.0.0"sv, false }, { "172.17.78.245"sv, false },
|
||||
{ "172.31.255.255"sv, false }, { "203.0.113.255"sv, false },
|
||||
{ "203.0.114.0"sv, false }, { "239.255.255.255"sv, false },
|
||||
{ "240.0.0.0"sv, false }, { "247.252.0.18"sv, false },
|
||||
{ "255.255.255.254"sv, false }, { "255.255.255.255"sv, true },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false }, { "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv4_limited_broadcast()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv6Unspecified)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 26>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "::"sv, true },
|
||||
{ "0:0:0:0:0:0:0:0"sv, true },
|
||||
{ "::1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:2"sv, false },
|
||||
{ "::fffe:ffff:ffff"sv, false },
|
||||
{ "::ffff:0:0"sv, false },
|
||||
{ "::ffff:255.255.255.255"sv, false },
|
||||
{ "::1:0:0:0"sv, false },
|
||||
{ "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001::"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
{ "2001:0:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001:1::"sv, false },
|
||||
{ "2001:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2002::"sv, false },
|
||||
{ "2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2003::"sv, false },
|
||||
{ "fe80::"sv, false },
|
||||
{ "fe80::1234:5678:9876:5432"sv, false },
|
||||
{ "fe80::ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "ff00::"sv, false },
|
||||
{ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv6_unspecified()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv6Loopback)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 26>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "::"sv, false },
|
||||
{ "0:0:0:0:0:0:0:0"sv, false },
|
||||
{ "::1"sv, true },
|
||||
{ "0:0:0:0:0:0:0:1"sv, true },
|
||||
{ "0:0:0:0:0:0:0:2"sv, false },
|
||||
{ "::fffe:ffff:ffff"sv, false },
|
||||
{ "::ffff:0:0"sv, false },
|
||||
{ "::ffff:255.255.255.255"sv, false },
|
||||
{ "::1:0:0:0"sv, false },
|
||||
{ "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001::"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
{ "2001:0:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001:1::"sv, false },
|
||||
{ "2001:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2002::"sv, false },
|
||||
{ "2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2003::"sv, false },
|
||||
{ "fe80::"sv, false },
|
||||
{ "fe80::1234:5678:9876:5432"sv, false },
|
||||
{ "fe80::ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "ff00::"sv, false },
|
||||
{ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv6_loopback()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv6IPv4Mapped)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 26>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "::"sv, false },
|
||||
{ "0:0:0:0:0:0:0:0"sv, false },
|
||||
{ "::1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:2"sv, false },
|
||||
{ "::fffe:ffff:ffff"sv, false },
|
||||
{ "::ffff:0:0"sv, true },
|
||||
{ "::ffff:255.255.255.255"sv, true },
|
||||
{ "::1:0:0:0"sv, false },
|
||||
{ "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001::"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
{ "2001:0:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001:1::"sv, false },
|
||||
{ "2001:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2002::"sv, false },
|
||||
{ "2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2003::"sv, false },
|
||||
{ "fe80::"sv, false },
|
||||
{ "fe80::1234:5678:9876:5432"sv, false },
|
||||
{ "fe80::ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "ff00::"sv, false },
|
||||
{ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv6_ipv4_mapped()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv6Teredo)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 26>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "::"sv, false },
|
||||
{ "0:0:0:0:0:0:0:0"sv, false },
|
||||
{ "::1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:2"sv, false },
|
||||
{ "::fffe:ffff:ffff"sv, false },
|
||||
{ "::ffff:0:0"sv, false },
|
||||
{ "::ffff:255.255.255.255"sv, false },
|
||||
{ "::1:0:0:0"sv, false },
|
||||
{ "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001::"sv, true },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, true },
|
||||
{ "2001:0:ffff:ffff:ffff:ffff:ffff:ffff"sv, true },
|
||||
{ "2001:1::"sv, false },
|
||||
{ "2001:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2002::"sv, false },
|
||||
{ "2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2003::"sv, false },
|
||||
{ "fe80::"sv, false },
|
||||
{ "fe80::1234:5678:9876:5432"sv, false },
|
||||
{ "fe80::ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "ff00::"sv, false },
|
||||
{ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv6_teredo()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv6And6to4)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 26>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "::"sv, false },
|
||||
{ "0:0:0:0:0:0:0:0"sv, false },
|
||||
{ "::1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:2"sv, false },
|
||||
{ "::fffe:ffff:ffff"sv, false },
|
||||
{ "::ffff:0:0"sv, false },
|
||||
{ "::ffff:255.255.255.255"sv, false },
|
||||
{ "::1:0:0:0"sv, false },
|
||||
{ "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001::"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
{ "2001:0:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001:1::"sv, false },
|
||||
{ "2001:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2002::"sv, true },
|
||||
{ "2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, true },
|
||||
{ "2003::"sv, false },
|
||||
{ "fe80::"sv, false },
|
||||
{ "fe80::1234:5678:9876:5432"sv, false },
|
||||
{ "fe80::ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "ff00::"sv, false },
|
||||
{ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv6_6to4()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv6LinkLocal)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 26>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "::"sv, false },
|
||||
{ "0:0:0:0:0:0:0:0"sv, false },
|
||||
{ "::1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:2"sv, false },
|
||||
{ "::fffe:ffff:ffff"sv, false },
|
||||
{ "::ffff:0:0"sv, false },
|
||||
{ "::ffff:255.255.255.255"sv, false },
|
||||
{ "::1:0:0:0"sv, false },
|
||||
{ "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001::"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
{ "2001:0:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001:1::"sv, false },
|
||||
{ "2001:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2002::"sv, false },
|
||||
{ "2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2003::"sv, false },
|
||||
{ "fe80::"sv, true },
|
||||
{ "fe80::1234:5678:9876:5432"sv, true },
|
||||
{ "fe80::ffff:ffff:ffff:ffff"sv, true },
|
||||
{ "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "ff00::"sv, false },
|
||||
{ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv6_link_local()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NetTest, isIPv6Multicast)
|
||||
{
|
||||
static auto constexpr Tests = std::array<std::pair<std::string_view, bool>, 26>{ {
|
||||
{ "0.0.0.0"sv, false },
|
||||
{ "169.254.0.0"sv, false },
|
||||
{ "::"sv, false },
|
||||
{ "0:0:0:0:0:0:0:0"sv, false },
|
||||
{ "::1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:1"sv, false },
|
||||
{ "0:0:0:0:0:0:0:2"sv, false },
|
||||
{ "::fffe:ffff:ffff"sv, false },
|
||||
{ "::ffff:0:0"sv, false },
|
||||
{ "::ffff:255.255.255.255"sv, false },
|
||||
{ "::1:0:0:0"sv, false },
|
||||
{ "2000:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001::"sv, false },
|
||||
{ "2001:0:0eab:dead::a0:abcd:4e"sv, false },
|
||||
{ "2001:0:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2001:1::"sv, false },
|
||||
{ "2001:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2002::"sv, false },
|
||||
{ "2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "2003::"sv, false },
|
||||
{ "fe80::"sv, false },
|
||||
{ "fe80::1234:5678:9876:5432"sv, false },
|
||||
{ "fe80::ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, false },
|
||||
{ "ff00::"sv, true },
|
||||
{ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv, true },
|
||||
} };
|
||||
|
||||
for (auto const& [presentation, expected] : Tests)
|
||||
{
|
||||
auto const address = tr_address::from_string(presentation);
|
||||
ASSERT_TRUE(address.has_value());
|
||||
EXPECT_EQ(expected, address->is_ipv6_multicast()) << presentation;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user