LCOV - code coverage report
Current view: top level - tests - catch_daemon.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.7 % 704 589
Test Date: 2025-08-17 08:58:50 Functions: 100.0 % 26 26
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright (c) 2016-2025  Made to Order Software Corp.  All Rights Reserved
       2              : //
       3              : // https://snapwebsites.org/project/cluck
       4              : // contact@m2osw.com
       5              : //
       6              : // This program is free software: you can redistribute it and/or modify
       7              : // it under the terms of the GNU General Public License as published by
       8              : // the Free Software Foundation, either version 3 of the License, or
       9              : // (at your option) any later version.
      10              : //
      11              : // This program is distributed in the hope that it will be useful,
      12              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14              : // GNU General Public License for more details.
      15              : //
      16              : // You should have received a copy of the GNU General Public License
      17              : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18              : 
      19              : // self
      20              : //
      21              : #include    "catch_main.h"
      22              : 
      23              : 
      24              : 
      25              : // cluckd
      26              : //
      27              : #include    <daemon/cluckd.h>
      28              : 
      29              : 
      30              : // cluck
      31              : //
      32              : #include    <cluck/exception.h>
      33              : 
      34              : 
      35              : // eventdispatcher
      36              : //
      37              : #include    <eventdispatcher/reporter/executor.h>
      38              : #include    <eventdispatcher/reporter/parser.h>
      39              : #include    <eventdispatcher/reporter/variable_integer.h>
      40              : 
      41              : 
      42              : // snapdev
      43              : //
      44              : #include    <snapdev/gethostname.h>
      45              : 
      46              : 
      47              : // advgetopt
      48              : //
      49              : #include    <advgetopt/exception.h>
      50              : 
      51              : 
      52              : // last include
      53              : //
      54              : #include    <snapdev/poison.h>
      55              : 
      56              : 
      57              : 
      58              : namespace
      59              : {
      60              : 
      61              : 
      62              : 
      63           16 : addr::addr get_address()
      64              : {
      65           16 :     addr::addr a;
      66           16 :     sockaddr_in ip = {
      67              :         .sin_family = AF_INET,
      68           16 :         .sin_port = htons(20002),
      69              :         .sin_addr = {
      70           16 :             .s_addr = htonl(0x7f000001),
      71              :         },
      72              :         .sin_zero = {},
      73           16 :     };
      74           16 :     a.set_ipv4(ip);
      75           32 :     return a;
      76            0 : }
      77              : 
      78              : 
      79              : 
      80              : } // no name namespace
      81              : 
      82              : 
      83              : 
      84            1 : CATCH_TEST_CASE("cluck_daemon_one_computer", "[cluckd][daemon]")
      85              : {
      86            3 :     CATCH_START_SECTION("cluck_daemon_one_computer: verify cluckd")
      87              :     {
      88            1 :         addr::addr a(get_address());
      89              : 
      90            1 :         std::vector<std::string> const args = {
      91              :             "cluckd", // name of command
      92              :             "--communicatord-listen",
      93            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
      94              :             "--path-to-message-definitions",
      95              : 
      96              :             // WARNING: the order matters, we want to test with our source
      97              :             //          (i.e. original) files first
      98              :             //
      99            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     100            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     101            9 :         };
     102              : 
     103              :         // convert arguments
     104              :         //
     105            1 :         std::vector<char const *> args_strings;
     106            1 :         args_strings.reserve(args.size() + 1);
     107            6 :         for(auto const & arg : args)
     108              :         {
     109            5 :             args_strings.push_back(arg.c_str());
     110              :         }
     111            1 :         args_strings.push_back(nullptr); // NULL terminated
     112              : 
     113            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     114            1 :         lock->add_connections();
     115              : 
     116              :         // no elections happened, 'lock' is not a leader
     117              :         //
     118            1 :         CATCH_REQUIRE(lock->is_leader() == nullptr);
     119            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     120              :               lock->get_leader_a()
     121              :             , cluck::logic_error
     122              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
     123            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     124              :               lock->get_leader_b()
     125              :             , cluck::logic_error
     126              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
     127              : 
     128              :         // messenger is not yet connected, it's not ready
     129              :         //
     130            1 :         CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
     131              : 
     132            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     133            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_one_computer.rprtr");
     134            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     135            1 :         CATCH_REQUIRE(l != nullptr);
     136            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     137            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     138            1 :         p->parse_program();
     139              : 
     140            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     141            1 :         e->start();
     142              : 
     143            1 :         e->set_thread_done_callback([lock]()
     144              :             {
     145            1 :                 lock->stop(true);
     146            1 :             });
     147              : 
     148              :         try
     149              :         {
     150            1 :             lock->run();
     151              :         }
     152            0 :         catch(std::exception const & ex)
     153              :         {
     154            0 :             SNAP_LOG_FATAL
     155              :                 << "an exception occurred while running cluckd (1 cluckd): "
     156              :                 << ex
     157              :                 << SNAP_LOG_SEND;
     158              : 
     159            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     160            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     161              :             {
     162            0 :                 SNAP_LOG_FATAL
     163              :                     << "    "
     164              :                     << line
     165              :                     << SNAP_LOG_SEND;
     166              :             }
     167              : 
     168            0 :             throw;
     169            0 :         }
     170              : 
     171            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     172            1 :     }
     173            2 :     CATCH_END_SECTION()
     174            6 : }
     175              : 
     176              : 
     177            1 : CATCH_TEST_CASE("cluck_daemon_two_computers", "[cluckd][daemon]")
     178              : {
     179            3 :     CATCH_START_SECTION("cluck_daemon_two_computers: verify cluckd")
     180              :     {
     181            1 :         addr::addr a(get_address());
     182              : 
     183            1 :         std::vector<std::string> const args = {
     184              :             "cluckd", // name of command
     185              :             "--communicatord-listen",
     186            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
     187              :             "--path-to-message-definitions",
     188              : 
     189              :             // WARNING: the order matters, we want to test with our source
     190              :             //          (i.e. original) files first
     191              :             //
     192            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     193            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     194              : 
     195              :             "--server-name",
     196              :             snapdev::gethostname(),
     197              :             "--candidate-priority",
     198              :             "10",
     199           13 :         };
     200              : 
     201              :         // convert arguments
     202              :         //
     203            1 :         std::vector<char const *> args_strings;
     204            1 :         args_strings.reserve(args.size() + 1);
     205           10 :         for(auto const & arg : args)
     206              :         {
     207            9 :             args_strings.push_back(arg.c_str());
     208              :         }
     209            1 :         args_strings.push_back(nullptr); // NULL terminated
     210              : 
     211            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     212            1 :         lock->add_connections();
     213              : 
     214              :         // no elections happened, 'lock' is not a leader
     215              :         //
     216            1 :         CATCH_REQUIRE(lock->is_leader() == nullptr);
     217            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     218              :               lock->get_leader_a()
     219              :             , cluck::logic_error
     220              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
     221            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     222              :               lock->get_leader_b()
     223              :             , cluck::logic_error
     224              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
     225              : 
     226              :         // messenger is not yet connected, it's not ready
     227              :         //
     228            1 :         CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
     229              : 
     230            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     231            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_two_computers.rprtr");
     232            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     233            1 :         CATCH_REQUIRE(l != nullptr);
     234            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     235            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     236            1 :         p->parse_program();
     237              : 
     238            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     239            1 :         e->start();
     240              : 
     241            1 :         e->set_thread_done_callback([lock]()
     242              :             {
     243            1 :                 lock->stop(true);
     244            1 :             });
     245              : 
     246              :         try
     247              :         {
     248            1 :             lock->run();
     249              :         }
     250            0 :         catch(std::exception const & ex)
     251              :         {
     252            0 :             SNAP_LOG_FATAL
     253              :                 << "an exception occurred while running cluckd (2 cluckd): "
     254              :                 << ex
     255              :                 << SNAP_LOG_SEND;
     256              : 
     257            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     258            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     259              :             {
     260            0 :                 SNAP_LOG_FATAL
     261              :                     << "    "
     262              :                     << line
     263              :                     << SNAP_LOG_SEND;
     264              :             }
     265              : 
     266            0 :             throw;
     267            0 :         }
     268              : 
     269            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     270            1 :     }
     271            2 :     CATCH_END_SECTION()
     272            6 : }
     273              : 
     274              : 
     275            1 : CATCH_TEST_CASE("cluck_daemon_three_computers", "[cluckd][daemon]")
     276              : {
     277            3 :     CATCH_START_SECTION("cluck_daemon_three_computers: verify cluckd")
     278              :     {
     279            1 :         addr::addr a(get_address());
     280              : 
     281            1 :         std::vector<std::string> const args = {
     282              :             "cluckd", // name of command
     283              :             "--communicatord-listen",
     284            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
     285              :             "--path-to-message-definitions",
     286              : 
     287              :             // WARNING: the order matters, we want to test with our source
     288              :             //          (i.e. original) files first
     289              :             //
     290            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     291            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     292            9 :         };
     293              : 
     294              :         // convert arguments
     295              :         //
     296            1 :         std::vector<char const *> args_strings;
     297            1 :         args_strings.reserve(args.size() + 1);
     298            6 :         for(auto const & arg : args)
     299              :         {
     300            5 :             args_strings.push_back(arg.c_str());
     301              :         }
     302            1 :         args_strings.push_back(nullptr); // NULL terminated
     303              : 
     304            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     305            1 :         lock->add_connections();
     306              : 
     307              :         // no elections happened, 'lock' is not a leader
     308              :         //
     309            1 :         CATCH_REQUIRE(lock->is_leader() == nullptr);
     310            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     311              :               lock->get_leader_a()
     312              :             , cluck::logic_error
     313              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
     314            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     315              :               lock->get_leader_b()
     316              :             , cluck::logic_error
     317              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
     318              : 
     319              :         // messenger is not yet connected, it's not ready
     320              :         //
     321            1 :         CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
     322              : 
     323            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     324            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_three_computers.rprtr");
     325            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     326            1 :         CATCH_REQUIRE(l != nullptr);
     327            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     328            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     329            1 :         p->parse_program();
     330              : 
     331            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     332            1 :         e->start();
     333              : 
     334            1 :         e->set_thread_done_callback([lock]()
     335              :             {
     336            1 :                 lock->stop(true);
     337            1 :             });
     338              : 
     339              :         try
     340              :         {
     341            1 :             lock->run();
     342              :         }
     343            0 :         catch(std::exception const & ex)
     344              :         {
     345            0 :             SNAP_LOG_FATAL
     346              :                 << "an exception occurred while running cluckd (3 cluckd): "
     347              :                 << ex
     348              :                 << SNAP_LOG_SEND;
     349              : 
     350            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     351            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     352              :             {
     353            0 :                 SNAP_LOG_FATAL
     354              :                     << "    "
     355              :                     << line
     356              :                     << SNAP_LOG_SEND;
     357              :             }
     358              : 
     359            0 :             throw;
     360            0 :         }
     361              : 
     362            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     363            1 :     }
     364            2 :     CATCH_END_SECTION()
     365            6 : }
     366              : 
     367              : 
     368            1 : CATCH_TEST_CASE("cluck_daemon_four_computers", "[cluckd][daemon]")
     369              : {
     370            3 :     CATCH_START_SECTION("cluck_daemon_four_computers: verify cluckd")
     371              :     {
     372            1 :         addr::addr a(get_address());
     373              : 
     374            1 :         std::vector<std::string> const args = {
     375              :             "cluckd", // name of command
     376              :             "--communicatord-listen",
     377            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
     378              :             "--path-to-message-definitions",
     379              : 
     380              :             // WARNING: the order matters, we want to test with our source
     381              :             //          (i.e. original) files first
     382              :             //
     383            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     384            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     385            9 :         };
     386              : 
     387              :         // convert arguments
     388              :         //
     389            1 :         std::vector<char const *> args_strings;
     390            1 :         args_strings.reserve(args.size() + 1);
     391            6 :         for(auto const & arg : args)
     392              :         {
     393            5 :             args_strings.push_back(arg.c_str());
     394              :         }
     395            1 :         args_strings.push_back(nullptr); // NULL terminated
     396              : 
     397            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     398            1 :         lock->add_connections();
     399              : 
     400              :         // no elections happened, 'lock' is not a leader
     401              :         //
     402            1 :         CATCH_REQUIRE(lock->is_leader() == nullptr);
     403            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     404              :               lock->get_leader_a()
     405              :             , cluck::logic_error
     406              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
     407            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     408              :               lock->get_leader_b()
     409              :             , cluck::logic_error
     410              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
     411              : 
     412              :         // messenger is not yet connected, it's not ready
     413              :         //
     414            1 :         CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
     415              : 
     416            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     417            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_four_computers.rprtr");
     418            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     419            1 :         CATCH_REQUIRE(l != nullptr);
     420            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     421            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     422            1 :         p->parse_program();
     423              : 
     424            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     425            1 :         e->start();
     426              : 
     427            1 :         e->set_thread_done_callback([lock]()
     428              :             {
     429            1 :                 lock->stop(true);
     430            1 :             });
     431              : 
     432              :         try
     433              :         {
     434            1 :             lock->run();
     435              :         }
     436            0 :         catch(std::exception const & ex)
     437              :         {
     438            0 :             SNAP_LOG_FATAL
     439              :                 << "an exception occurred while running cluckd (4 cluckd): "
     440              :                 << ex
     441              :                 << SNAP_LOG_SEND;
     442              : 
     443            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     444            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     445              :             {
     446            0 :                 SNAP_LOG_FATAL
     447              :                     << "    "
     448              :                     << line
     449              :                     << SNAP_LOG_SEND;
     450              :             }
     451              : 
     452            0 :             throw;
     453            0 :         }
     454              : 
     455            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     456            1 :     }
     457            2 :     CATCH_END_SECTION()
     458            6 : }
     459              : 
     460              : 
     461            1 : CATCH_TEST_CASE("cluck_daemon_ten_computers", "[cluckd][daemon]")
     462              : {
     463            3 :     CATCH_START_SECTION("cluck_daemon_ten_computers: verify cluckd")
     464              :     {
     465            1 :         addr::addr a(get_address());
     466              : 
     467            1 :         std::vector<std::string> const args = {
     468              :             "cluckd", // name of command
     469              :             "--communicatord-listen",
     470            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
     471              :             "--candidate-priority",
     472              :             "5",
     473              :             "--path-to-message-definitions",
     474              : 
     475              :             // WARNING: the order matters, we want to test with our source
     476              :             //          (i.e. original) files first
     477              :             //
     478            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     479            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     480           11 :         };
     481              : 
     482              :         // convert arguments
     483              :         //
     484            1 :         std::vector<char const *> args_strings;
     485            1 :         args_strings.reserve(args.size() + 1);
     486            8 :         for(auto const & arg : args)
     487              :         {
     488            7 :             args_strings.push_back(arg.c_str());
     489              :         }
     490            1 :         args_strings.push_back(nullptr); // NULL terminated
     491              : 
     492            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     493            1 :         lock->add_connections();
     494              : 
     495              :         // no elections happened, 'lock' is not a leader
     496              :         //
     497            1 :         CATCH_REQUIRE(lock->is_leader() == nullptr);
     498            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     499              :               lock->get_leader_a()
     500              :             , cluck::logic_error
     501              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
     502            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     503              :               lock->get_leader_b()
     504              :             , cluck::logic_error
     505              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
     506              : 
     507              :         // messenger is not yet connected, it's not ready
     508              :         //
     509            1 :         CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
     510              : 
     511            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     512            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_ten_computers.rprtr");
     513            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     514            1 :         CATCH_REQUIRE(l != nullptr);
     515            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     516            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     517            1 :         p->parse_program();
     518              : 
     519            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     520            1 :         e->start();
     521              : 
     522            1 :         e->set_thread_done_callback([lock]()
     523              :             {
     524            1 :                 lock->stop(true);
     525            1 :             });
     526              : 
     527              :         try
     528              :         {
     529            1 :             lock->run();
     530              :         }
     531            0 :         catch(std::exception const & ex)
     532              :         {
     533            0 :             SNAP_LOG_FATAL
     534              :                 << "an exception occurred while running cluckd (10 cluckd): "
     535              :                 << ex
     536              :                 << SNAP_LOG_SEND;
     537              : 
     538            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     539            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     540              :             {
     541            0 :                 SNAP_LOG_FATAL
     542              :                     << "    "
     543              :                     << line
     544              :                     << SNAP_LOG_SEND;
     545              :             }
     546              : 
     547            0 :             throw;
     548            0 :         }
     549              : 
     550            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     551            1 :     }
     552            2 :     CATCH_END_SECTION()
     553            6 : }
     554              : 
     555              : 
     556            1 : CATCH_TEST_CASE("cluck_daemon_lock_tickets", "[cluckd][daemon]")
     557              : {
     558            3 :     CATCH_START_SECTION("cluck_daemon_lock_tickets: verify cluckd")
     559              :     {
     560            1 :         addr::addr a(get_address());
     561              : 
     562            1 :         std::vector<std::string> const args = {
     563              :             "cluckd", // name of command
     564              :             "--communicatord-listen",
     565            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
     566              :             "--candidate-priority",
     567              :             "2",
     568              :             "--path-to-message-definitions",
     569              : 
     570              :             // WARNING: the order matters, we want to test with our source
     571              :             //          (i.e. original) files first
     572              :             //
     573            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     574            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     575           11 :         };
     576              : 
     577              :         // convert arguments
     578              :         //
     579            1 :         std::vector<char const *> args_strings;
     580            1 :         args_strings.reserve(args.size() + 1);
     581            8 :         for(auto const & arg : args)
     582              :         {
     583            7 :             args_strings.push_back(arg.c_str());
     584              :         }
     585            1 :         args_strings.push_back(nullptr); // NULL terminated
     586              : 
     587            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     588            1 :         lock->add_connections();
     589              : 
     590              :         // no elections happened, 'lock' is not a leader
     591              :         //
     592            1 :         CATCH_REQUIRE(lock->is_leader() == nullptr);
     593            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     594              :               lock->get_leader_a()
     595              :             , cluck::logic_error
     596              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
     597            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     598              :               lock->get_leader_b()
     599              :             , cluck::logic_error
     600              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
     601              : 
     602              :         // messenger is not yet connected, it's not ready
     603              :         //
     604            1 :         CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
     605              : 
     606            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     607            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_lock_tickets.rprtr");
     608            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     609            1 :         CATCH_REQUIRE(l != nullptr);
     610            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     611            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     612            1 :         p->parse_program();
     613              : 
     614            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     615            1 :         e->start();
     616              : 
     617            1 :         e->set_thread_done_callback([lock]()
     618              :             {
     619            1 :                 lock->stop(true);
     620            1 :             });
     621              : 
     622              :         try
     623              :         {
     624            1 :             lock->run();
     625              :         }
     626            0 :         catch(std::exception const & ex)
     627              :         {
     628            0 :             SNAP_LOG_FATAL
     629              :                 << "an exception occurred while running cluckd (10 cluckd): "
     630              :                 << ex
     631              :                 << SNAP_LOG_SEND;
     632              : 
     633            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     634            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     635              :             {
     636            0 :                 SNAP_LOG_FATAL
     637              :                     << "    "
     638              :                     << line
     639              :                     << SNAP_LOG_SEND;
     640              :             }
     641              : 
     642            0 :             throw;
     643            0 :         }
     644              : 
     645            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     646            1 :     }
     647            2 :     CATCH_END_SECTION()
     648            6 : }
     649              : 
     650              : 
     651            3 : CATCH_TEST_CASE("cluck_daemon_specialized_tests", "[cluckd][daemon]")
     652              : {
     653            5 :     CATCH_START_SECTION("cluck_daemon_specialized_tests: verify early LOCK_LEADERS")
     654              :     {
     655            1 :         addr::addr a(get_address());
     656              : 
     657            1 :         std::vector<std::string> const args = {
     658              :             "cluckd", // name of command
     659              :             "--communicatord-listen",
     660            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
     661              :             "--path-to-message-definitions",
     662              : 
     663              :             // WARNING: the order matters, we want to test with our source
     664              :             //          (i.e. original) files first
     665              :             //
     666            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     667            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     668            9 :         };
     669              : 
     670              :         // convert arguments
     671              :         //
     672            1 :         std::vector<char const *> args_strings;
     673            1 :         args_strings.reserve(args.size() + 1);
     674            6 :         for(auto const & arg : args)
     675              :         {
     676            5 :             args_strings.push_back(arg.c_str());
     677              :         }
     678            1 :         args_strings.push_back(nullptr); // NULL terminated
     679              : 
     680            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     681            1 :         lock->add_connections();
     682              : 
     683              :         // no elections happened, 'lock' is not a leader
     684              :         //
     685            1 :         CATCH_REQUIRE(lock->is_leader() == nullptr);
     686            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     687              :               lock->get_leader_a()
     688              :             , cluck::logic_error
     689              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
     690            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     691              :               lock->get_leader_b()
     692              :             , cluck::logic_error
     693              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
     694              : 
     695              :         // messenger is not yet connected, it's not ready
     696              :         //
     697            1 :         CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
     698              : 
     699            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     700            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_early_lock_leaders.rprtr");
     701            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     702            1 :         CATCH_REQUIRE(l != nullptr);
     703            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     704            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     705            1 :         p->parse_program();
     706              : 
     707            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     708            1 :         e->start();
     709              : 
     710            1 :         e->set_thread_done_callback([lock]()
     711              :             {
     712            1 :                 lock->stop(true);
     713            1 :             });
     714              : 
     715              :         try
     716              :         {
     717            1 :             lock->run();
     718              :         }
     719            0 :         catch(std::exception const & ex)
     720              :         {
     721            0 :             SNAP_LOG_FATAL
     722              :                 << "an exception occurred while running cluckd (3 cluckd): "
     723              :                 << ex
     724              :                 << SNAP_LOG_SEND;
     725              : 
     726            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     727            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     728              :             {
     729            0 :                 SNAP_LOG_FATAL
     730              :                     << "    "
     731              :                     << line
     732              :                     << SNAP_LOG_SEND;
     733              :             }
     734              : 
     735            0 :             throw;
     736            0 :         }
     737              : 
     738            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     739            1 :     }
     740            4 :     CATCH_END_SECTION()
     741              : 
     742            5 :     CATCH_START_SECTION("cluck_daemon_specialized_tests: verify forwarded (off)")
     743              :     {
     744            1 :         addr::addr a(get_address());
     745              : 
     746            1 :         std::vector<std::string> const args = {
     747              :             "cluckd", // name of command
     748              :             "--communicatord-listen",
     749            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
     750              :             "--candidate-priority",
     751              :             "off",
     752              :             "--path-to-message-definitions",
     753              : 
     754              :             // WARNING: the order matters, we want to test with our source
     755              :             //          (i.e. original) files first
     756              :             //
     757            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     758            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     759           11 :         };
     760              : 
     761              :         // convert arguments
     762              :         //
     763            1 :         std::vector<char const *> args_strings;
     764            1 :         args_strings.reserve(args.size() + 1);
     765            8 :         for(auto const & arg : args)
     766              :         {
     767            7 :             args_strings.push_back(arg.c_str());
     768              :         }
     769            1 :         args_strings.push_back(nullptr); // NULL terminated
     770              : 
     771            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     772            1 :         lock->add_connections();
     773              : 
     774              :         // no elections happened, 'lock' is not a leader
     775              :         //
     776            1 :         CATCH_REQUIRE(lock->is_leader() == nullptr);
     777            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     778              :               lock->get_leader_a()
     779              :             , cluck::logic_error
     780              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
     781            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     782              :               lock->get_leader_b()
     783              :             , cluck::logic_error
     784              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
     785              : 
     786              :         // messenger is not yet connected, it's not ready
     787              :         //
     788            1 :         CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
     789              : 
     790            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     791            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_forwarder.rprtr");
     792            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     793            1 :         CATCH_REQUIRE(l != nullptr);
     794            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     795            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     796            1 :         p->parse_program();
     797              : 
     798            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     799            1 :         e->start();
     800              : 
     801            1 :         e->set_thread_done_callback([lock]()
     802              :             {
     803            1 :                 lock->stop(true);
     804            1 :             });
     805              : 
     806              :         try
     807              :         {
     808            1 :             lock->run();
     809              :         }
     810            0 :         catch(std::exception const & ex)
     811              :         {
     812            0 :             SNAP_LOG_FATAL
     813              :                 << "an exception occurred while running cluckd (3 cluckd): "
     814              :                 << ex
     815              :                 << SNAP_LOG_SEND;
     816              : 
     817            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     818            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     819              :             {
     820            0 :                 SNAP_LOG_FATAL
     821              :                     << "    "
     822              :                     << line
     823              :                     << SNAP_LOG_SEND;
     824              :             }
     825              : 
     826            0 :             throw;
     827            0 :         }
     828              : 
     829            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     830            1 :     }
     831            4 :     CATCH_END_SECTION()
     832              : 
     833            5 :     CATCH_START_SECTION("cluck_daemon_specialized_tests: try an interrupt to stop the cluck daemon")
     834              :     {
     835            1 :         addr::addr a(get_address());
     836              : 
     837            1 :         std::vector<std::string> const args = {
     838              :             "cluckd", // name of command
     839              :             "--communicatord-listen",
     840            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
     841              :             "--path-to-message-definitions",
     842              : 
     843              :             // WARNING: the order matters, we want to test with our source
     844              :             //          (i.e. original) files first
     845              :             //
     846            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     847            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     848            9 :         };
     849              : 
     850              :         // convert arguments
     851              :         //
     852            1 :         std::vector<char const *> args_strings;
     853            1 :         args_strings.reserve(args.size() + 1);
     854            6 :         for(auto const & arg : args)
     855              :         {
     856            5 :             args_strings.push_back(arg.c_str());
     857              :         }
     858            1 :         args_strings.push_back(nullptr); // NULL terminated
     859              : 
     860            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     861            1 :         lock->add_connections();
     862              : 
     863              :         // no elections happened, 'lock' is not a leader
     864              :         //
     865            1 :         CATCH_REQUIRE(lock->is_leader() == nullptr);
     866            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     867              :               lock->get_leader_a()
     868              :             , cluck::logic_error
     869              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
     870            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     871              :               lock->get_leader_b()
     872              :             , cluck::logic_error
     873              :             , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
     874              : 
     875              :         // messenger is not yet connected, it's not ready
     876              :         //
     877            1 :         CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
     878              : 
     879            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     880            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_interrupt_signal.rprtr");
     881            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     882            1 :         CATCH_REQUIRE(l != nullptr);
     883            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     884            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     885            1 :         p->parse_program();
     886              : 
     887            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     888            1 :         e->start();
     889              : 
     890            1 :         e->set_thread_done_callback([lock]()
     891              :             {
     892            1 :                 lock->stop(true);
     893            1 :             });
     894              : 
     895              :         try
     896              :         {
     897            1 :             lock->run();
     898              :         }
     899            0 :         catch(std::exception const & ex)
     900              :         {
     901            0 :             SNAP_LOG_FATAL
     902              :                 << "an exception occurred while running cluckd (interrupt signal): "
     903              :                 << ex
     904              :                 << SNAP_LOG_SEND;
     905              : 
     906            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     907            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     908              :             {
     909            0 :                 SNAP_LOG_FATAL
     910              :                     << "    "
     911              :                     << line
     912              :                     << SNAP_LOG_SEND;
     913              :             }
     914              : 
     915            0 :             throw;
     916            0 :         }
     917              : 
     918            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     919            1 :     }
     920            4 :     CATCH_END_SECTION()
     921           18 : }
     922              : 
     923              : 
     924            4 : CATCH_TEST_CASE("cluck_daemon_failures", "[cluckd][daemon][fail]")
     925              : {
     926            6 :     CATCH_START_SECTION("cluck_daemon_failures: entering too slowly")
     927              :     {
     928            1 :         addr::addr a(get_address());
     929              : 
     930            1 :         std::vector<std::string> const args = {
     931              :             "cluckd", // name of command
     932              :             "--communicatord-listen",
     933            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
     934              :             "--path-to-message-definitions",
     935              : 
     936              :             // WARNING: the order matters, we want to test with our source
     937              :             //          (i.e. original) files first
     938              :             //
     939            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
     940            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
     941            9 :         };
     942              : 
     943              :         // convert arguments
     944              :         //
     945            1 :         std::vector<char const *> args_strings;
     946            1 :         args_strings.reserve(args.size() + 1);
     947            6 :         for(auto const & arg : args)
     948              :         {
     949            5 :             args_strings.push_back(arg.c_str());
     950              :         }
     951            1 :         args_strings.push_back(nullptr); // NULL terminated
     952              : 
     953            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
     954            1 :         lock->add_connections();
     955              : 
     956            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
     957            1 :         std::string const filename(source_dir + "/tests/rprtr/failed_with_timing_out_entering.rprtr");
     958            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
     959            1 :         CATCH_REQUIRE(l != nullptr);
     960            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
     961            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
     962            1 :         p->parse_program();
     963              : 
     964            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
     965            1 :         e->start();
     966              : 
     967            1 :         e->set_thread_done_callback([lock]()
     968              :             {
     969            1 :                 lock->stop(true);
     970            1 :             });
     971              : 
     972              :         try
     973              :         {
     974            1 :             lock->run();
     975              :         }
     976            0 :         catch(std::exception const & ex)
     977              :         {
     978            0 :             SNAP_LOG_FATAL
     979              :                 << "an exception occurred while running cluckd (entering timing out): "
     980              :                 << ex
     981              :                 << SNAP_LOG_SEND;
     982              : 
     983            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
     984            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
     985              :             {
     986            0 :                 SNAP_LOG_FATAL
     987              :                     << "    "
     988              :                     << line
     989              :                     << SNAP_LOG_SEND;
     990              :             }
     991              : 
     992            0 :             throw;
     993            0 :         }
     994              : 
     995            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
     996            1 :     }
     997            5 :     CATCH_END_SECTION()
     998              : 
     999            6 :     CATCH_START_SECTION("cluck_daemon_failures: cache timeout")
    1000              :     {
    1001            1 :         addr::addr a(get_address());
    1002              : 
    1003            1 :         std::vector<std::string> const args = {
    1004              :             "cluckd", // name of command
    1005              :             "--communicatord-listen",
    1006            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
    1007              :             "--path-to-message-definitions",
    1008              : 
    1009              :             // WARNING: the order matters, we want to test with our source
    1010              :             //          (i.e. original) files first
    1011              :             //
    1012            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
    1013            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
    1014            9 :         };
    1015              : 
    1016              :         // convert arguments
    1017              :         //
    1018            1 :         std::vector<char const *> args_strings;
    1019            1 :         args_strings.reserve(args.size() + 1);
    1020            6 :         for(auto const & arg : args)
    1021              :         {
    1022            5 :             args_strings.push_back(arg.c_str());
    1023              :         }
    1024            1 :         args_strings.push_back(nullptr); // NULL terminated
    1025              : 
    1026            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
    1027            1 :         lock->add_connections();
    1028              : 
    1029            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    1030            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_cache_timeout.rprtr");
    1031            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    1032            1 :         CATCH_REQUIRE(l != nullptr);
    1033            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    1034            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    1035            1 :         p->parse_program();
    1036              : 
    1037            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    1038            1 :         e->start();
    1039              : 
    1040            1 :         e->set_thread_done_callback([lock]()
    1041              :             {
    1042            1 :                 lock->stop(true);
    1043            1 :             });
    1044              : 
    1045              :         try
    1046              :         {
    1047            1 :             lock->run();
    1048              :         }
    1049            0 :         catch(std::exception const & ex)
    1050              :         {
    1051            0 :             SNAP_LOG_FATAL
    1052              :                 << "an exception occurred while running cluckd (entering timing out): "
    1053              :                 << ex
    1054              :                 << SNAP_LOG_SEND;
    1055              : 
    1056            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
    1057            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
    1058              :             {
    1059            0 :                 SNAP_LOG_FATAL
    1060              :                     << "    "
    1061              :                     << line
    1062              :                     << SNAP_LOG_SEND;
    1063              :             }
    1064              : 
    1065            0 :             throw;
    1066            0 :         }
    1067              : 
    1068            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    1069            1 :     }
    1070            5 :     CATCH_END_SECTION()
    1071              : 
    1072            6 :     CATCH_START_SECTION("cluck_daemon_failures: too many locks")
    1073              :     {
    1074            1 :         addr::addr a(get_address());
    1075              : 
    1076            1 :         cluck::timeout_t const default_obtention_timeout(cluck::get_lock_obtention_timeout());
    1077            1 :         cluck::set_lock_obtention_timeout(cluck::timeout_t(120, 0));
    1078              : 
    1079            1 :         std::vector<std::string> const args = {
    1080              :             "cluckd", // name of command
    1081              :             "--communicatord-listen",
    1082            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
    1083              :             "--candidate-priority",
    1084              :             "10",
    1085              :             "--path-to-message-definitions",
    1086              : 
    1087              :             // WARNING: the order matters, we want to test with our source
    1088              :             //          (i.e. original) files first
    1089              :             //
    1090            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
    1091            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
    1092           11 :         };
    1093              : 
    1094              :         // convert arguments
    1095              :         //
    1096            1 :         std::vector<char const *> args_strings;
    1097            1 :         args_strings.reserve(args.size() + 1);
    1098            8 :         for(auto const & arg : args)
    1099              :         {
    1100            7 :             args_strings.push_back(arg.c_str());
    1101              :         }
    1102            1 :         args_strings.push_back(nullptr); // NULL terminated
    1103              : 
    1104            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
    1105            1 :         lock->add_connections();
    1106              : 
    1107            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    1108            1 :         std::string const filename(source_dir + "/tests/rprtr/failed_with_too_many_locks.rprtr");
    1109            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    1110            1 :         CATCH_REQUIRE(l != nullptr);
    1111            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    1112            1 :         SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t var(
    1113              :                 std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(
    1114            1 :                           "cluck_maximum_entering_locks"));
    1115            1 :         var->set_integer(cluck::CLUCK_MAXIMUM_ENTERING_LOCKS);
    1116            1 :         s->set_variable(var);
    1117            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    1118            1 :         p->parse_program();
    1119              : 
    1120            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    1121            1 :         e->start();
    1122              : 
    1123            1 :         e->set_thread_done_callback([lock]()
    1124              :             {
    1125            1 :                 lock->stop(true);
    1126            1 :             });
    1127              : 
    1128              :         try
    1129              :         {
    1130            1 :             lock->run();
    1131              :         }
    1132            0 :         catch(std::exception const & ex)
    1133              :         {
    1134            0 :             SNAP_LOG_FATAL
    1135              :                 << "an exception occurred while running cluckd (entering timing out): "
    1136              :                 << ex
    1137              :                 << SNAP_LOG_SEND;
    1138              : 
    1139            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
    1140            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
    1141              :             {
    1142            0 :                 SNAP_LOG_FATAL
    1143              :                     << "    "
    1144              :                     << line
    1145              :                     << SNAP_LOG_SEND;
    1146              :             }
    1147              : 
    1148            0 :             throw;
    1149            0 :         }
    1150              : 
    1151            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    1152              : 
    1153            1 :         cluck::set_lock_obtention_timeout(default_obtention_timeout);
    1154            1 :     }
    1155            5 :     CATCH_END_SECTION()
    1156              : 
    1157            6 :     CATCH_START_SECTION("cluck_daemon_failures: send a DROP_TICKET to cancel an entering LOCK")
    1158              :     {
    1159            1 :         addr::addr a(get_address());
    1160              : 
    1161            1 :         std::vector<std::string> const args = {
    1162              :             "cluckd", // name of command
    1163              :             "--candidate-priority",
    1164              :             "10",
    1165              :             "--communicatord-listen",
    1166            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
    1167              :             "--path-to-message-definitions",
    1168              : 
    1169              :             // WARNING: the order matters, we want to test with our source
    1170              :             //          (i.e. original) files first
    1171              :             //
    1172            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
    1173            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
    1174              : 
    1175              :             "--server-name",
    1176              :             snapdev::gethostname(),
    1177           13 :         };
    1178              : 
    1179              :         // convert arguments
    1180              :         //
    1181            1 :         std::vector<char const *> args_strings;
    1182            1 :         args_strings.reserve(args.size() + 1);
    1183           10 :         for(auto const & arg : args)
    1184              :         {
    1185            9 :             args_strings.push_back(arg.c_str());
    1186              :         }
    1187            1 :         args_strings.push_back(nullptr); // NULL terminated
    1188              : 
    1189            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
    1190            1 :         lock->add_connections();
    1191              : 
    1192            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    1193            1 :         std::string const filename(source_dir + "/tests/rprtr/drop_entering_ticket.rprtr");
    1194            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    1195            1 :         CATCH_REQUIRE(l != nullptr);
    1196            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    1197            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    1198            1 :         p->parse_program();
    1199              : 
    1200            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    1201            1 :         e->start();
    1202              : 
    1203            1 :         e->set_thread_done_callback([lock]()
    1204              :             {
    1205            1 :                 lock->stop(true);
    1206            1 :             });
    1207              : 
    1208              :         try
    1209              :         {
    1210            1 :             lock->run();
    1211              :         }
    1212            0 :         catch(std::exception const & ex)
    1213              :         {
    1214            0 :             SNAP_LOG_FATAL
    1215              :                 << "an exception occurred while running cluckd (get max ticket overflow): "
    1216              :                 << ex
    1217              :                 << SNAP_LOG_SEND;
    1218              : 
    1219            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
    1220            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
    1221              :             {
    1222            0 :                 SNAP_LOG_FATAL
    1223              :                     << "    "
    1224              :                     << line
    1225              :                     << SNAP_LOG_SEND;
    1226              :             }
    1227              : 
    1228            0 :             throw;
    1229            0 :         }
    1230              : 
    1231            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    1232            1 :     }
    1233            5 :     CATCH_END_SECTION()
    1234           24 : }
    1235              : 
    1236              : 
    1237            6 : CATCH_TEST_CASE("cluck_daemon_errors", "[cluckd][daemon][error]")
    1238              : {
    1239            8 :     CATCH_START_SECTION("cluck_daemon_errors: invalid logger parameter")
    1240              :     {
    1241            1 :         SNAP_CATCH2_NAMESPACE::reset_log_errors safe_counters;
    1242            1 :         char const * const args[] = {
    1243              :             "cluckd", // name of command
    1244              :             "--log-severity",
    1245              :             "unknown-severity-name",
    1246              :             nullptr
    1247              :         };
    1248              : 
    1249            6 :         CATCH_REQUIRE_THROWS_MATCHES(
    1250              :               std::make_shared<cluck_daemon::cluckd>(3, const_cast<char **>(args))
    1251              :             , advgetopt::getopt_exit
    1252              :             , Catch::Matchers::ExceptionMessage("getopt_exception: logger options generated an error."));
    1253            1 :     }
    1254            7 :     CATCH_END_SECTION()
    1255              : 
    1256            8 :     CATCH_START_SECTION("cluck_daemon_errors: standalone command line options are not allowed")
    1257              :     {
    1258            1 :         SNAP_CATCH2_NAMESPACE::reset_log_errors safe_counters;
    1259            1 :         char const * const args[] = {
    1260              :             "cluckd", // name of command
    1261              :             "filename",
    1262              :             nullptr
    1263              :         };
    1264              : 
    1265            6 :         CATCH_REQUIRE_THROWS_MATCHES(
    1266              :               std::make_shared<cluck_daemon::cluckd>(2, const_cast<char **>(args))
    1267              :             , advgetopt::getopt_exit
    1268              :             , Catch::Matchers::ExceptionMessage("getopt_exception: errors were found on your command line, environment variable, or configuration file."));
    1269            1 :     }
    1270            7 :     CATCH_END_SECTION()
    1271              : 
    1272            8 :     CATCH_START_SECTION("cluck_daemon_errors: double severity")
    1273              :     {
    1274            1 :         SNAP_CATCH2_NAMESPACE::reset_log_errors safe_counters;
    1275            1 :         char const * const args[] = {
    1276              :             "cluckd", // name of command
    1277              :             "--log-severity",
    1278              :             "INFO",
    1279              :             "ERROR",        // oops, the log severity level "leaked"
    1280              :             nullptr
    1281              :         };
    1282              : 
    1283            6 :         CATCH_REQUIRE_THROWS_MATCHES(
    1284              :               std::make_shared<cluck_daemon::cluckd>(4, const_cast<char **>(args))
    1285              :             , advgetopt::getopt_exit
    1286              :             , Catch::Matchers::ExceptionMessage("getopt_exception: errors were found on your command line, environment variable, or configuration file."));
    1287            1 :     }
    1288            7 :     CATCH_END_SECTION()
    1289              : 
    1290            8 :     CATCH_START_SECTION("cluck_daemon_errors: get max ticket overflow")
    1291              :     {
    1292            1 :         addr::addr a(get_address());
    1293              : 
    1294            1 :         std::vector<std::string> const args = {
    1295              :             "cluckd", // name of command
    1296              :             "--candidate-priority",
    1297              :             "10",
    1298              :             "--communicatord-listen",
    1299            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
    1300              :             "--path-to-message-definitions",
    1301              : 
    1302              :             // WARNING: the order matters, we want to test with our source
    1303              :             //          (i.e. original) files first
    1304              :             //
    1305            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
    1306            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
    1307           11 :         };
    1308              : 
    1309              :         // convert arguments
    1310              :         //
    1311            1 :         std::vector<char const *> args_strings;
    1312            1 :         args_strings.reserve(args.size() + 1);
    1313            8 :         for(auto const & arg : args)
    1314              :         {
    1315            7 :             args_strings.push_back(arg.c_str());
    1316              :         }
    1317            1 :         args_strings.push_back(nullptr); // NULL terminated
    1318              : 
    1319            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
    1320            1 :         lock->add_connections();
    1321              : 
    1322            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    1323            1 :         std::string const filename(source_dir + "/tests/rprtr/failed_with_max_ticket_too_large.rprtr");
    1324            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    1325            1 :         CATCH_REQUIRE(l != nullptr);
    1326            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    1327            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    1328            1 :         p->parse_program();
    1329              : 
    1330            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    1331            1 :         e->start();
    1332              : 
    1333            1 :         e->set_thread_done_callback([lock]()
    1334              :             {
    1335            1 :                 lock->stop(true);
    1336            1 :             });
    1337              : 
    1338              :         try
    1339              :         {
    1340            1 :             lock->run();
    1341              :         }
    1342            1 :         catch(cluck::out_of_range const & ex)
    1343              :         {
    1344            2 :             SNAP_LOG_INFO
    1345              :                 << "got the expected exception: "
    1346              :                 << ex
    1347              :                 << SNAP_LOG_SEND;
    1348              : 
    1349            3 :             std::string const expected("out_of_range: ticket::max_ticket() tried to generate the next ticket and got a wrapping around number.");
    1350            1 :             CATCH_REQUIRE(ex.what() == expected);
    1351              : 
    1352              :             // the communicator daemon may still have connections because of
    1353              :             // the exception
    1354              :             //
    1355            1 :             ed::connection::vector_t connections(ed::communicator::instance()->get_connections());
    1356            1 :             for(auto c : connections)
    1357              :             {
    1358            0 :                 ed::communicator::instance()->remove_connection(c);
    1359            0 :             }
    1360            2 :         }
    1361            0 :         catch(std::exception const & ex)
    1362              :         {
    1363            0 :             SNAP_LOG_FATAL
    1364              :                 << "an exception occurred while running cluckd (get max ticket overflow): "
    1365              :                 << ex
    1366              :                 << SNAP_LOG_SEND;
    1367              : 
    1368            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
    1369            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
    1370              :             {
    1371            0 :                 SNAP_LOG_FATAL
    1372              :                     << "    "
    1373              :                     << line
    1374              :                     << SNAP_LOG_SEND;
    1375              :             }
    1376              : 
    1377            0 :             throw;
    1378            0 :         }
    1379              : 
    1380            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    1381            1 :     }
    1382            7 :     CATCH_END_SECTION()
    1383              : 
    1384            8 :     CATCH_START_SECTION("cluck_daemon_errors: too many computers are off")
    1385              :     {
    1386            1 :         addr::addr a(get_address());
    1387              : 
    1388            5 :         for(int version(1); version <= 4; ++version)
    1389              :         {
    1390           14 :             for(int off_mask(1); off_mask < (version == 4 ? 8 : 2); ++off_mask)
    1391              :             {
    1392           10 :                 std::string diagnostic_msg("version: " + std::to_string(version));
    1393           10 :                 if(version == 4)
    1394              :                 {
    1395            7 :                     diagnostic_msg += '/';
    1396            7 :                     diagnostic_msg += std::to_string(off_mask);
    1397              :                 }
    1398           10 :                 ::snaplogger::nested_diagnostic version_diagnostic(diagnostic_msg, true);
    1399              : 
    1400           10 :                 std::vector<std::string> const args = {
    1401              :                     "cluckd", // name of command
    1402              :                     "--candidate-priority",
    1403            9 :                     (version == 2 || (version == 4 && (off_mask & 0x04) != 0) ? "15" : "10"),
    1404              :                     "--communicatord-listen",
    1405           20 :                     "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
    1406              :                     "--path-to-message-definitions",
    1407              : 
    1408              :                     // WARNING: the order matters, we want to test with our source
    1409              :                     //          (i.e. original) files first
    1410              :                     //
    1411           20 :                     SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
    1412           40 :                         + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
    1413          110 :                 };
    1414              : 
    1415              :                 // convert arguments
    1416              :                 //
    1417           10 :                 std::vector<char const *> args_strings;
    1418           10 :                 args_strings.reserve(args.size() + 1);
    1419           80 :                 for(auto const & arg : args)
    1420              :                 {
    1421           70 :                     args_strings.push_back(arg.c_str());
    1422              :                 }
    1423           10 :                 args_strings.push_back(nullptr); // NULL terminated
    1424              : 
    1425           10 :                 cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
    1426           10 :                 lock->add_connections();
    1427              : 
    1428           10 :                 std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    1429           10 :                 std::string const filename(source_dir + "/tests/rprtr/failed_with_too_many_off_v" + std::to_string(version) + ".rprtr");
    1430           10 :                 SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    1431           10 :                 CATCH_REQUIRE(l != nullptr);
    1432           10 :                 SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    1433           10 :                 if(version == 4)
    1434              :                 {
    1435            7 :                     SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t var(
    1436              :                             std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(
    1437            7 :                                       "off_mask"));
    1438            7 :                     var->set_integer(off_mask);
    1439            7 :                     s->set_variable(var);
    1440            7 :                 }
    1441           10 :                 SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    1442           10 :                 p->parse_program();
    1443              : 
    1444           10 :                 SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    1445           10 :                 e->start();
    1446              : 
    1447           10 :                 e->set_thread_done_callback([lock]()
    1448              :                     {
    1449           10 :                         lock->stop(true);
    1450           10 :                     });
    1451              : 
    1452              :                 try
    1453              :                 {
    1454           10 :                     lock->run();
    1455              :                 }
    1456            0 :                 catch(std::exception const & ex)
    1457              :                 {
    1458            0 :                     SNAP_LOG_FATAL
    1459              :                         << "an exception occurred while running cluckd (get max ticket overflow): "
    1460              :                         << ex
    1461              :                         << SNAP_LOG_SEND;
    1462              : 
    1463            0 :                     libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
    1464            0 :                     if(b != nullptr) for(auto const & line : b->get_stack_trace())
    1465              :                     {
    1466            0 :                         SNAP_LOG_FATAL
    1467              :                             << "    "
    1468              :                             << line
    1469              :                             << SNAP_LOG_SEND;
    1470              :                     }
    1471              : 
    1472            0 :                     throw;
    1473            0 :                 }
    1474              : 
    1475           10 :                 CATCH_REQUIRE(s->get_exit_code() == 0);
    1476           10 :             }
    1477              :         }
    1478            1 :     }
    1479            7 :     CATCH_END_SECTION()
    1480              : 
    1481            8 :     CATCH_START_SECTION("cluck_daemon_errors: 100% time out")
    1482              :     {
    1483            1 :         addr::addr a(get_address());
    1484              : 
    1485            1 :         std::vector<std::string> const args = {
    1486              :             "cluckd", // name of command
    1487              :             "--candidate-priority",
    1488              :             "10",
    1489              :             "--communicatord-listen",
    1490            2 :             "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
    1491              :             "--path-to-message-definitions",
    1492              : 
    1493              :             // WARNING: the order matters, we want to test with our source
    1494              :             //          (i.e. original) files first
    1495              :             //
    1496            2 :             SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
    1497            4 :                 + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
    1498           11 :         };
    1499              : 
    1500              :         // convert arguments
    1501              :         //
    1502            1 :         std::vector<char const *> args_strings;
    1503            1 :         args_strings.reserve(args.size() + 1);
    1504            8 :         for(auto const & arg : args)
    1505              :         {
    1506            7 :             args_strings.push_back(arg.c_str());
    1507              :         }
    1508            1 :         args_strings.push_back(nullptr); // NULL terminated
    1509              : 
    1510            1 :         cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
    1511            1 :         lock->add_connections();
    1512              : 
    1513            1 :         std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
    1514            1 :         std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_timeout.rprtr");
    1515            1 :         SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
    1516            1 :         CATCH_REQUIRE(l != nullptr);
    1517            1 :         SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
    1518            1 :         SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
    1519            1 :         p->parse_program();
    1520              : 
    1521            1 :         SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
    1522            1 :         e->start();
    1523              : 
    1524            1 :         e->set_thread_done_callback([lock]()
    1525              :             {
    1526            1 :                 lock->stop(true);
    1527            1 :             });
    1528              : 
    1529              :         try
    1530              :         {
    1531            1 :             lock->run();
    1532              :         }
    1533            0 :         catch(std::exception const & ex)
    1534              :         {
    1535            0 :             SNAP_LOG_FATAL
    1536              :                 << "an exception occurred while running cluckd (get max ticket overflow): "
    1537              :                 << ex
    1538              :                 << SNAP_LOG_SEND;
    1539              : 
    1540            0 :             libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
    1541            0 :             if(b != nullptr) for(auto const & line : b->get_stack_trace())
    1542              :             {
    1543            0 :                 SNAP_LOG_FATAL
    1544              :                     << "    "
    1545              :                     << line
    1546              :                     << SNAP_LOG_SEND;
    1547              :             }
    1548              : 
    1549            0 :             throw;
    1550            0 :         }
    1551              : 
    1552            1 :         CATCH_REQUIRE(s->get_exit_code() == 0);
    1553            1 :     }
    1554            7 :     CATCH_END_SECTION()
    1555           75 : }
    1556              : 
    1557              : 
    1558              : 
    1559              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

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