1*6b3a42afSjmmv // Copyright 2010 Google Inc.
2*6b3a42afSjmmv // All rights reserved.
3*6b3a42afSjmmv //
4*6b3a42afSjmmv // Redistribution and use in source and binary forms, with or without
5*6b3a42afSjmmv // modification, are permitted provided that the following conditions are
6*6b3a42afSjmmv // met:
7*6b3a42afSjmmv //
8*6b3a42afSjmmv // * Redistributions of source code must retain the above copyright
9*6b3a42afSjmmv // notice, this list of conditions and the following disclaimer.
10*6b3a42afSjmmv // * Redistributions in binary form must reproduce the above copyright
11*6b3a42afSjmmv // notice, this list of conditions and the following disclaimer in the
12*6b3a42afSjmmv // documentation and/or other materials provided with the distribution.
13*6b3a42afSjmmv // * Neither the name of Google Inc. nor the names of its contributors
14*6b3a42afSjmmv // may be used to endorse or promote products derived from this software
15*6b3a42afSjmmv // without specific prior written permission.
16*6b3a42afSjmmv //
17*6b3a42afSjmmv // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*6b3a42afSjmmv // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*6b3a42afSjmmv // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*6b3a42afSjmmv // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*6b3a42afSjmmv // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*6b3a42afSjmmv // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*6b3a42afSjmmv // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*6b3a42afSjmmv // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*6b3a42afSjmmv // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*6b3a42afSjmmv // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*6b3a42afSjmmv // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*6b3a42afSjmmv
29*6b3a42afSjmmv #include "utils/sanity.hpp"
30*6b3a42afSjmmv
31*6b3a42afSjmmv extern "C" {
32*6b3a42afSjmmv #include <signal.h>
33*6b3a42afSjmmv #include <unistd.h>
34*6b3a42afSjmmv }
35*6b3a42afSjmmv
36*6b3a42afSjmmv #include <cstdlib>
37*6b3a42afSjmmv #include <iostream>
38*6b3a42afSjmmv
39*6b3a42afSjmmv #include <atf-c++.hpp>
40*6b3a42afSjmmv
41*6b3a42afSjmmv #include "utils/format/macros.hpp"
42*6b3a42afSjmmv #include "utils/fs/path.hpp"
43*6b3a42afSjmmv #include "utils/process/child.ipp"
44*6b3a42afSjmmv #include "utils/process/status.hpp"
45*6b3a42afSjmmv
46*6b3a42afSjmmv namespace fs = utils::fs;
47*6b3a42afSjmmv namespace process = utils::process;
48*6b3a42afSjmmv
49*6b3a42afSjmmv
50*6b3a42afSjmmv #define FILE_REGEXP __FILE__ ":[0-9]+: "
51*6b3a42afSjmmv
52*6b3a42afSjmmv
53*6b3a42afSjmmv static const fs::path Stdout_File("stdout.txt");
54*6b3a42afSjmmv static const fs::path Stderr_File("stderr.txt");
55*6b3a42afSjmmv
56*6b3a42afSjmmv
57*6b3a42afSjmmv #if NDEBUG
58*6b3a42afSjmmv static bool NDebug = true;
59*6b3a42afSjmmv #else
60*6b3a42afSjmmv static bool NDebug = false;
61*6b3a42afSjmmv #endif
62*6b3a42afSjmmv
63*6b3a42afSjmmv
64*6b3a42afSjmmv template< typename Function >
65*6b3a42afSjmmv static process::status
run_test(Function function)66*6b3a42afSjmmv run_test(Function function)
67*6b3a42afSjmmv {
68*6b3a42afSjmmv const process::status status = process::child::fork_files(
69*6b3a42afSjmmv function, Stdout_File, Stderr_File)->wait();
70*6b3a42afSjmmv atf::utils::cat_file(Stdout_File.str(), "Helper stdout: ");
71*6b3a42afSjmmv atf::utils::cat_file(Stderr_File.str(), "Helper stderr: ");
72*6b3a42afSjmmv return status;
73*6b3a42afSjmmv }
74*6b3a42afSjmmv
75*6b3a42afSjmmv
76*6b3a42afSjmmv static void
verify_success(const process::status & status)77*6b3a42afSjmmv verify_success(const process::status& status)
78*6b3a42afSjmmv {
79*6b3a42afSjmmv ATF_REQUIRE(status.exited());
80*6b3a42afSjmmv ATF_REQUIRE_EQ(EXIT_SUCCESS, status.exitstatus());
81*6b3a42afSjmmv ATF_REQUIRE(atf::utils::grep_file("Before test", Stdout_File.str()));
82*6b3a42afSjmmv ATF_REQUIRE(atf::utils::grep_file("After test", Stdout_File.str()));
83*6b3a42afSjmmv }
84*6b3a42afSjmmv
85*6b3a42afSjmmv
86*6b3a42afSjmmv static void
verify_failed(const process::status & status,const char * type,const char * exp_message,const bool check_ndebug)87*6b3a42afSjmmv verify_failed(const process::status& status, const char* type,
88*6b3a42afSjmmv const char* exp_message, const bool check_ndebug)
89*6b3a42afSjmmv {
90*6b3a42afSjmmv if (check_ndebug && NDebug) {
91*6b3a42afSjmmv std::cout << "Built with NDEBUG; skipping verification\n";
92*6b3a42afSjmmv verify_success(status);
93*6b3a42afSjmmv } else {
94*6b3a42afSjmmv ATF_REQUIRE(status.signaled());
95*6b3a42afSjmmv ATF_REQUIRE_EQ(SIGABRT, status.termsig());
96*6b3a42afSjmmv ATF_REQUIRE(atf::utils::grep_file("Before test", Stdout_File.str()));
97*6b3a42afSjmmv ATF_REQUIRE(!atf::utils::grep_file("After test", Stdout_File.str()));
98*6b3a42afSjmmv if (exp_message != NULL)
99*6b3a42afSjmmv ATF_REQUIRE(atf::utils::grep_file(F(FILE_REGEXP "%s: %s") %
100*6b3a42afSjmmv type % exp_message,
101*6b3a42afSjmmv Stderr_File.str()));
102*6b3a42afSjmmv else
103*6b3a42afSjmmv ATF_REQUIRE(atf::utils::grep_file(F(FILE_REGEXP "%s") % type,
104*6b3a42afSjmmv Stderr_File.str()));
105*6b3a42afSjmmv }
106*6b3a42afSjmmv }
107*6b3a42afSjmmv
108*6b3a42afSjmmv
109*6b3a42afSjmmv template< bool Expression, bool WithMessage >
110*6b3a42afSjmmv static void
do_inv_test(void)111*6b3a42afSjmmv do_inv_test(void)
112*6b3a42afSjmmv {
113*6b3a42afSjmmv std::cout << "Before test\n";
114*6b3a42afSjmmv if (WithMessage)
115*6b3a42afSjmmv INV_MSG(Expression, "Custom message");
116*6b3a42afSjmmv else
117*6b3a42afSjmmv INV(Expression);
118*6b3a42afSjmmv std::cout << "After test\n";
119*6b3a42afSjmmv std::exit(EXIT_SUCCESS);
120*6b3a42afSjmmv }
121*6b3a42afSjmmv
122*6b3a42afSjmmv
123*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(inv__holds);
ATF_TEST_CASE_BODY(inv__holds)124*6b3a42afSjmmv ATF_TEST_CASE_BODY(inv__holds)
125*6b3a42afSjmmv {
126*6b3a42afSjmmv const process::status status = run_test(do_inv_test< true, false >);
127*6b3a42afSjmmv verify_success(status);
128*6b3a42afSjmmv }
129*6b3a42afSjmmv
130*6b3a42afSjmmv
131*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(inv__triggers_default_message);
ATF_TEST_CASE_BODY(inv__triggers_default_message)132*6b3a42afSjmmv ATF_TEST_CASE_BODY(inv__triggers_default_message)
133*6b3a42afSjmmv {
134*6b3a42afSjmmv const process::status status = run_test(do_inv_test< false, false >);
135*6b3a42afSjmmv verify_failed(status, "Invariant check failed", "Expression", true);
136*6b3a42afSjmmv }
137*6b3a42afSjmmv
138*6b3a42afSjmmv
139*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(inv__triggers_custom_message);
ATF_TEST_CASE_BODY(inv__triggers_custom_message)140*6b3a42afSjmmv ATF_TEST_CASE_BODY(inv__triggers_custom_message)
141*6b3a42afSjmmv {
142*6b3a42afSjmmv const process::status status = run_test(do_inv_test< false, true >);
143*6b3a42afSjmmv verify_failed(status, "Invariant check failed", "Custom", true);
144*6b3a42afSjmmv }
145*6b3a42afSjmmv
146*6b3a42afSjmmv
147*6b3a42afSjmmv template< bool Expression, bool WithMessage >
148*6b3a42afSjmmv static void
do_pre_test(void)149*6b3a42afSjmmv do_pre_test(void)
150*6b3a42afSjmmv {
151*6b3a42afSjmmv std::cout << "Before test\n";
152*6b3a42afSjmmv if (WithMessage)
153*6b3a42afSjmmv PRE_MSG(Expression, "Custom message");
154*6b3a42afSjmmv else
155*6b3a42afSjmmv PRE(Expression);
156*6b3a42afSjmmv std::cout << "After test\n";
157*6b3a42afSjmmv std::exit(EXIT_SUCCESS);
158*6b3a42afSjmmv }
159*6b3a42afSjmmv
160*6b3a42afSjmmv
161*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(pre__holds);
ATF_TEST_CASE_BODY(pre__holds)162*6b3a42afSjmmv ATF_TEST_CASE_BODY(pre__holds)
163*6b3a42afSjmmv {
164*6b3a42afSjmmv const process::status status = run_test(do_pre_test< true, false >);
165*6b3a42afSjmmv verify_success(status);
166*6b3a42afSjmmv }
167*6b3a42afSjmmv
168*6b3a42afSjmmv
169*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(pre__triggers_default_message);
ATF_TEST_CASE_BODY(pre__triggers_default_message)170*6b3a42afSjmmv ATF_TEST_CASE_BODY(pre__triggers_default_message)
171*6b3a42afSjmmv {
172*6b3a42afSjmmv const process::status status = run_test(do_pre_test< false, false >);
173*6b3a42afSjmmv verify_failed(status, "Precondition check failed", "Expression", true);
174*6b3a42afSjmmv }
175*6b3a42afSjmmv
176*6b3a42afSjmmv
177*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(pre__triggers_custom_message);
ATF_TEST_CASE_BODY(pre__triggers_custom_message)178*6b3a42afSjmmv ATF_TEST_CASE_BODY(pre__triggers_custom_message)
179*6b3a42afSjmmv {
180*6b3a42afSjmmv const process::status status = run_test(do_pre_test< false, true >);
181*6b3a42afSjmmv verify_failed(status, "Precondition check failed", "Custom", true);
182*6b3a42afSjmmv }
183*6b3a42afSjmmv
184*6b3a42afSjmmv
185*6b3a42afSjmmv template< bool Expression, bool WithMessage >
186*6b3a42afSjmmv static void
do_post_test(void)187*6b3a42afSjmmv do_post_test(void)
188*6b3a42afSjmmv {
189*6b3a42afSjmmv std::cout << "Before test\n";
190*6b3a42afSjmmv if (WithMessage)
191*6b3a42afSjmmv POST_MSG(Expression, "Custom message");
192*6b3a42afSjmmv else
193*6b3a42afSjmmv POST(Expression);
194*6b3a42afSjmmv std::cout << "After test\n";
195*6b3a42afSjmmv std::exit(EXIT_SUCCESS);
196*6b3a42afSjmmv }
197*6b3a42afSjmmv
198*6b3a42afSjmmv
199*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(post__holds);
ATF_TEST_CASE_BODY(post__holds)200*6b3a42afSjmmv ATF_TEST_CASE_BODY(post__holds)
201*6b3a42afSjmmv {
202*6b3a42afSjmmv const process::status status = run_test(do_post_test< true, false >);
203*6b3a42afSjmmv verify_success(status);
204*6b3a42afSjmmv }
205*6b3a42afSjmmv
206*6b3a42afSjmmv
207*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(post__triggers_default_message);
ATF_TEST_CASE_BODY(post__triggers_default_message)208*6b3a42afSjmmv ATF_TEST_CASE_BODY(post__triggers_default_message)
209*6b3a42afSjmmv {
210*6b3a42afSjmmv const process::status status = run_test(do_post_test< false, false >);
211*6b3a42afSjmmv verify_failed(status, "Postcondition check failed", "Expression", true);
212*6b3a42afSjmmv }
213*6b3a42afSjmmv
214*6b3a42afSjmmv
215*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(post__triggers_custom_message);
ATF_TEST_CASE_BODY(post__triggers_custom_message)216*6b3a42afSjmmv ATF_TEST_CASE_BODY(post__triggers_custom_message)
217*6b3a42afSjmmv {
218*6b3a42afSjmmv const process::status status = run_test(do_post_test< false, true >);
219*6b3a42afSjmmv verify_failed(status, "Postcondition check failed", "Custom", true);
220*6b3a42afSjmmv }
221*6b3a42afSjmmv
222*6b3a42afSjmmv
223*6b3a42afSjmmv template< bool WithMessage >
224*6b3a42afSjmmv static void
do_unreachable_test(void)225*6b3a42afSjmmv do_unreachable_test(void)
226*6b3a42afSjmmv {
227*6b3a42afSjmmv std::cout << "Before test\n";
228*6b3a42afSjmmv if (WithMessage)
229*6b3a42afSjmmv UNREACHABLE_MSG("Custom message");
230*6b3a42afSjmmv else
231*6b3a42afSjmmv UNREACHABLE;
232*6b3a42afSjmmv std::cout << "After test\n";
233*6b3a42afSjmmv std::exit(EXIT_SUCCESS);
234*6b3a42afSjmmv }
235*6b3a42afSjmmv
236*6b3a42afSjmmv
237*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(unreachable__default_message);
ATF_TEST_CASE_BODY(unreachable__default_message)238*6b3a42afSjmmv ATF_TEST_CASE_BODY(unreachable__default_message)
239*6b3a42afSjmmv {
240*6b3a42afSjmmv const process::status status = run_test(do_unreachable_test< false >);
241*6b3a42afSjmmv verify_failed(status, "Unreachable point reached", NULL, false);
242*6b3a42afSjmmv }
243*6b3a42afSjmmv
244*6b3a42afSjmmv
245*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(unreachable__custom_message);
ATF_TEST_CASE_BODY(unreachable__custom_message)246*6b3a42afSjmmv ATF_TEST_CASE_BODY(unreachable__custom_message)
247*6b3a42afSjmmv {
248*6b3a42afSjmmv const process::status status = run_test(do_unreachable_test< true >);
249*6b3a42afSjmmv verify_failed(status, "Unreachable point reached", "Custom", false);
250*6b3a42afSjmmv }
251*6b3a42afSjmmv
252*6b3a42afSjmmv
253*6b3a42afSjmmv template< int Signo >
254*6b3a42afSjmmv static void
do_crash_handler_test(void)255*6b3a42afSjmmv do_crash_handler_test(void)
256*6b3a42afSjmmv {
257*6b3a42afSjmmv utils::install_crash_handlers("test-log.txt");
258*6b3a42afSjmmv ::kill(::getpid(), Signo);
259*6b3a42afSjmmv std::cout << "After signal\n";
260*6b3a42afSjmmv std::exit(EXIT_FAILURE);
261*6b3a42afSjmmv }
262*6b3a42afSjmmv
263*6b3a42afSjmmv
264*6b3a42afSjmmv template< int Signo >
265*6b3a42afSjmmv static void
crash_handler_test(void)266*6b3a42afSjmmv crash_handler_test(void)
267*6b3a42afSjmmv {
268*6b3a42afSjmmv const process::status status = run_test(do_crash_handler_test< Signo >);
269*6b3a42afSjmmv ATF_REQUIRE(status.signaled());
270*6b3a42afSjmmv ATF_REQUIRE_EQ(Signo, status.termsig());
271*6b3a42afSjmmv ATF_REQUIRE(atf::utils::grep_file(F("Fatal signal %s") % Signo,
272*6b3a42afSjmmv Stderr_File.str()));
273*6b3a42afSjmmv ATF_REQUIRE(atf::utils::grep_file("Log file is test-log.txt",
274*6b3a42afSjmmv Stderr_File.str()));
275*6b3a42afSjmmv ATF_REQUIRE(!atf::utils::grep_file("After signal", Stdout_File.str()));
276*6b3a42afSjmmv }
277*6b3a42afSjmmv
278*6b3a42afSjmmv
279*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(install_crash_handlers__sigabrt);
ATF_TEST_CASE_BODY(install_crash_handlers__sigabrt)280*6b3a42afSjmmv ATF_TEST_CASE_BODY(install_crash_handlers__sigabrt)
281*6b3a42afSjmmv {
282*6b3a42afSjmmv crash_handler_test< SIGABRT >();
283*6b3a42afSjmmv }
284*6b3a42afSjmmv
285*6b3a42afSjmmv
286*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(install_crash_handlers__sigbus);
ATF_TEST_CASE_BODY(install_crash_handlers__sigbus)287*6b3a42afSjmmv ATF_TEST_CASE_BODY(install_crash_handlers__sigbus)
288*6b3a42afSjmmv {
289*6b3a42afSjmmv crash_handler_test< SIGBUS >();
290*6b3a42afSjmmv }
291*6b3a42afSjmmv
292*6b3a42afSjmmv
293*6b3a42afSjmmv ATF_TEST_CASE_WITHOUT_HEAD(install_crash_handlers__sigsegv);
ATF_TEST_CASE_BODY(install_crash_handlers__sigsegv)294*6b3a42afSjmmv ATF_TEST_CASE_BODY(install_crash_handlers__sigsegv)
295*6b3a42afSjmmv {
296*6b3a42afSjmmv crash_handler_test< SIGSEGV >();
297*6b3a42afSjmmv }
298*6b3a42afSjmmv
299*6b3a42afSjmmv
ATF_INIT_TEST_CASES(tcs)300*6b3a42afSjmmv ATF_INIT_TEST_CASES(tcs)
301*6b3a42afSjmmv {
302*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, inv__holds);
303*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, inv__triggers_default_message);
304*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, inv__triggers_custom_message);
305*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, pre__holds);
306*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, pre__triggers_default_message);
307*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, pre__triggers_custom_message);
308*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, post__holds);
309*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, post__triggers_default_message);
310*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, post__triggers_custom_message);
311*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, unreachable__default_message);
312*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, unreachable__custom_message);
313*6b3a42afSjmmv
314*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, install_crash_handlers__sigabrt);
315*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, install_crash_handlers__sigbus);
316*6b3a42afSjmmv ATF_ADD_TEST_CASE(tcs, install_crash_handlers__sigsegv);
317*6b3a42afSjmmv }
318