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