LCOV - code coverage report
Current view: top level - tests - catch_range.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 896 896 100.0 %
Date: 2022-06-26 14:27:46 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2022  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          16 : CATCH_TEST_CASE("ipv4::range", "[ipv4]")
      63             : {
      64          28 :     CATCH_GIVEN("addr_range()")
      65             :     {
      66          18 :         addr::addr_range range;
      67             : 
      68          18 :         CATCH_START_SECTION("addr_range: verify defaults")
      69             :         {
      70           2 :             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           2 :             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             :         }
      90             :         CATCH_END_SECTION()
      91             : 
      92          18 :         CATCH_START_SECTION("addr_range: test normal range (from <= to)")
      93             :         {
      94           2 :             addr::addr a;
      95           2 :             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           2 :             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           2 :             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           2 :                 std::stringstream ss;
     167           1 :                 ss << range;
     168           1 :                 CATCH_REQUIRE(ss.str() == "10.0.0.1:" + std::to_string(fport) + "/32");
     169             : 
     170           2 :                 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             :             }
     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           2 :                 std::stringstream ss1;
     199           1 :                 ss1 << range;
     200           1 :                 CATCH_REQUIRE(ss1.str() == "-10.0.0.1:" + std::to_string(fport) + "/32");
     201             : 
     202           2 :                 std::stringstream ss2;
     203           1 :                 ss2 << addr::setaddrmode(addr::string_ip_t::STRING_IP_ONLY) << range;
     204           1 :                 CATCH_REQUIRE(ss2.str() == "-10.0.0.1");
     205             : 
     206           2 :                 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             :             }
     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           2 :                 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             :             }
     240             : 
     241           2 :             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           2 :                 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           2 :                 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             :             }
     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           2 :                 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             :             }
     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          20 :                 addr::addr b;
     301          10 :                 b.set_ipv4(bin);
     302             : 
     303          10 :                 CATCH_REQUIRE_FALSE(range.is_in(b));
     304             :             }
     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           2 :                 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             :             }
     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          20 :                 addr::addr after;
     335          10 :                 after.set_ipv4(ain);
     336             : 
     337          10 :                 CATCH_REQUIRE_FALSE(range.is_in(after));
     338             :             }
     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         508 :                 addr::addr i;
     353         254 :                 i.set_ipv4(iin);
     354             : 
     355         254 :                 CATCH_REQUIRE(range.is_in(i));
     356             :             }
     357             : 
     358             :             // range to vector of IPs addresses
     359             :             //
     360           2 :             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         508 :                 addr::addr e;
     373         254 :                 e.set_ipv4(ein);
     374         254 :                 CATCH_REQUIRE(vec.front() == e);
     375         254 :                 vec.erase(vec.begin());
     376             :             }
     377             :             // same, but use a limit so we get only the first 10 IPs
     378           1 :             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             :         }
     384             :         CATCH_END_SECTION()
     385             : 
     386          18 :         CATCH_START_SECTION("addr_range: test empty range (from > to)")
     387             :         {
     388           2 :             addr::addr a;
     389           2 :             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           2 :             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           2 :             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           2 :                 std::stringstream ss;
     455           1 :                 ss << range;
     456           1 :                 CATCH_REQUIRE(ss.str() == "10.0.0.254:" + std::to_string(fport) + "/32");
     457             :             }
     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           2 :                 std::stringstream ss;
     478           1 :                 ss << range;
     479           1 :                 CATCH_REQUIRE(ss.str() == "<empty address range>");
     480             :             }
     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           2 :                 addr::addr b;
     493           1 :                 b.set_ipv4(bin);
     494             : 
     495           1 :                 CATCH_REQUIRE_FALSE(range.is_in(b));
     496             :             }
     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          20 :                 addr::addr b;
     509          10 :                 b.set_ipv4(bin);
     510             : 
     511          10 :                 CATCH_REQUIRE_FALSE(range.is_in(b));
     512             :             }
     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           2 :                 addr::addr after;
     525           1 :                 after.set_ipv4(ain);
     526             : 
     527           1 :                 CATCH_REQUIRE_FALSE(range.is_in(after));
     528             :             }
     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          20 :                 addr::addr after;
     541          10 :                 after.set_ipv4(ain);
     542             : 
     543          10 :                 CATCH_REQUIRE_FALSE(range.is_in(after));
     544             :             }
     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         200 :                 addr::addr i;
     559         100 :                 i.set_ipv4(iin);
     560             : 
     561         100 :                 CATCH_REQUIRE_FALSE(range.is_in(i));
     562             :             }
     563             :         }
     564             :         CATCH_END_SECTION()
     565             : 
     566          18 :         CATCH_START_SECTION("addr_range: compare \"from\" ranges against each other")
     567             :         {
     568           2 :             addr::addr a;
     569           2 :             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             :         }
     609             :         CATCH_END_SECTION()
     610             : 
     611          18 :         CATCH_START_SECTION("addr_range: compare \"to\" ranges against each other")
     612             :         {
     613           2 :             addr::addr a;
     614           2 :             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             :         }
     654             :         CATCH_END_SECTION()
     655             : 
     656          18 :         CATCH_START_SECTION("addr_range: compare \"from\" against \"to\" ranges")
     657             :         {
     658           2 :             addr::addr a;
     659           2 :             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             :         }
     699             :         CATCH_END_SECTION()
     700             : 
     701          18 :         CATCH_START_SECTION("addr_range: compare full ranges (\"from\" and \"to\" defined)")
     702             :         {
     703           2 :             addr::addr a;
     704           2 :             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             :         }
     779             :         CATCH_END_SECTION()
     780             : 
     781          18 :         CATCH_START_SECTION("addr_range: compare mixed IPs")
     782             :         {
     783           2 :             addr::addr a;
     784           2 :             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             :         }
     821             :         CATCH_END_SECTION()
     822             : 
     823          18 :         CATCH_START_SECTION("addr_range: create range from CIDR")
     824             :         {
     825           2 :             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           1 :                 do
     883             :                 {
     884          17 :                     invalid_mask[i] = rand();
     885             :                 }
     886          17 :                 while(invalid_mask[i] == 0 || invalid_mask[i] == 0xFF);
     887             :             }
     888           1 :             a.set_mask(invalid_mask);
     889           1 :             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             :         }
     895             :         CATCH_END_SECTION()
     896             :     }
     897             : 
     898          28 :     CATCH_GIVEN("compute intersection of two ranges")
     899             :     {
     900           4 :         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           2 :             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           2 :             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           2 :             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           2 :             addr::addr t2;
     948           1 :             t2.set_ipv4(t2in);
     949             : 
     950           2 :             addr::addr_range range1;
     951           1 :             range1.set_from(f1);
     952           1 :             range1.set_to(t1);
     953             : 
     954           2 :             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           2 :             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_t::STRING_IP_ONLY) == "10.2.0.0");
     969           1 :             CATCH_REQUIRE(range3.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
     970             :         }
     971             :         CATCH_END_SECTION()
     972             : 
     973           4 :         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           2 :             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           2 :             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           2 :             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           2 :             addr::addr t2;
    1021           1 :             t2.set_ipv4(t2in);
    1022             : 
    1023           2 :             addr::addr_range range1;
    1024           1 :             range1.set_from(f1);
    1025           1 :             range1.set_to(t1);
    1026             : 
    1027           2 :             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           2 :             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_t::STRING_IP_ONLY) == "10.10.0.0");
    1044           1 :             CATCH_REQUIRE(range3.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
    1045             : 
    1046           2 :             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             :         }
    1054             :         CATCH_END_SECTION()
    1055             :     }
    1056             : 
    1057          28 :     CATCH_GIVEN("check for union of two ranges")
    1058             :     {
    1059           6 :         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           2 :             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           2 :             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           2 :             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           2 :             addr::addr t2;
    1107           1 :             t2.set_ipv4(t2in);
    1108             : 
    1109           2 :             addr::addr_range range1;
    1110           2 :             addr::addr_range range2;
    1111             : 
    1112             :             {
    1113           2 :                 addr::addr_range const r(range1.union_if_possible(range2));
    1114           1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1115             :             }
    1116             :             {
    1117           2 :                 addr::addr_range const r(range2.union_if_possible(range1));
    1118           1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1119             :             }
    1120             : 
    1121           1 :             range1.set_from(f1);
    1122             : 
    1123             :             {
    1124           2 :                 addr::addr_range const r(range1.union_if_possible(range2));
    1125           1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1126             :             }
    1127             :             {
    1128           2 :                 addr::addr_range const r(range2.union_if_possible(range1));
    1129           1 :                 CATCH_REQUIRE_FALSE(r.is_defined());
    1130             :             }
    1131             :             {
    1132           2 :                 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_t::STRING_IP_ONLY) == "10.1.0.0");
    1139             :             }
    1140             : 
    1141           1 :             range2.set_from(f2);
    1142             : 
    1143             :             {
    1144           2 :                 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             :             }
    1151             :             {
    1152           2 :                 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             :             }
    1159             : 
    1160           1 :             range1.set_to(t1);
    1161             : 
    1162             :             {
    1163           2 :                 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_t::STRING_IP_ONLY) == "10.1.0.0");
    1170           1 :                 CATCH_REQUIRE(r.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
    1171             :             }
    1172             :             {
    1173           2 :                 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_t::STRING_IP_ONLY) == "10.1.0.0");
    1180           1 :                 CATCH_REQUIRE(r.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
    1181             :             }
    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           2 :                 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_t::STRING_IP_ONLY) == "10.1.0.0");
    1201           1 :                 CATCH_REQUIRE(r.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "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             :             }
    1208             :         }
    1209             :         CATCH_END_SECTION()
    1210             : 
    1211           6 :         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           2 :             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           2 :             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           2 :             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           2 :             addr::addr t2;
    1259           1 :             t2.set_ipv4(t2in);
    1260             : 
    1261           2 :             addr::addr_range range1;
    1262           1 :             range1.set_from(f1);
    1263           1 :             range1.set_to(t1);
    1264             : 
    1265           2 :             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           2 :             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           2 :             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_t::STRING_IP_ONLY) == "10.1.0.0");
    1289           1 :             CATCH_REQUIRE(range4.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.11.255.255");
    1290             :         }
    1291             :         CATCH_END_SECTION()
    1292             : 
    1293           6 :         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           2 :             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           2 :             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           2 :             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           2 :             addr::addr t2;
    1345           1 :             t2.set_ipv4(t2in);
    1346             : 
    1347           2 :             addr::addr_range range1;
    1348           1 :             range1.set_from(f1);
    1349           1 :             range1.set_to(t1);
    1350             : 
    1351           2 :             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           2 :             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           2 :             std::string vec_result;
    1366           2 :             std::string vec_result_ip_only;
    1367             :             {
    1368           2 :                 std::stringstream ss;
    1369           1 :                 ss << range1;
    1370           2 :                 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             :             }
    1375             :             {
    1376           2 :                 std::stringstream ss;
    1377           1 :                 ss << range2;
    1378           2 :                 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             :             }
    1385             :             {
    1386           2 :                 std::stringstream ss;
    1387           1 :                 ss << addr::setaddrmode(addr::string_ip_t::STRING_IP_MASK) << range3;
    1388           2 :                 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             :             }
    1395             :             {
    1396           2 :                 addr::addr_range::vector_t vec{ range1, range2, range3 };
    1397           2 :                 std::stringstream ss;
    1398           1 :                 ss << vec;
    1399           1 :                 CATCH_REQUIRE(ss.str() == vec_result);
    1400             : 
    1401           2 :                 std::stringstream sm;
    1402           1 :                 sm << addr::setaddrmode(addr::string_ip_t::STRING_IP_ONLY) << vec;
    1403           1 :                 CATCH_REQUIRE(sm.str() == vec_result_ip_only);
    1404             : 
    1405           2 :                 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         512 :                     addr::addr v1;
    1421         256 :                     v1.set_ipv4(v1in);
    1422             : 
    1423         256 :                     CATCH_REQUIRE(all_addresses[idx] == v1);
    1424             :                 }
    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        1024 :                     addr::addr v2;
    1440         512 :                     v2.set_ipv4(v2in);
    1441             : 
    1442         512 :                     CATCH_REQUIRE(all_addresses[idx + 256] == v2);
    1443             :                 }
    1444             : 
    1445           1 :                 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             :             }
    1451             :         }
    1452             :         CATCH_END_SECTION()
    1453             :     }
    1454          20 : }
    1455             : 
    1456             : 
    1457             : 
    1458             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13