1240116Smarcel//
2240116Smarcel// Automated Testing Framework (atf)
3240116Smarcel//
4240116Smarcel// Copyright (c) 2008 The NetBSD Foundation, Inc.
5240116Smarcel// All rights reserved.
6240116Smarcel//
7240116Smarcel// Redistribution and use in source and binary forms, with or without
8240116Smarcel// modification, are permitted provided that the following conditions
9240116Smarcel// are met:
10240116Smarcel// 1. Redistributions of source code must retain the above copyright
11240116Smarcel//    notice, this list of conditions and the following disclaimer.
12240116Smarcel// 2. Redistributions in binary form must reproduce the above copyright
13240116Smarcel//    notice, this list of conditions and the following disclaimer in the
14240116Smarcel//    documentation and/or other materials provided with the distribution.
15240116Smarcel//
16240116Smarcel// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17240116Smarcel// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18240116Smarcel// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19240116Smarcel// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20240116Smarcel// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21240116Smarcel// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22240116Smarcel// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23240116Smarcel// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24240116Smarcel// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25240116Smarcel// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26240116Smarcel// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27240116Smarcel// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28240116Smarcel//
29240116Smarcel
30240116Smarcelextern "C" {
31240116Smarcel#include <sys/types.h>
32240116Smarcel#include <signal.h>
33240116Smarcel#include <unistd.h>
34240116Smarcel}
35240116Smarcel
36240116Smarcel#include <cerrno>
37240116Smarcel#include <cstdlib>
38240116Smarcel#include <iostream>
39240116Smarcel
40240116Smarcel#include "atf-c/defs.h"
41240116Smarcel
42240116Smarcel#include "atf-c++/macros.hpp"
43240116Smarcel
44240116Smarcel#include "atf-c++/detail/exceptions.hpp"
45240116Smarcel#include "atf-c++/detail/process.hpp"
46240116Smarcel
47240116Smarcel#include "signals.hpp"
48240116Smarcel
49240116Smarcel// ------------------------------------------------------------------------
50240116Smarcel// Auxiliary functions.
51240116Smarcel// ------------------------------------------------------------------------
52240116Smarcel
53240116Smarcelnamespace sigusr1 {
54240116Smarcel    static bool happened = false;
55240116Smarcel
56240116Smarcel    static
57240116Smarcel    void
58240116Smarcel    handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED)
59240116Smarcel    {
60240116Smarcel        happened = true;
61240116Smarcel    }
62240116Smarcel
63240116Smarcel    static
64240116Smarcel    void
65240116Smarcel    program(void)
66240116Smarcel    {
67240116Smarcel        struct sigaction sa;
68240116Smarcel        sa.sa_handler = handler;
69240116Smarcel        sigemptyset(&sa.sa_mask);
70240116Smarcel        sa.sa_flags = 0;
71240116Smarcel        if (::sigaction(SIGUSR1, &sa, NULL) == -1)
72240116Smarcel            throw atf::system_error("sigusr1::program",
73240116Smarcel                                    "sigaction(2) failed", errno);
74240116Smarcel    }
75240116Smarcel} // namespace sigusr1
76240116Smarcel
77240116Smarcelnamespace sigusr1_2 {
78240116Smarcel    static bool happened = false;
79240116Smarcel
80240116Smarcel    static
81240116Smarcel    void
82240116Smarcel    handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED)
83240116Smarcel    {
84240116Smarcel        happened = true;
85240116Smarcel    }
86240116Smarcel} // namespace sigusr1_2
87240116Smarcel
88240116Smarcel// ------------------------------------------------------------------------
89240116Smarcel// Tests for the "signal_holder" class.
90240116Smarcel// ------------------------------------------------------------------------
91240116Smarcel
92240116SmarcelATF_TEST_CASE(signal_holder_preserve);
93240116SmarcelATF_TEST_CASE_HEAD(signal_holder_preserve)
94240116Smarcel{
95240116Smarcel    set_md_var("descr", "Tests that signal_holder preserves the original "
96240116Smarcel               "signal handler and restores it upon destruction");
97240116Smarcel}
98240116SmarcelATF_TEST_CASE_BODY(signal_holder_preserve)
99240116Smarcel{
100240116Smarcel    using atf::atf_run::signal_holder;
101240116Smarcel
102240116Smarcel    sigusr1::program();
103240116Smarcel
104240116Smarcel    sigusr1::happened = false;
105240116Smarcel    ::kill(::getpid(), SIGUSR1);
106240116Smarcel    ATF_REQUIRE(sigusr1::happened);
107240116Smarcel
108240116Smarcel    {
109240116Smarcel        signal_holder hld(SIGUSR1);
110240116Smarcel        ::kill(::getpid(), SIGUSR1);
111240116Smarcel    }
112240116Smarcel
113240116Smarcel    sigusr1::happened = false;
114240116Smarcel    ::kill(::getpid(), SIGUSR1);
115240116Smarcel    ATF_REQUIRE(sigusr1::happened);
116240116Smarcel}
117240116Smarcel
118240116SmarcelATF_TEST_CASE(signal_holder_destructor);
119240116SmarcelATF_TEST_CASE_HEAD(signal_holder_destructor)
120240116Smarcel{
121240116Smarcel    set_md_var("descr", "Tests that signal_holder processes a pending "
122240116Smarcel               "signal upon destruction");
123240116Smarcel}
124240116SmarcelATF_TEST_CASE_BODY(signal_holder_destructor)
125240116Smarcel{
126240116Smarcel    using atf::atf_run::signal_holder;
127240116Smarcel
128240116Smarcel    sigusr1::program();
129240116Smarcel
130240116Smarcel    sigusr1::happened = false;
131240116Smarcel    ::kill(::getpid(), SIGUSR1);
132240116Smarcel    ATF_REQUIRE(sigusr1::happened);
133240116Smarcel
134240116Smarcel    {
135240116Smarcel        signal_holder hld(SIGUSR1);
136240116Smarcel
137240116Smarcel        sigusr1::happened = false;
138240116Smarcel        ::kill(::getpid(), SIGUSR1);
139240116Smarcel        ATF_REQUIRE(!sigusr1::happened);
140240116Smarcel    }
141240116Smarcel    ATF_REQUIRE(sigusr1::happened);
142240116Smarcel}
143240116Smarcel
144240116SmarcelATF_TEST_CASE(signal_holder_process);
145240116SmarcelATF_TEST_CASE_HEAD(signal_holder_process)
146240116Smarcel{
147240116Smarcel    set_md_var("descr", "Tests that signal_holder's process method works "
148240116Smarcel               "to process a delayed signal explicitly");
149240116Smarcel}
150240116SmarcelATF_TEST_CASE_BODY(signal_holder_process)
151240116Smarcel{
152240116Smarcel    using atf::atf_run::signal_holder;
153240116Smarcel
154240116Smarcel    sigusr1::program();
155240116Smarcel
156240116Smarcel    sigusr1::happened = false;
157240116Smarcel    ::kill(::getpid(), SIGUSR1);
158240116Smarcel    ATF_REQUIRE(sigusr1::happened);
159240116Smarcel
160240116Smarcel    {
161240116Smarcel        signal_holder hld(SIGUSR1);
162240116Smarcel
163240116Smarcel        sigusr1::happened = false;
164240116Smarcel        ::kill(::getpid(), SIGUSR1);
165240116Smarcel        ATF_REQUIRE(!sigusr1::happened);
166240116Smarcel
167240116Smarcel        hld.process();
168240116Smarcel        ATF_REQUIRE(sigusr1::happened);
169240116Smarcel
170240116Smarcel        sigusr1::happened = false;
171240116Smarcel    }
172240116Smarcel    ATF_REQUIRE(!sigusr1::happened);
173240116Smarcel}
174240116Smarcel
175240116Smarcel// ------------------------------------------------------------------------
176240116Smarcel// Tests for the "signal_programmer" class.
177240116Smarcel// ------------------------------------------------------------------------
178240116Smarcel
179240116SmarcelATF_TEST_CASE(signal_programmer_program);
180240116SmarcelATF_TEST_CASE_HEAD(signal_programmer_program)
181240116Smarcel{
182240116Smarcel    set_md_var("descr", "Tests that signal_programmer correctly installs a "
183240116Smarcel               "handler");
184240116Smarcel}
185240116SmarcelATF_TEST_CASE_BODY(signal_programmer_program)
186240116Smarcel{
187240116Smarcel    using atf::atf_run::signal_programmer;
188240116Smarcel
189240116Smarcel    signal_programmer sp(SIGUSR1, sigusr1_2::handler);
190240116Smarcel
191240116Smarcel    sigusr1_2::happened = false;
192240116Smarcel    ::kill(::getpid(), SIGUSR1);
193240116Smarcel    ATF_REQUIRE(sigusr1_2::happened);
194240116Smarcel}
195240116Smarcel
196240116SmarcelATF_TEST_CASE(signal_programmer_preserve);
197240116SmarcelATF_TEST_CASE_HEAD(signal_programmer_preserve)
198240116Smarcel{
199240116Smarcel    set_md_var("descr", "Tests that signal_programmer uninstalls the "
200240116Smarcel               "handler during destruction");
201240116Smarcel}
202240116SmarcelATF_TEST_CASE_BODY(signal_programmer_preserve)
203240116Smarcel{
204240116Smarcel    using atf::atf_run::signal_programmer;
205240116Smarcel
206240116Smarcel    sigusr1::program();
207240116Smarcel    sigusr1::happened = false;
208240116Smarcel
209240116Smarcel    {
210240116Smarcel        signal_programmer sp(SIGUSR1, sigusr1_2::handler);
211240116Smarcel
212240116Smarcel        sigusr1_2::happened = false;
213240116Smarcel        ::kill(::getpid(), SIGUSR1);
214240116Smarcel        ATF_REQUIRE(sigusr1_2::happened);
215240116Smarcel    }
216240116Smarcel
217240116Smarcel    ATF_REQUIRE(!sigusr1::happened);
218240116Smarcel    ::kill(::getpid(), SIGUSR1);
219240116Smarcel    ATF_REQUIRE(sigusr1::happened);
220240116Smarcel}
221240116Smarcel
222240116Smarcel// ------------------------------------------------------------------------
223240116Smarcel// Tests cases for the free functions.
224240116Smarcel// ------------------------------------------------------------------------
225240116Smarcel
226240116Smarcelstatic
227240116Smarcelvoid
228240116Smarcelreset_child(void *v ATF_DEFS_ATTRIBUTE_UNUSED)
229240116Smarcel{
230240116Smarcel    sigusr1::program();
231240116Smarcel
232240116Smarcel    sigusr1::happened = false;
233240116Smarcel    atf::atf_run::reset(SIGUSR1);
234240116Smarcel    kill(::getpid(), SIGUSR1);
235240116Smarcel
236240116Smarcel    if (sigusr1::happened) {
237240116Smarcel        std::cerr << "Signal was not resetted correctly\n";
238240116Smarcel        std::abort();
239240116Smarcel    } else {
240240116Smarcel        std::exit(EXIT_SUCCESS);
241240116Smarcel    }
242240116Smarcel}
243240116Smarcel
244240116SmarcelATF_TEST_CASE(reset);
245240116SmarcelATF_TEST_CASE_HEAD(reset)
246240116Smarcel{
247240116Smarcel    set_md_var("descr", "Tests the reset function");
248240116Smarcel}
249240116SmarcelATF_TEST_CASE_BODY(reset)
250240116Smarcel{
251240116Smarcel    atf::process::child c =
252240116Smarcel        atf::process::fork(reset_child, atf::process::stream_inherit(),
253240116Smarcel                           atf::process::stream_inherit(), NULL);
254240116Smarcel
255240116Smarcel    const atf::process::status s = c.wait();
256240116Smarcel    ATF_REQUIRE(s.exited() || s.signaled());
257240116Smarcel    ATF_REQUIRE(!s.signaled() || s.termsig() == SIGUSR1);
258240116Smarcel}
259240116Smarcel
260240116Smarcel// ------------------------------------------------------------------------
261240116Smarcel// Main.
262240116Smarcel// ------------------------------------------------------------------------
263240116Smarcel
264240116SmarcelATF_INIT_TEST_CASES(tcs)
265240116Smarcel{
266240116Smarcel    // Add the tests for the "signal_holder" class.
267240116Smarcel    ATF_ADD_TEST_CASE(tcs, signal_holder_preserve);
268240116Smarcel    ATF_ADD_TEST_CASE(tcs, signal_holder_destructor);
269240116Smarcel    ATF_ADD_TEST_CASE(tcs, signal_holder_process);
270240116Smarcel
271240116Smarcel    // Add the tests for the "signal_programmer" class.
272240116Smarcel    ATF_ADD_TEST_CASE(tcs, signal_programmer_program);
273240116Smarcel    ATF_ADD_TEST_CASE(tcs, signal_programmer_preserve);
274240116Smarcel
275240116Smarcel    // Add the test cases for the free functions.
276240116Smarcel    ATF_ADD_TEST_CASE(tcs, reset);
277240116Smarcel}
278