sanity_test.c revision 275988
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
51enum type { inv, pre, post, unreachable };
52
53struct test_data {
54    enum type m_type;
55    bool m_cond;
56};
57
58static void do_test_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
59
60static
61void
62do_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
88static
89void
90do_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
153static
154void
155require_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
166ATF_TC(inv);
167ATF_TC_HEAD(inv, tc)
168{
169    atf_tc_set_md_var(tc, "descr", "Tests the INV macro");
170}
171ATF_TC_BODY(inv, tc)
172{
173    require_ndebug();
174
175    do_test(inv, false);
176    do_test(inv, true);
177}
178
179ATF_TC(pre);
180ATF_TC_HEAD(pre, tc)
181{
182    atf_tc_set_md_var(tc, "descr", "Tests the PRE macro");
183}
184ATF_TC_BODY(pre, tc)
185{
186    require_ndebug();
187
188    do_test(pre, false);
189    do_test(pre, true);
190}
191
192ATF_TC(post);
193ATF_TC_HEAD(post, tc)
194{
195    atf_tc_set_md_var(tc, "descr", "Tests the POST macro");
196}
197ATF_TC_BODY(post, tc)
198{
199    require_ndebug();
200
201    do_test(post, false);
202    do_test(post, true);
203}
204
205ATF_TC(unreachable);
206ATF_TC_HEAD(unreachable, tc)
207{
208    atf_tc_set_md_var(tc, "descr", "Tests the UNREACHABLE macro");
209}
210ATF_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
222ATF_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