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