LCOV - code coverage report
Current view: top level - tests - catch_signal_handler.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 72.7 % 66 48
Test Date: 2025-05-30 15:24:13 Functions: 66.7 % 6 4
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            1 :             , &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            7 :         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            6 :         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            5 :         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 2.0-1

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