1 /* Copyright (c) 2008 The NetBSD Foundation, Inc.
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
25
26 #include "atf-c/detail/sanity.h"
27
28 #if defined(HAVE_CONFIG_H)
29 #include "config.h"
30 #endif
31
32 #include <sys/types.h>
33 #include <sys/wait.h>
34
35 #include <signal.h>
36 #include <stdbool.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include <atf-c.h>
42
43 #include "atf-c/detail/dynstr.h"
44 #include "atf-c/detail/process.h"
45 #include "atf-c/detail/test_helpers.h"
46
47 /* ---------------------------------------------------------------------
48 * Auxiliary functions.
49 * --------------------------------------------------------------------- */
50
51 enum type { inv, pre, post, unreachable };
52
53 struct test_data {
54 enum type m_type;
55 bool m_cond;
56 };
57
58 static void do_test_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
59
60 static
61 void
do_test_child(void * v)62 do_test_child(void *v)
63 {
64 struct test_data *td = v;
65
66 switch (td->m_type) {
67 case inv:
68 INV(td->m_cond);
69 break;
70
71 case pre:
72 PRE(td->m_cond);
73 break;
74
75 case post:
76 POST(td->m_cond);
77 break;
78
79 case unreachable:
80 if (!td->m_cond)
81 UNREACHABLE;
82 break;
83 }
84
85 exit(EXIT_SUCCESS);
86 }
87
88 static
89 void
do_test(enum type t,bool cond)90 do_test(enum type t, bool cond)
91 {
92 atf_process_child_t child;
93 atf_process_status_t status;
94 int nlines;
95 char *lines[3];
96
97 {
98 atf_process_stream_t outsb, errsb;
99 struct test_data td = { t, cond };
100
101 RE(atf_process_stream_init_inherit(&outsb));
102 RE(atf_process_stream_init_capture(&errsb));
103 RE(atf_process_fork(&child, do_test_child, &outsb, &errsb, &td));
104 atf_process_stream_fini(&errsb);
105 atf_process_stream_fini(&outsb);
106 }
107
108 nlines = 0;
109 while (nlines < 3 && (lines[nlines] =
110 atf_utils_readline(atf_process_child_stderr(&child))) != NULL)
111 nlines++;
112 ATF_REQUIRE(nlines == 0 || nlines == 3);
113
114 RE(atf_process_child_wait(&child, &status));
115 if (!cond) {
116 ATF_REQUIRE(atf_process_status_signaled(&status));
117 ATF_REQUIRE(atf_process_status_termsig(&status) == SIGABRT);
118 } else {
119 ATF_REQUIRE(atf_process_status_exited(&status));
120 ATF_REQUIRE(atf_process_status_exitstatus(&status) == EXIT_SUCCESS);
121 }
122 atf_process_status_fini(&status);
123
124 if (!cond) {
125 switch (t) {
126 case inv:
127 ATF_REQUIRE(atf_utils_grep_string("Invariant", lines[0]));
128 break;
129
130 case pre:
131 ATF_REQUIRE(atf_utils_grep_string("Precondition", lines[0]));
132 break;
133
134 case post:
135 ATF_REQUIRE(atf_utils_grep_string("Postcondition", lines[0]));
136 break;
137
138 case unreachable:
139 ATF_REQUIRE(atf_utils_grep_string("Invariant", lines[0]));
140 break;
141 }
142
143 ATF_REQUIRE(atf_utils_grep_string(__FILE__, lines[0]));
144 ATF_REQUIRE(atf_utils_grep_string(PACKAGE_BUGREPORT, lines[2]));
145 }
146
147 while (nlines > 0) {
148 nlines--;
149 free(lines[nlines]);
150 }
151 }
152
153 static
154 void
require_ndebug(void)155 require_ndebug(void)
156 {
157 #if defined(NDEBUG)
158 atf_tc_skip("Sanity checks not available; code built with -DNDEBUG");
159 #endif
160 }
161
162 /* ---------------------------------------------------------------------
163 * Test cases for the free functions.
164 * --------------------------------------------------------------------- */
165
166 ATF_TC(inv);
ATF_TC_HEAD(inv,tc)167 ATF_TC_HEAD(inv, tc)
168 {
169 atf_tc_set_md_var(tc, "descr", "Tests the INV macro");
170 }
ATF_TC_BODY(inv,tc)171 ATF_TC_BODY(inv, tc)
172 {
173 require_ndebug();
174
175 do_test(inv, false);
176 do_test(inv, true);
177 }
178
179 ATF_TC(pre);
ATF_TC_HEAD(pre,tc)180 ATF_TC_HEAD(pre, tc)
181 {
182 atf_tc_set_md_var(tc, "descr", "Tests the PRE macro");
183 }
ATF_TC_BODY(pre,tc)184 ATF_TC_BODY(pre, tc)
185 {
186 require_ndebug();
187
188 do_test(pre, false);
189 do_test(pre, true);
190 }
191
192 ATF_TC(post);
ATF_TC_HEAD(post,tc)193 ATF_TC_HEAD(post, tc)
194 {
195 atf_tc_set_md_var(tc, "descr", "Tests the POST macro");
196 }
ATF_TC_BODY(post,tc)197 ATF_TC_BODY(post, tc)
198 {
199 require_ndebug();
200
201 do_test(post, false);
202 do_test(post, true);
203 }
204
205 ATF_TC(unreachable);
ATF_TC_HEAD(unreachable,tc)206 ATF_TC_HEAD(unreachable, tc)
207 {
208 atf_tc_set_md_var(tc, "descr", "Tests the UNREACHABLE macro");
209 }
ATF_TC_BODY(unreachable,tc)210 ATF_TC_BODY(unreachable, tc)
211 {
212 require_ndebug();
213
214 do_test(unreachable, false);
215 do_test(unreachable, true);
216 }
217
218 /* ---------------------------------------------------------------------
219 * Main.
220 * --------------------------------------------------------------------- */
221
ATF_TP_ADD_TCS(tp)222 ATF_TP_ADD_TCS(tp)
223 {
224 ATF_TP_ADD_TC(tp, inv);
225 ATF_TP_ADD_TC(tp, pre);
226 ATF_TP_ADD_TC(tp, post);
227 ATF_TP_ADD_TC(tp, unreachable);
228
229 return atf_no_error();
230 }
231