LCOV - code coverage report
Current view: top level - tests - catch_signal_handler.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 48 66 72.7 %
Date: 2024-09-14 18:11:21 Functions: 4 6 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012-2024  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/eventdispatcher
       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 2 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 along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      19             : 
      20             : // test standalone header
      21             : //
      22             : #include    <eventdispatcher/signal_handler.h>
      23             : 
      24             : 
      25             : // self
      26             : //
      27             : #include    "catch_main.h"
      28             : 
      29             : 
      30             : // eventdispatcher
      31             : //
      32             : #include    <eventdispatcher/communicator.h>
      33             : #include    <eventdispatcher/dispatcher.h>
      34             : 
      35             : 
      36             : // C
      37             : //
      38             : #include    <unistd.h>
      39             : 
      40             : 
      41             : // last include
      42             : //
      43             : #include    <snapdev/poison.h>
      44             : 
      45             : 
      46             : 
      47             : 
      48             : namespace
      49             : {
      50             : 
      51             : 
      52             : 
      53             : int g_expected_sig = -1;
      54             : 
      55           0 : bool signal_handler_callback(
      56             :       ed::signal_handler::callback_id_t callback_id
      57             :     , int callback_sig
      58             :     , siginfo_t const * info
      59             :     , ucontext_t const * ucontext)
      60             : {
      61           0 :     CATCH_REQUIRE(g_expected_sig == callback_sig);
      62           0 :     g_expected_sig = -1;
      63             : 
      64           0 : std::cerr << "--- signal_handler_callback() was called... id: "
      65           0 : << callback_id
      66           0 : << ", sig: " << callback_sig
      67           0 : << ", info->si_pid: " << info->si_pid
      68           0 : << ", ucontext->uc_sigmask: " << std::boolalpha << sigismember(&ucontext->uc_sigmask, SIGINT)
      69           0 : << "\n";
      70             : 
      71             :     // call other callbacks
      72             :     //
      73           0 :     return true;
      74             : }
      75             : 
      76             : 
      77           0 : bool extra_signal_handler_callback(
      78             :       ed::signal_handler::callback_id_t callback_id
      79             :     , int callback_sig
      80             :     , siginfo_t const * info
      81             :     , ucontext_t const * ucontext)
      82             : {
      83           0 : std::cerr << "--- extra_signal_handler_callback() was called... id: "
      84           0 : << callback_id
      85           0 : << ", sig: " << callback_sig
      86           0 : << ", info->si_pid: " << info->si_pid
      87           0 : << ", ucontext->uc_sigmask: " << std::boolalpha << sigismember(&ucontext->uc_sigmask, SIGINT)
      88           0 : << "\n";
      89             : 
      90             :     // call other callbacks
      91             :     //
      92           0 :     return true;
      93             : }
      94             : 
      95             : 
      96           3 : ed::signal_handler::pointer_t get_signal_handler()
      97             : {
      98             :     static bool created(false);
      99             : 
     100           3 :     if(!created)
     101             :     {
     102           1 :         created = true;
     103             : 
     104           1 :         ed::signal_handler::pointer_t sh(ed::signal_handler::create_instance(
     105             :               ed::signal_handler::DEFAULT_SIGNAL_TERMINAL
     106             :             , ed::signal_handler::DEFAULT_SIGNAL_IGNORE
     107             :             , 123
     108             :             , SIGTERM
     109           2 :             , &signal_handler_callback));
     110             : 
     111           1 :         CATCH_REQUIRE(sh != nullptr);
     112           1 :         CATCH_REQUIRE(sh == ed::signal_handler::get_instance());
     113           1 :     }
     114             : 
     115           3 :     return ed::signal_handler::get_instance();
     116             : }
     117             : 
     118             : 
     119             : } // no name namespace
     120             : 
     121             : 
     122             : 
     123           1 : CATCH_TEST_CASE("signal_handler_name", "[signal_handler]")
     124             : {
     125           1 :     CATCH_START_SECTION("signal_handler_name: verify signal names")
     126             :     {
     127          85 :         for(int sig(-10); sig < 74; ++sig)
     128             :         {
     129          84 :             char const * system_name(sigabbrev_np(sig));
     130          84 :             if(system_name == nullptr)
     131             :             {
     132          53 :                 system_name = "UNKNOWN";
     133             :             }
     134             : 
     135          84 :             char const * eventdispatcher_name(ed::signal_handler::get_signal_name(sig));
     136          84 :             if(eventdispatcher_name == nullptr)
     137             :             {
     138          53 :                 eventdispatcher_name = "UNKNOWN";
     139             :             }
     140             : 
     141             : //std::cerr << "--- compare sig=" << sig << " -> \"" << system_name << "\" vs \"" << eventdispatcher_name << "\".\n";
     142          84 :             CATCH_CHECK(strcmp(system_name, eventdispatcher_name) == 0);
     143             :         }
     144             :     }
     145           1 :     CATCH_END_SECTION()
     146           1 : }
     147             : 
     148           1 : CATCH_TEST_CASE("signal_handler", "[signal_handler]")
     149             : {
     150           1 :     CATCH_START_SECTION("signal_handler: Create Signal Handler connection")
     151             :     {
     152           1 :         ed::signal_handler::pointer_t sh(get_signal_handler());
     153             : 
     154             :         // TODO: to test this properly we need to verify that the callback
     155             :         //       get called after an add and not called anymore after a
     156             :         //       remove
     157             :         //
     158           1 :         sh->add_callback(444, SIGILL, &extra_signal_handler_callback);
     159           1 :         sh->remove_callback(444);
     160             : 
     161           1 :         CATCH_CHECK(sh->get_show_stack() == ed::signal_handler::DEFAULT_SHOW_STACK);
     162           1 :         sh->set_show_stack(ed::signal_handler::SIGNAL_INTERRUPT);
     163           1 :         CATCH_CHECK(sh->get_show_stack() == ed::signal_handler::SIGNAL_INTERRUPT);
     164           1 :         sh->set_show_stack(ed::signal_handler::DEFAULT_SHOW_STACK);
     165           1 :         CATCH_CHECK(sh->get_show_stack() == ed::signal_handler::DEFAULT_SHOW_STACK);
     166           1 :     }
     167           1 :     CATCH_END_SECTION()
     168             : 
     169             : // Catch2 v3 is compiled with the POSIX signal handler always in place...
     170             : // The problem is that each time a test is run, the Catch2 signal is setup
     171             : // and then released, so calling get_signal_handler() is already not
     172             : // compatible
     173             : //
     174             : //    CATCH_START_SECTION("signal_handler: Test sending a SIGTERM and see we capture it")
     175             : //    {
     176             : //        ed::signal_handler::pointer_t sh(get_signal_handler());
     177             : //
     178             : //        g_expected_sig = SIGTERM;
     179             : //        kill(getpid(), SIGTERM);
     180             : //        CATCH_REQUIRE(g_expected_sig == -1);
     181             : //    }
     182             : //    CATCH_END_SECTION()
     183           1 : }
     184             : 
     185             : 
     186           2 : CATCH_TEST_CASE("signal_handler_errors", "[timer][error]")
     187             : {
     188           2 :     CATCH_START_SECTION("signal_handler_errors: create_instance() can only be called once")
     189             :     {
     190           1 :         ed::signal_handler::pointer_t sh(get_signal_handler());
     191           1 :         CATCH_REQUIRE(sh != nullptr);
     192             : 
     193             :         // calling the create_instance() a second time is an error
     194             :         //
     195           4 :         CATCH_REQUIRE_THROWS_MATCHES(
     196             :               ed::signal_handler::create_instance(
     197             :                       ed::signal_handler::DEFAULT_SIGNAL_TERMINAL
     198             :                     , ed::signal_handler::DEFAULT_SIGNAL_IGNORE
     199             :                     , 321
     200             :                     , SIGPIPE
     201             :                     , &signal_handler_callback)
     202             :             , ed::initialization_error
     203             :             , Catch::Matchers::ExceptionMessage(
     204             :                   "event_dispatcher_exception: signal_handler::create_instance() must be called once before signal_handler::get_instance() ever gets called."));
     205           1 :     }
     206           2 :     CATCH_END_SECTION()
     207             : 
     208           2 :     CATCH_START_SECTION("signal_handler_errors: invalid signal number & callback pointer")
     209             :     {
     210           1 :         ed::signal_handler::pointer_t sh(get_signal_handler());
     211             : 
     212           4 :         CATCH_REQUIRE_THROWS_MATCHES(
     213             :               sh->add_callback(555, 123, &extra_signal_handler_callback)
     214             :             , ed::invalid_signal
     215             :             , Catch::Matchers::ExceptionMessage(
     216             :                   "event_dispatcher_exception: signal_handler::add_callback() called with invalid signal number 123."));
     217             : 
     218           3 :         CATCH_REQUIRE_THROWS_MATCHES(
     219             :               sh->add_callback(555, SIGBUS, nullptr)
     220             :             , ed::invalid_callback
     221             :             , Catch::Matchers::ExceptionMessage(
     222             :                   "event_dispatcher_exception: signal_handler::add_callback() called with nullptr as the callback."));
     223           1 :     }
     224           2 :     CATCH_END_SECTION()
     225           2 : }
     226             : 
     227             : 
     228             : 
     229             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14

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