signals_test.cpp revision 1.1.1.1
1// 2// Automated Testing Framework (atf) 3// 4// Copyright (c) 2008, 2009, 2010 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 30extern "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++/macros.hpp" 41 42#include "atf-c++/detail/exceptions.hpp" 43#include "atf-c++/detail/process.hpp" 44 45#include "signals.hpp" 46 47// ------------------------------------------------------------------------ 48// Auxiliary functions. 49// ------------------------------------------------------------------------ 50 51namespace sigusr1 { 52 static bool happened = false; 53 54 static 55 void 56 handler(int signo) 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 atf::system_error("sigusr1::program", 71 "sigaction(2) failed", errno); 72 } 73} // namespace sigusr1 74 75namespace sigusr1_2 { 76 static bool happened = false; 77 78 static 79 void 80 handler(int signo) 81 { 82 happened = true; 83 } 84} // namespace sigusr1_2 85 86// ------------------------------------------------------------------------ 87// Tests for the "signal_holder" class. 88// ------------------------------------------------------------------------ 89 90ATF_TEST_CASE(signal_holder_preserve); 91ATF_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} 96ATF_TEST_CASE_BODY(signal_holder_preserve) 97{ 98 using atf::atf_run::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 116ATF_TEST_CASE(signal_holder_destructor); 117ATF_TEST_CASE_HEAD(signal_holder_destructor) 118{ 119 set_md_var("descr", "Tests that signal_holder processes a pending " 120 "signal upon destruction"); 121} 122ATF_TEST_CASE_BODY(signal_holder_destructor) 123{ 124 using atf::atf_run::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 142ATF_TEST_CASE(signal_holder_process); 143ATF_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} 148ATF_TEST_CASE_BODY(signal_holder_process) 149{ 150 using atf::atf_run::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 177ATF_TEST_CASE(signal_programmer_program); 178ATF_TEST_CASE_HEAD(signal_programmer_program) 179{ 180 set_md_var("descr", "Tests that signal_programmer correctly installs a " 181 "handler"); 182} 183ATF_TEST_CASE_BODY(signal_programmer_program) 184{ 185 using atf::atf_run::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 194ATF_TEST_CASE(signal_programmer_preserve); 195ATF_TEST_CASE_HEAD(signal_programmer_preserve) 196{ 197 set_md_var("descr", "Tests that signal_programmer uninstalls the " 198 "handler during destruction"); 199} 200ATF_TEST_CASE_BODY(signal_programmer_preserve) 201{ 202 using atf::atf_run::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 224static 225void 226reset_child(void *v) 227{ 228 sigusr1::program(); 229 230 sigusr1::happened = false; 231 atf::atf_run::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 242ATF_TEST_CASE(reset); 243ATF_TEST_CASE_HEAD(reset) 244{ 245 set_md_var("descr", "Tests the reset function"); 246} 247ATF_TEST_CASE_BODY(reset) 248{ 249 atf::process::child c = 250 atf::process::fork(reset_child, atf::process::stream_inherit(), 251 atf::process::stream_inherit(), NULL); 252 253 const atf::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 262ATF_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