Below is the file 'tests/atf/atf-c/t_sanity.c' from this revision. You can also download the file.

/*
 * Automated Testing Framework (atf)
 *
 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#if defined(HAVE_CONFIG_H)
#include "bconfig.h"
#endif

#include <sys/types.h>
#include <sys/wait.h>

#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <atf-c.h>

#include "atf-c/dynstr.h"
#include "atf-c/io.h"
#include "atf-c/process.h"
#include "atf-c/sanity.h"

#include "h_lib.h"

/* ---------------------------------------------------------------------
 * Auxiliary functions.
 * --------------------------------------------------------------------- */

enum type { inv, pre, post, unreachable };

static
bool
grep(const atf_dynstr_t *line, const char *text)
{
    const char *l = atf_dynstr_cstring(line);
    bool found;

    found = false;

    if (strstr(l, text) != NULL)
        found = true;

    return found;
}

static
void
do_test(enum type t, bool cond)
{
    int fds[2];
    pid_t pid;

    ATF_REQUIRE(pipe(fds) != -1);

    RE(atf_process_oldfork(&pid));
    if (pid == 0) {
        ATF_REQUIRE(dup2(fds[1], STDERR_FILENO) != -1);
        close(fds[0]);
        close(fds[1]);

        switch (t) {
        case inv:
            INV(cond);
            break;

        case pre:
            PRE(cond);
            break;

        case post:
            POST(cond);
            break;

        case unreachable:
            if (!cond)
                UNREACHABLE;
            break;
        }

        exit(EXIT_SUCCESS);
    } else {
        bool eof;
        int ecode, nlines;
        atf_dynstr_t lines[3];

        close(fds[1]);

        nlines = 0;
        do {
            RE(atf_dynstr_init(&lines[nlines]));
            if (!eof)
                RE(atf_io_readline(fds[0], &lines[nlines], &eof));
            nlines++;
        } while (nlines < 3);
        close(fds[0]);
        ATF_REQUIRE(nlines == 0 || nlines == 3);

        if (!cond) {
            switch (t) {
            case inv:
                ATF_REQUIRE(grep(&lines[0], "Invariant"));
                break;

            case pre:
                ATF_REQUIRE(grep(&lines[0], "Precondition"));
                break;

            case post:
                ATF_REQUIRE(grep(&lines[0], "Postcondition"));
                break;

            case unreachable:
                ATF_REQUIRE(grep(&lines[0], "Invariant"));
                break;
            }

            ATF_REQUIRE(grep(&lines[0], __FILE__));
            ATF_REQUIRE(grep(&lines[2], PACKAGE_BUGREPORT));
        }

        ATF_REQUIRE(waitpid(pid, &ecode, 0) != -1);
        if (!cond) {
            ATF_REQUIRE(WIFSIGNALED(ecode));
            ATF_REQUIRE(WTERMSIG(ecode) == SIGABRT);
        } else {
            ATF_REQUIRE(WIFEXITED(ecode));
            ATF_REQUIRE(WEXITSTATUS(ecode) == EXIT_SUCCESS);
        }

        while (nlines > 0) {
            nlines--;
            atf_dynstr_fini(&lines[nlines]);
        }
    }
}

static
void
require_ndebug(void)
{
#if defined(NDEBUG)
    atf_tc_skip("Sanity checks not available; code built with -DNDEBUG");
#endif
}

/* ---------------------------------------------------------------------
 * Test cases for the free functions.
 * --------------------------------------------------------------------- */

ATF_TC(inv);
ATF_TC_HEAD(inv, tc)
{
    atf_tc_set_md_var(tc, "descr", "Tests the INV macro");
}
ATF_TC_BODY(inv, tc)
{
    require_ndebug();

    do_test(inv, false);
    do_test(inv, true);
}

ATF_TC(pre);
ATF_TC_HEAD(pre, tc)
{
    atf_tc_set_md_var(tc, "descr", "Tests the PRE macro");
}
ATF_TC_BODY(pre, tc)
{
    require_ndebug();

    do_test(pre, false);
    do_test(pre, true);
}

ATF_TC(post);
ATF_TC_HEAD(post, tc)
{
    atf_tc_set_md_var(tc, "descr", "Tests the POST macro");
}
ATF_TC_BODY(post, tc)
{
    require_ndebug();

    do_test(post, false);
    do_test(post, true);
}

ATF_TC(unreachable);
ATF_TC_HEAD(unreachable, tc)
{
    atf_tc_set_md_var(tc, "descr", "Tests the UNREACHABLE macro");
}
ATF_TC_BODY(unreachable, tc)
{
    require_ndebug();

    do_test(unreachable, false);
    do_test(unreachable, true);
}

/* ---------------------------------------------------------------------
 * Tests cases for the header file.
 * --------------------------------------------------------------------- */

HEADER_TC(include, "atf-c/sanity.h", "d_include_sanity_h.c");

/* ---------------------------------------------------------------------
 * Main.
 * --------------------------------------------------------------------- */

ATF_TP_ADD_TCS(tp)
{
    ATF_TP_ADD_TC(tp, inv);
    ATF_TP_ADD_TC(tp, pre);
    ATF_TP_ADD_TC(tp, post);
    ATF_TP_ADD_TC(tp, unreachable);

    /* Add the test cases for the header file. */
    ATF_TP_ADD_TC(tp, include);

    return atf_no_error();
}