LCOV - code coverage report
Current view: top level - tests - catch_unix.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 99.7 % 739 737
Test Date: 2025-04-18 08:03:11 Functions: 100.0 % 7 7
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 Test the Unix address.
      34              :  *
      35              :  * These tests verify that the Unix address functions as expected.
      36              :  */
      37              : 
      38              : // addr
      39              : //
      40              : #include    <libaddr/addr_unix.h>
      41              : 
      42              : 
      43              : // self
      44              : //
      45              : #include    "catch_main.h"
      46              : 
      47              : 
      48              : // libutf8
      49              : //
      50              : #include    <libutf8/libutf8.h>
      51              : #include    <libutf8/exception.h>
      52              : 
      53              : 
      54              : // snapdev
      55              : //
      56              : #include    <snapdev/raii_generic_deleter.h>
      57              : 
      58              : 
      59              : // C
      60              : //
      61              : #include    <sys/stat.h>
      62              : 
      63              : 
      64              : // last include
      65              : //
      66              : #include    <snapdev/poison.h>
      67              : 
      68              : 
      69              : 
      70              : 
      71              : 
      72              : 
      73              : 
      74            5 : CATCH_TEST_CASE("addr_unix::unnamed", "[addr_unix]")
      75              : {
      76            5 :     CATCH_START_SECTION("addr_unix::unnamed: addr_unix() defaults (a.k.a. unnamed address)")
      77              :     {
      78            1 :         addr::addr_unix u;
      79              : 
      80            1 :         CATCH_REQUIRE_FALSE(u.is_file());
      81            1 :         CATCH_REQUIRE_FALSE(u.is_abstract());
      82            1 :         CATCH_REQUIRE(u.is_unnamed());
      83            1 :         CATCH_REQUIRE(u.to_string() == std::string());
      84            1 :         CATCH_REQUIRE(u.to_uri() == "unix:");
      85              : 
      86            1 :         sockaddr_un un;
      87            1 :         u.get_un(un);
      88            1 :         CATCH_REQUIRE(un.sun_family == AF_UNIX);
      89          109 :         for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
      90              :         {
      91          108 :             CATCH_CHECK(un.sun_path[idx] == 0);
      92              :         }
      93            1 :     }
      94            5 :     CATCH_END_SECTION()
      95              : 
      96            5 :     CATCH_START_SECTION("addr_unix::unnamed: addr_unix() with an unnamed address")
      97              :     {
      98            1 :         sockaddr_un init = addr::init_un();
      99            1 :         CATCH_REQUIRE(init.sun_family == AF_UNIX);
     100          109 :         for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
     101              :         {
     102          108 :             CATCH_CHECK(init.sun_path[idx] == 0);
     103              :         }
     104              : 
     105            1 :         addr::addr_unix u(init);
     106              : 
     107            1 :         CATCH_REQUIRE_FALSE(u.is_file());
     108            1 :         CATCH_REQUIRE_FALSE(u.is_abstract());
     109            1 :         CATCH_REQUIRE(u.is_unnamed());
     110            1 :         CATCH_REQUIRE(u.to_string() == std::string());
     111            1 :         CATCH_REQUIRE(u.to_uri() == "unix:");
     112              : 
     113            1 :         sockaddr_un un;
     114            1 :         u.get_un(un);
     115            1 :         CATCH_REQUIRE(un.sun_family == AF_UNIX);
     116          109 :         for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
     117              :         {
     118          108 :             CATCH_CHECK(un.sun_path[idx] == 0);
     119              :         }
     120            1 :     }
     121            5 :     CATCH_END_SECTION()
     122              : 
     123            5 :     CATCH_START_SECTION("addr_unix::unnamed: addr_unix() with an unnamed string")
     124              :     {
     125            1 :         std::string no_name;
     126            1 :         addr::addr_unix u(no_name);
     127              : 
     128            1 :         CATCH_REQUIRE_FALSE(u.is_file());
     129            1 :         CATCH_REQUIRE_FALSE(u.is_abstract());
     130            1 :         CATCH_REQUIRE(u.is_unnamed());
     131            1 :         CATCH_REQUIRE(u.to_string() == std::string());
     132            1 :         CATCH_REQUIRE(u.to_uri() == "unix:");
     133              : 
     134            1 :         sockaddr_un un;
     135            1 :         u.get_un(un);
     136            1 :         CATCH_REQUIRE(un.sun_family == AF_UNIX);
     137          109 :         for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
     138              :         {
     139          108 :             CATCH_CHECK(un.sun_path[idx] == 0);
     140              :         }
     141            1 :     }
     142            5 :     CATCH_END_SECTION()
     143              : 
     144            5 :     CATCH_START_SECTION("addr_unix::unnamed: addr_unix() with a forced unnamed URI")
     145              :     {
     146            1 :         addr::addr_unix u;
     147              : 
     148            3 :         u.set_uri("unix:?unnamed");
     149              : 
     150            1 :         CATCH_REQUIRE_FALSE(u.is_file());
     151            1 :         CATCH_REQUIRE_FALSE(u.is_abstract());
     152            1 :         CATCH_REQUIRE(u.is_unnamed());
     153            1 :         CATCH_REQUIRE(u.to_string() == std::string());
     154            1 :         CATCH_REQUIRE(u.to_uri() == "unix:");
     155            1 :         CATCH_REQUIRE(u.unlink() == 0);
     156              : 
     157            1 :         sockaddr_un un;
     158            1 :         u.get_un(un);
     159            1 :         CATCH_REQUIRE(un.sun_family == AF_UNIX);
     160          109 :         for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
     161              :         {
     162          108 :             CATCH_CHECK(un.sun_path[idx] == 0);
     163              :         }
     164            1 :     }
     165            5 :     CATCH_END_SECTION()
     166              : 
     167            5 :     CATCH_START_SECTION("addr_unix::unnamed: addr_unix() with an unnamed which we re-collect from socket")
     168              :     {
     169            1 :         sockaddr_un un;
     170              : 
     171            1 :         addr::addr_unix u;
     172              : 
     173            1 :         CATCH_REQUIRE_FALSE(u.is_file());
     174            1 :         CATCH_REQUIRE_FALSE(u.is_abstract());
     175            1 :         CATCH_REQUIRE(u.is_unnamed());
     176            1 :         CATCH_REQUIRE(u.to_string() == std::string());
     177            1 :         CATCH_REQUIRE(u.to_uri() == "unix:");
     178              : 
     179            1 :         u.get_un(un);
     180            1 :         CATCH_REQUIRE(un.sun_family == AF_UNIX);
     181          109 :         for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
     182              :         {
     183          108 :             CATCH_CHECK(un.sun_path[idx] == 0);
     184              :         }
     185              : 
     186            1 :         snapdev::raii_fd_t s(socket(AF_UNIX, SOCK_STREAM, 0));
     187            1 :         CATCH_REQUIRE(s != nullptr);
     188              : 
     189              :         // unnamed sockets are unbound...
     190              : 
     191            1 :         addr::addr_unix retrieve;
     192            1 :         retrieve.set_from_socket(s.get());
     193            1 :         CATCH_REQUIRE(retrieve == u);
     194            1 :     }
     195            5 :     CATCH_END_SECTION()
     196            5 : }
     197              : 
     198              : 
     199            7 : CATCH_TEST_CASE("addr_unix::file", "[addr_unix]")
     200              : {
     201            7 :     CATCH_START_SECTION("addr_unix::file: addr_unix() with a relative file name")
     202              :     {
     203           11 :         for(int count(0); count < 10; ++count)
     204              :         {
     205           30 :             std::string name("test");
     206           10 :             int const max(rand() % 5 + 3);
     207           60 :             for(int id(0); id < max; ++id)
     208              :             {
     209           50 :                 name += '0' + rand() % 10;
     210              :             }
     211              : 
     212              :             // verify the init_un() as we're at it
     213              :             //
     214           10 :             sockaddr_un init = addr::init_un();
     215           10 :             CATCH_REQUIRE(init.sun_family == AF_UNIX);
     216         1090 :             for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
     217              :             {
     218         1080 :                 CATCH_CHECK(init.sun_path[idx] == 0);
     219              :             }
     220           10 :             strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
     221              : 
     222           10 :             addr::addr_unix u(init);
     223              : 
     224           10 :             CATCH_REQUIRE(u.is_file());
     225           10 :             CATCH_REQUIRE_FALSE(u.is_abstract());
     226           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     227           10 :             CATCH_REQUIRE(u.to_string() == name);
     228           10 :             CATCH_REQUIRE(u.to_uri() == "unix:" + name);
     229              : 
     230           10 :             sockaddr_un un;
     231           10 :             u.get_un(un);
     232           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     233           10 :             CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
     234         1000 :             for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
     235              :             {
     236          990 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     237              :             }
     238           10 :         }
     239              :     }
     240            7 :     CATCH_END_SECTION()
     241              : 
     242            7 :     CATCH_START_SECTION("addr_unix::file: addr_unix() with a relative file name; string constructor")
     243              :     {
     244           11 :         for(int count(0); count < 10; ++count)
     245              :         {
     246           30 :             std::string name("test");
     247           10 :             int const max(rand() % 5 + 3);
     248           59 :             for(int id(0); id < max; ++id)
     249              :             {
     250           49 :                 name += '0' + rand() % 10;
     251              :             }
     252              : 
     253           10 :             addr::addr_unix u(name);
     254              : 
     255           10 :             CATCH_REQUIRE(u.is_file());
     256           10 :             CATCH_REQUIRE_FALSE(u.is_abstract());
     257           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     258           10 :             CATCH_REQUIRE(u.to_string() == name);
     259           10 :             CATCH_REQUIRE(u.to_uri() == "unix:" + name);
     260              : 
     261           10 :             sockaddr_un un;
     262           10 :             u.get_un(un);
     263           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     264           10 :             CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
     265         1001 :             for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
     266              :             {
     267          991 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     268              :             }
     269           10 :         }
     270              :     }
     271            7 :     CATCH_END_SECTION()
     272              : 
     273            7 :     CATCH_START_SECTION("addr_unix::file: addr_unix() with a relative file name using set_file()")
     274              :     {
     275            1 :         addr::addr_unix u;
     276              : 
     277           11 :         for(int count(0); count < 10; ++count)
     278              :         {
     279           30 :             std::string name("test");
     280           10 :             int const max(rand() % 25 + 3); // vary more to correctly verify that we clear the end of the buffer
     281          181 :             for(int id(0); id < max; ++id)
     282              :             {
     283          171 :                 name += '0' + rand() % 10;
     284              :             }
     285              : 
     286              :             // verify the init_un() as we're at it
     287              :             //
     288           10 :             sockaddr_un init = addr::init_un();
     289           10 :             CATCH_REQUIRE(init.sun_family == AF_UNIX);
     290         1090 :             for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
     291              :             {
     292         1080 :                 CATCH_CHECK(init.sun_path[idx] == 0);
     293              :             }
     294           10 :             strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
     295              : 
     296           10 :             u.set_file(name);
     297              : 
     298           10 :             CATCH_REQUIRE(u.is_file());
     299           10 :             CATCH_REQUIRE_FALSE(u.is_abstract());
     300           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     301           10 :             CATCH_REQUIRE(u.to_string() == name);
     302           10 :             CATCH_REQUIRE(u.to_uri() == "unix:" + name);
     303              : 
     304           10 :             sockaddr_un un;
     305           10 :             u.get_un(un);
     306           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     307           10 :             CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
     308          879 :             for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
     309              :             {
     310          869 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     311              :             }
     312           10 :         }
     313            1 :     }
     314            7 :     CATCH_END_SECTION()
     315              : 
     316            7 :     CATCH_START_SECTION("addr_unix::file: addr_unix() with a full file name")
     317              :     {
     318           11 :         for(int count(0); count < 10; ++count)
     319              :         {
     320           30 :             std::string name("/run/snapwebsites/sockets/test");
     321           10 :             int const max(rand() % 25 + 3);
     322          166 :             for(int id(0); id < max; ++id)
     323              :             {
     324          156 :                 name += '0' + rand() % 10;
     325              :             }
     326              : 
     327              :             // verify the init_un() as we're at it
     328              :             //
     329           10 :             sockaddr_un init = addr::init_un();
     330           10 :             CATCH_REQUIRE(init.sun_family == AF_UNIX);
     331         1090 :             for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
     332              :             {
     333         1080 :                 CATCH_CHECK(init.sun_path[idx] == 0);
     334              :             }
     335           10 :             strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
     336              : 
     337           10 :             addr::addr_unix u(init);
     338              : 
     339           10 :             CATCH_REQUIRE(u.is_file());
     340           10 :             CATCH_REQUIRE_FALSE(u.is_abstract());
     341           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     342           10 :             CATCH_REQUIRE(u.to_string() == name);
     343           10 :             CATCH_REQUIRE(u.to_uri() == "unix://" + name);
     344              : 
     345           10 :             sockaddr_un un;
     346           10 :             u.get_un(un);
     347           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     348           10 :             CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
     349          634 :             for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
     350              :             {
     351          624 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     352              :             }
     353           10 :         }
     354              :     }
     355            7 :     CATCH_END_SECTION()
     356              : 
     357            7 :     CATCH_START_SECTION("addr_unix::file: addr_unix() with a long file name")
     358              :     {
     359            1 :         sockaddr_un un;
     360          107 :         for(int count(1); count < static_cast<int>(sizeof(un.sun_path) - 1); ++count)
     361              :         {
     362          106 :             std::string name;
     363         5777 :             for(int id(0); id < count; ++id)
     364              :             {
     365         5671 :                 name += '0' + rand() % 10;
     366              :             }
     367              : 
     368          106 :             addr::addr_unix u(name);
     369              : 
     370          106 :             CATCH_REQUIRE(u.is_file());
     371          106 :             CATCH_REQUIRE_FALSE(u.is_abstract());
     372          106 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     373          106 :             CATCH_REQUIRE(u.to_string() == name);
     374          106 :             CATCH_REQUIRE(u.to_uri() == "unix:" + name);
     375              : 
     376          106 :             u.get_un(un);
     377          106 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     378          106 :             CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
     379         5883 :             for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
     380              :             {
     381         5777 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     382              :             }
     383          106 :         }
     384              :     }
     385            7 :     CATCH_END_SECTION()
     386              : 
     387            7 :     CATCH_START_SECTION("addr_unix::file: addr_unix() verify that file gets unlink()'ed")
     388              :     {
     389           11 :         for(int count(0); count < 10; ++count)
     390              :         {
     391           30 :             std::string name("test");
     392           10 :             int const max(rand() % 5 + 3);
     393           53 :             for(int id(0); id < max; ++id)
     394              :             {
     395           43 :                 name += '0' + rand() % 10;
     396              :             }
     397              : 
     398              :             // verify the init_un() as we're at it
     399              :             //
     400           10 :             addr::addr_unix u(name);
     401              : 
     402           30 :             std::string cmd("touch ");
     403           10 :             cmd += name;
     404           10 :             CATCH_REQUIRE(system(cmd.c_str()) == 0);
     405              : 
     406           10 :             struct stat s;
     407           10 :             CATCH_REQUIRE(stat(name.c_str(), &s) == 0);
     408              : 
     409           10 :             CATCH_REQUIRE(u.unlink() == 0);
     410              : 
     411           10 :             CATCH_REQUIRE(stat(name.c_str(), &s) != 0);
     412           10 :         }
     413              :     }
     414            7 :     CATCH_END_SECTION()
     415              : 
     416            7 :     CATCH_START_SECTION("addr_unix::file: addr_unix() with a file name which we re-collect from socket")
     417              :     {
     418            1 :         sockaddr_un un;
     419              : 
     420            3 :         std::string name("socket-test");
     421            1 :         int count(rand() % 5 + 3);
     422            4 :         for(int id(0); id < count; ++id)
     423              :         {
     424            3 :             name += '0' + rand() % 10;
     425              :         }
     426            1 :         unlink(name.c_str());
     427              : 
     428            1 :         addr::addr_unix u(name);
     429              : 
     430            1 :         CATCH_REQUIRE(u.is_file());
     431            1 :         CATCH_REQUIRE_FALSE(u.is_abstract());
     432            1 :         CATCH_REQUIRE_FALSE(u.is_unnamed());
     433            1 :         CATCH_REQUIRE(u.to_string() == name);
     434            1 :         CATCH_REQUIRE(u.to_uri() == "unix:" + name);
     435              : 
     436            1 :         u.get_un(un);
     437            1 :         CATCH_REQUIRE(un.sun_family == AF_UNIX);
     438            1 :         CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
     439           95 :         for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
     440              :         {
     441           94 :             CATCH_CHECK(un.sun_path[idx] == 0);
     442              :         }
     443              : 
     444            1 :         snapdev::raii_fd_t s(socket(AF_UNIX, SOCK_STREAM, 0));
     445            1 :         CATCH_REQUIRE(s != nullptr);
     446            1 :         sockaddr_un address;
     447            1 :         u.get_un(address);
     448            1 :         CATCH_REQUIRE(bind(s.get(), reinterpret_cast<sockaddr *>(&address), sizeof(address)) == 0);
     449              : 
     450            1 :         addr::addr_unix retrieve;
     451            1 :         retrieve.set_from_socket(s.get());
     452            1 :         CATCH_REQUIRE(retrieve == u);
     453            1 :     }
     454            7 :     CATCH_END_SECTION()
     455            7 : }
     456              : 
     457              : 
     458            6 : CATCH_TEST_CASE("addr_unix::abstract", "[addr_unix]")
     459              : {
     460            6 :     CATCH_START_SECTION("addr_unix::abstract: addr_unix() with a relative abstract name")
     461              :     {
     462           11 :         for(int count(0); count < 10; ++count)
     463              :         {
     464           30 :             std::string name("abstract/test");
     465           10 :             int const max(rand() % 25 + 3);
     466          129 :             for(int id(0); id < max; ++id)
     467              :             {
     468          119 :                 name += '0' + rand() % 10;
     469              :             }
     470              : 
     471              :             // verify the init_un() as we're at it
     472              :             //
     473           10 :             sockaddr_un init = addr::init_un();
     474           10 :             CATCH_REQUIRE(init.sun_family == AF_UNIX);
     475         1090 :             for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
     476              :             {
     477         1080 :                 CATCH_CHECK(init.sun_path[idx] == 0);
     478              :             }
     479           10 :             strncpy(init.sun_path + 1, name.c_str(), sizeof(init.sun_path) - 2);
     480              : 
     481           10 :             addr::addr_unix u(init);
     482              : 
     483           10 :             CATCH_REQUIRE_FALSE(u.is_file());
     484           10 :             CATCH_REQUIRE(u.is_abstract());
     485           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     486           10 :             CATCH_REQUIRE(u.to_string() == name);
     487           10 :             CATCH_REQUIRE(u.to_uri() == "unix:" + name + "?abstract");
     488           10 :             CATCH_REQUIRE(u.unlink() == 0);
     489              : 
     490           10 :             sockaddr_un un;
     491           10 :             u.get_un(un);
     492           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     493           10 :             CATCH_REQUIRE(un.sun_path[0] == '\0');
     494           10 :             CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
     495          831 :             for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
     496              :             {
     497          821 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     498              :             }
     499           10 :         }
     500              :     }
     501            6 :     CATCH_END_SECTION()
     502              : 
     503            6 :     CATCH_START_SECTION("addr_unix::abstract: addr_unix() with a relative abstract name with string constructor")
     504              :     {
     505           11 :         for(int count(0); count < 10; ++count)
     506              :         {
     507           30 :             std::string name("abstract/test");
     508           10 :             int const max(rand() % 25 + 3);
     509          197 :             for(int id(0); id < max; ++id)
     510              :             {
     511          187 :                 name += '0' + rand() % 10;
     512              :             }
     513              : 
     514           10 :             addr::addr_unix u(name, true);
     515              : 
     516           10 :             CATCH_REQUIRE_FALSE(u.is_file());
     517           10 :             CATCH_REQUIRE(u.is_abstract());
     518           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     519           10 :             CATCH_REQUIRE(u.to_string() == name);
     520           10 :             CATCH_REQUIRE(u.to_uri() == "unix:" + name + "?abstract");
     521              : 
     522           10 :             sockaddr_un un;
     523           10 :             u.get_un(un);
     524           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     525           10 :             CATCH_REQUIRE(un.sun_path[0] == '\0');
     526           10 :             CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
     527          763 :             for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
     528              :             {
     529          753 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     530              :             }
     531           10 :         }
     532              :     }
     533            6 :     CATCH_END_SECTION()
     534              : 
     535            6 :     CATCH_START_SECTION("addr_unix::abstract: addr_unix() with an abstract name using set_abstract()")
     536              :     {
     537            1 :         addr::addr_unix u;
     538              : 
     539           11 :         for(int count(0); count < 10; ++count)
     540              :         {
     541           30 :             std::string name("test");
     542           10 :             int const max(rand() % 25 + 3); // vary more to correctly verify that we clear the end of the buffer
     543          164 :             for(int id(0); id < max; ++id)
     544              :             {
     545          154 :                 name += '0' + rand() % 10;
     546              :             }
     547              : 
     548              :             // verify the init_un() as we're at it
     549              :             //
     550           10 :             sockaddr_un init = addr::init_un();
     551           10 :             CATCH_REQUIRE(init.sun_family == AF_UNIX);
     552         1090 :             for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
     553              :             {
     554         1080 :                 CATCH_CHECK(init.sun_path[idx] == 0);
     555              :             }
     556           10 :             strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
     557              : 
     558           10 :             u.set_abstract(name);
     559              : 
     560           10 :             CATCH_REQUIRE_FALSE(u.is_file());
     561           10 :             CATCH_REQUIRE(u.is_abstract());
     562           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     563           10 :             CATCH_REQUIRE(u.to_string() == name);
     564           10 :             CATCH_REQUIRE(u.to_uri() == "unix:" + name + "?abstract");
     565              : 
     566           10 :             sockaddr_un un;
     567           10 :             u.get_un(un);
     568           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     569           10 :             CATCH_REQUIRE(un.sun_path[0] == '\0');
     570           10 :             CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
     571          886 :             for(std::size_t idx(name.length() +1); idx < sizeof(un.sun_path); ++idx)
     572              :             {
     573          876 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     574              :             }
     575           10 :         }
     576            1 :     }
     577            6 :     CATCH_END_SECTION()
     578              : 
     579            6 :     CATCH_START_SECTION("addr_unix::abstract: addr_unix() with a full abstract name")
     580              :     {
     581           11 :         for(int count(0); count < 10; ++count)
     582              :         {
     583           30 :             std::string name("/net/snapwebsites/settings/test");
     584           10 :             int const max(rand() % 25 + 3);
     585          204 :             for(int id(0); id < max; ++id)
     586              :             {
     587          194 :                 name += '0' + rand() % 10;
     588              :             }
     589              : 
     590              :             // verify the init_un() as we're at it
     591              :             //
     592           10 :             sockaddr_un init = addr::init_un();
     593           10 :             CATCH_REQUIRE(init.sun_family == AF_UNIX);
     594         1090 :             for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
     595              :             {
     596         1080 :                 CATCH_CHECK(init.sun_path[idx] == 0);
     597              :             }
     598           10 :             strncpy(init.sun_path + 1, name.c_str(), sizeof(init.sun_path) - 2);
     599              : 
     600           10 :             addr::addr_unix u(init);
     601              : 
     602           10 :             CATCH_REQUIRE_FALSE(u.is_file());
     603           10 :             CATCH_REQUIRE(u.is_abstract());
     604           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     605           10 :             CATCH_REQUIRE(u.to_string() == name);
     606           10 :             CATCH_REQUIRE(u.to_uri() == "unix://" + name + "?abstract");
     607              : 
     608           10 :             sockaddr_un un;
     609           10 :             u.get_un(un);
     610           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     611           10 :             CATCH_REQUIRE(un.sun_path[0] == '\0');
     612           10 :             CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
     613          576 :             for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
     614              :             {
     615          566 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     616              :             }
     617           10 :         }
     618              :     }
     619            6 :     CATCH_END_SECTION()
     620              : 
     621            6 :     CATCH_START_SECTION("addr_unix::abstract: addr_unix() with a long abstract name")
     622              :     {
     623            1 :         sockaddr_un un;
     624          106 :         for(int count(1); count < static_cast<int>(sizeof(un.sun_path) - 2); ++count)
     625              :         {
     626          105 :             std::string name;
     627         5670 :             for(int id(0); id < count; ++id)
     628              :             {
     629         5565 :                 name += '0' + rand() % 10;
     630              :             }
     631              : 
     632          105 :             addr::addr_unix u(name, true);
     633              : 
     634          105 :             CATCH_REQUIRE_FALSE(u.is_file());
     635          105 :             CATCH_REQUIRE(u.is_abstract());
     636          105 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     637          105 :             CATCH_REQUIRE(u.to_string() == name);
     638          105 :             CATCH_REQUIRE(u.to_uri() == "unix:" + name + "?abstract");
     639              : 
     640          105 :             u.get_un(un);
     641          105 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     642          105 :             CATCH_REQUIRE(un.sun_path[0] == '\0');
     643          105 :             CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
     644         5775 :             for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
     645              :             {
     646         5670 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     647              :             }
     648          105 :         }
     649              :     }
     650            6 :     CATCH_END_SECTION()
     651              : 
     652            6 :     CATCH_START_SECTION("addr_unix::abstract: addr_unix() with an abstract name which we re-collect from socket")
     653              :     {
     654            1 :         sockaddr_un un;
     655              : 
     656            3 :         std::string name("/net/snapwebsites/test");
     657            1 :         int count(rand() % 5 + 3);
     658            7 :         for(int id(0); id < count; ++id)
     659              :         {
     660            6 :             name += '0' + rand() % 10;
     661              :         }
     662              : 
     663            1 :         addr::addr_unix u(name, true);
     664              : 
     665            1 :         CATCH_REQUIRE_FALSE(u.is_file());
     666            1 :         CATCH_REQUIRE(u.is_abstract());
     667            1 :         CATCH_REQUIRE_FALSE(u.is_unnamed());
     668            1 :         CATCH_REQUIRE(u.to_string() == name);
     669            1 :         CATCH_REQUIRE(u.to_uri() == "unix://" + name + "?abstract");
     670              : 
     671            1 :         u.get_un(un);
     672            1 :         CATCH_REQUIRE(un.sun_family == AF_UNIX);
     673            1 :         CATCH_REQUIRE(un.sun_path[0] == '\0');
     674            1 :         CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
     675           80 :         for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
     676              :         {
     677           79 :             CATCH_CHECK(un.sun_path[idx] == 0);
     678              :         }
     679              : 
     680            1 :         snapdev::raii_fd_t s(socket(AF_UNIX, SOCK_STREAM, 0));
     681            1 :         CATCH_REQUIRE(s != nullptr);
     682            1 :         sockaddr_un address;
     683            1 :         u.get_un(address);
     684            1 :         socklen_t const len(sizeof(address.sun_family) + 1 + strlen(address.sun_path + 1));
     685            1 :         CATCH_REQUIRE(bind(s.get(), reinterpret_cast<sockaddr *>(&address), len) == 0);
     686              : 
     687            1 :         addr::addr_unix retrieve;
     688            1 :         retrieve.set_from_socket(s.get());
     689            1 :         CATCH_REQUIRE(retrieve == u);
     690            1 :     }
     691            6 :     CATCH_END_SECTION()
     692            6 : }
     693              : 
     694              : 
     695            2 : CATCH_TEST_CASE("addr_unix::compare", "[addr_unix]")
     696              : {
     697            2 :     CATCH_START_SECTION("addr_unix::compare: two addr_unix() to compare with ==, !=, <, <=, >, >=")
     698              :     {
     699            1 :         addr::addr_unix a;
     700            1 :         addr::addr_unix b;
     701              : 
     702            1 :         CATCH_REQUIRE(a == b);
     703            1 :         CATCH_REQUIRE_FALSE(a != b);
     704            1 :         CATCH_REQUIRE_FALSE(a < b);
     705            1 :         CATCH_REQUIRE(a <= b);
     706            1 :         CATCH_REQUIRE_FALSE(a > b);
     707            1 :         CATCH_REQUIRE(a >= b);
     708              : 
     709            3 :         a.set_uri("unix:flowers");
     710            3 :         b.set_uri("unix:oranges");
     711              : 
     712            1 :         CATCH_REQUIRE_FALSE(a == b);
     713            1 :         CATCH_REQUIRE(a != b);
     714            1 :         CATCH_REQUIRE(a < b);
     715            1 :         CATCH_REQUIRE(a <= b);
     716            1 :         CATCH_REQUIRE_FALSE(a > b);
     717            1 :         CATCH_REQUIRE_FALSE(a >= b);
     718              : 
     719            1 :         std::swap(a, b);
     720              : 
     721            1 :         CATCH_REQUIRE_FALSE(a == b);
     722            1 :         CATCH_REQUIRE(a != b);
     723            1 :         CATCH_REQUIRE_FALSE(a < b);
     724            1 :         CATCH_REQUIRE_FALSE(a <= b);
     725            1 :         CATCH_REQUIRE(a > b);
     726            1 :         CATCH_REQUIRE(a >= b);
     727            1 :     }
     728            2 :     CATCH_END_SECTION()
     729              : 
     730            2 :     CATCH_START_SECTION("addr_unix::compare: two sockaddr_un to compare with ==, !=, <, <=, >, >=")
     731              :     {
     732            1 :         sockaddr_un a = addr::init_un();
     733            1 :         sockaddr_un b = addr::init_un();
     734              : 
     735            1 :         CATCH_REQUIRE(a == b);
     736            1 :         CATCH_REQUIRE_FALSE(a != b);
     737            1 :         CATCH_REQUIRE_FALSE(a < b);
     738            1 :         CATCH_REQUIRE(a <= b);
     739            1 :         CATCH_REQUIRE_FALSE(a > b);
     740            1 :         CATCH_REQUIRE(a >= b);
     741              : 
     742            1 :         strncpy(a.sun_path, "unix:flowers", sizeof(a.sun_path) - 1);
     743            1 :         strncpy(b.sun_path, "unix:oranges", sizeof(a.sun_path) - 1);
     744              : 
     745            1 :         CATCH_REQUIRE_FALSE(a == b);
     746            1 :         CATCH_REQUIRE(a != b);
     747            1 :         CATCH_REQUIRE(a < b);
     748            1 :         CATCH_REQUIRE(a <= b);
     749            1 :         CATCH_REQUIRE_FALSE(a > b);
     750            1 :         CATCH_REQUIRE_FALSE(a >= b);
     751              : 
     752            1 :         std::swap(a, b);
     753              : 
     754            1 :         CATCH_REQUIRE_FALSE(a == b);
     755            1 :         CATCH_REQUIRE(a != b);
     756            1 :         CATCH_REQUIRE_FALSE(a < b);
     757            1 :         CATCH_REQUIRE_FALSE(a <= b);
     758            1 :         CATCH_REQUIRE(a > b);
     759            1 :         CATCH_REQUIRE(a >= b);
     760              :     }
     761            2 :     CATCH_END_SECTION()
     762            2 : }
     763              : 
     764              : 
     765            3 : CATCH_TEST_CASE("addr_unix::mix", "[addr_unix]")
     766              : {
     767            3 :     CATCH_START_SECTION("addr_unix::mix: addr_unix() with a relative file name then unnamed")
     768              :     {
     769           11 :         for(int count(0); count < 10; ++count)
     770              :         {
     771           30 :             std::string name("test");
     772           10 :             int const max(rand() % 5 + 3);
     773           58 :             for(int id(0); id < max; ++id)
     774              :             {
     775           48 :                 name += '0' + rand() % 10;
     776              :             }
     777              : 
     778              :             // verify the init_un() as we're at it
     779              :             //
     780           10 :             sockaddr_un init = addr::init_un();
     781           10 :             CATCH_REQUIRE(init.sun_family == AF_UNIX);
     782         1090 :             for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
     783              :             {
     784         1080 :                 CATCH_CHECK(init.sun_path[idx] == 0);
     785              :             }
     786           10 :             strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
     787              : 
     788           10 :             addr::addr_unix u(init);
     789              : 
     790           10 :             CATCH_REQUIRE(u.is_file());
     791           10 :             CATCH_REQUIRE_FALSE(u.is_abstract());
     792           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     793           10 :             CATCH_REQUIRE(u.to_string() == name);
     794           10 :             CATCH_REQUIRE(u.to_uri() == "unix:" + name);
     795              : 
     796           10 :             sockaddr_un un;
     797           10 :             u.get_un(un);
     798           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     799           10 :             CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
     800         1002 :             for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
     801              :             {
     802          992 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     803              :             }
     804              : 
     805           10 :             u.make_unnamed();
     806              : 
     807           10 :             CATCH_REQUIRE_FALSE(u.is_file());
     808           10 :             CATCH_REQUIRE_FALSE(u.is_abstract());
     809           10 :             CATCH_REQUIRE(u.is_unnamed());
     810           10 :             CATCH_REQUIRE(u.to_string() == std::string());
     811           10 :             CATCH_REQUIRE(u.to_uri() == "unix:");
     812              : 
     813           10 :             u.get_un(un);
     814           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     815         1090 :             for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
     816              :             {
     817         1080 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     818              :             }
     819           10 :         }
     820              :     }
     821            3 :     CATCH_END_SECTION()
     822              : 
     823            3 :     CATCH_START_SECTION("addr_unix::mix: addr_unix() with a full abstract name then unnamed")
     824              :     {
     825           11 :         for(int count(0); count < 10; ++count)
     826              :         {
     827           30 :             std::string name("/net/snapwebsites/settings/test");
     828           10 :             int const max(rand() % 25 + 3);
     829          134 :             for(int id(0); id < max; ++id)
     830              :             {
     831          124 :                 name += '0' + rand() % 10;
     832              :             }
     833              : 
     834              :             // verify the init_un() as we're at it
     835              :             //
     836           10 :             sockaddr_un init = addr::init_un();
     837           10 :             CATCH_REQUIRE(init.sun_family == AF_UNIX);
     838         1090 :             for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
     839              :             {
     840         1080 :                 CATCH_CHECK(init.sun_path[idx] == 0);
     841              :             }
     842           10 :             strncpy(init.sun_path + 1, name.c_str(), sizeof(init.sun_path) - 2);
     843              : 
     844           10 :             addr::addr_unix u(init);
     845              : 
     846           10 :             CATCH_REQUIRE_FALSE(u.is_file());
     847           10 :             CATCH_REQUIRE(u.is_abstract());
     848           10 :             CATCH_REQUIRE_FALSE(u.is_unnamed());
     849           10 :             CATCH_REQUIRE(u.to_string() == name);
     850           10 :             CATCH_REQUIRE(u.to_uri() == "unix://" + name + "?abstract");
     851              : 
     852           10 :             sockaddr_un un;
     853           10 :             u.get_un(un);
     854           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     855           10 :             CATCH_REQUIRE(un.sun_path[0] == '\0');
     856           10 :             CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
     857          646 :             for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
     858              :             {
     859          636 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     860              :             }
     861              : 
     862           10 :             u.make_unnamed();
     863              : 
     864           10 :             CATCH_REQUIRE_FALSE(u.is_file());
     865           10 :             CATCH_REQUIRE_FALSE(u.is_abstract());
     866           10 :             CATCH_REQUIRE(u.is_unnamed());
     867           10 :             CATCH_REQUIRE(u.to_string() == std::string());
     868           10 :             CATCH_REQUIRE(u.to_uri() == "unix:");
     869              : 
     870           10 :             u.get_un(un);
     871           10 :             CATCH_REQUIRE(un.sun_family == AF_UNIX);
     872         1090 :             for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
     873              :             {
     874         1080 :                 CATCH_CHECK(un.sun_path[idx] == 0);
     875              :             }
     876           10 :         }
     877              :     }
     878            3 :     CATCH_END_SECTION()
     879              : 
     880            3 :     CATCH_START_SECTION("addr_unix::mix: addr_unix() with various set_uri()")
     881              :     {
     882            1 :         addr::addr_unix u;
     883              : 
     884          223 :         for(int count(0); count < 222; ++count)
     885              :         {
     886          222 :             int type(count % 3);
     887              : 
     888          222 :             std::string name;
     889          222 :             if(type != 2)
     890              :             {
     891          148 :                 name = "/run/snapwebsites/sockets/test";
     892          148 :                 int const max(rand() % 25 + 3);
     893          148 :                 switch(rand() % 4)
     894              :                 {
     895           36 :                 case 0:
     896           36 :                     break;
     897              : 
     898           35 :                 case 1:
     899           35 :                     name += '-';
     900           35 :                     break;
     901              : 
     902           44 :                 case 2:
     903           44 :                     name += '+';
     904           44 :                     break;
     905              : 
     906           33 :                 case 3:
     907           33 :                     name += '.';
     908           33 :                     break;
     909              : 
     910            0 :                 default:
     911            0 :                     throw std::runtime_error("unexpected case");
     912              : 
     913              :                 }
     914         2422 :                 for(int id(0); id < max; ++id)
     915              :                 {
     916         2274 :                     name += '0' + rand() % 10;
     917              :                 }
     918              :             }
     919              : 
     920          222 :             bool force(count % 6 != type);
     921              : 
     922          222 :             sockaddr_un un;
     923          222 :             switch(count % 3)
     924              :             {
     925           74 :             case 0:
     926           74 :                 u.set_uri("unix://" + name + (force ? "?file" : ""));
     927              : 
     928           74 :                 CATCH_REQUIRE(u.is_file());
     929           74 :                 CATCH_REQUIRE_FALSE(u.is_abstract());
     930           74 :                 CATCH_REQUIRE_FALSE(u.is_unnamed());
     931           74 :                 CATCH_REQUIRE(u.to_string() == name);
     932           74 :                 CATCH_REQUIRE(u.to_uri() == "unix://" + name);
     933              : 
     934           74 :                 u.get_un(un);
     935           74 :                 CATCH_REQUIRE(un.sun_family == AF_UNIX);
     936           74 :                 CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
     937         4657 :                 for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
     938              :                 {
     939         4583 :                     CATCH_CHECK(un.sun_path[idx] == 0);
     940              :                 }
     941           74 :                 break;
     942              : 
     943           74 :             case 1:
     944           74 :                 u.set_uri("unix://" + name + "?abstract");
     945              : 
     946           74 :                 CATCH_REQUIRE_FALSE(u.is_file());
     947           74 :                 CATCH_REQUIRE(u.is_abstract());
     948           74 :                 CATCH_REQUIRE_FALSE(u.is_unnamed());
     949           74 :                 CATCH_REQUIRE(u.to_string() == name);
     950           74 :                 CATCH_REQUIRE(u.to_uri() == "unix://" + name + "?abstract");
     951              : 
     952           74 :                 u.get_un(un);
     953           74 :                 CATCH_REQUIRE(un.sun_family == AF_UNIX);
     954           74 :                 CATCH_REQUIRE(un.sun_path[0] == '\0');
     955           74 :                 CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
     956         4575 :                 for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
     957              :                 {
     958         4501 :                     CATCH_CHECK(un.sun_path[idx] == 0);
     959              :                 }
     960           74 :                 break;
     961              : 
     962           74 :             case 2:
     963          222 :                 u.set_uri(force ? "unix:?unnamed" : "unix:");
     964              : 
     965           74 :                 CATCH_REQUIRE_FALSE(u.is_file());
     966           74 :                 CATCH_REQUIRE_FALSE(u.is_abstract());
     967           74 :                 CATCH_REQUIRE(u.is_unnamed());
     968           74 :                 CATCH_REQUIRE(u.to_string() == std::string());
     969           74 :                 CATCH_REQUIRE(u.to_uri() == "unix:");
     970              : 
     971           74 :                 u.get_un(un);
     972           74 :                 CATCH_REQUIRE(un.sun_family == AF_UNIX);
     973         8066 :                 for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
     974              :                 {
     975         7992 :                     CATCH_CHECK(un.sun_path[idx] == 0);
     976              :                 }
     977           74 :                 break;
     978              : 
     979              :             }
     980          222 :         }
     981            1 :     }
     982            3 :     CATCH_END_SECTION()
     983            3 : }
     984              : 
     985              : 
     986            2 : CATCH_TEST_CASE("addr_unix::owner", "[addr_unix]")
     987              : {
     988            2 :     CATCH_START_SECTION("addr_unix::owner: addr_unix() check group")
     989              :     {
     990            1 :         addr::addr_unix u;
     991              : 
     992           11 :         for(int count(0); count < 10; ++count)
     993              :         {
     994           30 :             std::string name("grp");
     995           10 :             int const max(rand() % 5 + 3);
     996           57 :             for(int id(0); id < max; ++id)
     997              :             {
     998           47 :                 name += '0' + rand() % 10;
     999              :             }
    1000           10 :             u.set_group(name);
    1001           10 :             CATCH_REQUIRE(u.get_group() == name);
    1002           10 :         }
    1003            1 :     }
    1004            2 :     CATCH_END_SECTION()
    1005              : 
    1006            2 :     CATCH_START_SECTION("addr_unix::owner: addr_unix() check mode")
    1007              :     {
    1008            1 :         addr::addr_unix u;
    1009              : 
    1010         1024 :         for(int m(0); m < 01777; ++m)
    1011              :         {
    1012         1023 :             u.set_mode(m);
    1013         1023 :             CATCH_REQUIRE(u.get_mode() == m);
    1014              :         }
    1015            1 :     }
    1016            2 :     CATCH_END_SECTION()
    1017            2 : }
    1018              : 
    1019              : 
    1020           14 : CATCH_TEST_CASE("addr_unix::invalid", "[addr_unix]")
    1021              : {
    1022           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with an invalid address family")
    1023              :     {
    1024           52 :         for(int family(-25); family <= 25; ++family)
    1025              :         {
    1026           51 :             if(family == AF_UNIX)
    1027              :             {
    1028            1 :                 continue;
    1029              :             }
    1030              : 
    1031           50 :             sockaddr_un init = addr::init_un();
    1032           50 :             init.sun_family = family;
    1033              : 
    1034              :             // constructor
    1035              :             //
    1036          100 :             CATCH_REQUIRE_THROWS_AS(addr::addr_unix(init), addr::addr_invalid_structure);
    1037              : 
    1038              :             // set_un()
    1039              :             //
    1040           50 :             addr::addr_unix u;
    1041           50 :             CATCH_REQUIRE_THROWS_AS(u.set_un(init), addr::addr_invalid_structure);
    1042           50 :         }
    1043              :     }
    1044           14 :     CATCH_END_SECTION()
    1045              : 
    1046           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with an unnamed string but marked abstract")
    1047              :     {
    1048            4 :         CATCH_REQUIRE_THROWS_AS(addr::addr_unix(std::string(), true), addr::addr_invalid_argument);
    1049              :     }
    1050           14 :     CATCH_END_SECTION()
    1051              : 
    1052           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a URI but a missing path")
    1053              :     {
    1054            1 :         addr::addr_unix u;
    1055            5 :         CATCH_REQUIRE_THROWS_AS(u.set_uri("unix://"), addr::addr_invalid_argument);
    1056            1 :     }
    1057           14 :     CATCH_END_SECTION()
    1058              : 
    1059           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a URI but a missing scheme")
    1060              :     {
    1061            1 :         addr::addr_unix u;
    1062            5 :         CATCH_REQUIRE_THROWS_AS(u.set_uri("://address"), addr::addr_invalid_argument);
    1063            1 :     }
    1064           14 :     CATCH_END_SECTION()
    1065              : 
    1066           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a URI but an invalid scheme")
    1067              :     {
    1068            1 :         addr::addr_unix u;
    1069              : 
    1070            7 :         CATCH_REQUIRE_THROWS_MATCHES(
    1071              :               u.set_uri("bad(scheme)://address")
    1072              :             , addr::addr_invalid_argument
    1073              :             , Catch::Matchers::ExceptionMessage("addr_error: \"bad(scheme)\" is not a supported URI scheme for a Unix address; supported scheme are limited to `[a-zA-Z][-+.a-zA-Z0-9]*`."));
    1074              : 
    1075            7 :         CATCH_REQUIRE_THROWS_MATCHES(
    1076              :               u.set_uri("other;scheme://address")
    1077              :             , addr::addr_invalid_argument
    1078              :             , Catch::Matchers::ExceptionMessage("addr_error: \"other;scheme\" is not a supported URI scheme for a Unix address; supported scheme are limited to `[a-zA-Z][-+.a-zA-Z0-9]*`."));
    1079              : 
    1080            7 :         CATCH_REQUIRE_THROWS_MATCHES(
    1081              :               u.set_uri("unknown|scheme://address")
    1082              :             , addr::addr_invalid_argument
    1083              :             , Catch::Matchers::ExceptionMessage("addr_error: \"unknown|scheme\" is not a supported URI scheme for a Unix address; supported scheme are limited to `[a-zA-Z][-+.a-zA-Z0-9]*`."));
    1084            1 :     }
    1085           14 :     CATCH_END_SECTION()
    1086              : 
    1087           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with too long a file name")
    1088              :     {
    1089              :         sockaddr_un un;
    1090           12 :         for(int count(static_cast<int>(sizeof(un.sun_path)));
    1091           12 :             count < static_cast<int>(sizeof(un.sun_path) + 11);
    1092              :             ++count)
    1093              :         {
    1094           11 :             std::string name;
    1095         1254 :             for(int id(0); id < count; ++id)
    1096              :             {
    1097         1243 :                 name += '0' + rand() % 10;
    1098              :             }
    1099              : 
    1100           22 :             CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name), addr::addr_invalid_argument);
    1101              : 
    1102           11 :             addr::addr_unix u;
    1103           33 :             CATCH_REQUIRE_THROWS_AS(u.set_uri("unix:" + name), addr::addr_invalid_argument);
    1104           11 :         }
    1105              :     }
    1106           14 :     CATCH_END_SECTION()
    1107              : 
    1108           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with too long an abstract name")
    1109              :     {
    1110              :         sockaddr_un un;
    1111           12 :         for(int count(static_cast<int>(sizeof(un.sun_path) - 1));
    1112           12 :             count < static_cast<int>(sizeof(un.sun_path) + 10);
    1113              :             ++count)
    1114              :         {
    1115           11 :             std::string name;
    1116         1243 :             for(int id(0); id < count; ++id)
    1117              :             {
    1118         1232 :                 name += '0' + rand() % 10;
    1119              :             }
    1120              : 
    1121           22 :             CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name, true), addr::addr_invalid_argument);
    1122              : 
    1123           11 :             addr::addr_unix u;
    1124           55 :             CATCH_REQUIRE_THROWS_AS(u.set_uri("unix:" + name + "?abstract"), addr::addr_invalid_argument);
    1125           11 :         }
    1126              :     }
    1127           14 :     CATCH_END_SECTION()
    1128              : 
    1129           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a long filename (missing '\\0')")
    1130              :     {
    1131            1 :         sockaddr_un init = addr::init_un();
    1132          109 :         for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
    1133              :         {
    1134          108 :             init.sun_path[idx] = '0' + rand() % 10;
    1135              :         }
    1136              : 
    1137              :         // constructor
    1138              :         //
    1139            2 :         CATCH_REQUIRE_THROWS_AS(addr::addr_unix(init), addr::addr_invalid_argument);
    1140              : 
    1141              :         // set_un()
    1142              :         //
    1143            1 :         addr::addr_unix u;
    1144            1 :         CATCH_REQUIRE_THROWS_AS(u.set_un(init), addr::addr_invalid_argument);
    1145            1 :     }
    1146           14 :     CATCH_END_SECTION()
    1147              : 
    1148           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a long abstract name (missing '\\0')")
    1149              :     {
    1150            1 :         sockaddr_un init = addr::init_un();
    1151          108 :         for(std::size_t idx(1); idx < sizeof(init.sun_path); ++idx)
    1152              :         {
    1153          107 :             init.sun_path[idx] = '0' + rand() % 10;
    1154              :         }
    1155              : 
    1156              :         // constructor
    1157              :         //
    1158            2 :         CATCH_REQUIRE_THROWS_AS(addr::addr_unix(init), addr::addr_invalid_argument);
    1159              : 
    1160              :         // set_un()
    1161              :         //
    1162            1 :         addr::addr_unix u;
    1163            1 :         CATCH_REQUIRE_THROWS_AS(u.set_un(init), addr::addr_invalid_argument);
    1164            1 :     }
    1165           14 :     CATCH_END_SECTION()
    1166              : 
    1167           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a long abstract name (missing '\\0')")
    1168              :     {
    1169            1 :         addr::addr_unix u;
    1170              : 
    1171              :         // missing ":"
    1172              :         //
    1173            7 :         CATCH_REQUIRE_THROWS_MATCHES(
    1174              :               u.set_uri("cu/run/snapwebsites/sockets")
    1175              :             , addr::addr_invalid_argument
    1176              :             , Catch::Matchers::ExceptionMessage("addr_error: invalid URI for a Unix address, scheme not found (':' missing)."));
    1177              : 
    1178              :         // "?alexis"
    1179              :         //
    1180            7 :         CATCH_REQUIRE_THROWS_MATCHES(
    1181              :               u.set_uri("unix:/run/snapwebsites/sockets?alexis")
    1182              :             , addr::addr_invalid_argument
    1183              :             , Catch::Matchers::ExceptionMessage("addr_error: \"alexis\" is not a supported URI query string for a Unix address; supported query strings are one of: \"unnamed\", \"file\" and \"abstract\"."));
    1184              : 
    1185              :         // "_test:"
    1186              :         //
    1187            7 :         CATCH_REQUIRE_THROWS_MATCHES(
    1188              :               u.set_uri("_test:/run/snapwebsites/sockets?abstract")
    1189              :             , addr::addr_invalid_argument
    1190              :             , Catch::Matchers::ExceptionMessage("addr_error: \"_test\" is not a supported URI scheme for a Unix address; supported scheme are limited to `[a-zA-Z][-+.a-zA-Z0-9]*`."));
    1191              : 
    1192              :         // name with "?unnamed"
    1193              :         //
    1194            7 :         CATCH_REQUIRE_THROWS_MATCHES(
    1195              :               u.set_uri("cd:not-empty?unnamed")
    1196              :             , addr::addr_invalid_argument
    1197              :             , Catch::Matchers::ExceptionMessage("addr_error: address \"not-empty\" must be empty to represent an unnamed Unix address."));
    1198            1 :     }
    1199           14 :     CATCH_END_SECTION()
    1200              : 
    1201           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with invalid characters (controls)")
    1202              :     {
    1203           32 :         for(int c(1); c < 0x20; ++c)
    1204              :         {
    1205           31 :             std::string name;
    1206           31 :             name += c;
    1207           62 :             CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name), addr::addr_invalid_argument);
    1208           31 :         }
    1209              : 
    1210           34 :         for(int c(0x7F); c < 0xA0; ++c)
    1211              :         {
    1212           33 :             std::u32string u32;
    1213           33 :             u32 += c;
    1214           33 :             std::string name(libutf8::to_u8string(u32));
    1215           66 :             CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name), addr::addr_invalid_argument);
    1216           33 :         }
    1217              :     }
    1218           14 :     CATCH_END_SECTION()
    1219              : 
    1220           14 :     CATCH_START_SECTION("addr_unix::invalid: addr_unix() with invalid UTF-8 characters")
    1221              :     {
    1222            1 :         std::string name;
    1223           11 :         for(int c(0); c < 10; ++c)
    1224              :         {
    1225           10 :             name += static_cast<char>(0x80);
    1226              :         }
    1227            2 :         CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name), libutf8::libutf8_exception_decoding);
    1228            1 :     }
    1229           14 :     CATCH_END_SECTION()
    1230              : 
    1231           14 :     CATCH_START_SECTION("addr_unix::invalid: get addr_unix() of socket set to -1")
    1232              :     {
    1233            1 :         addr::addr_unix u;
    1234            1 :         bool const result(u.set_from_socket(-1));
    1235            1 :         int const e(errno);
    1236            1 :         CATCH_REQUIRE_FALSE(result);
    1237            1 :         CATCH_REQUIRE(e == EBADF);
    1238            1 :     }
    1239           14 :     CATCH_END_SECTION()
    1240              : 
    1241           14 :     CATCH_START_SECTION("addr_unix::invalid: get addr_unix() of socket set to UDP")
    1242              :     {
    1243           10 :         addr::addr udp(addr::string_to_addr(
    1244              :                   "127.0.0.1:3999"
    1245              :                 , "127.0.0.1"
    1246              :                 , 3999
    1247            7 :                 , "udp"));
    1248            1 :         snapdev::raii_fd_t s(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
    1249            1 :         CATCH_REQUIRE(s != nullptr);
    1250            1 :         sockaddr_in in;
    1251            1 :         udp.get_ipv4(in);
    1252            1 :         CATCH_REQUIRE(bind(s.get(), reinterpret_cast<sockaddr *>(&in), sizeof(in)) == 0);
    1253              : 
    1254            1 :         addr::addr_unix u;
    1255            1 :         bool const result(u.set_from_socket(s.get()));
    1256            1 :         int const e(errno);
    1257            1 :         CATCH_REQUIRE_FALSE(result);
    1258            1 :         CATCH_REQUIRE(e == EADDRNOTAVAIL);
    1259            1 :     }
    1260           14 :     CATCH_END_SECTION()
    1261           14 : }
    1262              : 
    1263              : 
    1264              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

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