Home | History | Annotate | Line # | Download | only in tools
signals_test.cpp revision 1.1
      1 //
      2 // Automated Testing Framework (atf)
      3 //
      4 // Copyright (c) 2008 The NetBSD Foundation, Inc.
      5 // All rights reserved.
      6 //
      7 // Redistribution and use in source and binary forms, with or without
      8 // modification, are permitted provided that the following conditions
      9 // are met:
     10 // 1. Redistributions of source code must retain the above copyright
     11 //    notice, this list of conditions and the following disclaimer.
     12 // 2. Redistributions in binary form must reproduce the above copyright
     13 //    notice, this list of conditions and the following disclaimer in the
     14 //    documentation and/or other materials provided with the distribution.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 //
     29 
     30 extern "C" {
     31 #include <sys/types.h>
     32 #include <signal.h>
     33 #include <unistd.h>
     34 }
     35 
     36 #include <cerrno>
     37 #include <cstdlib>
     38 #include <iostream>
     39 
     40 #include <atf-c++.hpp>
     41 
     42 #include "defs.hpp"
     43 #include "exceptions.hpp"
     44 #include "process.hpp"
     45 #include "signals.hpp"
     46 
     47 // ------------------------------------------------------------------------
     48 // Auxiliary functions.
     49 // ------------------------------------------------------------------------
     50 
     51 namespace sigusr1 {
     52     static bool happened = false;
     53 
     54     static
     55     void
     56     handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED)
     57     {
     58         happened = true;
     59     }
     60 
     61     static
     62     void
     63     program(void)
     64     {
     65         struct sigaction sa;
     66         sa.sa_handler = handler;
     67         sigemptyset(&sa.sa_mask);
     68         sa.sa_flags = 0;
     69         if (::sigaction(SIGUSR1, &sa, NULL) == -1)
     70             throw tools::system_error("sigusr1::program",
     71                                     "sigaction(2) failed", errno);
     72     }
     73 } // namespace sigusr1
     74 
     75 namespace sigusr1_2 {
     76     static bool happened = false;
     77 
     78     static
     79     void
     80     handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED)
     81     {
     82         happened = true;
     83     }
     84 } // namespace sigusr1_2
     85 
     86 // ------------------------------------------------------------------------
     87 // Tests for the "signal_holder" class.
     88 // ------------------------------------------------------------------------
     89 
     90 ATF_TEST_CASE(signal_holder_preserve);
     91 ATF_TEST_CASE_HEAD(signal_holder_preserve)
     92 {
     93     set_md_var("descr", "Tests that signal_holder preserves the original "
     94                "signal handler and restores it upon destruction");
     95 }
     96 ATF_TEST_CASE_BODY(signal_holder_preserve)
     97 {
     98     using tools::signals::signal_holder;
     99 
    100     sigusr1::program();
    101 
    102     sigusr1::happened = false;
    103     ::kill(::getpid(), SIGUSR1);
    104     ATF_REQUIRE(sigusr1::happened);
    105 
    106     {
    107         signal_holder hld(SIGUSR1);
    108         ::kill(::getpid(), SIGUSR1);
    109     }
    110 
    111     sigusr1::happened = false;
    112     ::kill(::getpid(), SIGUSR1);
    113     ATF_REQUIRE(sigusr1::happened);
    114 }
    115 
    116 ATF_TEST_CASE(signal_holder_destructor);
    117 ATF_TEST_CASE_HEAD(signal_holder_destructor)
    118 {
    119     set_md_var("descr", "Tests that signal_holder processes a pending "
    120                "signal upon destruction");
    121 }
    122 ATF_TEST_CASE_BODY(signal_holder_destructor)
    123 {
    124     using tools::signals::signal_holder;
    125 
    126     sigusr1::program();
    127 
    128     sigusr1::happened = false;
    129     ::kill(::getpid(), SIGUSR1);
    130     ATF_REQUIRE(sigusr1::happened);
    131 
    132     {
    133         signal_holder hld(SIGUSR1);
    134 
    135         sigusr1::happened = false;
    136         ::kill(::getpid(), SIGUSR1);
    137         ATF_REQUIRE(!sigusr1::happened);
    138     }
    139     ATF_REQUIRE(sigusr1::happened);
    140 }
    141 
    142 ATF_TEST_CASE(signal_holder_process);
    143 ATF_TEST_CASE_HEAD(signal_holder_process)
    144 {
    145     set_md_var("descr", "Tests that signal_holder's process method works "
    146                "to process a delayed signal explicitly");
    147 }
    148 ATF_TEST_CASE_BODY(signal_holder_process)
    149 {
    150     using tools::signals::signal_holder;
    151 
    152     sigusr1::program();
    153 
    154     sigusr1::happened = false;
    155     ::kill(::getpid(), SIGUSR1);
    156     ATF_REQUIRE(sigusr1::happened);
    157 
    158     {
    159         signal_holder hld(SIGUSR1);
    160 
    161         sigusr1::happened = false;
    162         ::kill(::getpid(), SIGUSR1);
    163         ATF_REQUIRE(!sigusr1::happened);
    164 
    165         hld.process();
    166         ATF_REQUIRE(sigusr1::happened);
    167 
    168         sigusr1::happened = false;
    169     }
    170     ATF_REQUIRE(!sigusr1::happened);
    171 }
    172 
    173 // ------------------------------------------------------------------------
    174 // Tests for the "signal_programmer" class.
    175 // ------------------------------------------------------------------------
    176 
    177 ATF_TEST_CASE(signal_programmer_program);
    178 ATF_TEST_CASE_HEAD(signal_programmer_program)
    179 {
    180     set_md_var("descr", "Tests that signal_programmer correctly installs a "
    181                "handler");
    182 }
    183 ATF_TEST_CASE_BODY(signal_programmer_program)
    184 {
    185     using tools::signals::signal_programmer;
    186 
    187     signal_programmer sp(SIGUSR1, sigusr1_2::handler);
    188 
    189     sigusr1_2::happened = false;
    190     ::kill(::getpid(), SIGUSR1);
    191     ATF_REQUIRE(sigusr1_2::happened);
    192 }
    193 
    194 ATF_TEST_CASE(signal_programmer_preserve);
    195 ATF_TEST_CASE_HEAD(signal_programmer_preserve)
    196 {
    197     set_md_var("descr", "Tests that signal_programmer uninstalls the "
    198                "handler during destruction");
    199 }
    200 ATF_TEST_CASE_BODY(signal_programmer_preserve)
    201 {
    202     using tools::signals::signal_programmer;
    203 
    204     sigusr1::program();
    205     sigusr1::happened = false;
    206 
    207     {
    208         signal_programmer sp(SIGUSR1, sigusr1_2::handler);
    209 
    210         sigusr1_2::happened = false;
    211         ::kill(::getpid(), SIGUSR1);
    212         ATF_REQUIRE(sigusr1_2::happened);
    213     }
    214 
    215     ATF_REQUIRE(!sigusr1::happened);
    216     ::kill(::getpid(), SIGUSR1);
    217     ATF_REQUIRE(sigusr1::happened);
    218 }
    219 
    220 // ------------------------------------------------------------------------
    221 // Tests cases for the free functions.
    222 // ------------------------------------------------------------------------
    223 
    224 static
    225 void
    226 reset_child(void *v ATF_DEFS_ATTRIBUTE_UNUSED)
    227 {
    228     sigusr1::program();
    229 
    230     sigusr1::happened = false;
    231     tools::signals::reset(SIGUSR1);
    232     kill(::getpid(), SIGUSR1);
    233 
    234     if (sigusr1::happened) {
    235         std::cerr << "Signal was not resetted correctly\n";
    236         std::abort();
    237     } else {
    238         std::exit(EXIT_SUCCESS);
    239     }
    240 }
    241 
    242 ATF_TEST_CASE(reset);
    243 ATF_TEST_CASE_HEAD(reset)
    244 {
    245     set_md_var("descr", "Tests the reset function");
    246 }
    247 ATF_TEST_CASE_BODY(reset)
    248 {
    249     tools::process::child c =
    250         tools::process::fork(reset_child, tools::process::stream_inherit(),
    251                            tools::process::stream_inherit(), NULL);
    252 
    253     const tools::process::status s = c.wait();
    254     ATF_REQUIRE(s.exited() || s.signaled());
    255     ATF_REQUIRE(!s.signaled() || s.termsig() == SIGUSR1);
    256 }
    257 
    258 // ------------------------------------------------------------------------
    259 // Main.
    260 // ------------------------------------------------------------------------
    261 
    262 ATF_INIT_TEST_CASES(tcs)
    263 {
    264     // Add the tests for the "signal_holder" class.
    265     ATF_ADD_TEST_CASE(tcs, signal_holder_preserve);
    266     ATF_ADD_TEST_CASE(tcs, signal_holder_destructor);
    267     ATF_ADD_TEST_CASE(tcs, signal_holder_process);
    268 
    269     // Add the tests for the "signal_programmer" class.
    270     ATF_ADD_TEST_CASE(tcs, signal_programmer_program);
    271     ATF_ADD_TEST_CASE(tcs, signal_programmer_preserve);
    272 
    273     // Add the test cases for the free functions.
    274     ATF_ADD_TEST_CASE(tcs, reset);
    275 }
    276