David van Moolenbroek 00b67f09dd Import NetBSD named(8)
Also known as ISC bind.  This import adds utilities such as host(1),
dig(1), and nslookup(1), as well as many other tools and libraries.

Change-Id: I035ca46e64f1965d57019e773f4ff0ef035e4aa3
2017-03-21 22:00:06 +00:00

881 lines
31 KiB
C

/* $NetBSD: macros_test.c,v 1.3 2014/12/10 04:38:03 christos Exp $ */
/*
* Automated Testing Framework (atf)
*
* Copyright (c) 2008 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.
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <atf-c.h>
#include "detail/fs.h"
#include "detail/process.h"
#include "detail/test_helpers.h"
#include "detail/text.h"
/* ---------------------------------------------------------------------
* Auxiliary functions.
* --------------------------------------------------------------------- */
static
void
create_ctl_file(const char *name)
{
atf_fs_path_t p;
RE(atf_fs_path_init_fmt(&p, "%s", name));
ATF_REQUIRE(open(atf_fs_path_cstring(&p),
O_CREAT | O_WRONLY | O_TRUNC, 0644) != -1);
atf_fs_path_fini(&p);
}
static
bool
exists(const char *p)
{
bool b;
atf_fs_path_t pp;
RE(atf_fs_path_init_fmt(&pp, "%s", p));
RE(atf_fs_exists(&pp, &b));
atf_fs_path_fini(&pp);
return b;
}
static
void
init_and_run_h_tc(const char *name, void (*head)(atf_tc_t *),
void (*body)(const atf_tc_t *))
{
atf_tc_t tc;
const char *const config[] = { NULL };
RE(atf_tc_init(&tc, name, head, body, NULL, config));
run_h_tc(&tc, "output", "error", "result");
atf_tc_fini(&tc);
}
/* ---------------------------------------------------------------------
* Helper test cases.
* --------------------------------------------------------------------- */
#define H_DEF(id, macro) \
ATF_TC_HEAD(h_ ## id, tc) \
{ \
atf_tc_set_md_var(tc, "descr", "Helper test case"); \
} \
ATF_TC_BODY(h_ ## id, tc) \
{ \
create_ctl_file("before"); \
macro; \
create_ctl_file("after"); \
}
#define H_CHECK_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_ ## id)
#define H_CHECK_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_ ## id)
#define H_CHECK(id, condition) \
H_DEF(check_ ## id, ATF_CHECK(condition))
#define H_CHECK_MSG_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_msg_ ## id)
#define H_CHECK_MSG_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_msg_ ## id)
#define H_CHECK_MSG(id, condition, msg) \
H_DEF(check_msg_ ## id, ATF_CHECK_MSG(condition, msg))
#define H_CHECK_EQ_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_eq_ ## id)
#define H_CHECK_EQ_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_eq_ ## id)
#define H_CHECK_EQ(id, v1, v2) \
H_DEF(check_eq_ ## id, ATF_CHECK_EQ(v1, v2))
#define H_CHECK_STREQ_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_streq_ ## id)
#define H_CHECK_STREQ_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_streq_ ## id)
#define H_CHECK_STREQ(id, v1, v2) \
H_DEF(check_streq_ ## id, ATF_CHECK_STREQ(v1, v2))
#define H_CHECK_MATCH_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_match_ ## id)
#define H_CHECK_MATCH_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_match_ ## id)
#define H_CHECK_MATCH(id, v1, v2) \
H_DEF(check_match_ ## id, ATF_CHECK_MATCH(v1, v2))
#define H_CHECK_EQ_MSG_HEAD_NAME(id) \
ATF_TC_HEAD_NAME(h_check_eq_msg_ ## id)
#define H_CHECK_EQ_MSG_BODY_NAME(id) \
ATF_TC_BODY_NAME(h_check_eq_msg_ ## id)
#define H_CHECK_EQ_MSG(id, v1, v2, msg) \
H_DEF(check_eq_msg_ ## id, ATF_CHECK_EQ_MSG(v1, v2, msg))
#define H_CHECK_STREQ_MSG_HEAD_NAME(id) \
ATF_TC_HEAD_NAME(h_check_streq_msg_ ## id)
#define H_CHECK_STREQ_MSG_BODY_NAME(id) \
ATF_TC_BODY_NAME(h_check_streq_msg_ ## id)
#define H_CHECK_STREQ_MSG(id, v1, v2, msg) \
H_DEF(check_streq_msg_ ## id, ATF_CHECK_STREQ_MSG(v1, v2, msg))
#define H_CHECK_MATCH_MSG_HEAD_NAME(id) \
ATF_TC_HEAD_NAME(h_check_match_msg_ ## id)
#define H_CHECK_MATCH_MSG_BODY_NAME(id) \
ATF_TC_BODY_NAME(h_check_match_msg_ ## id)
#define H_CHECK_MATCH_MSG(id, v1, v2, msg) \
H_DEF(check_match_msg_ ## id, ATF_CHECK_MATCH_MSG(v1, v2, msg))
#define H_CHECK_ERRNO_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_errno_ ## id)
#define H_CHECK_ERRNO_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_errno_ ## id)
#define H_CHECK_ERRNO(id, exp_errno, bool_expr) \
H_DEF(check_errno_ ## id, ATF_CHECK_ERRNO(exp_errno, bool_expr))
#define H_REQUIRE_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_ ## id)
#define H_REQUIRE_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_ ## id)
#define H_REQUIRE(id, condition) \
H_DEF(require_ ## id, ATF_REQUIRE(condition))
#define H_REQUIRE_MSG_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_msg_ ## id)
#define H_REQUIRE_MSG_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_msg_ ## id)
#define H_REQUIRE_MSG(id, condition, msg) \
H_DEF(require_msg_ ## id, ATF_REQUIRE_MSG(condition, msg))
#define H_REQUIRE_EQ_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_eq_ ## id)
#define H_REQUIRE_EQ_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_eq_ ## id)
#define H_REQUIRE_EQ(id, v1, v2) \
H_DEF(require_eq_ ## id, ATF_REQUIRE_EQ(v1, v2))
#define H_REQUIRE_STREQ_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_streq_ ## id)
#define H_REQUIRE_STREQ_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_streq_ ## id)
#define H_REQUIRE_STREQ(id, v1, v2) \
H_DEF(require_streq_ ## id, ATF_REQUIRE_STREQ(v1, v2))
#define H_REQUIRE_MATCH_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_match_ ## id)
#define H_REQUIRE_MATCH_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_match_ ## id)
#define H_REQUIRE_MATCH(id, v1, v2) \
H_DEF(require_match_ ## id, ATF_REQUIRE_MATCH(v1, v2))
#define H_REQUIRE_EQ_MSG_HEAD_NAME(id) \
ATF_TC_HEAD_NAME(h_require_eq_msg_ ## id)
#define H_REQUIRE_EQ_MSG_BODY_NAME(id) \
ATF_TC_BODY_NAME(h_require_eq_msg_ ## id)
#define H_REQUIRE_EQ_MSG(id, v1, v2, msg) \
H_DEF(require_eq_msg_ ## id, ATF_REQUIRE_EQ_MSG(v1, v2, msg))
#define H_REQUIRE_STREQ_MSG_HEAD_NAME(id) \
ATF_TC_HEAD_NAME(h_require_streq_msg_ ## id)
#define H_REQUIRE_STREQ_MSG_BODY_NAME(id) \
ATF_TC_BODY_NAME(h_require_streq_msg_ ## id)
#define H_REQUIRE_STREQ_MSG(id, v1, v2, msg) \
H_DEF(require_streq_msg_ ## id, ATF_REQUIRE_STREQ_MSG(v1, v2, msg))
#define H_REQUIRE_MATCH_MSG_HEAD_NAME(id) \
ATF_TC_HEAD_NAME(h_require_match_msg_ ## id)
#define H_REQUIRE_MATCH_MSG_BODY_NAME(id) \
ATF_TC_BODY_NAME(h_require_match_msg_ ## id)
#define H_REQUIRE_MATCH_MSG(id, v1, v2, msg) \
H_DEF(require_match_msg_ ## id, ATF_REQUIRE_MATCH_MSG(v1, v2, msg))
#define H_REQUIRE_ERRNO_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_errno_ ## id)
#define H_REQUIRE_ERRNO_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_errno_ ## id)
#define H_REQUIRE_ERRNO(id, exp_errno, bool_expr) \
H_DEF(require_errno_ ## id, ATF_REQUIRE_ERRNO(exp_errno, bool_expr))
/* ---------------------------------------------------------------------
* Test cases for the ATF_{CHECK,REQUIRE}_ERRNO macros.
* --------------------------------------------------------------------- */
static int
errno_fail_stub(const int raised_errno)
{
errno = raised_errno;
return -1;
}
static int
errno_ok_stub(void)
{
return 0;
}
H_CHECK_ERRNO(no_error, -1, errno_ok_stub() == -1);
H_CHECK_ERRNO(errno_ok, 2, errno_fail_stub(2) == -1);
H_CHECK_ERRNO(errno_fail, 3, errno_fail_stub(4) == -1);
H_REQUIRE_ERRNO(no_error, -1, errno_ok_stub() == -1);
H_REQUIRE_ERRNO(errno_ok, 2, errno_fail_stub(2) == -1);
H_REQUIRE_ERRNO(errno_fail, 3, errno_fail_stub(4) == -1);
ATF_TC(check_errno);
ATF_TC_HEAD(check_errno, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK_ERRNO macro");
}
ATF_TC_BODY(check_errno, tc)
{
struct test {
void (*head)(atf_tc_t *);
void (*body)(const atf_tc_t *);
bool ok;
const char *exp_regex;
} *t, tests[] = {
{ H_CHECK_ERRNO_HEAD_NAME(no_error),
H_CHECK_ERRNO_BODY_NAME(no_error),
false, "Expected true value in errno_ok_stub\\(\\) == -1" },
{ H_CHECK_ERRNO_HEAD_NAME(errno_ok),
H_CHECK_ERRNO_BODY_NAME(errno_ok),
true, NULL },
{ H_CHECK_ERRNO_HEAD_NAME(errno_fail),
H_CHECK_ERRNO_BODY_NAME(errno_fail),
false, "Expected errno 3, got 4, in errno_fail_stub\\(4\\) == -1" },
{ NULL, NULL, false, NULL }
};
for (t = &tests[0]; t->head != NULL; t++) {
init_and_run_h_tc("h_check_errno", t->head, t->body);
ATF_REQUIRE(exists("before"));
ATF_REQUIRE(exists("after"));
if (t->ok) {
ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
} else {
ATF_REQUIRE(atf_utils_grep_file("^failed", "result"));
ATF_REQUIRE(atf_utils_grep_file(
"macros_test.c:[0-9]+: %s$", "error", t->exp_regex));
}
ATF_REQUIRE(unlink("before") != -1);
ATF_REQUIRE(unlink("after") != -1);
}
}
ATF_TC(require_errno);
ATF_TC_HEAD(require_errno, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE_ERRNO macro");
}
ATF_TC_BODY(require_errno, tc)
{
struct test {
void (*head)(atf_tc_t *);
void (*body)(const atf_tc_t *);
bool ok;
const char *exp_regex;
} *t, tests[] = {
{ H_REQUIRE_ERRNO_HEAD_NAME(no_error),
H_REQUIRE_ERRNO_BODY_NAME(no_error),
false, "Expected true value in errno_ok_stub\\(\\) == -1" },
{ H_REQUIRE_ERRNO_HEAD_NAME(errno_ok),
H_REQUIRE_ERRNO_BODY_NAME(errno_ok),
true, NULL },
{ H_REQUIRE_ERRNO_HEAD_NAME(errno_fail),
H_REQUIRE_ERRNO_BODY_NAME(errno_fail),
false, "Expected errno 3, got 4, in errno_fail_stub\\(4\\) == -1" },
{ NULL, NULL, false, NULL }
};
for (t = &tests[0]; t->head != NULL; t++) {
init_and_run_h_tc("h_require_errno", t->head, t->body);
ATF_REQUIRE(exists("before"));
if (t->ok) {
ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
ATF_REQUIRE(exists("after"));
} else {
ATF_REQUIRE(atf_utils_grep_file(
"^failed: .*macros_test.c:[0-9]+: %s$", "result",
t->exp_regex));
ATF_REQUIRE(!exists("after"));
}
ATF_REQUIRE(unlink("before") != -1);
if (t->ok)
ATF_REQUIRE(unlink("after") != -1);
}
}
/* ---------------------------------------------------------------------
* Test cases for the ATF_CHECK and ATF_CHECK_MSG macros.
* --------------------------------------------------------------------- */
H_CHECK(0, 0);
H_CHECK(1, 1);
H_CHECK_MSG(0, 0, "expected a false value");
H_CHECK_MSG(1, 1, "expected a true value");
ATF_TC(check);
ATF_TC_HEAD(check, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK and "
"ATF_CHECK_MSG macros");
}
ATF_TC_BODY(check, tc)
{
struct test {
void (*head)(atf_tc_t *);
void (*body)(const atf_tc_t *);
bool value;
const char *msg;
bool ok;
} *t, tests[] = {
{ H_CHECK_HEAD_NAME(0), H_CHECK_BODY_NAME(0), 0,
"0 not met", false },
{ H_CHECK_HEAD_NAME(1), H_CHECK_BODY_NAME(1), 1,
"1 not met", true },
{ H_CHECK_MSG_HEAD_NAME(0), H_CHECK_MSG_BODY_NAME(0), 0,
"expected a false value", false },
{ H_CHECK_MSG_HEAD_NAME(1), H_CHECK_MSG_BODY_NAME(1), 1,
"expected a true value", true },
{ NULL, NULL, false, NULL, false }
};
for (t = &tests[0]; t->head != NULL; t++) {
printf("Checking with a %d value\n", t->value);
init_and_run_h_tc("h_check", t->head, t->body);
ATF_REQUIRE(exists("before"));
ATF_REQUIRE(exists("after"));
if (t->ok) {
ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
} else {
ATF_REQUIRE(atf_utils_grep_file("^failed", "result"));
ATF_REQUIRE(atf_utils_grep_file("Check failed: .*"
"macros_test.c:[0-9]+: %s$", "error", t->msg));
}
ATF_REQUIRE(unlink("before") != -1);
ATF_REQUIRE(unlink("after") != -1);
}
}
/* ---------------------------------------------------------------------
* Test cases for the ATF_CHECK_*EQ_ macros.
* --------------------------------------------------------------------- */
struct check_eq_test {
void (*head)(atf_tc_t *);
void (*body)(const atf_tc_t *);
const char *v1;
const char *v2;
const char *msg;
bool ok;
};
static
void
do_check_eq_tests(const struct check_eq_test *tests)
{
const struct check_eq_test *t;
for (t = &tests[0]; t->head != NULL; t++) {
printf("Checking with %s, %s and expecting %s\n", t->v1, t->v2,
t->ok ? "true" : "false");
init_and_run_h_tc("h_check", t->head, t->body);
ATF_CHECK(exists("before"));
ATF_CHECK(exists("after"));
if (t->ok) {
ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
} else {
ATF_REQUIRE(atf_utils_grep_file("^failed", "result"));
ATF_CHECK(atf_utils_grep_file("Check failed: .*"
"macros_test.c:[0-9]+: %s$", "error", t->msg));
}
ATF_CHECK(unlink("before") != -1);
ATF_CHECK(unlink("after") != -1);
}
}
H_CHECK_EQ(1_1, 1, 1);
H_CHECK_EQ(1_2, 1, 2);
H_CHECK_EQ(2_1, 2, 1);
H_CHECK_EQ(2_2, 2, 2);
H_CHECK_EQ_MSG(1_1, 1, 1, "1 does not match 1");
H_CHECK_EQ_MSG(1_2, 1, 2, "1 does not match 2");
H_CHECK_EQ_MSG(2_1, 2, 1, "2 does not match 1");
H_CHECK_EQ_MSG(2_2, 2, 2, "2 does not match 2");
ATF_TC(check_eq);
ATF_TC_HEAD(check_eq, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK_EQ and "
"ATF_CHECK_EQ_MSG macros");
}
ATF_TC_BODY(check_eq, tc)
{
struct check_eq_test tests[] = {
{ H_CHECK_EQ_HEAD_NAME(1_1), H_CHECK_EQ_BODY_NAME(1_1),
"1", "1", "1 != 1", true },
{ H_CHECK_EQ_HEAD_NAME(1_2), H_CHECK_EQ_BODY_NAME(1_2),
"1", "2", "1 != 2", false },
{ H_CHECK_EQ_HEAD_NAME(2_1), H_CHECK_EQ_BODY_NAME(2_1),
"2", "1", "2 != 1", false },
{ H_CHECK_EQ_HEAD_NAME(2_2), H_CHECK_EQ_BODY_NAME(2_2),
"2", "2", "2 != 2", true },
{ H_CHECK_EQ_MSG_HEAD_NAME(1_1), H_CHECK_EQ_MSG_BODY_NAME(1_1),
"1", "1", "1 != 1: 1 does not match 1", true },
{ H_CHECK_EQ_MSG_HEAD_NAME(1_2), H_CHECK_EQ_MSG_BODY_NAME(1_2),
"1", "2", "1 != 2: 1 does not match 2", false },
{ H_CHECK_EQ_MSG_HEAD_NAME(2_1), H_CHECK_EQ_MSG_BODY_NAME(2_1),
"2", "1", "2 != 1: 2 does not match 1", false },
{ H_CHECK_EQ_MSG_HEAD_NAME(2_2), H_CHECK_EQ_MSG_BODY_NAME(2_2),
"2", "2", "2 != 2: 2 does not match 2", true },
{ NULL, NULL, 0, 0, "", false }
};
do_check_eq_tests(tests);
}
H_CHECK_STREQ(1_1, "1", "1");
H_CHECK_STREQ(1_2, "1", "2");
H_CHECK_STREQ(2_1, "2", "1");
H_CHECK_STREQ(2_2, "2", "2");
H_CHECK_STREQ_MSG(1_1, "1", "1", "1 does not match 1");
H_CHECK_STREQ_MSG(1_2, "1", "2", "1 does not match 2");
H_CHECK_STREQ_MSG(2_1, "2", "1", "2 does not match 1");
H_CHECK_STREQ_MSG(2_2, "2", "2", "2 does not match 2");
#define CHECK_STREQ_VAR1 "5"
#define CHECK_STREQ_VAR2 "9"
const char *check_streq_var1 = CHECK_STREQ_VAR1;
const char *check_streq_var2 = CHECK_STREQ_VAR2;
H_CHECK_STREQ(vars, check_streq_var1, check_streq_var2);
ATF_TC(check_streq);
ATF_TC_HEAD(check_streq, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK_STREQ and "
"ATF_CHECK_STREQ_MSG macros");
}
ATF_TC_BODY(check_streq, tc)
{
struct check_eq_test tests[] = {
{ H_CHECK_STREQ_HEAD_NAME(1_1), H_CHECK_STREQ_BODY_NAME(1_1),
"1", "1", "\"1\" != \"1\" \\(1 != 1\\)", true },
{ H_CHECK_STREQ_HEAD_NAME(1_2), H_CHECK_STREQ_BODY_NAME(1_2),
"1", "2", "\"1\" != \"2\" \\(1 != 2\\)", false },
{ H_CHECK_STREQ_HEAD_NAME(2_1), H_CHECK_STREQ_BODY_NAME(2_1),
"2", "1", "\"2\" != \"1\" \\(2 != 1\\)", false },
{ H_CHECK_STREQ_HEAD_NAME(2_2), H_CHECK_STREQ_BODY_NAME(2_2),
"2", "2", "\"2\" != \"2\" \\(2 != 2\\)", true },
{ H_CHECK_STREQ_MSG_HEAD_NAME(1_1),
H_CHECK_STREQ_MSG_BODY_NAME(1_1),
"1", "1", "\"1\" != \"1\" \\(1 != 1\\): 1 does not match 1", true },
{ H_CHECK_STREQ_MSG_HEAD_NAME(1_2),
H_CHECK_STREQ_MSG_BODY_NAME(1_2),
"1", "2", "\"1\" != \"2\" \\(1 != 2\\): 1 does not match 2", false },
{ H_CHECK_STREQ_MSG_HEAD_NAME(2_1),
H_CHECK_STREQ_MSG_BODY_NAME(2_1),
"2", "1", "\"2\" != \"1\" \\(2 != 1\\): 2 does not match 1", false },
{ H_CHECK_STREQ_MSG_HEAD_NAME(2_2),
H_CHECK_STREQ_MSG_BODY_NAME(2_2),
"2", "2", "\"2\" != \"2\" \\(2 != 2\\): 2 does not match 2", true },
{ H_CHECK_STREQ_HEAD_NAME(vars), H_CHECK_STREQ_BODY_NAME(vars),
check_streq_var1, check_streq_var2,
"check_streq_var1 != check_streq_var2 \\("
CHECK_STREQ_VAR1 " != " CHECK_STREQ_VAR2 "\\)", false },
{ NULL, NULL, 0, 0, "", false }
};
do_check_eq_tests(tests);
}
/* ---------------------------------------------------------------------
* Test cases for the ATF_CHECK_MATCH and ATF_CHECK_MATCH_MSG macros.
* --------------------------------------------------------------------- */
H_CHECK_MATCH(yes, "hello [a-z]+", "abc hello world");
H_CHECK_MATCH(no, "hello [a-z]+", "abc hello WORLD");
H_CHECK_MATCH_MSG(yes, "hello [a-z]+", "abc hello world", "lowercase");
H_CHECK_MATCH_MSG(no, "hello [a-z]+", "abc hello WORLD", "uppercase");
ATF_TC(check_match);
ATF_TC_HEAD(check_match, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK_MATCH and "
"ATF_CHECK_MATCH_MSG macros");
}
ATF_TC_BODY(check_match, tc)
{
struct check_eq_test tests[] = {
{ H_CHECK_MATCH_HEAD_NAME(yes), H_CHECK_MATCH_BODY_NAME(yes),
"hello [a-z]+", "abc hello world", "", true },
{ H_CHECK_MATCH_HEAD_NAME(no), H_CHECK_MATCH_BODY_NAME(no),
"hello [a-z]+", "abc hello WORLD",
"'hello \\[a-z\\]\\+' not matched in 'abc hello WORLD'", false },
{ H_CHECK_MATCH_MSG_HEAD_NAME(yes), H_CHECK_MATCH_MSG_BODY_NAME(yes),
"hello [a-z]+", "abc hello world", "", true },
{ H_CHECK_MATCH_MSG_HEAD_NAME(no), H_CHECK_MATCH_MSG_BODY_NAME(no),
"hello [a-z]+", "abc hello WORLD",
"'hello \\[a-z\\]\\+' not matched in 'abc hello WORLD': uppercase",
false },
{ NULL, NULL, 0, 0, "", false }
};
do_check_eq_tests(tests);
}
/* ---------------------------------------------------------------------
* Test cases for the ATF_REQUIRE and ATF_REQUIRE_MSG macros.
* --------------------------------------------------------------------- */
H_REQUIRE(0, 0);
H_REQUIRE(1, 1);
H_REQUIRE_MSG(0, 0, "expected a false value");
H_REQUIRE_MSG(1, 1, "expected a true value");
ATF_TC(require);
ATF_TC_HEAD(require, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE and "
"ATF_REQUIRE_MSG macros");
}
ATF_TC_BODY(require, tc)
{
struct test {
void (*head)(atf_tc_t *);
void (*body)(const atf_tc_t *);
bool value;
const char *msg;
bool ok;
} *t, tests[] = {
{ H_REQUIRE_HEAD_NAME(0), H_REQUIRE_BODY_NAME(0), 0,
"0 not met", false },
{ H_REQUIRE_HEAD_NAME(1), H_REQUIRE_BODY_NAME(1), 1,
"1 not met", true },
{ H_REQUIRE_MSG_HEAD_NAME(0), H_REQUIRE_MSG_BODY_NAME(0), 0,
"expected a false value", false },
{ H_REQUIRE_MSG_HEAD_NAME(1), H_REQUIRE_MSG_BODY_NAME(1), 1,
"expected a true value", true },
{ NULL, NULL, false, NULL, false }
};
for (t = &tests[0]; t->head != NULL; t++) {
printf("Checking with a %d value\n", t->value);
init_and_run_h_tc("h_require", t->head, t->body);
ATF_REQUIRE(exists("before"));
if (t->ok) {
ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
ATF_REQUIRE(exists("after"));
} else {
ATF_REQUIRE(atf_utils_grep_file(
"^failed: .*macros_test.c:[0-9]+: %s$", "result", t->msg));
ATF_REQUIRE(!exists("after"));
}
ATF_REQUIRE(unlink("before") != -1);
if (t->ok)
ATF_REQUIRE(unlink("after") != -1);
}
}
/* ---------------------------------------------------------------------
* Test cases for the ATF_REQUIRE_*EQ_ macros.
* --------------------------------------------------------------------- */
struct require_eq_test {
void (*head)(atf_tc_t *);
void (*body)(const atf_tc_t *);
const char *v1;
const char *v2;
const char *msg;
bool ok;
};
static
void
do_require_eq_tests(const struct require_eq_test *tests)
{
const struct require_eq_test *t;
for (t = &tests[0]; t->head != NULL; t++) {
printf("Checking with %s, %s and expecting %s\n", t->v1, t->v2,
t->ok ? "true" : "false");
init_and_run_h_tc("h_require", t->head, t->body);
ATF_REQUIRE(exists("before"));
if (t->ok) {
ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
ATF_REQUIRE(exists("after"));
} else {
ATF_REQUIRE(atf_utils_grep_file("^failed: .*macros_test.c"
":[0-9]+: %s$", "result", t->msg));
ATF_REQUIRE(!exists("after"));
}
ATF_REQUIRE(unlink("before") != -1);
if (t->ok)
ATF_REQUIRE(unlink("after") != -1);
}
}
H_REQUIRE_EQ(1_1, 1, 1);
H_REQUIRE_EQ(1_2, 1, 2);
H_REQUIRE_EQ(2_1, 2, 1);
H_REQUIRE_EQ(2_2, 2, 2);
H_REQUIRE_EQ_MSG(1_1, 1, 1, "1 does not match 1");
H_REQUIRE_EQ_MSG(1_2, 1, 2, "1 does not match 2");
H_REQUIRE_EQ_MSG(2_1, 2, 1, "2 does not match 1");
H_REQUIRE_EQ_MSG(2_2, 2, 2, "2 does not match 2");
ATF_TC(require_eq);
ATF_TC_HEAD(require_eq, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE_EQ and "
"ATF_REQUIRE_EQ_MSG macros");
}
ATF_TC_BODY(require_eq, tc)
{
struct require_eq_test tests[] = {
{ H_REQUIRE_EQ_HEAD_NAME(1_1), H_REQUIRE_EQ_BODY_NAME(1_1),
"1", "1", "1 != 1", true },
{ H_REQUIRE_EQ_HEAD_NAME(1_2), H_REQUIRE_EQ_BODY_NAME(1_2),
"1", "2", "1 != 2", false },
{ H_REQUIRE_EQ_HEAD_NAME(2_1), H_REQUIRE_EQ_BODY_NAME(2_1),
"2", "1", "2 != 1", false },
{ H_REQUIRE_EQ_HEAD_NAME(2_2), H_REQUIRE_EQ_BODY_NAME(2_2),
"2", "2", "2 != 2", true },
{ H_REQUIRE_EQ_MSG_HEAD_NAME(1_1), H_REQUIRE_EQ_MSG_BODY_NAME(1_1),
"1", "1", "1 != 1: 1 does not match 1", true },
{ H_REQUIRE_EQ_MSG_HEAD_NAME(1_2), H_REQUIRE_EQ_MSG_BODY_NAME(1_2),
"1", "2", "1 != 2: 1 does not match 2", false },
{ H_REQUIRE_EQ_MSG_HEAD_NAME(2_1), H_REQUIRE_EQ_MSG_BODY_NAME(2_1),
"2", "1", "2 != 1: 2 does not match 1", false },
{ H_REQUIRE_EQ_MSG_HEAD_NAME(2_2), H_REQUIRE_EQ_MSG_BODY_NAME(2_2),
"2", "2", "2 != 2: 2 does not match 2", true },
{ NULL, NULL, 0, 0, "", false }
};
do_require_eq_tests(tests);
}
H_REQUIRE_STREQ(1_1, "1", "1");
H_REQUIRE_STREQ(1_2, "1", "2");
H_REQUIRE_STREQ(2_1, "2", "1");
H_REQUIRE_STREQ(2_2, "2", "2");
H_REQUIRE_STREQ_MSG(1_1, "1", "1", "1 does not match 1");
H_REQUIRE_STREQ_MSG(1_2, "1", "2", "1 does not match 2");
H_REQUIRE_STREQ_MSG(2_1, "2", "1", "2 does not match 1");
H_REQUIRE_STREQ_MSG(2_2, "2", "2", "2 does not match 2");
#define REQUIRE_STREQ_VAR1 "5"
#define REQUIRE_STREQ_VAR2 "9"
const char *require_streq_var1 = REQUIRE_STREQ_VAR1;
const char *require_streq_var2 = REQUIRE_STREQ_VAR2;
H_REQUIRE_STREQ(vars, require_streq_var1, require_streq_var2);
ATF_TC(require_streq);
ATF_TC_HEAD(require_streq, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE_STREQ and "
"ATF_REQUIRE_STREQ_MSG macros");
}
ATF_TC_BODY(require_streq, tc)
{
struct require_eq_test tests[] = {
{ H_REQUIRE_STREQ_HEAD_NAME(1_1), H_REQUIRE_STREQ_BODY_NAME(1_1),
"1", "1", "\"1\" != \"1\" \\(1 != 1\\)", true },
{ H_REQUIRE_STREQ_HEAD_NAME(1_2), H_REQUIRE_STREQ_BODY_NAME(1_2),
"1", "2", "\"1\" != \"2\" \\(1 != 2\\)", false },
{ H_REQUIRE_STREQ_HEAD_NAME(2_1), H_REQUIRE_STREQ_BODY_NAME(2_1),
"2", "1", "\"2\" != \"1\" \\(2 != 1\\)", false },
{ H_REQUIRE_STREQ_HEAD_NAME(2_2), H_REQUIRE_STREQ_BODY_NAME(2_2),
"2", "2", "\"2\" != \"2\" \\(2 != 2\\)", true },
{ H_REQUIRE_STREQ_MSG_HEAD_NAME(1_1),
H_REQUIRE_STREQ_MSG_BODY_NAME(1_1),
"1", "1", "\"1\" != \"1\" \\(1 != 1\\): 1 does not match 1", true },
{ H_REQUIRE_STREQ_MSG_HEAD_NAME(1_2),
H_REQUIRE_STREQ_MSG_BODY_NAME(1_2),
"1", "2", "\"1\" != \"2\" \\(1 != 2\\): 1 does not match 2", false },
{ H_REQUIRE_STREQ_MSG_HEAD_NAME(2_1),
H_REQUIRE_STREQ_MSG_BODY_NAME(2_1),
"2", "1", "\"2\" != \"1\" \\(2 != 1\\): 2 does not match 1", false },
{ H_REQUIRE_STREQ_MSG_HEAD_NAME(2_2),
H_REQUIRE_STREQ_MSG_BODY_NAME(2_2),
"2", "2", "\"2\" != \"2\" \\(2 != 2\\): 2 does not match 2", true },
{ H_REQUIRE_STREQ_HEAD_NAME(vars), H_REQUIRE_STREQ_BODY_NAME(vars),
require_streq_var1, require_streq_var2,
"require_streq_var1 != require_streq_var2 \\("
REQUIRE_STREQ_VAR1 " != " REQUIRE_STREQ_VAR2 "\\)", false },
{ NULL, NULL, 0, 0, "", false }
};
do_require_eq_tests(tests);
}
/* ---------------------------------------------------------------------
* Test cases for the ATF_REQUIRE_MATCH and ATF_REQUIRE_MATCH_MSG macros.
* --------------------------------------------------------------------- */
H_REQUIRE_MATCH(yes, "hello [a-z]+", "abc hello world");
H_REQUIRE_MATCH(no, "hello [a-z]+", "abc hello WORLD");
H_REQUIRE_MATCH_MSG(yes, "hello [a-z]+", "abc hello world", "lowercase");
H_REQUIRE_MATCH_MSG(no, "hello [a-z]+", "abc hello WORLD", "uppercase");
ATF_TC(require_match);
ATF_TC_HEAD(require_match, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE_MATCH and "
"ATF_REQUIRE_MATCH_MSG macros");
}
ATF_TC_BODY(require_match, tc)
{
struct require_eq_test tests[] = {
{ H_REQUIRE_MATCH_HEAD_NAME(yes), H_REQUIRE_MATCH_BODY_NAME(yes),
"hello [a-z]+", "abc hello world", "", true },
{ H_REQUIRE_MATCH_HEAD_NAME(no), H_REQUIRE_MATCH_BODY_NAME(no),
"hello [a-z]+", "abc hello WORLD",
"'hello \\[a-z\\]\\+' not matched in 'abc hello WORLD'", false },
{ H_REQUIRE_MATCH_MSG_HEAD_NAME(yes),
H_REQUIRE_MATCH_MSG_BODY_NAME(yes),
"hello [a-z]+", "abc hello world", "", true },
{ H_REQUIRE_MATCH_MSG_HEAD_NAME(no), H_REQUIRE_MATCH_MSG_BODY_NAME(no),
"hello [a-z]+", "abc hello WORLD",
"'hello \\[a-z\\]\\+' not matched in 'abc hello WORLD': uppercase",
false },
{ NULL, NULL, 0, 0, "", false }
};
do_require_eq_tests(tests);
}
/* ---------------------------------------------------------------------
* Miscellaneous test cases covering several macros.
* --------------------------------------------------------------------- */
static
bool
aux_bool(const char *fmt ATF_DEFS_ATTRIBUTE_UNUSED)
{
return false;
}
static
const char *
aux_str(const char *fmt ATF_DEFS_ATTRIBUTE_UNUSED)
{
return "foo";
}
H_CHECK(msg, aux_bool("%d"));
H_REQUIRE(msg, aux_bool("%d"));
H_CHECK_STREQ(msg, aux_str("%d"), "");
H_REQUIRE_STREQ(msg, aux_str("%d"), "");
ATF_TC(msg_embedded_fmt);
ATF_TC_HEAD(msg_embedded_fmt, tc)
{
atf_tc_set_md_var(tc, "descr", "Tests that format strings passed "
"as part of the automatically-generated messages "
"do not get expanded");
}
ATF_TC_BODY(msg_embedded_fmt, tc)
{
struct test {
void (*head)(atf_tc_t *);
void (*body)(const atf_tc_t *);
bool fatal;
const char *msg;
} *t, tests[] = {
{ H_CHECK_HEAD_NAME(msg), H_CHECK_BODY_NAME(msg), false,
"aux_bool\\(\"%d\"\\) not met" },
{ H_REQUIRE_HEAD_NAME(msg), H_REQUIRE_BODY_NAME(msg), true,
"aux_bool\\(\"%d\"\\) not met" },
{ H_CHECK_STREQ_HEAD_NAME(msg), H_CHECK_STREQ_BODY_NAME(msg), false,
"aux_str\\(\"%d\"\\) != \"\" \\(foo != \\)" },
{ H_REQUIRE_STREQ_HEAD_NAME(msg), H_REQUIRE_STREQ_BODY_NAME(msg), true,
"aux_str\\(\"%d\"\\) != \"\" \\(foo != \\)" },
{ NULL, NULL, false, NULL }
};
for (t = &tests[0]; t->head != NULL; t++) {
printf("Checking with an expected '%s' message\n", t->msg);
init_and_run_h_tc("h_check", t->head, t->body);
if (t->fatal) {
bool matched =
atf_utils_grep_file(
"^failed: .*macros_test.c:[0-9]+: %s$", "result", t->msg);
ATF_CHECK_MSG(matched, "couldn't find error string in result");
} else {
bool matched = atf_utils_grep_file("Check failed: .*"
"macros_test.c:[0-9]+: %s$", "error", t->msg);
ATF_CHECK_MSG(matched, "couldn't find error string in output");
}
}
}
/* ---------------------------------------------------------------------
* Tests cases for the header file.
* --------------------------------------------------------------------- */
HEADER_TC(include, "atf-c/macros.h");
BUILD_TC(use, "macros_h_test.c",
"Tests that the macros provided by the atf-c/macros.h file "
"do not cause syntax errors when used",
"Build of macros_h_test.c failed; some macros in atf-c/macros.h "
"are broken");
BUILD_TC_FAIL(detect_unused_tests, "unused_test.c",
"Tests that defining an unused test case raises a warning (and thus "
"an error)",
"Build of unused_test.c passed; unused test cases are not properly "
"detected");
/* ---------------------------------------------------------------------
* Main.
* --------------------------------------------------------------------- */
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, check);
ATF_TP_ADD_TC(tp, check_eq);
ATF_TP_ADD_TC(tp, check_streq);
ATF_TP_ADD_TC(tp, check_errno);
ATF_TP_ADD_TC(tp, check_match);
ATF_TP_ADD_TC(tp, require);
ATF_TP_ADD_TC(tp, require_eq);
ATF_TP_ADD_TC(tp, require_streq);
ATF_TP_ADD_TC(tp, require_errno);
ATF_TP_ADD_TC(tp, require_match);
ATF_TP_ADD_TC(tp, msg_embedded_fmt);
/* Add the test cases for the header file. */
ATF_TP_ADD_TC(tp, include);
ATF_TP_ADD_TC(tp, use);
ATF_TP_ADD_TC(tp, detect_unused_tests);
return atf_no_error();
}