blob: 4fdbd5d0ccd0fdfee596c2136b68e4e8439e2e80 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0
// Copyright 2014 Network Geographics
/** @file
IP address support testing.
*/
#include "catch.hpp"
#include <set>
#include <iostream>
#include "swoc/TextView.h"
#include "swoc/swoc_ip.h"
#include "swoc/bwf_ip.h"
#include "swoc/bwf_std.h"
#include "swoc/Lexicon.h"
using namespace std::literals;
using namespace swoc::literals;
using swoc::TextView;
using swoc::IPEndpoint;
using swoc::IP4Addr;
using swoc::IP4Range;
using swoc::IP6Addr;
using swoc::IP6Range;
using swoc::IPAddr;
using swoc::IPRange;
using swoc::IPMask;
using swoc::IPSpace;
using swoc::IPRangeSet;
using W = swoc::LocalBufferWriter<256>;
namespace {
template<typename P> void dump(IPSpace < P > const& space) {
for ( auto && [ r, p ] : space ) {
std::cout << W().print("{} : {}\n", r, p).view();
}
}
} // namespace
TEST_CASE("Basic IP", "[libswoc][ip]") {
IPEndpoint ep;
// Use TextView because string_view(nullptr) fails. Gah.
struct ip_parse_spec {
TextView hostspec;
TextView host;
TextView port;
TextView rest;
};
constexpr ip_parse_spec names[] = {
{ {"::"} , {"::"} , {nullptr}, {nullptr}}
, {{"[::1]:99"} , {"::1"} , {"99"} , {nullptr}}
, {{"127.0.0.1:8080"} , {"127.0.0.1"} , {"8080"} , {nullptr}}
, {{"127.0.0.1:8080-Bob"} , {"127.0.0.1"} , {"8080"} , {"-Bob"}}
, {{"127.0.0.1:"} , {"127.0.0.1"} , {nullptr}, {":"}}
, {{"foo.example.com"} , {"foo.example.com"} , {nullptr}, {nullptr}}
, {{"foo.example.com:99"} , {"foo.example.com"} , {"99"} , {nullptr}}
, {{"ffee::24c3:3349:3cee:0143"} , {"ffee::24c3:3349:3cee:0143"} , {nullptr}, {nullptr}}
, {{"fe80:88b5:4a:20c:29ff:feae:1c33:8080"}, {"fe80:88b5:4a:20c:29ff:feae:1c33:8080"}, {nullptr}, {nullptr}}
, {{"[ffee::24c3:3349:3cee:0143]"} , {"ffee::24c3:3349:3cee:0143"} , {nullptr}, {nullptr}}
, {{"[ffee::24c3:3349:3cee:0143]:80"} , {"ffee::24c3:3349:3cee:0143"} , {"80"} , {nullptr}}
, {{"[ffee::24c3:3349:3cee:0143]:8080x"} , {"ffee::24c3:3349:3cee:0143"} , {"8080"} , {"x"}}
};
for (auto const&s : names) {
std::string_view host, port, rest;
REQUIRE(IPEndpoint::tokenize(s.hostspec, &host, &port, &rest) == true);
REQUIRE(s.host == host);
REQUIRE(s.port == port);
REQUIRE(s.rest == rest);
}
IP4Addr alpha{"172.96.12.134"};
CHECK(alpha == IP4Addr{"172.96.12.134"});
CHECK(alpha == IPAddr{IPEndpoint{"172.96.12.134:80"}});
CHECK(alpha == IPAddr{IPEndpoint{"172.96.12.134"}});
REQUIRE(alpha[1] == 96);
REQUIRE(alpha[2] == 12);
REQUIRE(alpha[3] == 134);
// Alternate forms - inet_aton compabitility. Note in truncated forms, the last value is for
// all remaining octets, those are not zero filled as in IPv6.
CHECK(alpha.load("172.96.12"));
REQUIRE(alpha[0] == 172);
REQUIRE(alpha[2] == 0);
REQUIRE(alpha[3] == 12);
CHECK_FALSE(alpha.load("172.96.71117"));
CHECK(alpha.load("172.96.3136"));
REQUIRE(alpha[0] == 172);
REQUIRE(alpha[2] == 0xC);
REQUIRE(alpha[3] == 0x40);
CHECK(alpha.load("172.12586118"));
REQUIRE(alpha[0] == 172);
REQUIRE(alpha[1] == 192);
REQUIRE(alpha[2] == 12);
REQUIRE(alpha[3] == 134);
CHECK(alpha.load("172.0xD00D56"));
REQUIRE(alpha[0] == 172);
REQUIRE(alpha[1] == 0xD0);
REQUIRE(alpha[2] == 0x0D);
REQUIRE(alpha[3] == 0x56);
CHECK_FALSE(alpha.load("192.172.3."));
CHECK(alpha.load("192.0xAC.014.135"));
REQUIRE(alpha[0] == 192);
REQUIRE(alpha[1] == 172);
REQUIRE(alpha[2] == 12);
REQUIRE(alpha[3] == 135);
CHECK(IP6Addr().load("ffee:1f2d:c587:24c3:9128:3349:3cee:143"));
IP4Addr lo{"127.0.0.1"};
CHECK(lo.is_loopback());
REQUIRE(lo.is_any() == false);
REQUIRE(lo.is_multicast() == false);
REQUIRE(lo.is_link_local() == false);
REQUIRE(lo[0] == 0x7F);
IP4Addr any{"0.0.0.0"};
REQUIRE(any.is_loopback() == false);
REQUIRE(any.is_any() == true);
REQUIRE(lo.is_link_local() == false);
REQUIRE(any == IP4Addr("0"));
IP6Addr lo6{"::1"};
REQUIRE(lo6.is_loopback() == true);
REQUIRE(lo6.is_any() == false);
REQUIRE(lo6.is_multicast() == false);
REQUIRE(lo.is_link_local() == false);
IP6Addr any6{"::"};
REQUIRE(any6.is_loopback() == false);
REQUIRE(any6.is_any() == true);
REQUIRE(lo.is_link_local() == false);
IP6Addr multi6{"FF02::19"};
REQUIRE(multi6.is_loopback() == false);
REQUIRE(multi6.is_multicast() == true);
REQUIRE(lo.is_link_local() == false);
REQUIRE(IPAddr(multi6).is_multicast() == true);
IP6Addr ll{"FE80::56"};
REQUIRE(ll.is_link_local() == true);
REQUIRE(ll.is_multicast() == false);
REQUIRE(IPAddr(ll).is_link_local() == true);
// Do a bit of IPv6 testing.
IP6Addr a6_null;
IP6Addr a6_1{"fe80:88b5:4a:20c:29ff:feae:5587:1c33"};
IP6Addr a6_2{"fe80:88b5:4a:20c:29ff:feae:5587:1c34"};
IP6Addr a6_3{"de80:88b5:4a:20c:29ff:feae:5587:1c35"};
REQUIRE(a6_1 != a6_null);
REQUIRE(a6_1 != a6_2);
REQUIRE(a6_1 < a6_2);
REQUIRE(a6_2 > a6_1);
++a6_1;
REQUIRE(a6_1 == a6_2);
++a6_1;
REQUIRE(a6_1 != a6_2);
REQUIRE(a6_1 > a6_2);
REQUIRE(a6_3 != a6_2);
REQUIRE(a6_3 < a6_2);
REQUIRE(a6_2 > a6_3);
REQUIRE(-1 == a6_3.cmp(a6_2));
REQUIRE(0 == a6_2.cmp(a6_2));
REQUIRE(1 == a6_1.cmp(a6_2));
REQUIRE(a6_1[0] == 0xFE);
REQUIRE(a6_1[1] == 0x80);
REQUIRE(a6_2[3] == 0xB5);
REQUIRE(a6_3[11] == 0xAE);
REQUIRE(a6_3[14] == 0x1C);
REQUIRE(a6_2[15] == 0x34);
a6_1.copy_to(&ep.sa);
REQUIRE(a6_1 == IP6Addr(ep.ip6()));
a6_2.copy_to(&ep.sa6);
REQUIRE(a6_2 == IP6Addr(&ep.sa6));
REQUIRE(a6_1 != IP6Addr(ep.ip6()));
in6_addr in6;
a6_1.network_order(in6);
REQUIRE(a6_1 == IP6Addr(in6));
a6_1.network_order(ep.sa6.sin6_addr);
REQUIRE(a6_1 == IP6Addr(ep.ip6()));
in6 = a6_2.network_order();
REQUIRE(a6_2 == IP6Addr(in6));
a6_2.host_order(in6);
REQUIRE(in6.s6_addr[0] == 0x34);
REQUIRE(in6.s6_addr[6] == 0xff);
REQUIRE(in6.s6_addr[13] == 0x88);
// Little bit of IP4 address arithmetic / comparison testing.
IP4Addr a4_null;
IP4Addr a4_1{"172.28.56.33"};
IP4Addr a4_2{"172.28.56.34"};
IP4Addr a4_3{"170.28.56.35"};
IP4Addr a4_loopback{"127.0.0.1"_tv};
IP4Addr ip4_loopback{INADDR_LOOPBACK};
REQUIRE(a4_loopback == ip4_loopback);
REQUIRE(a4_loopback.is_loopback() == true);
REQUIRE(ip4_loopback.is_loopback() == true);
CHECK(a4_2.is_private());
CHECK_FALSE(a4_3.is_private());
REQUIRE(a4_1 != a4_null);
REQUIRE(a4_1 != a4_2);
REQUIRE(a4_1 < a4_2);
REQUIRE(a4_2 > a4_1);
++a4_1;
REQUIRE(a4_1 == a4_2);
++a4_1;
REQUIRE(a4_1 != a4_2);
REQUIRE(a4_1 > a4_2);
REQUIRE(a4_3 != a4_2);
REQUIRE(a4_3 < a4_2);
REQUIRE(a4_2 > a4_3);
REQUIRE(IPAddr(a4_1) > IPAddr(a4_2));
REQUIRE(IPAddr(a4_1) >= IPAddr(a4_2));
REQUIRE(false == (IPAddr(a4_1) < IPAddr(a4_2)));
REQUIRE(IPAddr(a6_2) < IPAddr(a6_1));
REQUIRE(IPAddr(a6_2) <= IPAddr(a6_1));
REQUIRE(false == (IPAddr(a6_2) > IPAddr(a6_1)));
REQUIRE(IPAddr(a4_3) == IPAddr(a4_3));
REQUIRE(IPAddr(a4_3) <= IPAddr(a4_3));
REQUIRE(IPAddr(a4_3) >= IPAddr(a4_3));
REQUIRE(IPAddr(a4_3) < IPAddr(a6_3));
REQUIRE(IPAddr{} < IPAddr(a4_3));
REQUIRE(IPAddr{} == IPAddr{});
REQUIRE(IPAddr(a4_3).cmp(IPAddr(a6_3)) == -1);
REQUIRE(IPAddr{}.cmp(IPAddr(a4_3)) == -1);
REQUIRE(IPAddr{}.cmp(IPAddr{}) == 0);
REQUIRE(IPAddr(a6_3).cmp(IPAddr(a4_3)) == 1);
REQUIRE(IPAddr{a4_3}.cmp(IPAddr{}) == 1);
// For this data, the bytes should be in IPv6 network order.
static const std::tuple<TextView, bool, IP6Addr::raw_type> ipv6_ex[] = {
{ "::" , true , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
, {"::1" , true , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}
, {":::" , false, {}}
, {"fe80::20c:29ff:feae:5587:1c33" , true , {0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0C, 0x29, 0xFF, 0xFE, 0xAE, 0x55, 0x87, 0x1C, 0x33}}
, {"fe80:20c:29ff:feae:5587::1c33" , true , {0xFE, 0x80, 0x02, 0x0C, 0x29, 0xFF, 0xFE, 0xAE, 0x55, 0x87, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x33}}
, {"fe80:20c:29ff:feae:5587:1c33::" , true , {0xFE, 0x80, 0x02, 0x0C, 0x29, 0xFF, 0xFE, 0xAE, 0x55, 0x87, 0x1c, 0x33, 0x00, 0x00, 0x00, 0x00}}
, {"::fe80:20c:29ff:feae:5587:1c33" , true , {0x00, 0x00, 0x00, 0x00, 0xFE, 0x80, 0x02, 0x0C, 0x29, 0xFF, 0xFE, 0xAE, 0x55, 0x87, 0x1c, 0x33}}
, {":fe80:20c:29ff:feae:5587:4A43:1c33", false, {}}
, {"fe80:20c::29ff:feae:5587::1c33" , false, {}}
};
for (auto const&item : ipv6_ex) {
auto &&[text, result, data]{item};
IP6Addr addr;
REQUIRE(result == addr.load(text));
if (result) {
union {
in6_addr _inet;
IP6Addr::raw_type _raw;
} ar;
ar._inet = addr.network_order();
REQUIRE(ar._raw == data);
}
}
IPRange r;
IP4Range r4;
IP6Range r6;
REQUIRE(r4.load("10.242.129.0-10.242.129.127") == true);
REQUIRE(r4.min() == IP4Addr("10.242.129.0"));
REQUIRE(r4.max() == IP4Addr("10.242.129.127"));
REQUIRE(r4.load("10.242.129.0/25") == true);
REQUIRE(r4.min() == IP4Addr("10.242.129.0"));
REQUIRE(r4.max() == IP4Addr("10.242.129.127"));
REQUIRE(r4.load("2.2.2.2") == true);
REQUIRE(r4.min() == IP4Addr("2.2.2.2"));
REQUIRE(r4.max() == IP4Addr("2.2.2.2"));
REQUIRE(r4.load("2.2.2.2.2") == false);
REQUIRE(r4.load("2.2.2.2-fe80:20c::29ff:feae:5587::1c33") == false);
CHECK(r4.load("0xC0A83801"));
REQUIRE(r4 == IP4Addr("192.168.56.1"));
// A few special cases.
static constexpr TextView all_4_txt { "0/0" };
static constexpr TextView all_6_txt { "::/0" };
CHECK(r4.load(all_4_txt));
CHECK(r.load(all_4_txt));
REQUIRE(r.ip4() == r4);
REQUIRE(r4.min() == IP4Addr::MIN);
REQUIRE(r4.max() == IP4Addr::MAX);
CHECK(r.load(all_6_txt));
CHECK(r6.load(all_6_txt));
REQUIRE(r.ip6() == r6);
REQUIRE(r6.min() == IP6Addr::MIN);
REQUIRE(r6.max() == IP6Addr::MAX);
CHECK_FALSE(r6.load("2.2.2.2-fe80:20c::29ff:feae:5587::1c33"));
CHECK_FALSE(r.load("2.2.2.2-fe80:20c::29ff:feae:5587::1c33"));
ep.set_to_any(AF_INET);
REQUIRE(ep.is_loopback() == false);
REQUIRE(ep.is_any() == true);
REQUIRE(ep.raw_addr().length() == sizeof(in_addr_t));
ep.set_to_loopback(AF_INET6);
REQUIRE(ep.is_loopback() == true);
REQUIRE(ep.is_any() == false);
REQUIRE(ep.raw_addr().length() == sizeof(in6_addr));
ep.set_to_any(AF_INET6);
REQUIRE(ep.is_loopback() == false);
REQUIRE(ep.is_any() == true);
CHECK(ep.ip4() == nullptr);
IP6Addr a6{ep.ip6()};
REQUIRE(a6.is_loopback() == false);
REQUIRE(a6.is_any() == true);
ep.set_to_loopback(AF_INET);
REQUIRE(ep.is_loopback() == true);
REQUIRE(ep.is_any() == false);
CHECK(ep.ip6() == nullptr);
IP4Addr a4 { ep.ip4() };
REQUIRE(a4.is_loopback() == true);
REQUIRE(a4.is_any() == false);
CHECK_FALSE(IP6Addr("1337:0:0:ded:BEEF:0:0:0").is_mapped_ip4());
CHECK_FALSE(IP6Addr("1337:0:0:ded:BEEF::").is_mapped_ip4());
CHECK(IP6Addr("::FFFF:C0A8:381F").is_mapped_ip4());
CHECK_FALSE(IP6Addr("FFFF:C0A8:381F::").is_mapped_ip4());
CHECK_FALSE(IP6Addr("::C0A8:381F").is_mapped_ip4());
CHECK(IP6Addr(a4_2).is_mapped_ip4());
};
TEST_CASE("IP Formatting", "[libswoc][ip][bwformat]") {
IPEndpoint ep;
std::string_view addr_1{"[ffee::24c3:3349:3cee:143]:8080"};
std::string_view addr_2{"172.17.99.231:23995"};
std::string_view addr_3{"[1337:ded:BEEF::]:53874"};
std::string_view addr_4{"[1337::ded:BEEF]:53874"};
std::string_view addr_5{"[1337:0:0:ded:BEEF:0:0:956]:53874"};
std::string_view addr_6{"[1337:0:0:ded:BEEF:0:0:0]:53874"};
std::string_view addr_7{"172.19.3.105:4951"};
std::string_view addr_8{"[1337:0:0:ded:BEEF:0:0:0]"};
std::string_view addr_9{"1337:0:0:ded:BEEF:0:0:0"};
std::string_view addr_A{"172.19.3.105"};
std::string_view addr_null{"[::]:53874"};
std::string_view localhost{"[::1]:8080"};
swoc::LocalBufferWriter<1024> w;
REQUIRE(ep.parse(addr_null) == true);
w.clear().print("{::a}", ep);
REQUIRE(w.view() == "::");
ep.set_to_loopback(AF_INET6);
w.clear().print("{::a}", ep);
REQUIRE(w.view() == "::1");
REQUIRE(ep.parse(addr_1) == true);
w.clear().print("{}", ep);
REQUIRE(w.view() == addr_1);
w.clear().print("{::p}", ep);
REQUIRE(w.view() == "8080");
w.clear().print("{::a}", ep);
REQUIRE(w.view() == addr_1.substr(1, 24)); // check the brackets are dropped.
w.clear().print("[{::a}]", ep);
REQUIRE(w.view() == addr_1.substr(0, 26)); // check the brackets are dropped.
w.clear().print("[{0::a}]:{0::p}", ep);
REQUIRE(w.view() == addr_1); // check the brackets are dropped.
w.clear().print("{::=a}", ep);
REQUIRE(w.view() == "ffee:0000:0000:0000:24c3:3349:3cee:0143");
w.clear().print("{:: =a}", ep);
REQUIRE(w.view() == "ffee: 0: 0: 0:24c3:3349:3cee: 143");
// Verify @c IPEndpoint will parse without the port.
REQUIRE(ep.parse(addr_8) == true);
REQUIRE(ep.network_order_port() == 0);
REQUIRE(ep.parse(addr_9) == true);
REQUIRE(ep.network_order_port() == 0);
REQUIRE(ep.parse(addr_A) == true);
REQUIRE(ep.network_order_port() == 0);
REQUIRE(ep.parse(addr_2) == true);
w.clear().print("{::a}", ep);
REQUIRE(w.view() == addr_2.substr(0, 13));
w.clear().print("{0::a}", ep);
REQUIRE(w.view() == addr_2.substr(0, 13));
w.clear().print("{::ap}", ep);
REQUIRE(w.view() == addr_2);
w.clear().print("{::f}", ep);
REQUIRE(w.view() == "ipv4");
w.clear().print("{::fpa}", ep);
REQUIRE(w.view() == "172.17.99.231:23995 ipv4");
w.clear().print("{0::a} .. {0::p}", ep);
REQUIRE(w.view() == "172.17.99.231 .. 23995");
w.clear().print("<+> {0::a} <+> {0::p}", ep);
REQUIRE(w.view() == "<+> 172.17.99.231 <+> 23995");
w.clear().print("<+> {0::a} <+> {0::p} <+>", ep);
REQUIRE(w.view() == "<+> 172.17.99.231 <+> 23995 <+>");
w.clear().print("{:: =a}", ep);
REQUIRE(w.view() == "172. 17. 99.231");
w.clear().print("{::=a}", ep);
REQUIRE(w.view() == "172.017.099.231");
REQUIRE(ep.parse(addr_3) == true);
w.clear().print("{::a}", ep);
REQUIRE(w.view() == "1337:ded:beef::"_tv);
REQUIRE(ep.parse(addr_4) == true);
w.clear().print("{::a}", ep);
REQUIRE(w.view() == "1337::ded:beef"_tv);
REQUIRE(ep.parse(addr_5) == true);
w.clear().print("{:X:a}", ep);
REQUIRE(w.view() == "1337::DED:BEEF:0:0:956");
REQUIRE(ep.parse(addr_6) == true);
w.clear().print("{::a}", ep);
REQUIRE(w.view() == "1337:0:0:ded:beef::");
// Documentation examples
REQUIRE(ep.parse(addr_7) == true);
w.clear().print("To {}", ep);
REQUIRE(w.view() == "To 172.19.3.105:4951");
w.clear().print("To {0::a} on port {0::p}", ep); // no need to pass the argument twice.
REQUIRE(w.view() == "To 172.19.3.105 on port 4951");
w.clear().print("To {::=}", ep);
REQUIRE(w.view() == "To 172.019.003.105:04951");
w.clear().print("{::a}", ep);
REQUIRE(w.view() == "172.19.3.105");
w.clear().print("{::=a}", ep);
REQUIRE(w.view() == "172.019.003.105");
w.clear().print("{::0=a}", ep);
REQUIRE(w.view() == "172.019.003.105");
w.clear().print("{:: =a}", ep);
REQUIRE(w.view() == "172. 19. 3.105");
w.clear().print("{:>20:a}", ep);
REQUIRE(w.view() == " 172.19.3.105");
w.clear().print("{:>20:=a}", ep);
REQUIRE(w.view() == " 172.019.003.105");
w.clear().print("{:>20: =a}", ep);
REQUIRE(w.view() == " 172. 19. 3.105");
w.clear().print("{:<20:a}", ep);
REQUIRE(w.view() == "172.19.3.105 ");
REQUIRE(ep.parse(localhost) == true);
w.clear().print("{}", ep);
REQUIRE(w.view() == localhost);
w.clear().print("{::p}", ep);
REQUIRE(w.view() == "8080");
w.clear().print("{::a}", ep);
REQUIRE(w.view() == localhost.substr(1, 3)); // check the brackets are dropped.
w.clear().print("[{::a}]", ep);
REQUIRE(w.view() == localhost.substr(0, 5));
w.clear().print("[{0::a}]:{0::p}", ep);
REQUIRE(w.view() == localhost); // check the brackets are dropped.
w.clear().print("{::=a}", ep);
REQUIRE(w.view() == "0000:0000:0000:0000:0000:0000:0000:0001");
w.clear().print("{:: =a}", ep);
REQUIRE(w.view() == " 0: 0: 0: 0: 0: 0: 0: 1");
std::string_view r_1{"10.1.0.0-10.1.0.127"};
std::string_view r_2{"10.2.0.1-10.2.0.127"}; // not a network - bad start
std::string_view r_3{"10.3.0.0-10.3.0.126"}; // not a network - bad end
std::string_view r_4{"10.4.1.1-10.4.1.1"}; // singleton
std::string_view r_5{"10.20.30.40- 50.60.70.80"};
std::string_view r_6{"10.20.30.40 -50.60.70.80"};
std::string_view r_7{"10.20.30.40 - 50.60.70.80"};
IPRange r;
r.load(r_1);
w.clear().print("{}", r);
REQUIRE(w.view() == r_1);
w.clear().print("{::c}", r);
REQUIRE(w.view() == "10.1.0.0/25");
r.load(r_2);
w.clear().print("{}", r);
REQUIRE(w.view() == r_2);
w.clear().print("{::c}", r);
REQUIRE(w.view() == r_2);
r.load(r_3);
w.clear().print("{}", r);
REQUIRE(w.view() == r_3);
w.clear().print("{::c}", r);
REQUIRE(w.view() == r_3);
r.load(r_4);
w.clear().print("{}", r);
REQUIRE(w.view() == r_4);
w.clear().print("{::c}", r);
REQUIRE(w.view() == "10.4.1.1");
REQUIRE(r.load(r_5));
REQUIRE(r.load(r_6));
REQUIRE(r.load(r_7));
}
TEST_CASE("IP ranges and networks", "[libswoc][ip][net][range]") {
swoc::IP4Range r_0;
swoc::IP4Range r_1{"1.1.1.0-1.1.1.9"};
swoc::IP4Range r_2{"1.1.2.0-1.1.2.97"};
swoc::IP4Range r_3{"1.1.0.0-1.2.0.0"};
swoc::IP4Range r_4{"10.33.45.19-10.33.45.76"};
swoc::IP6Range r_5{
"2001:1f2d:c587:24c3:9128:3349:3cee:143-ffee:1f2d:c587:24c3:9128:3349:3cFF:FFFF"_tv};
CHECK(r_0.empty());
CHECK_FALSE(r_1.empty());
swoc::IPMask mask{127};
CHECK(r_5.min() == (r_5.min() | swoc::IPMask(128)));
CHECK(r_5.min() == (r_5.min() | mask));
CHECK(r_5.min() != (r_5.min() & mask));
swoc::IP6Addr aa_1{"2001:1f2d:c587:24c4::"};
CHECK(aa_1 == (aa_1 & swoc::IPMask{62}));
// Verify a family specific range only works with the same family range.
TextView r4_txt{"10.33.45.19-10.33.45.76"};
TextView r6_txt{"2001:1f2d:c587:24c3:9128:3349:3cee:143-ffee:1f2d:c587:24c3:9128:3349:3cFF:FFFF"};
IP4Range rr4;
IP6Range rr6;
CHECK(rr4.load(r4_txt));
CHECK_FALSE(rr4.load(r6_txt));
CHECK_FALSE(rr6.load(r4_txt));
CHECK(rr6.load(r6_txt));
std::array<swoc::IP4Net, 7> r_4_nets =
{{
"10.33.45.19/32"_tv
, "10.33.45.20/30"_tv
, "10.33.45.24/29"_tv
, "10.33.45.32/27"_tv
, "10.33.45.64/29"_tv
, "10.33.45.72/30"_tv
, "10.33.45.76/32"_tv
}};
auto r4_net = r_4_nets.begin();
for (auto net : r_4.networks()) {
REQUIRE(r4_net != r_4_nets.end());
CHECK(*r4_net == net);
++r4_net;
}
// Let's try that again, with @c IPRange instead.
r4_net = r_4_nets.begin();
for (auto const& net : IPRange{r_4}.networks()) {
REQUIRE(r4_net != r_4_nets.end());
CHECK(*r4_net == net);
++r4_net;
}
std::array<swoc::IP6Net, 130> r_5_nets =
{{
{IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:143"}, IPMask{
128}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:144"}, IPMask{126}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:148"}, IPMask{125}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:150"}, IPMask{124}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:160"}, IPMask{123}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:180"}, IPMask{121}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:200"}, IPMask{119}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:400"}, IPMask{118}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:800"}, IPMask{117}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:1000"}, IPMask{116}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:2000"}, IPMask{115}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:4000"}, IPMask{114}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cee:8000"}, IPMask{113}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cef:0"}, IPMask{112}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3cf0:0"}, IPMask{108}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3d00:0"}, IPMask{104}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:3e00:0"}, IPMask{103}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:4000:0"}, IPMask{98}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3349:8000:0"}, IPMask{97}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:334a::"}, IPMask{95}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:334c::"}, IPMask{94}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3350::"}, IPMask{92}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3360::"}, IPMask{91}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3380::"}, IPMask{89}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3400::"}, IPMask{86}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:3800::"}, IPMask{85}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:4000::"}, IPMask{82}}
, {IP6Addr{
"2001:1f2d:c587:24c3:9128:8000::"}, IPMask{81}}
, {IP6Addr{"2001:1f2d:c587:24c3:9129::"}, IPMask{
80}}
, {IP6Addr{"2001:1f2d:c587:24c3:912a::"}, IPMask{
79}}
, {IP6Addr{"2001:1f2d:c587:24c3:912c::"}, IPMask{
78}}
, {IP6Addr{"2001:1f2d:c587:24c3:9130::"}, IPMask{
76}}
, {IP6Addr{"2001:1f2d:c587:24c3:9140::"}, IPMask{
74}}
, {IP6Addr{"2001:1f2d:c587:24c3:9180::"}, IPMask{
73}}
, {IP6Addr{"2001:1f2d:c587:24c3:9200::"}, IPMask{
71}}
, {IP6Addr{"2001:1f2d:c587:24c3:9400::"}, IPMask{
70}}
, {IP6Addr{"2001:1f2d:c587:24c3:9800::"}, IPMask{
69}}
, {IP6Addr{"2001:1f2d:c587:24c3:a000::"}, IPMask{
67}}
, {IP6Addr{"2001:1f2d:c587:24c3:c000::"}, IPMask{
66}}
, {IP6Addr{"2001:1f2d:c587:24c4::"}, IPMask{62}}
, {IP6Addr{"2001:1f2d:c587:24c8::"}, IPMask{61}}
, {IP6Addr{"2001:1f2d:c587:24d0::"}, IPMask{60}}
, {IP6Addr{"2001:1f2d:c587:24e0::"}, IPMask{59}}
, {IP6Addr{"2001:1f2d:c587:2500::"}, IPMask{56}}
, {IP6Addr{"2001:1f2d:c587:2600::"}, IPMask{55}}
, {IP6Addr{"2001:1f2d:c587:2800::"}, IPMask{53}}
, {IP6Addr{"2001:1f2d:c587:3000::"}, IPMask{52}}
, {IP6Addr{"2001:1f2d:c587:4000::"}, IPMask{50}}
, {IP6Addr{"2001:1f2d:c587:8000::"}, IPMask{49}}
, {IP6Addr{"2001:1f2d:c588::"}, IPMask{45}}
, {IP6Addr{"2001:1f2d:c590::"}, IPMask{44}}
, {IP6Addr{"2001:1f2d:c5a0::"}, IPMask{43}}
, {IP6Addr{"2001:1f2d:c5c0::"}, IPMask{42}}
, {IP6Addr{"2001:1f2d:c600::"}, IPMask{39}}
, {IP6Addr{"2001:1f2d:c800::"}, IPMask{37}}
, {IP6Addr{"2001:1f2d:d000::"}, IPMask{36}}
, {IP6Addr{"2001:1f2d:e000::"}, IPMask{35}}
, {IP6Addr{"2001:1f2e::"}, IPMask{31}}
, {IP6Addr{"2001:1f30::"}, IPMask{28}}
, {IP6Addr{"2001:1f40::"}, IPMask{26}}
, {IP6Addr{"2001:1f80::"}, IPMask{25}}
, {IP6Addr{"2001:2000::"}, IPMask{19}}
, {IP6Addr{"2001:4000::"}, IPMask{18}}
, {IP6Addr{"2001:8000::"}, IPMask{17}}
, {IP6Addr{"2002::"}, IPMask{15}}
, {IP6Addr{"2004::"}, IPMask{14}}
, {IP6Addr{"2008::"}, IPMask{13}}
, {IP6Addr{"2010::"}, IPMask{12}}
, {IP6Addr{"2020::"}, IPMask{11}}
, {IP6Addr{"2040::"}, IPMask{10}}
, {IP6Addr{"2080::"}, IPMask{9}}
, {IP6Addr{"2100::"}, IPMask{8}}
, {IP6Addr{"2200::"}, IPMask{7}}
, {IP6Addr{"2400::"}, IPMask{6}}
, {IP6Addr{"2800::"}, IPMask{5}}
, {IP6Addr{"3000::"}, IPMask{4}}
, {IP6Addr{"4000::"}, IPMask{2}}
, {IP6Addr{"8000::"}, IPMask{2}}
, {IP6Addr{"c000::"}, IPMask{3}}
, {IP6Addr{"e000::"}, IPMask{4}}
, {IP6Addr{"f000::"}, IPMask{5}}
, {IP6Addr{"f800::"}, IPMask{6}}
, {IP6Addr{"fc00::"}, IPMask{7}}
, {IP6Addr{"fe00::"}, IPMask{8}}
, {IP6Addr{"ff00::"}, IPMask{9}}
, {IP6Addr{"ff80::"}, IPMask{10}}
, {IP6Addr{"ffc0::"}, IPMask{11}}
, {IP6Addr{"ffe0::"}, IPMask{13}}
, {IP6Addr{"ffe8::"}, IPMask{14}}
, {IP6Addr{"ffec::"}, IPMask{15}}
, {IP6Addr{"ffee::"}, IPMask{20}}
, {IP6Addr{"ffee:1000::"}, IPMask{21}}
, {IP6Addr{"ffee:1800::"}, IPMask{22}}
, {IP6Addr{"ffee:1c00::"}, IPMask{23}}
, {IP6Addr{"ffee:1e00::"}, IPMask{24}}
, {IP6Addr{"ffee:1f00::"}, IPMask{27}}
, {IP6Addr{"ffee:1f20::"}, IPMask{29}}
, {IP6Addr{"ffee:1f28::"}, IPMask{30}}
, {IP6Addr{"ffee:1f2c::"}, IPMask{32}}
, {IP6Addr{"ffee:1f2d::"}, IPMask{33}}
, {IP6Addr{"ffee:1f2d:8000::"}, IPMask{34}}
, {IP6Addr{"ffee:1f2d:c000::"}, IPMask{38}}
, {IP6Addr{"ffee:1f2d:c400::"}, IPMask{40}}
, {IP6Addr{"ffee:1f2d:c500::"}, IPMask{41}}
, {IP6Addr{"ffee:1f2d:c580::"}, IPMask{46}}
, {IP6Addr{"ffee:1f2d:c584::"}, IPMask{47}}
, {IP6Addr{"ffee:1f2d:c586::"}, IPMask{48}}
, {IP6Addr{"ffee:1f2d:c587::"}, IPMask{51}}
, {IP6Addr{"ffee:1f2d:c587:2000::"}, IPMask{54}}
, {IP6Addr{"ffee:1f2d:c587:2400::"}, IPMask{57}}
, {IP6Addr{"ffee:1f2d:c587:2480::"}, IPMask{58}}
, {IP6Addr{"ffee:1f2d:c587:24c0::"}, IPMask{63}}
, {IP6Addr{"ffee:1f2d:c587:24c2::"}, IPMask{64}}
, {IP6Addr{"ffee:1f2d:c587:24c3::"}, IPMask{65}}
, {IP6Addr{"ffee:1f2d:c587:24c3:8000::"}, IPMask{
68}}
, {IP6Addr{"ffee:1f2d:c587:24c3:9000::"}, IPMask{
72}}
, {IP6Addr{"ffee:1f2d:c587:24c3:9100::"}, IPMask{
75}}
, {IP6Addr{"ffee:1f2d:c587:24c3:9120::"}, IPMask{
77}}
, {IP6Addr{"ffee:1f2d:c587:24c3:9128::"}, IPMask{
83}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:2000::"}, IPMask{84}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3000::"}, IPMask{87}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3200::"}, IPMask{88}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3300::"}, IPMask{90}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3340::"}, IPMask{93}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3348::"}, IPMask{96}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3349::"}, IPMask{99}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3349:2000:0"}, IPMask{100}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3349:3000:0"}, IPMask{101}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3349:3800:0"}, IPMask{102}}
, {IP6Addr{
"ffee:1f2d:c587:24c3:9128:3349:3c00:0"}, IPMask{104}}
}};
auto r5_net = r_5_nets.begin();
for (auto const&[a, m] : r_5.networks()) {
REQUIRE(r5_net != r_5_nets.end());
CHECK(*r5_net == swoc::IP6Net{a, m});
++r5_net;
}
// Try it again, using @c IPNet.
r5_net = r_5_nets.begin();
for ( auto const&[a, m] : IPRange{r_5}.networks()) {
REQUIRE(r5_net != r_5_nets.end());
CHECK(*r5_net == swoc::IPNet{a, m});
++r5_net;
}
}
TEST_CASE("IP Space Int", "[libswoc][ip][ipspace]") {
using uint_space = swoc::IPSpace<unsigned>;
uint_space space;
REQUIRE(space.count() == 0);
space.mark(IPRange{{IP4Addr("172.16.0.0"), IP4Addr("172.16.0.255")}}, 1);
auto result = space.find(IPAddr{"172.16.0.97"});
REQUIRE(result != space.end());
REQUIRE(std::get<1>(*result) == 1);
result = space.find(IPAddr{"172.17.0.97"});
REQUIRE(result == space.end());
space.mark(IPRange{"172.16.0.12-172.16.0.25"_tv}, 2);
result = space.find(IPAddr{"172.16.0.21"});
REQUIRE(result != space.end());
REQUIRE(std::get<1>(*result) == 2);
REQUIRE(space.count() == 3);
space.clear();
auto BF = [](unsigned&lhs, unsigned rhs) -> bool {
lhs |= rhs;
return true;
};
swoc::IP4Range r_1{"1.1.1.0-1.1.1.9"};
swoc::IP4Range r_2{"1.1.2.0-1.1.2.97"};
swoc::IP4Range r_3{"1.1.0.0-1.2.0.0"};
// Compiler check - make sure both of these work.
REQUIRE(r_1.min() == IP4Addr("1.1.1.0"_tv));
REQUIRE(r_1.max() == IPAddr("1.1.1.9"_tv));
space.blend(r_1, 0x1, BF);
REQUIRE(space.count() == 1);
REQUIRE(space.end() == space.find(r_2.min()));
REQUIRE(space.end() != space.find(r_1.min()));
REQUIRE(space.end() != space.find(r_1.max()));
REQUIRE(space.end() != space.find(IP4Addr{"1.1.1.7"}));
CHECK(0x1 == std::get<1>(*space.find(IP4Addr{"1.1.1.7"})));
space.blend(r_2, 0x2, BF);
REQUIRE(space.count() == 2);
REQUIRE(space.end() != space.find(r_1.min()));
auto spot = space.find(r_2.min());
REQUIRE(spot != space.end());
REQUIRE(std::get<1>(*spot) == 0x2);
spot = space.find(r_2.max());
REQUIRE(spot != space.end());
REQUIRE(std::get<1>(*spot) == 0x2);
space.blend(r_3, 0x4, BF);
REQUIRE(space.count() == 5);
spot = space.find(r_2.min());
REQUIRE(spot != space.end());
REQUIRE(std::get<1>(*spot) == 0x6);
spot = space.find(r_3.min());
REQUIRE(spot != space.end());
REQUIRE(std::get<1>(*spot) == 0x4);
spot = space.find(r_1.max());
REQUIRE(spot != space.end());
REQUIRE(std::get<1>(*spot) == 0x5);
space.blend(IPRange{r_2.min(), r_3.max()}, 0x6, BF);
REQUIRE(space.count() == 4);
std::array<std::tuple<TextView, int>, 9> ranges = {
{
{"100.0.0.0-100.0.0.255", 0}
, {"100.0.1.0-100.0.1.255", 1}
, {"100.0.2.0-100.0.2.255", 2}
, {"100.0.3.0-100.0.3.255", 3}
, {"100.0.4.0-100.0.4.255", 4}
, {"100.0.5.0-100.0.5.255", 5}
, {"100.0.6.0-100.0.6.255", 6}
, {"100.0.0.0-100.0.0.255", 31}
, {"100.0.1.0-100.0.1.255", 30}
}};
space.clear();
for (auto &&[text, value] : ranges) {
IPRange range{text};
space.mark(IPRange{text}, value);
}
CHECK(7 == space.count());
// Make sure all of these addresses yield the same result.
CHECK(space.end() != space.find(IP4Addr{"100.0.4.16"}));
CHECK(space.end() != space.find(IPAddr{"100.0.4.16"}));
CHECK(space.end() != space.find(IPAddr{IPEndpoint{"100.0.4.16:80"}}));
// same for negative result
CHECK(space.end() == space.find(IP4Addr{"10.0.4.16"}));
CHECK(space.end() == space.find(IPAddr{"10.0.4.16"}));
CHECK(space.end() == space.find(IPAddr{IPEndpoint{"10.0.4.16:80"}}));
std::array<std::tuple<TextView, int>, 3> r_clear = {
{
{"2.2.2.2-2.2.2.40", 0}
, {"2.2.2.50-2.2.2.60", 1}
, {"2.2.2.70-2.2.2.100", 2}
}};
space.clear();
for (auto &&[text, value] : r_clear) {
IPRange range{text};
space.mark(IPRange{text}, value);
}
CHECK(space.count() == 3);
space.erase(IPRange{"2.2.2.35-2.2.2.75"});
CHECK(space.count() == 2);
{
spot = space.begin();
auto [ r0, p0 ] = *spot;
auto [ r2, p2 ] = *++spot;
CHECK(r0 == IPRange{"2.2.2.2-2.2.2.34"});
CHECK(p0 == 0);
CHECK(r2 == IPRange{"2.2.2.76-2.2.2.100"});
CHECK(p2 == 2);
}
// This is about testing repeated colorings of the same addresses, which happens quite a
// bit in normal network datasets. In fact, the test dataset is based on such a dataset
// and its use.
auto b2 = [] (unsigned &lhs, unsigned const& rhs) { lhs = rhs; return true; };
std::array<std::tuple<TextView, unsigned>, 31> r2 = {
{
{"2001:4998:58:400::1/128", 1} // 1
, {"2001:4998:58:400::2/128", 1}
, {"2001:4998:58:400::3/128", 1}
, {"2001:4998:58:400::4/128", 1}
, {"2001:4998:58:400::5/128", 1}
, {"2001:4998:58:400::6/128", 1}
, {"2001:4998:58:400::7/128", 1}
, {"2001:4998:58:400::8/128", 1}
, {"2001:4998:58:400::9/128", 1}
, {"2001:4998:58:400::A/127", 1}
, {"2001:4998:58:400::10/127", 1} // 2
, {"2001:4998:58:400::12/127", 1}
, {"2001:4998:58:400::14/127", 1}
, {"2001:4998:58:400::16/127", 1}
, {"2001:4998:58:400::18/127", 1}
, {"2001:4998:58:400::1a/127", 1}
, {"2001:4998:58:400::1c/127", 1}
, {"2001:4998:58:400::1e/127", 1}
, {"2001:4998:58:400::20/127", 1}
, {"2001:4998:58:400::22/127", 1}
, {"2001:4998:58:400::24/127", 1}
, {"2001:4998:58:400::26/127", 1}
, {"2001:4998:58:400::2a/127", 1} // 3
, {"2001:4998:58:400::2c/127", 1}
, {"2001:4998:58:400::2e/127", 1}
, {"2001:4998:58:400::30/127", 1}
, {"2001:4998:58:400::140/127", 1} // 4
, {"2001:4998:58:400::142/127", 1}
, {"2001:4998:58:400::146/127", 1} // 5
, {"2001:4998:58:400::148/127", 1}
, {"2001:4998:58:400::150/127", 1} // 6
}};
space.clear();
// Start with basic blending.
for (auto &&[text, value] : r2) {
IPRange range{text};
space.blend(IPRange{text}, value, b2);
REQUIRE(space.end() != space.find(range.min()));
REQUIRE(space.end() != space.find(range.max()));
}
CHECK(6 == space.count());
// Do the exact same networks again, should not change the range count.
for (auto &&[text, value] : r2) {
IPRange range{text};
space.blend(IPRange{text}, value, b2);
REQUIRE(space.end() != space.find(range.min()));
REQUIRE(space.end() != space.find(range.max()));
}
CHECK(6 == space.count());
// Verify that earlier ranges are still valid after the double blend.
for (auto &&[text, value] : r2) {
IPRange range{text};
REQUIRE(space.end() != space.find(range.min()));
REQUIRE(space.end() != space.find(range.max()));
}
// Color the non-intersecting range between ranges 1 and 2, verify coalesce.
space.blend(IPRange{"2001:4998:58:400::C/126"_tv}, 1, b2);
CHECK(5 == space.count());
// Verify all the data is in the ranges.
for (auto &&[text, value] : r2) {
IPRange range{text};
REQUIRE(space.end() != space.find(range.min()));
REQUIRE(space.end() != space.find(range.max()));
}
// Check some syntax.
{
auto && [ r, p ] = *space.find(IPAddr{"2001:4998:58:400::1E"});
REQUIRE(false == r.empty());
REQUIRE(p == 1);
}
{
auto && [ r, p ] = *space.find(IPAddr{"2001:4997:58:400::1E"});
REQUIRE(true == r.empty());
}
}
TEST_CASE("IPSpace bitset", "[libswoc][ipspace][bitset]") {
using PAYLOAD = std::bitset<32>;
using Space = swoc::IPSpace<PAYLOAD>;
std::array<std::tuple<TextView, std::initializer_list<unsigned>>, 6> ranges = {
{
{"172.28.56.12-172.28.56.99"_tv, {0, 2, 3}}
, {"10.10.35.0/24"_tv, {1, 2}}
, {"192.168.56.0/25"_tv, {10, 12, 31}}
, {"1337::ded:beef-1337::ded:ceef"_tv, {4, 5, 6, 7}}
, {"ffee:1f2d:c587:24c3:9128:3349:3cee:143-ffee:1f2d:c587:24c3:9128:3349:3cFF:FFFF"_tv, {9, 10, 18}}
, {"10.12.148.0/23"_tv, {1, 2, 17}}
}};
Space space;
for (auto &&[text, bit_list] : ranges) {
PAYLOAD bits;
for (auto bit : bit_list) {
bits[bit] = true;
}
space.mark(IPRange{text}, bits);
}
REQUIRE(space.count() == ranges.size());
// Check that if an IPv4 lookup misses, it doesn't pass on to the first IPv6
auto && [ r1, p1 ] = *(space.find(IP4Addr{"172.28.56.100"}));
REQUIRE(true == r1.empty());
auto && [ r2, p2 ] = *(space.find(IPAddr{"172.28.56.100"}));
REQUIRE(true == r2.empty());
}
TEST_CASE("IPSpace docJJ", "[libswoc][ipspace][docJJ]") {
using PAYLOAD = std::bitset<32>;
using Space = swoc::IPSpace<PAYLOAD>;
// Add the bits in @rhs to the range.
auto blender = [](PAYLOAD&lhs, PAYLOAD const&rhs) -> bool {
lhs |= rhs;
return true;
};
// Add bit @a idx iff bits are already set.
auto additive = [](PAYLOAD & lhs, unsigned idx) -> bool {
if (! lhs.any()) {
return false;
}
lhs[idx] = true;
return true;
};
auto make_bits = [](std::initializer_list<unsigned> idx) -> PAYLOAD {
PAYLOAD bits;
for (auto bit : idx) {
bits[bit] = true;
}
return bits;
};
std::array<std::tuple<TextView, PAYLOAD>, 9> ranges = {
{
{"100.0.0.0-100.0.0.255", make_bits({0})}
, {"100.0.1.0-100.0.1.255", make_bits({1})}
, {"100.0.2.0-100.0.2.255", make_bits({2})}
, {"100.0.3.0-100.0.3.255", make_bits({3})}
, {"100.0.4.0-100.0.4.255", make_bits({4})}
, {"100.0.5.0-100.0.5.255", make_bits({5})}
, {"100.0.6.0-100.0.6.255", make_bits({6})}
, {"100.0.0.0-100.0.0.255", make_bits({31})}
, {"100.0.1.0-100.0.1.255", make_bits({30})}
}};
static constexpr std::array<std::initializer_list<unsigned>, 7> results = {{
{0, 31}
, {1, 30}
, {2}
, {3}
, {4}
, {5}
, {6}
}};
Space space;
for (auto && [text, bit_list] : ranges) {
space.blend(IPRange{text}, bit_list, blender);
}
// Check iteration - verify forward and reverse iteration yield the correct number of ranges
// and the range payloads match what is expected.
REQUIRE(space.count() == results.size());
unsigned idx;
idx = 0;
for (auto spot = space.begin() ; spot != space.end() && idx < results.size() ; ++spot) {
auto const& [ range, bits ] { *spot };
REQUIRE(idx < results.size());
CHECK(bits == make_bits(results[idx]));
++idx;
}
idx = 0;
for (auto const& [range, bits] : space) {
CHECK(bits == make_bits(results[idx]));
++idx;
}
idx = results.size();
for (auto spot = space.end(); spot != space.begin();) {
auto const&[range, bits]{*--spot};
REQUIRE(idx > 0);
--idx;
CHECK(bits == make_bits(results[idx]));
}
// Check iterator copying.
idx = 0;
Space::iterator iter;
IPRange range;
PAYLOAD bits;
for (auto spot = space.begin(); spot != space.end() ; ++spot, ++idx) {
iter = spot;
std::tie(range, bits) = *iter;
CHECK(bits == make_bits(results[idx]));
}
// This blend should change only existing ranges, not add range.
space.blend(IPRange{"99.128.0.0-100.0.1.255"}, 27, additive);
REQUIRE(space.count() == results.size()); // no more ranges.
// Verify first two ranges modified, but not the next.
REQUIRE(std::get<1>(*(space.find(IP4Addr{"100.0.0.37"}))) == make_bits({0,27,31}));
REQUIRE(std::get<1>(*(space.find(IP4Addr{"100.0.1.37"}))) == make_bits({1,27,30}));
REQUIRE(std::get<1>(*(space.find(IP4Addr{"100.0.2.37"}))) == make_bits({2}));
space.blend(IPRange{"100.10.1.1-100.10.2.2"}, make_bits({15}), blender);
REQUIRE(space.count() == results.size() + 1);
// Color in empty range - should not add range.
space.blend(IPRange{"100.8.10.25"}, 27, additive);
REQUIRE(space.count() == results.size() + 1);
}
TEST_CASE("IPSpace Uthira", "[libswoc][ipspace][uthira]") {
struct Data {
TextView _pod;
int _rack = 0;
int _code = 0;
bool operator== (Data const& that) const {
return _pod == that._pod && _rack == that._rack && _code == that._code;
}
};
auto pod_blender = [] (Data &data, TextView const& p) { data._pod = p; return true; };
auto rack_blender = [] (Data &data, int r) { data._rack = r; return true; };
auto code_blender = [] (Data &data, int c) { data._code = c; return true; };
swoc::IPSpace<Data> space;
// This is overkill, but no reason to not slam the code.
// For the original bug that triggered this testing, only the first line is actually necessary
// to cause the problem.
TextView content = R"(10.215.88.12-10.215.88.12,pdb,9
10.215.88.13-10.215.88.13,pdb,9
10.215.88.0-10.215.88.1,pdb,9
10.215.88.2-10.215.88.3,pdb,9
10.215.88.4-10.215.88.5,pdb,9
10.215.88.6-10.215.88.7,pdb,9
10.215.88.8-10.215.88.9,pdb,9
10.215.88.10-10.215.88.11,pdb,9
10.214.128.0-10.214.128.63,pda,1
10.214.128.64-10.214.128.127,pda,1
10.214.128.128-10.214.128.191,pda,1
10.214.128.192-10.214.128.255,pda,1
10.214.129.0-10.214.129.63,pda,1
10.214.129.64-10.214.129.127,pda,1
10.214.129.128-10.214.129.191,pda,1
10.214.129.192-10.214.129.255,pda,1
10.214.130.0-10.214.130.63,pda,1
10.214.130.64-10.214.130.127,pda,1
10.214.130.128-10.214.130.191,pda,1
10.214.130.192-10.214.130.255,pda,1
10.214.131.0-10.214.131.63,pda,1
10.214.131.64-10.214.131.127,pda,1
10.214.131.128-10.214.131.191,pda,1
10.214.131.192-10.214.131.255,pda,1
10.214.132.0-10.214.132.63,pda,1
10.214.132.64-10.214.132.127,pda,1
10.214.132.128-10.214.132.191,pda,1
10.214.132.192-10.214.132.255,pda,1
10.214.133.0-10.214.133.63,pda,1
10.214.133.64-10.214.133.127,pda,1
10.214.133.128-10.214.133.191,pda,1
10.214.133.192-10.214.133.255,pda,1
10.214.134.0-10.214.134.63,pda,1
10.214.134.64-10.214.134.127,pda,1
10.214.134.128-10.214.134.191,pda,1
10.214.134.192-10.214.134.255,pda,1
10.214.135.0-10.214.135.63,pda,1
10.214.135.64-10.214.135.127,pda,1
10.214.135.128-10.214.135.191,pda,1
10.214.135.192-10.214.135.255,pda,1
10.214.140.0-10.214.140.63,pda,1
10.214.140.64-10.214.140.127,pda,1
10.214.140.128-10.214.140.191,pda,1
10.214.140.192-10.214.140.255,pda,1
10.214.141.0-10.214.141.63,pda,1
10.214.141.64-10.214.141.127,pda,1
10.214.141.128-10.214.141.191,pda,1
10.214.141.192-10.214.141.255,pda,1
10.214.145.0-10.214.145.63,pda,1
10.214.145.64-10.214.145.127,pda,1
10.214.145.128-10.214.145.191,pda,1
10.214.145.192-10.214.145.255,pda,1
10.214.146.0-10.214.146.63,pda,1
10.214.146.64-10.214.146.127,pda,1
10.214.146.128-10.214.146.191,pda,1
10.214.146.192-10.214.146.255,pda,1
10.214.147.0-10.214.147.63,pda,1
10.214.147.64-10.214.147.127,pda,1
10.214.147.128-10.214.147.191,pda,1
10.214.147.192-10.214.147.255,pda,1
10.214.152.0-10.214.152.63,pda,1
10.214.152.64-10.214.152.127,pda,1
10.214.152.128-10.214.152.191,pda,1
10.214.152.192-10.214.152.255,pda,1
10.214.153.0-10.214.153.63,pda,1
10.214.153.64-10.214.153.127,pda,1
10.214.153.128-10.214.153.191,pda,1
10.214.153.192-10.214.153.255,pda,1
10.214.154.0-10.214.154.63,pda,1
10.214.154.64-10.214.154.127,pda,1
10.214.154.128-10.214.154.191,pda,1
10.214.154.192-10.214.154.255,pda,1
10.214.155.0-10.214.155.63,pda,1
10.214.155.64-10.214.155.127,pda,1
10.214.155.128-10.214.155.191,pda,1
10.214.155.192-10.214.155.255,pda,1
10.214.156.0-10.214.156.63,pda,1
10.214.156.64-10.214.156.127,pda,1
10.214.156.128-10.214.156.191,pda,1
10.214.156.192-10.214.156.255,pda,1
10.214.157.0-10.214.157.63,pda,1
10.214.157.64-10.214.157.127,pda,1
10.214.157.128-10.214.157.191,pda,1
10.214.157.192-10.214.157.255,pda,1
10.214.158.0-10.214.158.63,pda,1
10.214.158.64-10.214.158.127,pda,1
10.214.158.128-10.214.158.191,pda,1
10.214.158.192-10.214.158.255,pda,1
10.214.164.0-10.214.164.63,pda,1
10.214.164.64-10.214.164.127,pda,1
10.214.167.0-10.214.167.63,pda,1
10.214.167.64-10.214.167.127,pda,1
10.214.167.128-10.214.167.191,pda,1
10.214.167.192-10.214.167.255,pda,1
10.214.168.0-10.214.168.63,pda,1
10.214.168.64-10.214.168.127,pda,1
10.214.168.128-10.214.168.191,pda,1
10.214.168.192-10.214.168.255,pda,1
10.214.169.0-10.214.169.63,pda,1
10.214.169.64-10.214.169.127,pda,1
10.214.169.128-10.214.169.191,pda,1
10.214.169.192-10.214.169.255,pda,1
10.214.172.0-10.214.172.63,pda,1
10.214.172.64-10.214.172.127,pda,1
10.214.172.128-10.214.172.191,pda,1
10.214.172.192-10.214.172.255,pda,1
10.214.173.0-10.214.173.63,pda,1
10.214.173.64-10.214.173.127,pda,1
10.214.173.128-10.214.173.191,pda,1
10.214.173.192-10.214.173.255,pda,1
10.214.219.128-10.214.219.191,pda,1
10.214.219.192-10.214.219.255,pda,1
10.214.245.0-10.214.245.63,pda,1
10.214.245.64-10.214.245.127,pda,1
10.215.64.0-10.215.64.63,pda,1
10.215.64.64-10.215.64.127,pda,1
10.215.64.128-10.215.64.191,pda,1
10.215.64.192-10.215.64.255,pda,1
10.215.65.128-10.215.65.191,pda,1
10.215.65.192-10.215.65.255,pda,1
10.215.66.0-10.215.66.63,pda,1
10.215.66.64-10.215.66.127,pda,1
10.215.66.128-10.215.66.191,pda,1
10.215.66.192-10.215.66.255,pda,1
10.215.67.0-10.215.67.63,pda,1
10.215.67.64-10.215.67.127,pda,1
10.215.71.0-10.215.71.63,pda,1
10.215.71.64-10.215.71.127,pda,1
10.215.71.128-10.215.71.191,pda,1
10.215.71.192-10.215.71.255,pda,1
10.215.72.0-10.215.72.63,pda,1
10.215.72.64-10.215.72.127,pda,1
10.215.72.128-10.215.72.191,pda,1
10.215.72.192-10.215.72.255,pda,1
10.215.80.0-10.215.80.63,pda,1
10.215.80.64-10.215.80.127,pda,1
10.215.80.128-10.215.80.191,pda,1
10.215.80.192-10.215.80.255,pda,1
10.215.81.0-10.215.81.63,pda,1
10.215.81.64-10.215.81.127,pda,1
10.215.81.128-10.215.81.191,pda,1
10.215.81.192-10.215.81.255,pda,1
10.215.82.0-10.215.82.63,pda,1
10.215.82.64-10.215.82.127,pda,1
10.215.82.128-10.215.82.191,pda,1
10.215.82.192-10.215.82.255,pda,1
10.215.84.0-10.215.84.63,pda,1
10.215.84.64-10.215.84.127,pda,1
10.215.84.128-10.215.84.191,pda,1
10.215.84.192-10.215.84.255,pda,1
10.215.88.64-10.215.88.127,pdb,1
10.215.88.128-10.215.88.191,pdb,1
10.215.88.192-10.215.88.255,pdb,1
10.215.89.0-10.215.89.63,pdb,1
10.215.89.64-10.215.89.127,pdb,1
10.215.89.128-10.215.89.191,pdb,1
10.215.89.192-10.215.89.255,pdb,1
10.215.90.0-10.215.90.63,pdb,1
10.215.90.64-10.215.90.127,pdb,1
10.215.90.128-10.215.90.191,pdb,1
10.215.100.0-10.215.100.63,pda,1
10.215.132.0-10.215.132.63,pda,1
10.215.132.64-10.215.132.127,pda,1
10.215.132.128-10.215.132.191,pda,1
10.215.132.192-10.215.132.255,pda,1
10.215.133.0-10.215.133.63,pda,1
10.215.133.64-10.215.133.127,pda,1
10.215.133.128-10.215.133.191,pda,1
10.215.133.192-10.215.133.255,pda,1
10.215.134.0-10.215.134.63,pda,1
10.215.134.64-10.215.134.127,pda,1
10.215.134.128-10.215.134.191,pda,1
10.215.134.192-10.215.134.255,pda,1
10.215.135.0-10.215.135.63,pda,1
10.215.135.64-10.215.135.127,pda,1
10.215.135.128-10.215.135.191,pda,1
10.215.135.192-10.215.135.255,pda,1
10.215.136.0-10.215.136.63,pda,1
10.215.136.64-10.215.136.127,pda,1
10.215.136.128-10.215.136.191,pda,1
10.215.136.192-10.215.136.255,pda,1
10.215.137.0-10.215.137.63,pda,1
10.215.137.64-10.215.137.127,pda,1
10.215.137.128-10.215.137.191,pda,1
10.215.137.192-10.215.137.255,pda,1
10.215.138.0-10.215.138.63,pda,1
10.215.138.64-10.215.138.127,pda,1
10.215.138.128-10.215.138.191,pda,1
10.215.138.192-10.215.138.255,pda,1
10.215.139.0-10.215.139.63,pda,1
10.215.139.64-10.215.139.127,pda,1
10.215.139.128-10.215.139.191,pda,1
10.215.139.192-10.215.139.255,pda,1
10.215.144.0-10.215.144.63,pda,1
10.215.144.64-10.215.144.127,pda,1
10.215.144.128-10.215.144.191,pda,1
10.215.144.192-10.215.144.255,pda,1
10.215.145.0-10.215.145.63,pda,1
10.215.145.64-10.215.145.127,pda,1
10.215.145.128-10.215.145.191,pda,1
10.215.145.192-10.215.145.255,pda,1
10.215.146.0-10.215.146.63,pda,1
10.215.146.64-10.215.146.127,pda,1
10.215.146.128-10.215.146.191,pda,1
10.215.146.192-10.215.146.255,pda,1
10.215.147.0-10.215.147.63,pda,1
10.215.147.64-10.215.147.127,pda,1
10.215.147.128-10.215.147.191,pda,1
10.215.147.192-10.215.147.255,pda,1
10.215.166.0-10.215.166.63,pda,1
10.215.166.64-10.215.166.127,pda,1
10.215.166.128-10.215.166.191,pda,1
10.215.166.192-10.215.166.255,pda,1
10.215.167.0-10.215.167.63,pda,1
10.215.167.64-10.215.167.127,pda,1
10.215.167.128-10.215.167.191,pda,1
10.215.167.192-10.215.167.255,pda,1
10.215.170.0-10.215.170.63,pda,1
10.215.170.64-10.215.170.127,pda,1
10.215.170.128-10.215.170.191,pda,1
10.215.170.192-10.215.170.255,pda,1
10.215.171.0-10.215.171.63,pda,1
10.215.171.64-10.215.171.127,pda,1
10.215.171.128-10.215.171.191,pda,1
10.215.171.192-10.215.171.255,pda,1
10.215.172.0-10.215.172.63,pda,1
10.215.172.64-10.215.172.127,pda,1
10.215.172.128-10.215.172.191,pda,1
10.215.172.192-10.215.172.255,pda,1
10.215.173.0-10.215.173.63,pda,1
10.215.173.64-10.215.173.127,pda,1
10.215.173.128-10.215.173.191,pda,1
10.215.173.192-10.215.173.255,pda,1
10.215.174.0-10.215.174.63,pda,1
10.215.174.64-10.215.174.127,pda,1
10.215.174.128-10.215.174.191,pda,1
10.215.174.192-10.215.174.255,pda,1
10.215.178.0-10.215.178.63,pda,1
10.215.178.64-10.215.178.127,pda,1
10.215.178.128-10.215.178.191,pda,1
10.215.178.192-10.215.178.255,pda,1
10.215.179.0-10.215.179.63,pda,1
10.215.179.64-10.215.179.127,pda,1
10.215.179.128-10.215.179.191,pda,1
10.215.179.192-10.215.179.255,pda,1
10.215.192.0-10.215.192.63,pda,1
10.215.192.64-10.215.192.127,pda,1
10.215.192.128-10.215.192.191,pda,1
10.215.192.192-10.215.192.255,pda,1
10.215.193.0-10.215.193.63,pda,1
10.215.193.64-10.215.193.127,pda,1
10.215.193.128-10.215.193.191,pda,1
10.215.193.192-10.215.193.255,pda,1
10.215.194.0-10.215.194.63,pda,1
10.215.194.64-10.215.194.127,pda,1
10.215.194.128-10.215.194.191,pda,1
10.215.194.192-10.215.194.255,pda,1
10.215.195.0-10.215.195.63,pda,1
10.215.195.64-10.215.195.127,pda,1
10.215.195.128-10.215.195.191,pda,1
10.215.195.192-10.215.195.255,pda,1
10.215.196.0-10.215.196.63,pda,1
10.215.196.64-10.215.196.127,pda,1
10.215.196.128-10.215.196.191,pda,1
10.215.196.192-10.215.196.255,pda,1
10.215.197.0-10.215.197.63,pda,1
10.215.197.64-10.215.197.127,pda,1
10.215.197.128-10.215.197.191,pda,1
10.215.197.192-10.215.197.255,pda,1
10.215.198.0-10.215.198.63,pda,1
10.215.198.64-10.215.198.127,pda,1
10.215.198.128-10.215.198.191,pda,1
10.215.198.192-10.215.198.255,pda,1
10.215.199.0-10.215.199.63,pda,1
10.215.199.64-10.215.199.127,pda,1
10.215.199.128-10.215.199.191,pda,1
10.215.199.192-10.215.199.255,pda,1
10.215.200.0-10.215.200.63,pda,1
10.215.200.64-10.215.200.127,pda,1
10.215.200.128-10.215.200.191,pda,1
10.215.200.192-10.215.200.255,pda,1
10.215.201.0-10.215.201.63,pda,1
10.215.201.64-10.215.201.127,pda,1
10.215.201.128-10.215.201.191,pda,1
10.215.201.192-10.215.201.255,pda,1
10.215.202.0-10.215.202.63,pda,1
10.215.202.64-10.215.202.127,pda,1
10.215.202.128-10.215.202.191,pda,1
10.215.202.192-10.215.202.255,pda,1
10.215.203.0-10.215.203.63,pda,1
10.215.203.64-10.215.203.127,pda,1
10.215.203.128-10.215.203.191,pda,1
10.215.203.192-10.215.203.255,pda,1
10.215.204.0-10.215.204.63,pda,1
10.215.204.64-10.215.204.127,pda,1
10.215.204.128-10.215.204.191,pda,1
10.215.204.192-10.215.204.255,pda,1
10.215.205.0-10.215.205.63,pda,1
10.215.205.64-10.215.205.127,pda,1
10.215.205.128-10.215.205.191,pda,1
10.215.205.192-10.215.205.255,pda,1
10.215.206.0-10.215.206.63,pda,1
10.215.206.64-10.215.206.127,pda,1
10.215.206.128-10.215.206.191,pda,1
10.215.206.192-10.215.206.255,pda,1
10.215.207.0-10.215.207.63,pda,1
10.215.207.64-10.215.207.127,pda,1
10.215.207.128-10.215.207.191,pda,1
10.215.207.192-10.215.207.255,pda,1
10.215.208.0-10.215.208.63,pda,1
10.215.208.64-10.215.208.127,pda,1
10.215.208.128-10.215.208.191,pda,1
10.215.208.192-10.215.208.255,pda,1
10.215.209.0-10.215.209.63,pda,1
10.215.209.64-10.215.209.127,pda,1
10.215.209.128-10.215.209.191,pda,1
10.215.209.192-10.215.209.255,pda,1
10.215.210.0-10.215.210.63,pda,1
10.215.210.64-10.215.210.127,pda,1
10.215.210.128-10.215.210.191,pda,1
10.215.210.192-10.215.210.255,pda,1
10.215.211.0-10.215.211.63,pda,1
10.215.211.64-10.215.211.127,pda,1
10.215.211.128-10.215.211.191,pda,1
10.215.211.192-10.215.211.255,pda,1
10.215.212.0-10.215.212.63,pda,1
10.215.212.64-10.215.212.127,pda,1
10.215.212.128-10.215.212.191,pda,1
10.215.212.192-10.215.212.255,pda,1
10.215.213.0-10.215.213.63,pda,1
10.215.213.64-10.215.213.127,pda,1
10.215.213.128-10.215.213.191,pda,1
10.215.213.192-10.215.213.255,pda,1
10.215.214.0-10.215.214.63,pda,1
10.215.214.64-10.215.214.127,pda,1
10.215.214.128-10.215.214.191,pda,1
10.215.214.192-10.215.214.255,pda,1
10.215.215.0-10.215.215.63,pda,1
10.215.215.64-10.215.215.127,pda,1
10.215.215.128-10.215.215.191,pda,1
10.215.215.192-10.215.215.255,pda,1
10.215.216.0-10.215.216.63,pda,1
10.215.216.64-10.215.216.127,pda,1
10.215.216.128-10.215.216.191,pda,1
10.215.216.192-10.215.216.255,pda,1
10.215.217.0-10.215.217.63,pda,1
10.215.217.64-10.215.217.127,pda,1
10.215.217.128-10.215.217.191,pda,1
10.215.217.192-10.215.217.255,pda,1
10.215.218.0-10.215.218.63,pda,1
10.215.218.64-10.215.218.127,pda,1
10.215.218.128-10.215.218.191,pda,1
10.215.218.192-10.215.218.255,pda,1
10.215.219.0-10.215.219.63,pda,1
10.215.219.64-10.215.219.127,pda,1
10.215.219.128-10.215.219.191,pda,1
10.215.219.192-10.215.219.255,pda,1
10.215.220.0-10.215.220.63,pda,1
10.215.220.64-10.215.220.127,pda,1
10.215.220.128-10.215.220.191,pda,1
10.215.220.192-10.215.220.255,pda,1
10.215.221.0-10.215.221.63,pda,1
10.215.221.64-10.215.221.127,pda,1
10.215.221.128-10.215.221.191,pda,1
10.215.221.192-10.215.221.255,pda,1
10.215.222.0-10.215.222.63,pda,1
10.215.222.64-10.215.222.127,pda,1
10.215.222.128-10.215.222.191,pda,1
10.215.222.192-10.215.222.255,pda,1
10.215.223.0-10.215.223.63,pda,1
10.215.223.64-10.215.223.127,pda,1
10.215.223.128-10.215.223.191,pda,1
10.215.223.192-10.215.223.255,pda,1
10.215.224.0-10.215.224.63,pda,1
10.215.224.64-10.215.224.127,pda,1
10.215.224.128-10.215.224.191,pda,1
10.215.224.192-10.215.224.255,pda,1
10.215.225.0-10.215.225.63,pda,1
10.215.225.64-10.215.225.127,pda,1
10.215.225.128-10.215.225.191,pda,1
10.215.225.192-10.215.225.255,pda,1
10.215.226.0-10.215.226.63,pda,1
10.215.226.64-10.215.226.127,pda,1
10.215.226.128-10.215.226.191,pda,1
10.215.226.192-10.215.226.255,pda,1
10.215.227.0-10.215.227.63,pda,1
10.215.227.64-10.215.227.127,pda,1
10.215.227.128-10.215.227.191,pda,1
10.215.227.192-10.215.227.255,pda,1
10.215.228.0-10.215.228.63,pda,1
10.215.228.64-10.215.228.127,pda,1
10.215.228.128-10.215.228.191,pda,1
10.215.228.192-10.215.228.255,pda,1
10.215.229.0-10.215.229.63,pda,1
10.215.229.64-10.215.229.127,pda,1
10.215.229.128-10.215.229.191,pda,1
10.215.229.192-10.215.229.255,pda,1
10.215.230.0-10.215.230.63,pda,1
10.215.230.64-10.215.230.127,pda,1
10.215.230.128-10.215.230.191,pda,1
10.215.230.192-10.215.230.255,pda,1
10.215.231.0-10.215.231.63,pda,1
10.215.231.64-10.215.231.127,pda,1
10.215.231.128-10.215.231.191,pda,1
10.215.231.192-10.215.231.255,pda,1
10.215.232.0-10.215.232.63,pda,1
10.215.232.64-10.215.232.127,pda,1
10.215.232.128-10.215.232.191,pda,1
10.215.232.192-10.215.232.255,pda,1
10.215.233.0-10.215.233.63,pda,1
10.215.233.64-10.215.233.127,pda,1
10.215.233.128-10.215.233.191,pda,1
10.215.233.192-10.215.233.255,pda,1
10.215.234.0-10.215.234.63,pda,1
10.215.234.64-10.215.234.127,pda,1
10.215.234.128-10.215.234.191,pda,1
10.215.234.192-10.215.234.255,pda,1
10.215.235.0-10.215.235.63,pda,1
10.215.235.64-10.215.235.127,pda,1
10.215.235.128-10.215.235.191,pda,1
10.215.235.192-10.215.235.255,pda,1
10.215.236.0-10.215.236.63,pda,1
10.215.236.64-10.215.236.127,pda,1
10.215.236.128-10.215.236.191,pda,1
10.215.236.192-10.215.236.255,pda,1
10.215.237.0-10.215.237.63,pda,1
10.215.237.64-10.215.237.127,pda,1
10.215.237.128-10.215.237.191,pda,1
10.215.237.192-10.215.237.255,pda,1
10.215.238.0-10.215.238.63,pda,1
10.215.238.64-10.215.238.127,pda,1
10.215.238.128-10.215.238.191,pda,1
10.215.238.192-10.215.238.255,pda,1
10.215.239.0-10.215.239.63,pda,1
10.215.239.64-10.215.239.127,pda,1
10.215.239.128-10.215.239.191,pda,1
10.215.239.192-10.215.239.255,pda,1
10.215.240.0-10.215.240.63,pda,1
10.215.240.64-10.215.240.127,pda,1
10.215.240.128-10.215.240.191,pda,1
10.215.240.192-10.215.240.255,pda,1
10.215.241.0-10.215.241.63,pda,1
10.215.241.64-10.215.241.127,pda,1
10.215.241.128-10.215.241.191,pda,1
10.215.241.192-10.215.241.255,pda,1
10.215.242.0-10.215.242.63,pda,1
10.215.242.64-10.215.242.127,pda,1
10.215.242.128-10.215.242.191,pda,1
10.215.242.192-10.215.242.255,pda,1
10.215.243.0-10.215.243.63,pda,1
10.215.243.64-10.215.243.127,pda,1
10.215.243.128-10.215.243.191,pda,1
10.215.243.192-10.215.243.255,pda,1
10.215.244.0-10.215.244.63,pda,1
10.215.244.64-10.215.244.127,pda,1
10.215.244.128-10.215.244.191,pda,1
10.215.244.192-10.215.244.255,pda,1
10.215.245.0-10.215.245.63,pda,1
10.215.245.64-10.215.245.127,pda,1
10.215.245.128-10.215.245.191,pda,1
10.215.245.192-10.215.245.255,pda,1
10.215.246.0-10.215.246.63,pda,1
10.215.246.64-10.215.246.127,pda,1
10.215.246.128-10.215.246.191,pda,1
10.215.246.192-10.215.246.255,pda,1
10.215.247.0-10.215.247.63,pda,1
10.215.247.64-10.215.247.127,pda,1
10.215.247.128-10.215.247.191,pda,1
10.215.247.192-10.215.247.255,pda,1
10.215.248.0-10.215.248.63,pda,1
10.215.248.64-10.215.248.127,pda,1
10.215.248.128-10.215.248.191,pda,1
10.215.248.192-10.215.248.255,pda,1
10.215.249.0-10.215.249.63,pda,1
10.215.249.64-10.215.249.127,pda,1
10.215.249.128-10.215.249.191,pda,1
10.215.249.192-10.215.249.255,pda,1
10.215.250.0-10.215.250.63,pda,1
10.215.250.64-10.215.250.127,pda,1
10.215.250.128-10.215.250.191,pda,1
10.215.250.192-10.215.250.255,pda,1
10.215.251.0-10.215.251.63,pda,1
10.215.251.64-10.215.251.127,pda,1
10.215.251.128-10.215.251.191,pda,1
10.215.251.192-10.215.251.255,pda,1
10.215.252.0-10.215.252.63,pda,1
10.215.252.64-10.215.252.127,pda,1
10.215.252.128-10.215.252.191,pda,1
10.215.252.192-10.215.252.255,pda,1
10.215.253.0-10.215.253.63,pda,1
10.215.253.64-10.215.253.127,pda,1
10.215.253.128-10.215.253.191,pda,1
10.215.253.192-10.215.253.255,pda,1
10.215.254.0-10.215.254.63,pda,1
10.215.254.64-10.215.254.127,pda,1
10.215.254.128-10.215.254.191,pda,1
10.215.254.192-10.215.254.255,pda,1
10.215.255.0-10.215.255.63,pda,1
10.215.255.64-10.215.255.127,pda,1
10.215.255.128-10.215.255.191,pda,1
10.215.255.192-10.215.255.255,pda,1
10.214.164.128-10.214.164.255,pda,1
10.214.219.0-10.214.219.127,pda,1
10.214.245.128-10.214.245.255,pda,1
10.215.65.0-10.215.65.127,pda,1
10.215.67.128-10.215.67.255,pda,1
10.215.73.0-10.215.73.127,pda,1
10.215.73.128-10.215.73.255,pda,1
10.215.78.0-10.215.78.127,pda,1
10.215.78.128-10.215.78.255,pda,1
10.215.79.0-10.215.79.127,pda,1
10.215.79.128-10.215.79.255,pda,1
10.214.136.0-10.214.136.255,pda,1
10.214.137.0-10.214.137.255,pda,1
10.214.138.0-10.214.138.255,pda,1
10.214.139.0-10.214.139.255,pda,1
10.214.142.0-10.214.142.255,pda,1
10.214.143.0-10.214.143.255,pda,1
10.214.144.0-10.214.144.255,pda,1
10.214.159.0-10.214.159.255,pda,1
10.214.160.0-10.214.160.255,pda,1
10.214.161.0-10.214.161.255,pda,1
10.214.162.0-10.214.162.255,pda,1
10.214.163.0-10.214.163.255,pda,1
10.214.165.0-10.214.165.255,pda,1
10.214.166.0-10.214.166.255,pda,1
10.214.170.0-10.214.170.255,pda,1
10.214.171.0-10.214.171.255,pda,1
10.214.218.0-10.214.218.255,pda,1
10.214.244.0-10.214.244.255,pda,1
10.215.70.0-10.215.70.255,pda,1
10.215.83.0-10.215.83.255,pda,1
10.215.85.0-10.215.85.255,pda,1
10.215.101.0-10.215.101.255,pda,1
10.215.104.0-10.215.104.255,pda,1
10.215.164.0-10.215.164.255,pda,1
10.215.165.0-10.215.165.255,pda,1
10.215.175.0-10.215.175.255,pda,1
10.214.148.0-10.214.149.255,pda,1
10.214.150.0-10.214.151.255,pda,1
10.214.174.0-10.214.175.255,pda,1
10.214.216.0-10.214.217.255,pda,1
10.214.246.0-10.214.247.255,pda,1
10.215.68.0-10.215.69.255,pda,1
10.215.74.0-10.215.75.255,pda,1
10.215.76.0-10.215.77.255,pda,1
10.215.96.0-10.215.97.255,pda,1
10.215.98.0-10.215.99.255,pda,1
10.215.102.0-10.215.103.255,pda,1
10.215.140.0-10.215.141.255,pda,1
10.215.142.0-10.215.143.255,pda,1
10.215.148.0-10.215.149.255,pda,1
10.215.150.0-10.215.151.255,pda,1
10.215.152.0-10.215.153.255,pda,1
10.215.154.0-10.215.155.255,pda,1
10.215.168.0-10.215.169.255,pda,1
10.215.176.0-10.215.177.255,pda,1
10.214.220.0-10.214.223.255,pda,1
10.214.240.0-10.214.243.255,pda,1
10.215.108.0-10.215.111.255,pda,1
10.215.128.0-10.215.131.255,pda,1
10.215.156.0-10.215.159.255,pda,1
10.215.160.0-10.215.163.255,pda,1
10.215.180.0-10.215.183.255,pda,1
10.214.208.0-10.214.215.255,pda,1
10.214.248.0-10.214.255.255,pda,1
10.215.184.0-10.215.191.255,pda,1
10.214.176.0-10.214.191.255,pda,1
10.214.192.0-10.214.207.255,pda,1
10.214.224.0-10.214.239.255,pda,1
10.215.112.0-10.215.127.255,pda,1
10.215.32.0-10.215.63.255,pda,9
10.214.0.0-10.214.127.255,pda,9
)";
// Need to have the working ranges covered first, before they're blended.
space.blend(IP4Range{"10.214.0.0/15"}, 1, code_blender);
// Now blend the working ranges over the base range.
while (content) {
auto line = content.take_prefix_at('\n').trim_if(&isspace);
if (line.empty()) {
continue;
}
IP4Range range{line.take_prefix_at(',')};
auto pod = line.take_prefix_at(',');
int r = swoc::svtoi(line.take_prefix_at(','));
space.blend(range, pod, pod_blender);
space.blend(range, r, rack_blender);
if (space.count() > 2) {
auto spot = space.begin();
auto [ r1, p1 ] = *++spot;
auto [ r2, p2 ] = *++spot;
REQUIRE(r1.max() < r2.min()); // This is supposed to be an invariant! Make sure.
auto back = space.end();
auto [ br1, bp1 ] = *--back;
auto [ br2, bp2 ] = *--back;
REQUIRE(br2.max() < br1.min()); // This is supposed to be an invariant! Make sure.
}
}
// Do some range intersection checks.
}
TEST_CASE("IPSpace skew overlap blend", "[libswoc][ipspace][blend][skew]") {
std::string buff;
enum class Pod {
INVALID, zio, zaz, zlz
};
swoc::Lexicon<Pod> PodNames {{ { Pod::zio, "zio"}, { Pod::zaz, "zaz"} , { Pod::zlz, "zlz"} }, "-1"};
struct Data {
int _state = 0;
int _country = -1;
int _rack = 0;
Pod _pod = Pod::INVALID;
int _code = 0;
bool operator==(Data const& that) const {
return _pod == that._pod && _rack == that._rack && _code == that._code &&
_state == that._state && _country == that._country;
}
};
using Src_1 = std::tuple<int, Pod, int>; // rack, pod, code
using Src_2 = std::tuple<int, int>; // state, country.
auto blend_1 = [](Data& data, Src_1 const& src) {
std::tie(data._rack, data._pod, data._code) = src;
return true;
};
[[maybe_unused]] auto blend_2 = [](Data& data, Src_2 const& src) {
std::tie(data._state, data._country) = src;
return true;
};
swoc::IPSpace<Data> space;
space.blend(IPRange("14.6.128.0-14.6.191.255"), Src_2{32, 231}, blend_2);
space.blend(IPRange("14.6.192.0-14.6.223.255"), Src_2{32, 231}, blend_2);
REQUIRE(space.count() == 1);
space.blend(IPRange("14.6.160.0-14.6.160.1"), Src_1{1, Pod::zaz, 1}, blend_1);
REQUIRE(space.count() == 3);
space.blend(IPRange("14.6.160.64-14.6.160.95"), Src_1{1, Pod::zio, 1}, blend_1);
space.blend(IPRange("14.6.160.96-14.6.160.127"),Src_1{1, Pod::zlz, 1}, blend_1);
space.blend(IPRange("14.6.160.128-14.6.160.255"),Src_1{1, Pod::zlz, 1}, blend_1);
space.blend(IPRange("14.6.0.0-14.6.127.255"), Src_2{32, 231}, blend_2);
std::array<std::tuple<IPRange, Data>, 6> results = {
{{IPRange("14.6.0.0-14.6.159.255"), Data{32,231,0,Pod::INVALID,0} }
, {IPRange("14.6.160.0-14.6.160.1"), Data{32,231,1,Pod::zaz,1}}
, {IPRange("14.6.160.2-14.6.160.63"), Data{32,231,0,Pod::INVALID,0}}
, {IPRange("14.6.160.64-14.6.160.95"), Data{32,231,1,Pod::zio,1}}
, {IPRange("14.6.160.96-14.6.160.255"), Data{32,231,1,Pod::zlz,1}}
, {IPRange("14.6.161.0-14.6.223.255"), Data{32,231,0,Pod::INVALID,0}}
}};
REQUIRE(space.count() == results.size());
unsigned idx = 0;
for ( auto const& v : space ) {
REQUIRE(v == results[idx]);
++idx;
}
}
TEST_CASE("IPSpace fill", "[libswoc][ipspace][fill]") {
using PAYLOAD = unsigned;
using Space = swoc::IPSpace<PAYLOAD>;
std::array<std::tuple<TextView, unsigned>, 6> ranges {
{
{"172.28.56.12-172.28.56.99"_tv, 1}
, {"10.10.35.0/24"_tv, 2}
, {"192.168.56.0/25"_tv, 3}
, {"1337::ded:beef-1337::ded:ceef"_tv, 4}
, {"ffee:1f2d:c587:24c3:9128:3349:3cee:143-ffee:1f2d:c587:24c3:9128:3349:3cFF:FFFF"_tv, 5}
, {"10.12.148.0/23"_tv, 6}
}};
Space space;
for (auto &&[text, v] : ranges) {
space.fill(IPRange{text}, v);
}
REQUIRE(space.count() == ranges.size());
auto && [ r1, p1 ] = *(space.find(IP4Addr{"172.28.56.100"}));
REQUIRE(true == r1.empty());
auto && [ r2, p2 ] = *(space.find(IPAddr{"172.28.56.87"}));
REQUIRE(false == r2.empty());
space.fill(IPRange{"10.0.0.0/8"} , 7);
REQUIRE(space.count() == ranges.size() + 3);
space.fill(IPRange{"9.0.0.0-11.255.255.255"}, 7);
REQUIRE(space.count() == ranges.size() + 3);
{
auto &&[r, p] = *(space.find(IPAddr{"10.99.88.77"}));
REQUIRE(false == r.empty());
REQUIRE(p == 7);
}
{
auto &&[r, p] = *(space.find(IPAddr{"10.10.35.35"}));
REQUIRE(false == r.empty());
REQUIRE(p == 2);
}
{
auto &&[r, p] = *(space.find(IPAddr{"192.168.56.56"}));
REQUIRE(false == r.empty());
REQUIRE(p == 3);
}
{
auto &&[r, p] = *(space.find(IPAddr{"11.11.11.11"}));
REQUIRE(false == r.empty());
REQUIRE(p == 7);
}
space.fill(IPRange{"192.168.56.0-192.168.56.199"}, 8);
REQUIRE(space.count() == ranges.size() + 4);
{
auto &&[r, p] = *(space.find(IPAddr{"192.168.55.255"}));
REQUIRE(true == r.empty());
}
{
auto &&[r, p] = *(space.find(IPAddr{"192.168.56.0"}));
REQUIRE(false == r.empty());
REQUIRE(p == 3);
}
{
auto &&[r, p] = *(space.find(IPAddr{"192.168.56.128"}));
REQUIRE(false == r.empty());
REQUIRE(p == 8);
}
space.fill(IPRange{"0.0.0.0/0"}, 0);
{
auto &&[r, p] = *(space.find(IPAddr{"192.168.55.255"}));
REQUIRE(false == r.empty());
REQUIRE(p == 0);
}
}
TEST_CASE("IPSpace intersect", "[libswoc][ipspace][intersect]") {
std::string dbg;
using PAYLOAD = unsigned;
using Space = swoc::IPSpace<PAYLOAD>;
std::array<std::tuple<TextView, unsigned>, 7> ranges{{
{"172.28.56.12-172.28.56.99"_tv, 1},
{"10.10.35.0/24"_tv, 2},
{"192.168.56.0/25"_tv, 3},
{"10.12.148.0/23"_tv, 6},
{"10.14.56.0/24"_tv, 9},
{"192.168.57.0/25"_tv, 7},
{"192.168.58.0/25"_tv, 5}
}};
Space space;
for (auto &&[text, v] : ranges) {
space.fill(IPRange{text}, v);
}
{
IPRange r{"172.0.0.0/16"};
auto && [ begin, end ] = space.intersection(r);
REQUIRE(begin == end);
}
{
IPRange r{"172.0.0.0/8"};
auto && [ begin, end ] = space.intersection(r);
REQUIRE(std::distance(begin, end) == 1);
}
{
IPRange r{"10.0.0.0/8"};
auto && [ begin, end ] = space.intersection(r);
REQUIRE(std::distance(begin, end) == 3);
}
{
IPRange r{"10.10.35.17-10.12.148.7"};
auto && [ begin, end ] = space.intersection(r);
REQUIRE(std::distance(begin, end) == 2);
}
{
IPRange r{"10.10.35.0-10.14.56.0"};
auto && [ begin, end ] = space.intersection(r);
REQUIRE(std::distance(begin, end) == 3);
}
{
IPRange r{"10.13.0.0-10.15.148.7"}; // past the end
auto && [ begin, end ] = space.intersection(r);
REQUIRE(std::distance(begin, end) == 1);
}
{
IPRange r{"10.13.0.0-10.14.55.127"}; // inside a gap.
auto && [ begin, end ] = space.intersection(r);
REQUIRE(begin == end);
}
{
IPRange r{"192.168.56.127-192.168.67.35"}; // include last range.
auto && [ begin, end ] = space.intersection(r);
REQUIRE(std::distance(begin,end) == 3);
}
{
IPRange r{"192.168.57.128-192.168.67.35"}; // only last range.
auto && [ begin, end ] = space.intersection(r);
REQUIRE(std::distance(begin,end) == 1);
}
{
IPRange r{"192.168.57.128-192.168.58.10"}; // only last range.
auto && [ begin, end ] = space.intersection(r);
REQUIRE(std::distance(begin,end) == 1);
}
{
IPRange r{"192.168.50.0-192.168.57.35"}; // include last range.
auto && [ begin, end ] = space.intersection(r);
REQUIRE(std::distance(begin,end) == 2);
}
}
TEST_CASE("IPSrv", "[libswoc][IPSrv]") {
using swoc::IP4Srv;
using swoc::IP6Srv;
using swoc::IPSrv;
IP4Srv s4;
IP6Srv s6;
IPSrv s;
IP4Addr a1 { "192.168.34.56" };
IP4Addr a2 { "10.9.8.7" };
IP6Addr aa1 { "ffee:1f2d:c587:24c3:9128:3349:3cee:143" };
s6.assign(aa1, 99);
REQUIRE(s6.addr() == aa1);
REQUIRE(s6.host_order_port() == 99);
REQUIRE(s6 == IP6Srv(aa1, 99));
// Test various constructors.
s4.assign(a2, 88);
IP4Addr tmp1{s4.addr()};
REQUIRE(s4 == tmp1);
IP4Addr tmp2 = s4;
REQUIRE(s4 == tmp2);
IP4Addr tmp3{s4};
REQUIRE(s4 == tmp3);
REQUIRE(s4.addr() == tmp3); // double check equality.
IP4Srv s4_1 { "10.9.8.7:56" };
REQUIRE(s4_1.host_order_port() == 56);
REQUIRE(s4_1 == a2);
CHECK(s4_1.load("10.2:56"));
CHECK_FALSE(s4_1.load("10.1.2.3.567899"));
CHECK_FALSE(s4_1.load("10.1.2.3.56f"));
CHECK_FALSE(s4_1.load("10.1.2.56f"));
CHECK(s4_1.load("10.1.2.3"));
REQUIRE(s4_1.host_order_port() == 0);
CHECK(s6.load("[ffee:1f2d:c587:24c3:9128:3349:3cee:143]:956"));
REQUIRE(s6 == aa1);
REQUIRE(s6.host_order_port() == 956);
CHECK(s6.load("ffee:1f2d:c587:24c3:9128:3349:3cee:143"));
REQUIRE(s6 == aa1);
REQUIRE(s6.host_order_port() == 0);
CHECK(s.load("[ffee:1f2d:c587:24c3:9128:3349:3cee:143]:956"));
REQUIRE(s == aa1);
REQUIRE(s.host_order_port() == 956);
CHECK(s.load("ffee:1f2d:c587:24c3:9128:3349:3cee:143"));
REQUIRE(s == aa1);
REQUIRE(s.host_order_port() == 0);
}
TEST_CASE("IPRangeSet", "[libswoc][iprangeset]") {
std::array<TextView, 6> ranges = {"172.28.56.12-172.28.56.99"_tv,
"10.10.35.0/24"_tv,
"192.168.56.0/25"_tv,
"1337::ded:beef-1337::ded:ceef"_tv,
"ffee:1f2d:c587:24c3:9128:3349:3cee:143-ffee:1f2d:c587:24c3:9128:3349:3cFF:FFFF"_tv,
"10.12.148.0/23"_tv};
IPRangeSet addrs;
for ( auto rtxt : ranges ) {
IPRange r{rtxt};
addrs.mark(r);
}
unsigned n = 0;
bool valid_p = true;
for ( auto r : addrs ) {
valid_p = valid_p && ! r.empty();
++n;
}
REQUIRE(n == addrs.count());
REQUIRE(valid_p);
}