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/defs.h" 41 42 #include "atf-c++/macros.hpp" 43 44 #include "atf-c++/detail/exceptions.hpp" 45 #include "atf-c++/detail/process.hpp" 46 47 #include "signals.hpp" 48 49 // ------------------------------------------------------------------------ 50 // Auxiliary functions. 51 // ------------------------------------------------------------------------ 52 53 namespace sigusr1 { 54 static bool happened = false; 55 56 static 57 void 58 handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED) 59 { 60 happened = true; 61 } 62 63 static 64 void 65 program(void) 66 { 67 struct sigaction sa; 68 sa.sa_handler = handler; 69 sigemptyset(&sa.sa_mask); 70 sa.sa_flags = 0; 71 if (::sigaction(SIGUSR1, &sa, NULL) == -1) 72 throw atf::system_error("sigusr1::program", 73 "sigaction(2) failed", errno); 74 } 75 } // namespace sigusr1 76 77 namespace sigusr1_2 { 78 static bool happened = false; 79 80 static 81 void 82 handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED) 83 { 84 happened = true; 85 } 86 } // namespace sigusr1_2 87 88 // ------------------------------------------------------------------------ 89 // Tests for the "signal_holder" class. 90 // ------------------------------------------------------------------------ 91 92 ATF_TEST_CASE(signal_holder_preserve); 93 ATF_TEST_CASE_HEAD(signal_holder_preserve) 94 { 95 set_md_var("descr", "Tests that signal_holder preserves the original " 96 "signal handler and restores it upon destruction"); 97 } 98 ATF_TEST_CASE_BODY(signal_holder_preserve) 99 { 100 using atf::atf_run::signal_holder; 101 102 sigusr1::program(); 103 104 sigusr1::happened = false; 105 ::kill(::getpid(), SIGUSR1); 106 ATF_REQUIRE(sigusr1::happened); 107 108 { 109 signal_holder hld(SIGUSR1); 110 ::kill(::getpid(), SIGUSR1); 111 } 112 113 sigusr1::happened = false; 114 ::kill(::getpid(), SIGUSR1); 115 ATF_REQUIRE(sigusr1::happened); 116 } 117 118 ATF_TEST_CASE(signal_holder_destructor); 119 ATF_TEST_CASE_HEAD(signal_holder_destructor) 120 { 121 set_md_var("descr", "Tests that signal_holder processes a pending " 122 "signal upon destruction"); 123 } 124 ATF_TEST_CASE_BODY(signal_holder_destructor) 125 { 126 using atf::atf_run::signal_holder; 127 128 sigusr1::program(); 129 130 sigusr1::happened = false; 131 ::kill(::getpid(), SIGUSR1); 132 ATF_REQUIRE(sigusr1::happened); 133 134 { 135 signal_holder hld(SIGUSR1); 136 137 sigusr1::happened = false; 138 ::kill(::getpid(), SIGUSR1); 139 ATF_REQUIRE(!sigusr1::happened); 140 } 141 ATF_REQUIRE(sigusr1::happened); 142 } 143 144 ATF_TEST_CASE(signal_holder_process); 145 ATF_TEST_CASE_HEAD(signal_holder_process) 146 { 147 set_md_var("descr", "Tests that signal_holder's process method works " 148 "to process a delayed signal explicitly"); 149 } 150 ATF_TEST_CASE_BODY(signal_holder_process) 151 { 152 using atf::atf_run::signal_holder; 153 154 sigusr1::program(); 155 156 sigusr1::happened = false; 157 ::kill(::getpid(), SIGUSR1); 158 ATF_REQUIRE(sigusr1::happened); 159 160 { 161 signal_holder hld(SIGUSR1); 162 163 sigusr1::happened = false; 164 ::kill(::getpid(), SIGUSR1); 165 ATF_REQUIRE(!sigusr1::happened); 166 167 hld.process(); 168 ATF_REQUIRE(sigusr1::happened); 169 170 sigusr1::happened = false; 171 } 172 ATF_REQUIRE(!sigusr1::happened); 173 } 174 175 // ------------------------------------------------------------------------ 176 // Tests for the "signal_programmer" class. 177 // ------------------------------------------------------------------------ 178 179 ATF_TEST_CASE(signal_programmer_program); 180 ATF_TEST_CASE_HEAD(signal_programmer_program) 181 { 182 set_md_var("descr", "Tests that signal_programmer correctly installs a " 183 "handler"); 184 } 185 ATF_TEST_CASE_BODY(signal_programmer_program) 186 { 187 using atf::atf_run::signal_programmer; 188 189 signal_programmer sp(SIGUSR1, sigusr1_2::handler); 190 191 sigusr1_2::happened = false; 192 ::kill(::getpid(), SIGUSR1); 193 ATF_REQUIRE(sigusr1_2::happened); 194 } 195 196 ATF_TEST_CASE(signal_programmer_preserve); 197 ATF_TEST_CASE_HEAD(signal_programmer_preserve) 198 { 199 set_md_var("descr", "Tests that signal_programmer uninstalls the " 200 "handler during destruction"); 201 } 202 ATF_TEST_CASE_BODY(signal_programmer_preserve) 203 { 204 using atf::atf_run::signal_programmer; 205 206 sigusr1::program(); 207 sigusr1::happened = false; 208 209 { 210 signal_programmer sp(SIGUSR1, sigusr1_2::handler); 211 212 sigusr1_2::happened = false; 213 ::kill(::getpid(), SIGUSR1); 214 ATF_REQUIRE(sigusr1_2::happened); 215 } 216 217 ATF_REQUIRE(!sigusr1::happened); 218 ::kill(::getpid(), SIGUSR1); 219 ATF_REQUIRE(sigusr1::happened); 220 } 221 222 // ------------------------------------------------------------------------ 223 // Tests cases for the free functions. 224 // ------------------------------------------------------------------------ 225 226 static 227 void 228 reset_child(void *v ATF_DEFS_ATTRIBUTE_UNUSED) 229 { 230 sigusr1::program(); 231 232 sigusr1::happened = false; 233 atf::atf_run::reset(SIGUSR1); 234 kill(::getpid(), SIGUSR1); 235 236 if (sigusr1::happened) { 237 std::cerr << "Signal was not resetted correctly\n"; 238 std::abort(); 239 } else { 240 std::exit(EXIT_SUCCESS); 241 } 242 } 243 244 ATF_TEST_CASE(reset); 245 ATF_TEST_CASE_HEAD(reset) 246 { 247 set_md_var("descr", "Tests the reset function"); 248 } 249 ATF_TEST_CASE_BODY(reset) 250 { 251 atf::process::child c = 252 atf::process::fork(reset_child, atf::process::stream_inherit(), 253 atf::process::stream_inherit(), NULL); 254 255 const atf::process::status s = c.wait(); 256 ATF_REQUIRE(s.exited() || s.signaled()); 257 ATF_REQUIRE(!s.signaled() || s.termsig() == SIGUSR1); 258 } 259 260 // ------------------------------------------------------------------------ 261 // Main. 262 // ------------------------------------------------------------------------ 263 264 ATF_INIT_TEST_CASES(tcs) 265 { 266 // Add the tests for the "signal_holder" class. 267 ATF_ADD_TEST_CASE(tcs, signal_holder_preserve); 268 ATF_ADD_TEST_CASE(tcs, signal_holder_destructor); 269 ATF_ADD_TEST_CASE(tcs, signal_holder_process); 270 271 // Add the tests for the "signal_programmer" class. 272 ATF_ADD_TEST_CASE(tcs, signal_programmer_program); 273 ATF_ADD_TEST_CASE(tcs, signal_programmer_preserve); 274 275 // Add the test cases for the free functions. 276 ATF_ADD_TEST_CASE(tcs, reset); 277 } 278