LCOV - code coverage report
Current view: top level - tests - catch_range.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 1067 1067
Test Date: 2025-04-18 08:03:11 Functions: 100.0 % 1 1
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright (c) 2011-2025  Made to Order Software Corp.  All Rights Reserved
       2              : //
       3              : // https://snapwebsites.org/project/libaddr
       4              : // contact@m2osw.com
       5              : //
       6              : // Permission is hereby granted, free of charge, to any
       7              : // person obtaining a copy of this software and
       8              : // associated documentation files (the "Software"), to
       9              : // deal in the Software without restriction, including
      10              : // without limitation the rights to use, copy, modify,
      11              : // merge, publish, distribute, sublicense, and/or sell
      12              : // copies of the Software, and to permit persons to whom
      13              : // the Software is furnished to do so, subject to the
      14              : // following conditions:
      15              : //
      16              : // The above copyright notice and this permission notice
      17              : // shall be included in all copies or substantial
      18              : // portions of the Software.
      19              : //
      20              : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
      21              : // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
      22              : // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      23              : // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
      24              : // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      25              : // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      26              : // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      27              : // ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      28              : // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      29              : // SOFTWARE.
      30              : 
      31              : 
      32              : /** \file
      33              :  * \brief Check the addr_range class basics.
      34              :  *
      35              :  * This set of unit tests do basic verification of the range class.
      36              :  *
      37              :  * The point here is to test the range functionality and not the
      38              :  * addr_parser class.
      39              :  */
      40              : 
      41              : 
      42              : // self
      43              : //
      44              : #include    "catch_main.h"
      45              : 
      46              : 
      47              : // snapdev
      48              : //
      49              : #include    <snapdev/int128_literal.h>
      50              : #include    <snapdev/ostream_int128.h>
      51              : 
      52              : 
      53              : // last include
      54              : //
      55              : #include    <snapdev/poison.h>
      56              : 
      57              : 
      58              : using namespace snapdev::literals;
      59              : 
      60              : 
      61              : 
      62           19 : CATCH_TEST_CASE("ipv4::range", "[ipv4]")
      63              : {
      64           19 :     CATCH_GIVEN("addr_range()")
      65              :     {
      66            9 :         addr::addr_range range;
      67              : 
      68            9 :         CATCH_START_SECTION("addr_range: verify defaults")
      69              :         {
      70            1 :             addr::addr a;
      71              : 
      72            1 :             CATCH_REQUIRE_FALSE(range.has_from());
      73            1 :             CATCH_REQUIRE_FALSE(range.has_to());
      74            1 :             CATCH_REQUIRE_FALSE(range.is_range());
      75            1 :             CATCH_REQUIRE_FALSE(range.is_empty());
      76            1 :             CATCH_REQUIRE(range.get_from() == a);
      77            1 :             CATCH_REQUIRE(range.get_to() == a);
      78              : 
      79              :             // to use the const version of the get_from/to() functions
      80              :             // we have to define a const refence to range
      81              :             //
      82            1 :             auto const & r(range);
      83            1 :             CATCH_REQUIRE(r.get_from() == a);
      84            1 :             CATCH_REQUIRE(r.get_to() == a);
      85              : 
      86            1 :             addr::addr other;
      87            1 :             CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
      88            1 :             CATCH_REQUIRE_THROWS_AS(r.is_in(other), addr::addr_invalid_state);
      89            1 :         }
      90            9 :         CATCH_END_SECTION()
      91              : 
      92            9 :         CATCH_START_SECTION("addr_range: test normal range (from <= to)")
      93              :         {
      94            1 :             addr::addr a;
      95            1 :             addr::addr other;
      96              : 
      97              :             // from 10.0.0.1
      98            1 :             struct sockaddr_in fin = sockaddr_in();
      99            1 :             fin.sin_family = AF_INET;
     100            1 :             int const fport(rand() & 0xFFFF);
     101            1 :             fin.sin_port = htons(fport);
     102            1 :             uint32_t const faddress((10 << 24)
     103              :                           | (0 << 16)
     104              :                           | (0 << 8)
     105              :                           | 1);
     106            1 :             fin.sin_addr.s_addr = htonl(faddress);
     107            1 :             addr::addr f;
     108            1 :             f.set_ipv4(fin);
     109              : 
     110              :             // to 10.0.0.254
     111            1 :             struct sockaddr_in tin = sockaddr_in();
     112            1 :             tin.sin_family = AF_INET;
     113            1 :             int const tport(rand() & 0xFFFF);
     114            1 :             tin.sin_port = htons(tport);
     115            1 :             uint32_t const taddress((10 << 24)
     116              :                           | (0 << 16)
     117              :                           | (0 << 8)
     118              :                           | 254);
     119            1 :             tin.sin_addr.s_addr = htonl(taddress);
     120            1 :             addr::addr t;
     121            1 :             t.set_ipv4(tin);
     122              : 
     123              :             // test defaults first
     124              :             //
     125            1 :             CATCH_REQUIRE_FALSE(range.has_from());
     126            1 :             CATCH_REQUIRE_FALSE(range.has_to());
     127            1 :             CATCH_REQUIRE_FALSE(range.is_range());
     128            1 :             CATCH_REQUIRE_FALSE(range.is_empty());
     129            1 :             CATCH_REQUIRE_FALSE(range.is_ipv4());
     130            1 :             CATCH_REQUIRE(range.get_from() == a);
     131            1 :             CATCH_REQUIRE(range.get_to() == a);
     132            1 :             CATCH_REQUIRE(range.size() == 0);
     133            1 :             auto const & r1(range);
     134            1 :             CATCH_REQUIRE(r1.get_from() == a);
     135            1 :             CATCH_REQUIRE(r1.get_to() == a);
     136            1 :             CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
     137            1 :             CATCH_REQUIRE_THROWS_AS(r1.is_in(other), addr::addr_invalid_state);
     138            1 :             CATCH_REQUIRE(r1.size() == 0);
     139            1 :             CATCH_REQUIRE(range.match(a));
     140            1 :             CATCH_REQUIRE_FALSE(range.match(f));
     141            1 :             CATCH_REQUIRE_FALSE(range.match(t));
     142              : 
     143            1 :             range.set_from(f);
     144              : 
     145              :             // defined "from", test the results
     146              :             //
     147            1 :             CATCH_REQUIRE(range.has_from());
     148            1 :             CATCH_REQUIRE_FALSE(range.has_to());
     149            1 :             CATCH_REQUIRE_FALSE(range.is_range());
     150            1 :             CATCH_REQUIRE_FALSE(range.is_empty());
     151            1 :             CATCH_REQUIRE(range.is_ipv4());
     152            1 :             CATCH_REQUIRE(range.get_from() == f);
     153            1 :             CATCH_REQUIRE(range.get_to() == a);
     154            1 :             CATCH_REQUIRE(range.size() == 1);
     155            1 :             auto const & r2(range);
     156            1 :             CATCH_REQUIRE(r2.get_from() == f);
     157            1 :             CATCH_REQUIRE(r2.get_to() == a);
     158            1 :             CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
     159            1 :             CATCH_REQUIRE_THROWS_AS(r2.is_in(other), addr::addr_invalid_state);
     160            1 :             CATCH_REQUIRE(r2.size() == 1);
     161            1 :             CATCH_REQUIRE_FALSE(range.match(a));
     162            1 :             CATCH_REQUIRE(range.match(f));
     163            1 :             CATCH_REQUIRE_FALSE(range.match(t));
     164              : 
     165              :             {
     166            1 :                 std::stringstream ss;
     167            1 :                 ss << range;
     168            1 :                 CATCH_REQUIRE(ss.str() == "10.0.0.1:" + std::to_string(fport) + "/32");
     169              : 
     170            1 :                 addr::addr::vector_t from_vec(range.to_addresses(1000));
     171            1 :                 CATCH_REQUIRE(from_vec.size() == 1);
     172            1 :                 CATCH_REQUIRE(from_vec[0] == f);
     173            1 :             }
     174              : 
     175            1 :             range.swap_from_to();
     176              : 
     177              :             // swaped "from" & "to", test the results
     178              :             //
     179            1 :             CATCH_REQUIRE_FALSE(range.has_from());
     180            1 :             CATCH_REQUIRE(range.has_to());
     181            1 :             CATCH_REQUIRE_FALSE(range.is_range());
     182            1 :             CATCH_REQUIRE_FALSE(range.is_empty());
     183            1 :             CATCH_REQUIRE(range.is_ipv4());
     184            1 :             CATCH_REQUIRE(range.get_from() == a);
     185            1 :             CATCH_REQUIRE(range.get_to() == f);
     186            1 :             CATCH_REQUIRE(range.size() == 1);
     187            1 :             auto const & r2b(range);
     188            1 :             CATCH_REQUIRE(r2b.get_from() == a);
     189            1 :             CATCH_REQUIRE(r2b.get_to() == f);
     190            1 :             CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
     191            1 :             CATCH_REQUIRE_THROWS_AS(r2b.is_in(other), addr::addr_invalid_state);
     192            1 :             CATCH_REQUIRE(r2b.size() == 1);
     193            1 :             CATCH_REQUIRE_FALSE(range.match(a));
     194            1 :             CATCH_REQUIRE(range.match(f));
     195            1 :             CATCH_REQUIRE_FALSE(range.match(t));
     196              : 
     197              :             {
     198            1 :                 std::stringstream ss1;
     199            1 :                 ss1 << range;
     200            1 :                 CATCH_REQUIRE(ss1.str() == "-10.0.0.1:" + std::to_string(fport) + "/32");
     201              : 
     202            1 :                 std::stringstream ss2;
     203            1 :                 ss2 << addr::setaddrmode(addr::STRING_IP_ADDRESS) << range;
     204            1 :                 CATCH_REQUIRE(ss2.str() == "-10.0.0.1");
     205              : 
     206            1 :                 addr::addr::vector_t from_vec(range.to_addresses(1000));
     207            1 :                 CATCH_REQUIRE(from_vec.size() == 1);
     208            1 :                 CATCH_REQUIRE(from_vec[0] == f);
     209            1 :             }
     210              : 
     211            1 :             range.swap_from_to(); // restore before we go on
     212            1 :             CATCH_REQUIRE(range.get_from() == f);
     213            1 :             CATCH_REQUIRE(range.get_to() == a);
     214              : 
     215            1 :             range.set_to(t);
     216              : 
     217              :             // defined "to", test the results
     218              :             //
     219            1 :             CATCH_REQUIRE(range.has_from());
     220            1 :             CATCH_REQUIRE(range.has_to());
     221            1 :             CATCH_REQUIRE(range.is_range());
     222            1 :             CATCH_REQUIRE_FALSE(range.is_empty());
     223            1 :             CATCH_REQUIRE(range.is_ipv4());
     224            1 :             CATCH_REQUIRE(range.get_from() == f);
     225            1 :             CATCH_REQUIRE(range.get_to() == t);
     226            1 :             CATCH_REQUIRE(range.size() == 254); // all but .0 and .255, that's 254 addresses
     227            1 :             auto const & r3(range);
     228            1 :             CATCH_REQUIRE(r3.get_from() == f);
     229            1 :             CATCH_REQUIRE(r3.get_to() == t);
     230            1 :             CATCH_REQUIRE(r3.size() == 254);
     231            1 :             CATCH_REQUIRE_FALSE(range.match(a));
     232            1 :             CATCH_REQUIRE(range.match(f));
     233            1 :             CATCH_REQUIRE(range.match(t));
     234              : 
     235              :             {
     236            1 :                 std::stringstream ss;
     237            1 :                 ss << range;
     238            1 :                 CATCH_REQUIRE(ss.str() == "10.0.0.1-10.0.0.254:" + std::to_string(tport) + "/32");
     239            1 :             }
     240              : 
     241            1 :             addr::addr_range to_range;  // to-only range
     242            1 :             to_range.set_to(t);
     243              : 
     244              :             // defined "to", but not from
     245              :             //
     246            1 :             CATCH_REQUIRE_FALSE(to_range.has_from());
     247            1 :             CATCH_REQUIRE(to_range.has_to());
     248            1 :             CATCH_REQUIRE_FALSE(to_range.is_range());
     249            1 :             CATCH_REQUIRE_FALSE(to_range.is_empty());
     250            1 :             CATCH_REQUIRE(to_range.is_ipv4());
     251            1 :             CATCH_REQUIRE(to_range.get_from() == a);
     252            1 :             CATCH_REQUIRE(to_range.get_to() == t);
     253            1 :             CATCH_REQUIRE(to_range.size() == 1);
     254            1 :             auto const & r4(to_range);
     255            1 :             CATCH_REQUIRE(r4.get_from() == a);
     256            1 :             CATCH_REQUIRE(r4.get_to() == t);
     257            1 :             CATCH_REQUIRE(r4.size() == 1);
     258            1 :             CATCH_REQUIRE_FALSE(to_range.match(a));
     259            1 :             CATCH_REQUIRE_FALSE(to_range.match(f));
     260            1 :             CATCH_REQUIRE(to_range.match(t));
     261              : 
     262              :             {
     263            1 :                 std::stringstream ss;
     264            1 :                 ss << to_range;
     265            1 :                 CATCH_REQUIRE(ss.str() == "-10.0.0.254:" + std::to_string(tport) + "/32");
     266              : 
     267            1 :                 addr::addr::vector_t to_vec(to_range.to_addresses(1000));
     268            1 :                 CATCH_REQUIRE(to_vec.size() == 1);
     269            1 :                 CATCH_REQUIRE(to_vec[0] == t);
     270            1 :             }
     271              : 
     272              :             // IP before range
     273              :             {
     274            1 :                 struct sockaddr_in bin = sockaddr_in();
     275            1 :                 bin.sin_family = AF_INET;
     276            1 :                 bin.sin_port = htons(rand());
     277            1 :                 uint32_t baddress((10 << 24)
     278              :                               | (0 << 16)
     279              :                               | (0 << 8)
     280              :                               | 0);
     281            1 :                 bin.sin_addr.s_addr = htonl(baddress);
     282            1 :                 addr::addr b;
     283            1 :                 b.set_ipv4(bin);
     284            1 :                 CATCH_REQUIRE(f.is_previous(b));
     285            1 :                 CATCH_REQUIRE(b.is_next(f));
     286              : 
     287            1 :                 CATCH_REQUIRE_FALSE(range.is_in(b));
     288            1 :             }
     289              : 
     290           11 :             for(int idx(0); idx < 10; ++idx)
     291              :             {
     292           10 :                 struct sockaddr_in bin = sockaddr_in();
     293           10 :                 bin.sin_family = AF_INET;
     294           10 :                 bin.sin_port = htons(rand());
     295           10 :                 uint32_t baddress(((rand() % 10) << 24)
     296           10 :                               | ((rand() & 255) << 16)
     297           10 :                               | ((rand() & 255) << 8)
     298           10 :                               | (rand() & 255));
     299           10 :                 bin.sin_addr.s_addr = htonl(baddress);
     300           10 :                 addr::addr b;
     301           10 :                 b.set_ipv4(bin);
     302              : 
     303           10 :                 CATCH_REQUIRE_FALSE(range.is_in(b));
     304           10 :             }
     305              : 
     306              :             // IP after range
     307              :             {
     308            1 :                 struct sockaddr_in ain = sockaddr_in();
     309            1 :                 ain.sin_family = AF_INET;
     310            1 :                 ain.sin_port = htons(rand());
     311            1 :                 uint32_t aaddress((10 << 24)
     312              :                               | (0 << 16)
     313              :                               | (0 << 8)
     314              :                               | 255);
     315            1 :                 ain.sin_addr.s_addr = htonl(aaddress);
     316            1 :                 addr::addr after;
     317            1 :                 after.set_ipv4(ain);
     318            1 :                 CATCH_REQUIRE(after.is_previous(t));
     319            1 :                 CATCH_REQUIRE(t.is_next(after));
     320              : 
     321            1 :                 CATCH_REQUIRE_FALSE(range.is_in(after));
     322            1 :             }
     323              : 
     324           11 :             for(int idx(0); idx < 10; ++idx)
     325              :             {
     326           10 :                 struct sockaddr_in ain = sockaddr_in();
     327           10 :                 ain.sin_family = AF_INET;
     328           10 :                 ain.sin_port = htons(rand());
     329           10 :                 uint32_t aaddress(((rand() % (256 - 11) + 11) << 24)
     330           10 :                               | ((rand() & 255) << 16)
     331           10 :                               | ((rand() & 255) << 8)
     332           10 :                               | (rand() & 255));
     333           10 :                 ain.sin_addr.s_addr = htonl(aaddress);
     334           10 :                 addr::addr after;
     335           10 :                 after.set_ipv4(ain);
     336              : 
     337           10 :                 CATCH_REQUIRE_FALSE(range.is_in(after));
     338           10 :             }
     339              : 
     340              :             // IP in range
     341              :             //
     342          255 :             for(int idx(1); idx < 255; ++idx)
     343              :             {
     344          254 :                 struct sockaddr_in iin = sockaddr_in();
     345          254 :                 iin.sin_family = AF_INET;
     346          254 :                 iin.sin_port = htons(rand());
     347          254 :                 uint32_t iaddress((10 << 24)
     348              :                               | (0 << 16)
     349              :                               | (0 << 8)
     350          254 :                               | idx);
     351          254 :                 iin.sin_addr.s_addr = htonl(iaddress);
     352          254 :                 addr::addr i;
     353          254 :                 i.set_ipv4(iin);
     354              : 
     355          254 :                 CATCH_REQUIRE(range.is_in(i));
     356          254 :             }
     357              : 
     358              :             // range to vector of IPs addresses
     359              :             //
     360            1 :             addr::addr::vector_t vec(range.to_addresses(1000));
     361          255 :             for(int idx(1); idx <= 254; ++idx)
     362              :             {
     363          254 :                 struct sockaddr_in ein = sockaddr_in();
     364          254 :                 ein.sin_family = AF_INET;
     365          254 :                 int const eport(rand() & 0xFFFF);
     366          254 :                 ein.sin_port = htons(eport);
     367          254 :                 uint32_t const eaddress((10 << 24)
     368              :                               | (0 << 16)
     369              :                               | (0 << 8)
     370          254 :                               | idx);
     371          254 :                 ein.sin_addr.s_addr = htonl(eaddress);
     372          254 :                 addr::addr e;
     373          254 :                 e.set_ipv4(ein);
     374          254 :                 CATCH_REQUIRE(vec.front() == e);
     375          254 :                 vec.erase(vec.begin());
     376          254 :             }
     377              :             // same, but use a limit so we get only the first 10 IPs
     378            4 :             CATCH_REQUIRE_THROWS_MATCHES(
     379              :                       range.to_addresses(10)
     380              :                     , addr::out_of_range
     381              :                     , Catch::Matchers::ExceptionMessage(
     382              :                               "out_of_range: too many addresses in this range: 254 > 10"));
     383            1 :         }
     384            9 :         CATCH_END_SECTION()
     385              : 
     386            9 :         CATCH_START_SECTION("addr_range: test empty range (from > to)")
     387              :         {
     388            1 :             addr::addr a;
     389            1 :             addr::addr other;
     390              : 
     391              :             // from is set to 10.0.0.254
     392            1 :             struct sockaddr_in fin = sockaddr_in();
     393            1 :             fin.sin_family = AF_INET;
     394            1 :             int const fport(rand() & 0xFFFF);
     395            1 :             fin.sin_port = htons(fport);
     396            1 :             uint32_t const faddress((10 << 24)
     397              :                           | (0 << 16)
     398              :                           | (0 << 8)
     399              :                           | 254);
     400            1 :             fin.sin_addr.s_addr = htonl(faddress);
     401            1 :             addr::addr f;
     402            1 :             f.set_ipv4(fin);
     403              : 
     404              :             // from is set to 10.0.0.1
     405            1 :             struct sockaddr_in tin = sockaddr_in();
     406            1 :             tin.sin_family = AF_INET;
     407            1 :             int const tport(rand() & 0xFFFF);
     408            1 :             tin.sin_port = htons(tport);
     409            1 :             uint32_t const taddress((10 << 24)
     410              :                           | (0 << 16)
     411              :                           | (0 << 8)
     412              :                           | 1);
     413            1 :             tin.sin_addr.s_addr = htonl(taddress);
     414            1 :             addr::addr t;
     415            1 :             t.set_ipv4(tin);
     416              : 
     417              :             // test defaults first
     418              :             //
     419            1 :             CATCH_REQUIRE_FALSE(range.has_from());
     420            1 :             CATCH_REQUIRE_FALSE(range.has_to());
     421            1 :             CATCH_REQUIRE_FALSE(range.is_range());
     422            1 :             CATCH_REQUIRE_FALSE(range.is_empty());
     423            1 :             CATCH_REQUIRE(range.get_from() == a);
     424            1 :             CATCH_REQUIRE(range.get_to() == a);
     425            1 :             auto const & r1(range);
     426            1 :             CATCH_REQUIRE(r1.get_from() == a);
     427            1 :             CATCH_REQUIRE(r1.get_to() == a);
     428            1 :             CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
     429            1 :             CATCH_REQUIRE_THROWS_AS(r1.is_in(other), addr::addr_invalid_state);
     430            1 :             CATCH_REQUIRE(range.match(a));
     431            1 :             CATCH_REQUIRE_FALSE(range.match(f));
     432            1 :             CATCH_REQUIRE_FALSE(range.match(t));
     433              : 
     434            1 :             range.set_from(f);
     435              : 
     436              :             // defined "from", test the results
     437              :             //
     438            1 :             CATCH_REQUIRE(range.has_from());
     439            1 :             CATCH_REQUIRE_FALSE(range.has_to());
     440            1 :             CATCH_REQUIRE_FALSE(range.is_range());
     441            1 :             CATCH_REQUIRE_FALSE(range.is_empty());
     442            1 :             CATCH_REQUIRE(range.get_from() == f);
     443            1 :             CATCH_REQUIRE(range.get_to() == a);
     444            1 :             auto const & r2(range);
     445            1 :             CATCH_REQUIRE(r2.get_from() == f);
     446            1 :             CATCH_REQUIRE(r2.get_to() == a);
     447            1 :             CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
     448            1 :             CATCH_REQUIRE_THROWS_AS(r2.is_in(other), addr::addr_invalid_state);
     449            1 :             CATCH_REQUIRE_FALSE(range.match(a));
     450            1 :             CATCH_REQUIRE(range.match(f));
     451            1 :             CATCH_REQUIRE_FALSE(range.match(t));
     452              : 
     453              :             {
     454            1 :                 std::stringstream ss;
     455            1 :                 ss << range;
     456            1 :                 CATCH_REQUIRE(ss.str() == "10.0.0.254:" + std::to_string(fport) + "/32");
     457            1 :             }
     458              : 
     459            1 :             range.set_to(t);
     460              : 
     461              :             // defined "to", test the results
     462              :             //
     463            1 :             CATCH_REQUIRE(range.has_from());
     464            1 :             CATCH_REQUIRE(range.has_to());
     465            1 :             CATCH_REQUIRE(range.is_range());
     466            1 :             CATCH_REQUIRE(range.is_empty());
     467            1 :             CATCH_REQUIRE(range.get_from() == f);
     468            1 :             CATCH_REQUIRE(range.get_to() == t);
     469            1 :             auto const & r3(range);
     470            1 :             CATCH_REQUIRE(r3.get_from() == f);
     471            1 :             CATCH_REQUIRE(r3.get_to() == t);
     472            1 :             CATCH_REQUIRE_FALSE(range.match(a));
     473            1 :             CATCH_REQUIRE_FALSE(range.match(f));
     474            1 :             CATCH_REQUIRE_FALSE(range.match(t));
     475              : 
     476              :             {
     477            1 :                 std::stringstream ss;
     478            1 :                 ss << range;
     479            1 :                 CATCH_REQUIRE(ss.str() == "<empty address range>");
     480            1 :             }
     481              : 
     482              :             // IP before range
     483              :             {
     484            1 :                 struct sockaddr_in bin = sockaddr_in();
     485            1 :                 bin.sin_family = AF_INET;
     486            1 :                 bin.sin_port = htons(rand());
     487            1 :                 uint32_t baddress((10 << 24)
     488              :                               | (0 << 16)
     489              :                               | (0 << 8)
     490              :                               | 0);
     491            1 :                 bin.sin_addr.s_addr = htonl(baddress);
     492            1 :                 addr::addr b;
     493            1 :                 b.set_ipv4(bin);
     494              : 
     495            1 :                 CATCH_REQUIRE_FALSE(range.is_in(b));
     496            1 :             }
     497              : 
     498           11 :             for(int idx(0); idx < 10; ++idx)
     499              :             {
     500           10 :                 struct sockaddr_in bin = sockaddr_in();
     501           10 :                 bin.sin_family = AF_INET;
     502           10 :                 bin.sin_port = htons(rand());
     503           10 :                 uint32_t baddress(((rand() % 10) << 24)
     504           10 :                               | ((rand() & 255) << 16)
     505           10 :                               | ((rand() & 255) << 8)
     506           10 :                               | (rand() & 255));
     507           10 :                 bin.sin_addr.s_addr = htonl(baddress);
     508           10 :                 addr::addr b;
     509           10 :                 b.set_ipv4(bin);
     510              : 
     511           10 :                 CATCH_REQUIRE_FALSE(range.is_in(b));
     512           10 :             }
     513              : 
     514              :             // IP after range
     515              :             {
     516            1 :                 struct sockaddr_in ain = sockaddr_in();
     517            1 :                 ain.sin_family = AF_INET;
     518            1 :                 ain.sin_port = htons(rand());
     519            1 :                 uint32_t aaddress((10 << 24)
     520              :                               | (0 << 16)
     521              :                               | (0 << 8)
     522              :                               | 255);
     523            1 :                 ain.sin_addr.s_addr = htonl(aaddress);
     524            1 :                 addr::addr after;
     525            1 :                 after.set_ipv4(ain);
     526              : 
     527            1 :                 CATCH_REQUIRE_FALSE(range.is_in(after));
     528            1 :             }
     529              : 
     530           11 :             for(int idx(0); idx < 10; ++idx)
     531              :             {
     532           10 :                 struct sockaddr_in ain = sockaddr_in();
     533           10 :                 ain.sin_family = AF_INET;
     534           10 :                 ain.sin_port = htons(rand());
     535           10 :                 uint32_t aaddress(((rand() % (256 - 11) + 11) << 24)
     536           10 :                               | ((rand() & 255) << 16)
     537           10 :                               | ((rand() & 255) << 8)
     538           10 :                               | (rand() & 255));
     539           10 :                 ain.sin_addr.s_addr = htonl(aaddress);
     540           10 :                 addr::addr after;
     541           10 :                 after.set_ipv4(ain);
     542              : 
     543           10 :                 CATCH_REQUIRE_FALSE(range.is_in(after));
     544           10 :             }
     545              : 
     546              :             // IP in range
     547              :             //
     548          101 :             for(int idx(0); idx < 100; ++idx)
     549              :             {
     550          100 :                 struct sockaddr_in iin = sockaddr_in();
     551          100 :                 iin.sin_family = AF_INET;
     552          100 :                 iin.sin_port = htons(rand());
     553              :                 uint32_t iaddress((10 << 24)
     554              :                               | (0 << 16)
     555              :                               | (0 << 8)
     556          100 :                               | ((rand() & 253) + 1));
     557          100 :                 iin.sin_addr.s_addr = htonl(iaddress);
     558          100 :                 addr::addr i;
     559          100 :                 i.set_ipv4(iin);
     560              : 
     561          100 :                 CATCH_REQUIRE_FALSE(range.is_in(i));
     562          100 :             }
     563            1 :         }
     564            9 :         CATCH_END_SECTION()
     565              : 
     566            9 :         CATCH_START_SECTION("addr_range: compare \"from\" ranges against each other")
     567              :         {
     568            1 :             addr::addr a;
     569            1 :             addr::addr_range other;
     570              : 
     571            1 :             CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     572            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     573            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     574              : 
     575            1 :             struct sockaddr_in in = sockaddr_in();
     576            1 :             in.sin_family = AF_INET;
     577            1 :             in.sin_port = htons(rand());
     578              :             uint32_t address((10 << 24)
     579            1 :                           | ((rand() & 255) << 16)
     580            1 :                           | ((rand() & 255) << 8)
     581            1 :                           | (rand() & 255));
     582            1 :             in.sin_addr.s_addr = htonl(address);
     583            1 :             a.set_ipv4(in);
     584            1 :             range.set_from(a);
     585              : 
     586            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     587            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     588            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     589              : 
     590            1 :             address = (20 << 24)
     591            1 :                           | ((rand() & 255) << 16)
     592            1 :                           | ((rand() & 255) << 8)
     593            1 :                           | (rand() & 255);
     594            1 :             in.sin_addr.s_addr = htonl(address);
     595            1 :             a.set_ipv4(in);
     596            1 :             other.set_from(a);
     597              : 
     598            1 :             CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_EQUAL);
     599            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
     600            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
     601            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
     602              : 
     603            1 :             a = range.get_from();
     604            1 :             other.set_from(a + 1);
     605              : 
     606            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_PRECEDES);
     607            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_FOLLOWS);
     608            1 :         }
     609            9 :         CATCH_END_SECTION()
     610              : 
     611            9 :         CATCH_START_SECTION("addr_range: compare \"to\" ranges against each other")
     612              :         {
     613            1 :             addr::addr a;
     614            1 :             addr::addr_range other;
     615              : 
     616            1 :             CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     617            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     618            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     619              : 
     620            1 :             struct sockaddr_in in = sockaddr_in();
     621            1 :             in.sin_family = AF_INET;
     622            1 :             in.sin_port = htons(rand());
     623              :             uint32_t address((10 << 24)
     624            1 :                           | ((rand() & 255) << 16)
     625            1 :                           | ((rand() & 255) << 8)
     626            1 :                           | (rand() & 255));
     627            1 :             in.sin_addr.s_addr = htonl(address);
     628            1 :             a.set_ipv4(in);
     629            1 :             range.set_to(a);
     630              : 
     631            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     632            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     633            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     634              : 
     635            1 :             address = (20 << 24)
     636            1 :                           | ((rand() & 255) << 16)
     637            1 :                           | ((rand() & 255) << 8)
     638            1 :                           | (rand() & 255);
     639            1 :             in.sin_addr.s_addr = htonl(address);
     640            1 :             a.set_ipv4(in);
     641            1 :             other.set_to(a);
     642              : 
     643            1 :             CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_EQUAL);
     644            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
     645            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
     646            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
     647              : 
     648            1 :             a = range.get_to();
     649            1 :             other.set_to(a + 1);
     650              : 
     651            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_PRECEDES);
     652            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_FOLLOWS);
     653            1 :         }
     654            9 :         CATCH_END_SECTION()
     655              : 
     656            9 :         CATCH_START_SECTION("addr_range: compare \"from\" against \"to\" ranges")
     657              :         {
     658            1 :             addr::addr a;
     659            1 :             addr::addr_range other;
     660              : 
     661            1 :             CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     662            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     663            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     664              : 
     665            1 :             struct sockaddr_in in = sockaddr_in();
     666            1 :             in.sin_family = AF_INET;
     667            1 :             in.sin_port = htons(rand());
     668              :             uint32_t address((10 << 24)
     669            1 :                           | ((rand() & 255) << 16)
     670            1 :                           | ((rand() & 255) << 8)
     671            1 :                           | (rand() & 255));
     672            1 :             in.sin_addr.s_addr = htonl(address);
     673            1 :             a.set_ipv4(in);
     674            1 :             range.set_from(a);
     675              : 
     676            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     677            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     678            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     679              : 
     680            1 :             address = (20 << 24)
     681            1 :                           | ((rand() & 255) << 16)
     682            1 :                           | ((rand() & 255) << 8)
     683            1 :                           | (rand() & 255);
     684            1 :             in.sin_addr.s_addr = htonl(address);
     685            1 :             a.set_ipv4(in);
     686            1 :             other.set_to(a);
     687              : 
     688            1 :             CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_EQUAL);
     689            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
     690            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
     691            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
     692              : 
     693            1 :             a = range.get_from();
     694            1 :             other.set_to(a + 1);
     695              : 
     696            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_PRECEDES);
     697            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_FOLLOWS);
     698            1 :         }
     699            9 :         CATCH_END_SECTION()
     700              : 
     701            9 :         CATCH_START_SECTION("addr_range: compare full ranges (\"from\" and \"to\" defined)")
     702              :         {
     703            1 :             addr::addr a;
     704            1 :             addr::addr_range other;
     705              : 
     706            1 :             struct sockaddr_in in = sockaddr_in();
     707            1 :             in.sin_family = AF_INET;
     708            1 :             in.sin_port = htons(rand());
     709            1 :             uint32_t address((10 << 24)
     710              :                           | (5 << 16)
     711              :                           | (7 << 8)
     712              :                           | (32 << 0));
     713            1 :             in.sin_addr.s_addr = htonl(address);
     714            1 :             a.set_ipv4(in);
     715            1 :             range.set_from(a);
     716              : 
     717            1 :             address = (10 << 24)
     718              :                           | (5 << 16)
     719              :                           | (7 << 8)
     720              :                           | (37 << 0);
     721            1 :             in.sin_addr.s_addr = htonl(address);
     722            1 :             a.set_ipv4(in);
     723            1 :             range.set_to(a);
     724              : 
     725            1 :             CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_EQUAL);
     726            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     727            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
     728            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     729              : 
     730            1 :             address = (20 << 24)
     731              :                           | (5 << 16)
     732              :                           | (7 << 8)
     733              :                           | (32 << 0);
     734            1 :             in.sin_addr.s_addr = htonl(address);
     735            1 :             a.set_ipv4(in);
     736            1 :             other.set_from(a);
     737              : 
     738            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
     739            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
     740            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
     741              : 
     742            1 :             other.swap_from_to();
     743              : 
     744            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
     745            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
     746            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
     747              : 
     748            1 :             address = (20 << 24)
     749              :                           | (5 << 16)
     750              :                           | (7 << 8)
     751              :                           | (22 << 0);
     752            1 :             in.sin_addr.s_addr = htonl(address);
     753            1 :             a.set_ipv4(in);
     754            1 :             other.set_from(a);      // it was swapped, so set from again
     755              : 
     756            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
     757            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
     758            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
     759              : 
     760            1 :             other.swap_from_to();
     761              : 
     762            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_FIRST);
     763            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LAST);
     764            1 :             CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
     765              : 
     766            1 :             other.swap_from_to();
     767              : 
     768            1 :             a = range.get_to();
     769            1 :             other.set_from(a + 1);
     770              : 
     771            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_PRECEDES);
     772            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_FOLLOWS);
     773              : 
     774            1 :             other.set_from(a);
     775              : 
     776            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_OVERLAP_SMALL_VS_LARGE);
     777            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_OVERLAP_LARGE_VS_SMALL);
     778            1 :         }
     779            9 :         CATCH_END_SECTION()
     780              : 
     781            9 :         CATCH_START_SECTION("addr_range: compare mixed IPs")
     782              :         {
     783            1 :             addr::addr a;
     784            1 :             addr::addr_range other;
     785              : 
     786            1 :             struct sockaddr_in in4 = sockaddr_in();
     787            1 :             in4.sin_family = AF_INET;
     788            1 :             in4.sin_port = htons(rand());
     789            1 :             uint32_t address((10 << 24)
     790              :                           | (5 << 16)
     791              :                           | (7 << 8)
     792              :                           | (32 << 0));
     793            1 :             in4.sin_addr.s_addr = htonl(address);
     794            1 :             a.set_ipv4(in4);
     795            1 :             range.set_from(a);
     796              : 
     797            1 :             struct sockaddr_in6 in6 = sockaddr_in6();
     798            1 :             in6.sin6_family = AF_INET6;
     799            1 :             in6.sin6_port = htons(rand());
     800            1 :             in6.sin6_addr.s6_addr[0] = 0xF8;
     801            1 :             a.set_ipv6(in6);
     802            1 :             other.set_from(a);
     803              : 
     804            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_IPV4_VS_IPV6);
     805            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_IPV6_VS_IPV4);
     806              : 
     807            1 :             CATCH_REQUIRE(range.compare(other, true) == addr::compare_t::COMPARE_SMALLER);
     808            1 :             CATCH_REQUIRE(other.compare(range, true) == addr::compare_t::COMPARE_LARGER);
     809              : 
     810            1 :             in6.sin6_addr.s6_addr[0] = 0;
     811            1 :             in6.sin6_addr.s6_addr[15] = 1;
     812            1 :             a.set_ipv6(in6);
     813            1 :             other.set_from(a);
     814              : 
     815            1 :             CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_IPV4_VS_IPV6);
     816            1 :             CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_IPV6_VS_IPV4);
     817              : 
     818            1 :             CATCH_REQUIRE(range.compare(other, true) == addr::compare_t::COMPARE_LARGER);
     819            1 :             CATCH_REQUIRE(other.compare(range, true) == addr::compare_t::COMPARE_SMALLER);
     820            1 :         }
     821            9 :         CATCH_END_SECTION()
     822              : 
     823            9 :         CATCH_START_SECTION("addr_range: create range from CIDR")
     824              :         {
     825            1 :             addr::addr a;
     826              : 
     827              :             // from is set to 10.x.x.x
     828            1 :             struct sockaddr_in fin = sockaddr_in();
     829            1 :             fin.sin_family = AF_INET;
     830            1 :             fin.sin_port = htons(rand());
     831              :             uint32_t faddress((10 << 24)
     832            1 :                           | ((rand() & 255) << 16)
     833            1 :                           | ((rand() & 255) << 8)
     834            1 :                           | (rand() & 255));
     835            1 :             fin.sin_addr.s_addr = htonl(faddress);
     836            1 :             a.set_ipv4(fin);
     837              : 
     838              :             // no mask defined, that means the range will be [a..a]
     839            1 :             range.from_cidr(a);
     840              : 
     841            1 :             CATCH_REQUIRE(range.has_from());
     842            1 :             CATCH_REQUIRE(range.has_to());
     843            1 :             CATCH_REQUIRE(range.is_range());
     844            1 :             CATCH_REQUIRE_FALSE(range.is_empty());
     845            1 :             CATCH_REQUIRE(range.is_ipv4());
     846            1 :             CATCH_REQUIRE(range.get_from() == a);
     847            1 :             CATCH_REQUIRE(range.get_to() == a);
     848            1 :             CATCH_REQUIRE(range.size() == 1);
     849              : 
     850              : #pragma GCC diagnostic push
     851              : #pragma GCC diagnostic ignored "-Wpedantic"
     852           34 :             for(int size(96); size <= 128; ++size)
     853              :             {
     854           33 :                 a.set_mask_count(size);
     855           33 :                 range.from_cidr(a);
     856              : 
     857           33 :                 CATCH_REQUIRE(range.has_from());
     858           33 :                 CATCH_REQUIRE(range.has_to());
     859           33 :                 CATCH_REQUIRE(range.is_range());
     860           33 :                 CATCH_REQUIRE_FALSE(range.is_empty());
     861           33 :                 CATCH_REQUIRE(range.is_ipv4());
     862           33 :                 unsigned __int128 mask(0xffffffffffffffffffffffffffffffff_uint128);
     863           33 :                 mask <<= 128 - size;
     864           33 :                 addr::addr const & f(range.get_from());
     865           33 :                 addr::addr const & t(range.get_to());
     866           33 :                 unsigned __int128 aa(a.ip_to_uint128());
     867           33 :                 unsigned __int128 fa(f.ip_to_uint128());
     868           33 :                 unsigned __int128 ta(t.ip_to_uint128());
     869           33 :                 unsigned __int128 fm(aa & mask);
     870           33 :                 unsigned __int128 tm(aa | ~mask);
     871           33 :                 CATCH_REQUIRE(fa == fm);
     872           33 :                 CATCH_REQUIRE(ta == tm);
     873           33 :                 CATCH_REQUIRE(range.size() == 1ULL << (128 - size));
     874              :             }
     875              : #pragma GCC diagnostic pop
     876              : 
     877              :             // create an invalid mask as far as from_cidr() is concerned
     878              :             //
     879            1 :             uint8_t invalid_mask[16] = {};
     880           17 :             for(int i(0); i < 16; ++i)
     881              :             {
     882              :                 do
     883              :                 {
     884           16 :                     invalid_mask[i] = rand();
     885              :                 }
     886           16 :                 while(invalid_mask[i] == 0 || invalid_mask[i] == 0xFF);
     887              :             }
     888            1 :             a.set_mask(invalid_mask);
     889            3 :             CATCH_REQUIRE_THROWS_MATCHES(
     890              :                       range.from_cidr(a)
     891              :                     , addr::addr_unsupported_as_range
     892              :                     , Catch::Matchers::ExceptionMessage(
     893              :                               "addr_error: unsupported mask for a range"));
     894            1 :         }
     895            9 :         CATCH_END_SECTION()
     896           28 :     }
     897              : 
     898           19 :     CATCH_GIVEN("compute intersection of two ranges")
     899              :     {
     900            2 :         CATCH_START_SECTION("addr_range: intersection of two ranges that overlap")
     901              :         {
     902              :             // from is set to 10.1.0.0
     903            1 :             struct sockaddr_in f1in = sockaddr_in();
     904            1 :             f1in.sin_family = AF_INET;
     905            1 :             f1in.sin_port = htons(rand());
     906            1 :             uint32_t f1address((10 << 24)
     907              :                           | (1 << 16)
     908              :                           | (0 << 8)
     909              :                           | 0);
     910            1 :             f1in.sin_addr.s_addr = htonl(f1address);
     911            1 :             addr::addr f1;
     912            1 :             f1.set_ipv4(f1in);
     913              : 
     914              :             // to is set to 10.5.255.255
     915            1 :             struct sockaddr_in t1in = sockaddr_in();
     916            1 :             t1in.sin_family = AF_INET;
     917            1 :             t1in.sin_port = htons(rand());
     918            1 :             uint32_t t1address((10 << 24)
     919              :                           | (5 << 16)
     920              :                           | (255 << 8)
     921              :                           | 255);
     922            1 :             t1in.sin_addr.s_addr = htonl(t1address);
     923            1 :             addr::addr t1;
     924            1 :             t1.set_ipv4(t1in);
     925              : 
     926              :             // from is set to 10.2.0.0
     927            1 :             struct sockaddr_in f2in = sockaddr_in();
     928            1 :             f2in.sin_family = AF_INET;
     929            1 :             f2in.sin_port = htons(rand());
     930            1 :             uint32_t f2address((10 << 24)
     931              :                           | (2 << 16)
     932              :                           | (0 << 8)
     933              :                           | 0);
     934            1 :             f2in.sin_addr.s_addr = htonl(f2address);
     935            1 :             addr::addr f2;
     936            1 :             f2.set_ipv4(f2in);
     937              : 
     938              :             // to is set to 10.10.255.255
     939            1 :             struct sockaddr_in t2in = sockaddr_in();
     940            1 :             t2in.sin_family = AF_INET;
     941            1 :             t2in.sin_port = htons(rand());
     942            1 :             uint32_t t2address((10 << 24)
     943              :                           | (10 << 16)
     944              :                           | (255 << 8)
     945              :                           | 255);
     946            1 :             t2in.sin_addr.s_addr = htonl(t2address);
     947            1 :             addr::addr t2;
     948            1 :             t2.set_ipv4(t2in);
     949              : 
     950            1 :             addr::addr_range range1;
     951            1 :             range1.set_from(f1);
     952            1 :             range1.set_to(t1);
     953              : 
     954            1 :             addr::addr_range range2;
     955            1 :             range2.set_from(f2);
     956            1 :             range2.set_to(t2);
     957              : 
     958            1 :             CATCH_REQUIRE(range1.is_range());
     959            1 :             CATCH_REQUIRE_FALSE(range1.is_empty());
     960            1 :             CATCH_REQUIRE(range2.is_range());
     961            1 :             CATCH_REQUIRE_FALSE(range2.is_empty());
     962              : 
     963            1 :             addr::addr_range const range3(range1.intersection(range2));
     964              : 
     965            1 :             CATCH_REQUIRE(range3.is_range());
     966            1 :             CATCH_REQUIRE_FALSE(range3.is_empty());
     967              : 
     968            1 :             CATCH_REQUIRE(range3.get_from().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.2.0.0");
     969            1 :             CATCH_REQUIRE(range3.get_to().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.5.255.255");
     970            1 :         }
     971            2 :         CATCH_END_SECTION()
     972              : 
     973            2 :         CATCH_START_SECTION("addr_range: intersection of two ranges that do not overlap")
     974              :         {
     975              :             // from is set to 10.1.0.0
     976            1 :             struct sockaddr_in f1in = sockaddr_in();
     977            1 :             f1in.sin_family = AF_INET;
     978            1 :             f1in.sin_port = htons(rand());
     979            1 :             uint32_t f1address((10 << 24)
     980              :                           | (1 << 16)
     981              :                           | (0 << 8)
     982              :                           | 0);
     983            1 :             f1in.sin_addr.s_addr = htonl(f1address);
     984            1 :             addr::addr f1;
     985            1 :             f1.set_ipv4(f1in);
     986              : 
     987              :             // to is set to 10.5.255.255
     988            1 :             struct sockaddr_in t1in = sockaddr_in();
     989            1 :             t1in.sin_family = AF_INET;
     990            1 :             t1in.sin_port = htons(rand());
     991            1 :             uint32_t t1address((10 << 24)
     992              :                           | (5 << 16)
     993              :                           | (255 << 8)
     994              :                           | 255);
     995            1 :             t1in.sin_addr.s_addr = htonl(t1address);
     996            1 :             addr::addr t1;
     997            1 :             t1.set_ipv4(t1in);
     998              : 
     999              :             // from is set to 10.10.0.0
    1000            1 :             struct sockaddr_in f2in = sockaddr_in();
    1001            1 :             f2in.sin_family = AF_INET;
    1002            1 :             f2in.sin_port = htons(rand());
    1003            1 :             uint32_t f2address((10 << 24)
    1004              :                           | (10 << 16)
    1005              :                           | (0 << 8)
    1006              :                           | 0);
    1007            1 :             f2in.sin_addr.s_addr = htonl(f2address);
    1008            1 :             addr::addr f2;
    1009            1 :             f2.set_ipv4(f2in);
    1010              : 
    1011              :             // to is set to 10.20.255.255
    1012            1 :             struct sockaddr_in t2in = sockaddr_in();
    1013            1 :             t2in.sin_family = AF_INET;
    1014            1 :             t2in.sin_port = htons(rand());
    1015            1 :             uint32_t t2address((10 << 24)
    1016              :                           | (20 << 16)
    1017              :                           | (255 << 8)
    1018              :                           | 255);
    1019            1 :             t2in.sin_addr.s_addr = htonl(t2address);
    1020            1 :             addr::addr t2;
    1021            1 :             t2.set_ipv4(t2in);
    1022              : 
    1023            1 :             addr::addr_range range1;
    1024            1 :             range1.set_from(f1);
    1025            1 :             range1.set_to(t1);
    1026              : 
    1027            1 :             addr::addr_range range2;
    1028            1 :             range2.set_from(f2);
    1029            1 :             range2.set_to(t2);
    1030              : 
    1031            1 :             CATCH_REQUIRE(range1.is_range());
    1032            1 :             CATCH_REQUIRE_FALSE(range1.is_empty());
    1033            1 :             CATCH_REQUIRE(range2.is_range());
    1034            1 :             CATCH_REQUIRE_FALSE(range2.is_empty());
    1035              : 
    1036            1 :             addr::addr_range const range3(range1.intersection(range2));
    1037              : 
    1038            1 :             CATCH_REQUIRE(range3.is_range());
    1039            1 :             CATCH_REQUIRE(range3.is_empty());
    1040              : 
    1041              :             // although it is "empty" we know the IPs and can test them
    1042              :             //
    1043            1 :             CATCH_REQUIRE(range3.get_from().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.10.0.0");
    1044            1 :             CATCH_REQUIRE(range3.get_to().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.5.255.255");
    1045              : 
    1046            1 :             addr::addr_range::vector_t rlist;
    1047            1 :             rlist.push_back(range1);
    1048            1 :             rlist.push_back(range2);
    1049            1 :             CATCH_REQUIRE(addr::address_match_ranges(rlist, f1));
    1050            1 :             CATCH_REQUIRE(addr::address_match_ranges(rlist, f2));
    1051            1 :             CATCH_REQUIRE(addr::address_match_ranges(rlist, t1));
    1052            1 :             CATCH_REQUIRE(addr::address_match_ranges(rlist, t2));
    1053            1 :         }
    1054            2 :         CATCH_END_SECTION()
    1055           19 :     }
    1056              : 
    1057           19 :     CATCH_GIVEN("check for union of two ranges")
    1058              :     {
    1059            3 :         CATCH_START_SECTION("addr_range: union of two ranges that overlap")
    1060              :         {
    1061              :             // from 10.1.0.0
    1062            1 :             struct sockaddr_in f1in = sockaddr_in();
    1063            1 :             f1in.sin_family = AF_INET;
    1064            1 :             f1in.sin_port = htons(rand());
    1065            1 :             uint32_t f1address((10 << 24)
    1066              :                           | (1 << 16)
    1067              :                           | (0 << 8)
    1068              :                           | 0);
    1069            1 :             f1in.sin_addr.s_addr = htonl(f1address);
    1070            1 :             addr::addr f1;
    1071            1 :             f1.set_ipv4(f1in);
    1072              : 
    1073              :             // to 10.5.255.255
    1074            1 :             struct sockaddr_in t1in = sockaddr_in();
    1075            1 :             t1in.sin_family = AF_INET;
    1076            1 :             t1in.sin_port = htons(rand());
    1077            1 :             uint32_t t1address((10 << 24)
    1078              :                           | (5 << 16)
    1079              :                           | (255 << 8)
    1080              :                           | 255);
    1081            1 :             t1in.sin_addr.s_addr = htonl(t1address);
    1082            1 :             addr::addr t1;
    1083            1 :             t1.set_ipv4(t1in);
    1084              : 
    1085              :             // from is set to 10.2.0.0
    1086            1 :             struct sockaddr_in f2in = sockaddr_in();
    1087            1 :             f2in.sin_family = AF_INET;
    1088            1 :             f2in.sin_port = htons(rand());
    1089            1 :             uint32_t f2address((10 << 24)
    1090              :                           | (2 << 16)
    1091              :                           | (0 << 8)
    1092              :                           | 0);
    1093            1 :             f2in.sin_addr.s_addr = htonl(f2address);
    1094            1 :             addr::addr f2;
    1095            1 :             f2.set_ipv4(f2in);
    1096              : 
    1097              :             // from is set to 10.10.255.255
    1098            1 :             struct sockaddr_in t2in = sockaddr_in();
    1099            1 :             t2in.sin_family = AF_INET;
    1100            1 :             t2in.sin_port = htons(rand());
    1101            1 :             uint32_t t2address((10 << 24)
    1102              :                           | (10 << 16)
    1103              :                           | (255 << 8)
    1104              :                           | 255);
    1105            1 :             t2in.sin_addr.s_addr = htonl(t2address);
    1106            1 :             addr::addr t2;
    1107            1 :             t2.set_ipv4(t2in);
    1108              : 
    1109            1 :             addr::addr_range range1;
    1110            1 :             addr::addr_range range2;
    1111              : 
    1112              :             {
    1113            1 :                 addr::addr_range const r(range1.union_if_possible(range2));
    1114            1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1115            1 :             }
    1116              :             {
    1117            1 :                 addr::addr_range const r(range2.union_if_possible(range1));
    1118            1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1119            1 :             }
    1120              : 
    1121            1 :             range1.set_from(f1);
    1122              : 
    1123              :             {
    1124            1 :                 addr::addr_range const r(range1.union_if_possible(range2));
    1125            1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1126            1 :             }
    1127              :             {
    1128            1 :                 addr::addr_range const r(range2.union_if_possible(range1));
    1129            1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1130            1 :             }
    1131              :             {
    1132            1 :                 addr::addr_range const r(range1.union_if_possible(range1));
    1133            1 :                 CATCH_REQUIRE(r.is_defined());
    1134            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1135            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1136            1 :                 CATCH_REQUIRE(r.has_from());
    1137            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1138            1 :                 CATCH_REQUIRE(r.get_from().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.1.0.0");
    1139            1 :             }
    1140              : 
    1141            1 :             range2.set_from(f2);
    1142              : 
    1143              :             {
    1144            1 :                 addr::addr_range const r(range1.union_if_possible(range2));
    1145            1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1146            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1147            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1148            1 :                 CATCH_REQUIRE_FALSE(r.has_from());
    1149            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1150            1 :             }
    1151              :             {
    1152            1 :                 addr::addr_range const r(range2.union_if_possible(range1));
    1153            1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1154            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1155            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1156            1 :                 CATCH_REQUIRE_FALSE(r.has_from());
    1157            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1158            1 :             }
    1159              : 
    1160            1 :             range1.set_to(t1);
    1161              : 
    1162              :             {
    1163            1 :                 addr::addr_range const r(range1.union_if_possible(range2));
    1164            1 :                 CATCH_REQUIRE(r.is_defined());
    1165            1 :                 CATCH_REQUIRE(r.is_range());
    1166            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1167            1 :                 CATCH_REQUIRE(r.has_from());
    1168            1 :                 CATCH_REQUIRE(r.has_to());
    1169            1 :                 CATCH_REQUIRE(r.get_from().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.1.0.0");
    1170            1 :                 CATCH_REQUIRE(r.get_to().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.5.255.255");
    1171            1 :             }
    1172              :             {
    1173            1 :                 addr::addr_range const r(range2.union_if_possible(range1));
    1174            1 :                 CATCH_REQUIRE(r.is_defined());
    1175            1 :                 CATCH_REQUIRE(r.is_range());
    1176            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1177            1 :                 CATCH_REQUIRE(r.has_from());
    1178            1 :                 CATCH_REQUIRE(r.has_to());
    1179            1 :                 CATCH_REQUIRE(r.get_from().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.1.0.0");
    1180            1 :                 CATCH_REQUIRE(r.get_to().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.5.255.255");
    1181            1 :             }
    1182              : 
    1183            1 :             range2.set_to(t2);
    1184              : 
    1185            1 :             CATCH_REQUIRE(range1.compare(range2) == addr::compare_t::COMPARE_OVERLAP_SMALL_VS_LARGE);
    1186            1 :             CATCH_REQUIRE(range2.compare(range1) == addr::compare_t::COMPARE_OVERLAP_LARGE_VS_SMALL);
    1187              : 
    1188            1 :             CATCH_REQUIRE(range1.is_range());
    1189            1 :             CATCH_REQUIRE_FALSE(range1.is_empty());
    1190            1 :             CATCH_REQUIRE(range2.is_range());
    1191            1 :             CATCH_REQUIRE_FALSE(range2.is_empty());
    1192              : 
    1193              :             {
    1194            1 :                 addr::addr_range const r(range1.union_if_possible(range2));
    1195            1 :                 CATCH_REQUIRE(r.is_defined());
    1196            1 :                 CATCH_REQUIRE(r.is_range());
    1197            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1198            1 :                 CATCH_REQUIRE(r.has_from());
    1199            1 :                 CATCH_REQUIRE(r.has_to());
    1200            1 :                 CATCH_REQUIRE(r.get_from().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.1.0.0");
    1201            1 :                 CATCH_REQUIRE(r.get_to().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.10.255.255");
    1202              : 
    1203            1 :                 CATCH_REQUIRE(range1.compare(r) == addr::compare_t::COMPARE_INCLUDES);
    1204            1 :                 CATCH_REQUIRE(r.compare(range1) == addr::compare_t::COMPARE_INCLUDED);
    1205            1 :                 CATCH_REQUIRE(range2.compare(r) == addr::compare_t::COMPARE_INCLUDES);
    1206            1 :                 CATCH_REQUIRE(r.compare(range2) == addr::compare_t::COMPARE_INCLUDED);
    1207            1 :             }
    1208            1 :         }
    1209            3 :         CATCH_END_SECTION()
    1210              : 
    1211            3 :         CATCH_START_SECTION("addr_range: union of two ranges that touch")
    1212              :         {
    1213              :             // from 10.1.0.0
    1214            1 :             struct sockaddr_in f1in = sockaddr_in();
    1215            1 :             f1in.sin_family = AF_INET;
    1216            1 :             f1in.sin_port = htons(rand());
    1217            1 :             uint32_t f1address((10 << 24)
    1218              :                           | (1 << 16)
    1219              :                           | (0 << 8)
    1220              :                           | 0);
    1221            1 :             f1in.sin_addr.s_addr = htonl(f1address);
    1222            1 :             addr::addr f1;
    1223            1 :             f1.set_ipv4(f1in);
    1224              : 
    1225              :             // to 10.5.32.21
    1226            1 :             struct sockaddr_in t1in = sockaddr_in();
    1227            1 :             t1in.sin_family = AF_INET;
    1228            1 :             t1in.sin_port = htons(rand());
    1229            1 :             uint32_t t1address((10 << 24)
    1230              :                           | (5 << 16)
    1231              :                           | (32 << 8)
    1232              :                           | 21);
    1233            1 :             t1in.sin_addr.s_addr = htonl(t1address);
    1234            1 :             addr::addr t1;
    1235            1 :             t1.set_ipv4(t1in);
    1236              : 
    1237              :             // from is set to 10.5.32.22
    1238            1 :             struct sockaddr_in f2in = sockaddr_in();
    1239            1 :             f2in.sin_family = AF_INET;
    1240            1 :             f2in.sin_port = htons(rand());
    1241            1 :             uint32_t f2address((10 << 24)
    1242              :                           | (5 << 16)
    1243              :                           | (32 << 8)
    1244              :                           | 22);
    1245            1 :             f2in.sin_addr.s_addr = htonl(f2address);
    1246            1 :             addr::addr f2;
    1247            1 :             f2.set_ipv4(f2in);
    1248              : 
    1249              :             // from is set to 10.11.255.255
    1250            1 :             struct sockaddr_in t2in = sockaddr_in();
    1251            1 :             t2in.sin_family = AF_INET;
    1252            1 :             t2in.sin_port = htons(rand());
    1253            1 :             uint32_t t2address((10 << 24)
    1254              :                           | (11 << 16)
    1255              :                           | (255 << 8)
    1256              :                           | 255);
    1257            1 :             t2in.sin_addr.s_addr = htonl(t2address);
    1258            1 :             addr::addr t2;
    1259            1 :             t2.set_ipv4(t2in);
    1260              : 
    1261            1 :             addr::addr_range range1;
    1262            1 :             range1.set_from(f1);
    1263            1 :             range1.set_to(t1);
    1264              : 
    1265            1 :             addr::addr_range range2;
    1266            1 :             range2.set_from(f2);
    1267            1 :             range2.set_to(t2);
    1268              : 
    1269            1 :             CATCH_REQUIRE(range1.is_range());
    1270            1 :             CATCH_REQUIRE_FALSE(range1.is_empty());
    1271            1 :             CATCH_REQUIRE(range2.is_range());
    1272            1 :             CATCH_REQUIRE_FALSE(range2.is_empty());
    1273              : 
    1274              :             // the intersection is going to be empty (nothing overlaps)
    1275              :             //
    1276            1 :             addr::addr_range const range3(range1.intersection(range2));
    1277              : 
    1278            1 :             CATCH_REQUIRE(range3.is_range());
    1279            1 :             CATCH_REQUIRE(range3.is_empty());
    1280              : 
    1281              :             // the union works as expected
    1282              :             //
    1283            1 :             addr::addr_range const range4(range1.union_if_possible(range2));
    1284              : 
    1285            1 :             CATCH_REQUIRE(range4.is_range());
    1286            1 :             CATCH_REQUIRE_FALSE(range4.is_empty());
    1287              : 
    1288            1 :             CATCH_REQUIRE(range4.get_from().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.1.0.0");
    1289            1 :             CATCH_REQUIRE(range4.get_to().to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.11.255.255");
    1290            1 :         }
    1291            3 :         CATCH_END_SECTION()
    1292              : 
    1293            3 :         CATCH_START_SECTION("addr_range: union two ranges that do not overlap")
    1294              :         {
    1295              :             // from 10.1.0.0
    1296            1 :             struct sockaddr_in f1in = sockaddr_in();
    1297            1 :             f1in.sin_family = AF_INET;
    1298            1 :             int const f1port(rand() & 0xFFFF);
    1299            1 :             f1in.sin_port = htons(f1port);
    1300            1 :             uint32_t const f1address((10 << 24)
    1301              :                           | (1 << 16)
    1302              :                           | (0 << 8)
    1303              :                           | 0);
    1304            1 :             f1in.sin_addr.s_addr = htonl(f1address);
    1305            1 :             addr::addr f1;
    1306            1 :             f1.set_ipv4(f1in);
    1307              : 
    1308              :             // to 10.1.0.255
    1309            1 :             struct sockaddr_in t1in = sockaddr_in();
    1310            1 :             t1in.sin_family = AF_INET;
    1311            1 :             int const t1port(rand() & 0xFFFF);
    1312            1 :             t1in.sin_port = htons(t1port);
    1313            1 :             uint32_t const t1address((10 << 24)
    1314              :                           | (1 << 16)
    1315              :                           | (0 << 8)
    1316              :                           | 255);
    1317            1 :             t1in.sin_addr.s_addr = htonl(t1address);
    1318            1 :             addr::addr t1;
    1319            1 :             t1.set_ipv4(t1in);
    1320              : 
    1321              :             // from 10.10.0.0
    1322            1 :             struct sockaddr_in f2in = sockaddr_in();
    1323            1 :             f2in.sin_family = AF_INET;
    1324            1 :             int const f2port(rand() & 0xFFFF);
    1325            1 :             f2in.sin_port = htons(f2port);
    1326            1 :             uint32_t const f2address((10 << 24)
    1327              :                           | (10 << 16)
    1328              :                           | (0 << 8)
    1329              :                           | 0);
    1330            1 :             f2in.sin_addr.s_addr = htonl(f2address);
    1331            1 :             addr::addr f2;
    1332            1 :             f2.set_ipv4(f2in);
    1333              : 
    1334              :             // to 10.10.1.255
    1335            1 :             struct sockaddr_in t2in = sockaddr_in();
    1336            1 :             t2in.sin_family = AF_INET;
    1337            1 :             int const t2port(rand() & 0xFFFF);
    1338            1 :             t2in.sin_port = htons(t2port);
    1339            1 :             uint32_t const t2address((10 << 24)
    1340              :                           | (10 << 16)
    1341              :                           | (1 << 8)
    1342              :                           | 255);
    1343            1 :             t2in.sin_addr.s_addr = htonl(t2address);
    1344            1 :             addr::addr t2;
    1345            1 :             t2.set_ipv4(t2in);
    1346              : 
    1347            1 :             addr::addr_range range1;
    1348            1 :             range1.set_from(f1);
    1349            1 :             range1.set_to(t1);
    1350              : 
    1351            1 :             addr::addr_range range2;
    1352            1 :             range2.set_from(f2);
    1353            1 :             range2.set_to(t2);
    1354              : 
    1355            1 :             CATCH_REQUIRE(range1.is_range());
    1356            1 :             CATCH_REQUIRE_FALSE(range1.is_empty());
    1357            1 :             CATCH_REQUIRE(range2.is_range());
    1358            1 :             CATCH_REQUIRE_FALSE(range2.is_empty());
    1359              : 
    1360            1 :             addr::addr_range const range3(range1.union_if_possible(range2));
    1361              : 
    1362            1 :             CATCH_REQUIRE_FALSE(range3.is_range());
    1363            1 :             CATCH_REQUIRE_FALSE(range3.is_empty());
    1364              : 
    1365            1 :             std::string vec_result;
    1366            1 :             std::string vec_result_ip_only;
    1367              :             {
    1368            1 :                 std::stringstream ss;
    1369            1 :                 ss << range1;
    1370            1 :                 std::string const range1_result("10.1.0.0-10.1.0.255:" + std::to_string(t1port) + "/32");
    1371            1 :                 CATCH_REQUIRE(ss.str() == range1_result);
    1372            1 :                 vec_result += range1_result;
    1373            1 :                 vec_result_ip_only += "10.1.0.0-10.1.0.255";
    1374            1 :             }
    1375              :             {
    1376            1 :                 std::stringstream ss;
    1377            1 :                 ss << range2;
    1378            1 :                 std::string const range2_result("10.10.0.0-10.10.1.255:" + std::to_string(t2port) + "/32");
    1379            1 :                 CATCH_REQUIRE(ss.str() == range2_result);
    1380            1 :                 vec_result += ',';
    1381            1 :                 vec_result += range2_result;
    1382            1 :                 vec_result_ip_only += ',';
    1383            1 :                 vec_result_ip_only += "10.10.0.0-10.10.1.255";
    1384            1 :             }
    1385              :             {
    1386            1 :                 std::stringstream ss;
    1387            1 :                 ss << addr::setaddrmode(addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK) << range3;
    1388            3 :                 std::string const range3_result("<empty address range>");
    1389            1 :                 CATCH_REQUIRE(ss.str() == range3_result);
    1390            1 :                 vec_result += ',';
    1391            1 :                 vec_result += range3_result;
    1392            1 :                 vec_result_ip_only += ',';
    1393            1 :                 vec_result_ip_only += "<empty address range>";
    1394            1 :             }
    1395              :             {
    1396            6 :                 addr::addr_range::vector_t vec{ range1, range2, range3 };
    1397            1 :                 std::stringstream ss;
    1398            1 :                 ss << vec;
    1399            1 :                 CATCH_REQUIRE(ss.str() == vec_result);
    1400              : 
    1401            1 :                 std::stringstream sm;
    1402            1 :                 sm << addr::setaddrmode(addr::STRING_IP_ADDRESS) << vec;
    1403            1 :                 CATCH_REQUIRE(sm.str() == vec_result_ip_only);
    1404              : 
    1405            1 :                 addr::addr::vector_t all_addresses(addr::addr_range::to_addresses(vec, 1000));
    1406              : 
    1407              :                 // the first 256 are 10.1.0.0 to 10.1.0.255
    1408              :                 //
    1409          257 :                 for(int idx(0); idx < 256; ++idx)
    1410              :                 {
    1411          256 :                     struct sockaddr_in v1in = sockaddr_in();
    1412          256 :                     v1in.sin_family = AF_INET;
    1413          256 :                     int const v1port(rand() & 0xFFFF);
    1414          256 :                     v1in.sin_port = htons(v1port);
    1415          256 :                     uint32_t const v1address((10 << 24)
    1416              :                                   | (1 << 16)
    1417              :                                   | (0 << 8)
    1418          256 :                                   | idx);
    1419          256 :                     v1in.sin_addr.s_addr = htonl(v1address);
    1420          256 :                     addr::addr v1;
    1421          256 :                     v1.set_ipv4(v1in);
    1422              : 
    1423          256 :                     CATCH_REQUIRE(all_addresses[idx] == v1);
    1424          256 :                 }
    1425              : 
    1426              :                 // the following 512 are 10.10.0.0 to 10.10.1.255
    1427              :                 //
    1428          513 :                 for(int idx(0); idx < 512; ++idx)
    1429              :                 {
    1430          512 :                     struct sockaddr_in v2in = sockaddr_in();
    1431          512 :                     v2in.sin_family = AF_INET;
    1432          512 :                     int const v2port(rand() & 0xFFFF);
    1433          512 :                     v2in.sin_port = htons(v2port);
    1434          512 :                     uint32_t const v2address((10 << 24)
    1435              :                                   | (10 << 16)
    1436              :                                   | (0 << 8)
    1437          512 :                                   | idx);       // this one leaks in the next as expected
    1438          512 :                     v2in.sin_addr.s_addr = htonl(v2address);
    1439          512 :                     addr::addr v2;
    1440          512 :                     v2.set_ipv4(v2in);
    1441              : 
    1442          512 :                     CATCH_REQUIRE(all_addresses[idx + 256] == v2);
    1443          512 :                 }
    1444              : 
    1445            6 :                 CATCH_REQUIRE_THROWS_MATCHES(
    1446              :                           addr::addr_range::to_addresses(vec, 256 + 512 - 1)
    1447              :                         , addr::out_of_range
    1448              :                         , Catch::Matchers::ExceptionMessage(
    1449              :                                   "out_of_range: too many addresses in this range: 768 > 767"));
    1450            1 :             }
    1451            1 :         }
    1452            3 :         CATCH_END_SECTION()
    1453           19 :     }
    1454              : 
    1455           19 :     CATCH_GIVEN("addr_range() create address with CIDR")
    1456              :     {
    1457            4 :         CATCH_START_SECTION("addr_range: to_cidr() without ranges")
    1458              :         {
    1459            1 :             addr::addr_range r;
    1460            1 :             addr::addr a;
    1461            1 :             CATCH_REQUIRE_FALSE(r.to_cidr(a));
    1462            1 :         }
    1463            4 :         CATCH_END_SECTION()
    1464              : 
    1465            4 :         CATCH_START_SECTION("addr_range: valid network range /16")
    1466              :         {
    1467              :             // from 192.168.0.0
    1468            1 :             struct sockaddr_in fin = sockaddr_in();
    1469            1 :             fin.sin_family = AF_INET;
    1470            1 :             int const fport(rand() & 0xFFFF);
    1471            1 :             fin.sin_port = htons(fport);
    1472            1 :             uint32_t const faddress((192 << 24)
    1473              :                           | (168 << 16)
    1474              :                           | (0 << 8)
    1475              :                           | 0);
    1476            1 :             fin.sin_addr.s_addr = htonl(faddress);
    1477            1 :             addr::addr f;
    1478            1 :             f.set_ipv4(fin);
    1479            1 :             f.set_mask_count(128 - 16);
    1480              : 
    1481              :             // to 192.168.255.255
    1482            1 :             addr::addr t(f);
    1483            1 :             t.apply_mask(true);
    1484              : 
    1485            1 :             addr::addr_range r;
    1486            1 :             r.set_from(f);
    1487            1 :             r.set_to(t);
    1488              : 
    1489            1 :             CATCH_REQUIRE(r.is_defined());
    1490            1 :             CATCH_REQUIRE(r.is_range());
    1491              : 
    1492            1 :             addr::addr a;
    1493            1 :             CATCH_REQUIRE(r.to_cidr(a));
    1494            1 :             CATCH_REQUIRE(a.ip_to_uint128() == f.ip_to_uint128());
    1495            1 :             CATCH_REQUIRE(a.get_mask_size() == 128 - 16);
    1496            1 :         }
    1497            4 :         CATCH_END_SECTION()
    1498              : 
    1499            4 :         CATCH_START_SECTION("addr_range: valid network range /24")
    1500              :         {
    1501              :             // from 10.0.0.0
    1502            1 :             struct sockaddr_in fin = sockaddr_in();
    1503            1 :             fin.sin_family = AF_INET;
    1504            1 :             int const fport(rand() & 0xFFFF);
    1505            1 :             fin.sin_port = htons(fport);
    1506            1 :             uint32_t const faddress((10 << 24)
    1507              :                           | (0 << 16)
    1508              :                           | (0 << 8)
    1509              :                           | 0);
    1510            1 :             fin.sin_addr.s_addr = htonl(faddress);
    1511            1 :             addr::addr f;
    1512            1 :             f.set_ipv4(fin);
    1513            1 :             f.set_mask_count(128 - 24);
    1514              : 
    1515              :             // to 10.255.255.255
    1516            1 :             addr::addr t(f);
    1517            1 :             t.apply_mask(true);
    1518              : 
    1519            1 :             addr::addr_range r;
    1520            1 :             r.set_from(f);
    1521            1 :             r.set_to(t);
    1522              : 
    1523            1 :             CATCH_REQUIRE(r.is_defined());
    1524            1 :             CATCH_REQUIRE(r.is_range());
    1525              : 
    1526            1 :             addr::addr a;
    1527            1 :             CATCH_REQUIRE(r.to_cidr(a));
    1528            1 :             CATCH_REQUIRE(a.ip_to_uint128() == f.ip_to_uint128());
    1529            1 :             CATCH_REQUIRE(a.get_mask_size() == 128 - 24);
    1530            1 :         }
    1531            4 :         CATCH_END_SECTION()
    1532              : 
    1533            4 :         CATCH_START_SECTION("addr_range: valid network range but not for a cidr")
    1534              :         {
    1535            1 :             int const port(rand() & 0xFFFF);
    1536              : 
    1537              :             // from 10.0.0.0
    1538            1 :             struct sockaddr_in fin = sockaddr_in();
    1539            1 :             fin.sin_family = AF_INET;
    1540            1 :             fin.sin_port = htons(port);
    1541            1 :             std::uint32_t const faddress((10 << 24)
    1542              :                           | (0 << 16)
    1543              :                           | (0 << 8)
    1544              :                           | 0);
    1545            1 :             fin.sin_addr.s_addr = htonl(faddress);
    1546            1 :             addr::addr f;
    1547            1 :             f.set_ipv4(fin);
    1548            1 :             f.set_mask_count(128 - 24);
    1549              : 
    1550              :             // to 10.255.255.255
    1551            1 :             struct sockaddr_in tin = sockaddr_in();
    1552            1 :             tin.sin_family = AF_INET;
    1553            1 :             tin.sin_port = htons(port);
    1554            1 :             std::uint32_t const taddress((10 << 24)
    1555              :                           | (205 << 16)
    1556              :                           | (111 << 8)
    1557              :                           | 64);
    1558            1 :             tin.sin_addr.s_addr = htonl(taddress);
    1559            1 :             addr::addr t;
    1560            1 :             t.set_ipv4(tin);
    1561              : 
    1562            1 :             addr::addr_range r;
    1563            1 :             r.set_from(f);
    1564            1 :             r.set_to(t);
    1565              : 
    1566            1 :             CATCH_REQUIRE(r.is_defined());
    1567            1 :             CATCH_REQUIRE(r.is_range());
    1568              : 
    1569            1 :             addr::addr a;
    1570            1 :             CATCH_REQUIRE_FALSE(r.to_cidr(a));
    1571            1 :         }
    1572            4 :         CATCH_END_SECTION()
    1573           19 :     }
    1574              : 
    1575           19 :     CATCH_GIVEN("addr_range() optimize address with CIDR")
    1576              :     {
    1577            1 :         CATCH_START_SECTION("addr_range: optimize IPv4 addresses")
    1578              :         {
    1579            1 :             addr::addr::vector_t list;
    1580              : 
    1581              :             // from 192.168.0.0
    1582            1 :             struct sockaddr_in fin = sockaddr_in();
    1583            1 :             fin.sin_family = AF_INET;
    1584            1 :             int const fport(rand() & 0xFFFF);
    1585            1 :             fin.sin_port = htons(fport);
    1586            1 :             uint32_t const faddress((192 << 24)
    1587              :                           | (168 << 16)
    1588              :                           | (45 << 8)
    1589              :                           | 3);
    1590            1 :             fin.sin_addr.s_addr = htonl(faddress);
    1591            1 :             addr::addr f;
    1592            1 :             f.set_ipv4(fin);
    1593            1 :             list.push_back(f);
    1594            1 :             int final_mask_size(0);
    1595            6 :             for(int count(0); count < 5; ++count)
    1596              :             {
    1597            5 :                 int const mask_size(rand() % 32);
    1598            5 :                 if(mask_size > final_mask_size)
    1599              :                 {
    1600            2 :                     final_mask_size = mask_size;
    1601              :                 }
    1602            5 :                 addr::addr a(f);
    1603            5 :                 a.set_mask_count(128 - mask_size);
    1604            5 :                 a.apply_mask();
    1605            5 :                 list.push_back(a);
    1606            5 :             }
    1607              : 
    1608            1 :             CATCH_REQUIRE(addr::optimize_vector(list));
    1609            1 :             CATCH_REQUIRE(list.size() == 1);
    1610            1 :             CATCH_REQUIRE(list[0].get_mask_size() == 128 - final_mask_size);
    1611            1 :         }
    1612            1 :         CATCH_END_SECTION()
    1613           19 :     }
    1614           20 : }
    1615              : 
    1616              : 
    1617              : 
    1618              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions