116190Sdfuchs/* Copyright (c) 2008 The NetBSD Foundation, Inc.
216190Sdfuchs * All rights reserved.
316190Sdfuchs *
416190Sdfuchs * Redistribution and use in source and binary forms, with or without
516190Sdfuchs * modification, are permitted provided that the following conditions
616190Sdfuchs * are met:
716190Sdfuchs * 1. Redistributions of source code must retain the above copyright
816190Sdfuchs *    notice, this list of conditions and the following disclaimer.
916190Sdfuchs * 2. Redistributions in binary form must reproduce the above copyright
1016190Sdfuchs *    notice, this list of conditions and the following disclaimer in the
1116190Sdfuchs *    documentation and/or other materials provided with the distribution.
1216190Sdfuchs *
1316190Sdfuchs * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
1416190Sdfuchs * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1516190Sdfuchs * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1616190Sdfuchs * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1716190Sdfuchs * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
1816190Sdfuchs * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1916190Sdfuchs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2016190Sdfuchs * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2116190Sdfuchs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2216190Sdfuchs * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2316190Sdfuchs * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
2416190Sdfuchs * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
2516190Sdfuchs
2616190Sdfuchs#include "atf-c/detail/sanity.h"
2716190Sdfuchs
2816190Sdfuchs#if defined(HAVE_CONFIG_H)
2916190Sdfuchs#include "config.h"
3016190Sdfuchs#endif
3116190Sdfuchs
3216190Sdfuchs#include <sys/types.h>
3316190Sdfuchs#include <sys/wait.h>
3416190Sdfuchs
3516190Sdfuchs#include <signal.h>
3616190Sdfuchs#include <stdbool.h>
3716190Sdfuchs#include <stdlib.h>
3816190Sdfuchs#include <string.h>
3916190Sdfuchs#include <unistd.h>
4016190Sdfuchs
4116190Sdfuchs#include <atf-c.h>
4216190Sdfuchs
4316190Sdfuchs#include "atf-c/detail/dynstr.h"
4416190Sdfuchs#include "atf-c/detail/process.h"
4516190Sdfuchs#include "atf-c/detail/test_helpers.h"
4616190Sdfuchs
4716190Sdfuchs/* ---------------------------------------------------------------------
4816190Sdfuchs * Auxiliary functions.
4916190Sdfuchs * --------------------------------------------------------------------- */
5016190Sdfuchs
5116190Sdfuchsenum type { inv, pre, post, unreachable };
5216190Sdfuchs
5316608Sdfuchsstruct test_data {
5416190Sdfuchs    enum type m_type;
5516190Sdfuchs    bool m_cond;
5616190Sdfuchs};
5716190Sdfuchs
5816190Sdfuchsstatic void do_test_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
5916608Sdfuchs
6016190Sdfuchsstatic
6116190Sdfuchsvoid
6216190Sdfuchsdo_test_child(void *v)
6316190Sdfuchs{
6416190Sdfuchs    struct test_data *td = v;
6516190Sdfuchs
6616190Sdfuchs    switch (td->m_type) {
6716190Sdfuchs    case inv:
6816190Sdfuchs        INV(td->m_cond);
6916190Sdfuchs        break;
7016190Sdfuchs
7116190Sdfuchs    case pre:
7216190Sdfuchs        PRE(td->m_cond);
7316190Sdfuchs        break;
7416190Sdfuchs
7516190Sdfuchs    case post:
7616190Sdfuchs        POST(td->m_cond);
7716190Sdfuchs        break;
7816190Sdfuchs
7916190Sdfuchs    case unreachable:
8016190Sdfuchs        if (!td->m_cond)
8116190Sdfuchs            UNREACHABLE;
8216190Sdfuchs        break;
8316190Sdfuchs    }
8416190Sdfuchs
8516190Sdfuchs    exit(EXIT_SUCCESS);
8616190Sdfuchs}
8716190Sdfuchs
8816190Sdfuchsstatic
8916190Sdfuchsvoid
9016190Sdfuchsdo_test(enum type t, bool cond)
9116190Sdfuchs{
9216190Sdfuchs    atf_process_child_t child;
9316190Sdfuchs    atf_process_status_t status;
9416190Sdfuchs    int nlines;
9516190Sdfuchs    char *lines[3];
9616190Sdfuchs
9716190Sdfuchs    {
9816190Sdfuchs        atf_process_stream_t outsb, errsb;
9916190Sdfuchs        struct test_data td = { t, cond };
10016190Sdfuchs
10116190Sdfuchs        RE(atf_process_stream_init_inherit(&outsb));
10216190Sdfuchs        RE(atf_process_stream_init_capture(&errsb));
10316190Sdfuchs        RE(atf_process_fork(&child, do_test_child, &outsb, &errsb, &td));
10416190Sdfuchs        atf_process_stream_fini(&errsb);
10516190Sdfuchs        atf_process_stream_fini(&outsb);
10616190Sdfuchs    }
10716190Sdfuchs
10816190Sdfuchs    nlines = 0;
10916190Sdfuchs    while (nlines < 3 && (lines[nlines] =
11016190Sdfuchs           atf_utils_readline(atf_process_child_stderr(&child))) != NULL)
11116190Sdfuchs        nlines++;
11216190Sdfuchs    ATF_REQUIRE(nlines == 0 || nlines == 3);
11316190Sdfuchs
11416190Sdfuchs    RE(atf_process_child_wait(&child, &status));
11516190Sdfuchs    if (!cond) {
11616190Sdfuchs        ATF_REQUIRE(atf_process_status_signaled(&status));
11716190Sdfuchs        ATF_REQUIRE(atf_process_status_termsig(&status) == SIGABRT);
11816190Sdfuchs    } else {
11916190Sdfuchs        ATF_REQUIRE(atf_process_status_exited(&status));
12016190Sdfuchs        ATF_REQUIRE(atf_process_status_exitstatus(&status) == EXIT_SUCCESS);
12116190Sdfuchs    }
12216190Sdfuchs    atf_process_status_fini(&status);
12316190Sdfuchs
12416190Sdfuchs    if (!cond) {
12516190Sdfuchs        switch (t) {
12616190Sdfuchs        case inv:
12716190Sdfuchs            ATF_REQUIRE(atf_utils_grep_string("Invariant", lines[0]));
12816190Sdfuchs            break;
12916190Sdfuchs
13016190Sdfuchs        case pre:
13116190Sdfuchs            ATF_REQUIRE(atf_utils_grep_string("Precondition", lines[0]));
13216190Sdfuchs            break;
13316190Sdfuchs
13416190Sdfuchs        case post:
13516190Sdfuchs            ATF_REQUIRE(atf_utils_grep_string("Postcondition", lines[0]));
13616190Sdfuchs            break;
13716190Sdfuchs
13816190Sdfuchs        case unreachable:
13916190Sdfuchs            ATF_REQUIRE(atf_utils_grep_string("Invariant", lines[0]));
14016190Sdfuchs            break;
14116190Sdfuchs        }
14216190Sdfuchs
14316190Sdfuchs        ATF_REQUIRE(atf_utils_grep_string(__FILE__, lines[0]));
14416190Sdfuchs        ATF_REQUIRE(atf_utils_grep_string(PACKAGE_BUGREPORT, lines[2]));
14516190Sdfuchs    }
14616190Sdfuchs
14716190Sdfuchs    while (nlines > 0) {
14816190Sdfuchs        nlines--;
14916190Sdfuchs        free(lines[nlines]);
15016608Sdfuchs    }
15116608Sdfuchs}
15216608Sdfuchs
15316608Sdfuchsstatic
15416608Sdfuchsvoid
15516608Sdfuchsrequire_ndebug(void)
15616608Sdfuchs{
15716608Sdfuchs#if defined(NDEBUG)
15816608Sdfuchs    atf_tc_skip("Sanity checks not available; code built with -DNDEBUG");
15916608Sdfuchs#endif
16016608Sdfuchs}
16116608Sdfuchs
16216608Sdfuchs/* ---------------------------------------------------------------------
16316608Sdfuchs * Test cases for the free functions.
16416608Sdfuchs * --------------------------------------------------------------------- */
16516608Sdfuchs
16616608SdfuchsATF_TC(inv);
16716608SdfuchsATF_TC_HEAD(inv, tc)
16816608Sdfuchs{
16916608Sdfuchs    atf_tc_set_md_var(tc, "descr", "Tests the INV macro");
17016608Sdfuchs}
17116608SdfuchsATF_TC_BODY(inv, tc)
17216608Sdfuchs{
17316608Sdfuchs    require_ndebug();
17416608Sdfuchs
17516608Sdfuchs    do_test(inv, false);
17616608Sdfuchs    do_test(inv, true);
17716608Sdfuchs}
17816608Sdfuchs
17916608SdfuchsATF_TC(pre);
18016608SdfuchsATF_TC_HEAD(pre, tc)
18116608Sdfuchs{
18216608Sdfuchs    atf_tc_set_md_var(tc, "descr", "Tests the PRE macro");
18316608Sdfuchs}
18416608SdfuchsATF_TC_BODY(pre, tc)
18516608Sdfuchs{
18616608Sdfuchs    require_ndebug();
18716608Sdfuchs
18816608Sdfuchs    do_test(pre, false);
18916608Sdfuchs    do_test(pre, true);
19016608Sdfuchs}
19116608Sdfuchs
19216608SdfuchsATF_TC(post);
19316608SdfuchsATF_TC_HEAD(post, tc)
19416608Sdfuchs{
19516608Sdfuchs    atf_tc_set_md_var(tc, "descr", "Tests the POST macro");
19616608Sdfuchs}
19716608SdfuchsATF_TC_BODY(post, tc)
19816608Sdfuchs{
19916608Sdfuchs    require_ndebug();
20016608Sdfuchs
20116608Sdfuchs    do_test(post, false);
20216608Sdfuchs    do_test(post, true);
20316190Sdfuchs}
20416190Sdfuchs
20516608SdfuchsATF_TC(unreachable);
20616608SdfuchsATF_TC_HEAD(unreachable, tc)
20716190Sdfuchs{
20816190Sdfuchs    atf_tc_set_md_var(tc, "descr", "Tests the UNREACHABLE macro");
20916190Sdfuchs}
21016190SdfuchsATF_TC_BODY(unreachable, tc)
21116190Sdfuchs{
21216190Sdfuchs    require_ndebug();
21316190Sdfuchs
21416190Sdfuchs    do_test(unreachable, false);
21516190Sdfuchs    do_test(unreachable, true);
21616190Sdfuchs}
21716190Sdfuchs
21816190Sdfuchs/* ---------------------------------------------------------------------
21916190Sdfuchs * Main.
22016190Sdfuchs * --------------------------------------------------------------------- */
22116190Sdfuchs
22216190SdfuchsATF_TP_ADD_TCS(tp)
22316190Sdfuchs{
22416190Sdfuchs    ATF_TP_ADD_TC(tp, inv);
22516190Sdfuchs    ATF_TP_ADD_TC(tp, pre);
22616190Sdfuchs    ATF_TP_ADD_TC(tp, post);
22716190Sdfuchs    ATF_TP_ADD_TC(tp, unreachable);
22816190Sdfuchs
22916190Sdfuchs    return atf_no_error();
23016190Sdfuchs}
23116190Sdfuchs