summaryrefslogtreecommitdiffstats
path: root/contrib/atf/atf-c
diff options
context:
space:
mode:
authorjmmv <jmmv@FreeBSD.org>2013-11-17 23:51:19 +0000
committerjmmv <jmmv@FreeBSD.org>2013-11-17 23:51:19 +0000
commit8c7e11817a76331c10afb89d609a304c49dd588b (patch)
treee69b0ffecc81ada4e0d39442aa0f39a4abc93806 /contrib/atf/atf-c
parenta21ab9564f9972a893699a0178df90fd60e11b47 (diff)
parentb849e3606cf0dc725ff02712cd92907131c0188c (diff)
downloadFreeBSD-src-8c7e11817a76331c10afb89d609a304c49dd588b.zip
FreeBSD-src-8c7e11817a76331c10afb89d609a304c49dd588b.tar.gz
MFV: Import atf-0.18.
Approved by: rpaulo (mentor)
Diffstat (limited to 'contrib/atf/atf-c')
-rw-r--r--contrib/atf/atf-c/Makefile.am.inc157
-rw-r--r--contrib/atf/atf-c/atf-c-api.3277
-rw-r--r--contrib/atf/atf-c/check_test.c50
-rw-r--r--contrib/atf/atf-c/detail/Atffile1
-rw-r--r--contrib/atf/atf-c/detail/Kyuafile1
-rw-r--r--contrib/atf/atf-c/detail/Makefile.am.inc104
-rw-r--r--contrib/atf/atf-c/detail/process_test.c40
-rw-r--r--contrib/atf/atf-c/detail/sanity_test.c40
-rw-r--r--contrib/atf/atf-c/detail/test_helpers.c67
-rw-r--r--contrib/atf/atf-c/detail/test_helpers.h2
-rw-r--r--contrib/atf/atf-c/detail/test_helpers_test.c185
-rw-r--r--contrib/atf/atf-c/macros.h20
-rw-r--r--contrib/atf/atf-c/macros_test.c154
-rw-r--r--contrib/atf/atf-c/pkg_config_test.sh2
-rw-r--r--contrib/atf/atf-c/utils.c374
-rw-r--r--contrib/atf/atf-c/utils.h19
-rw-r--r--contrib/atf/atf-c/utils_test.c480
17 files changed, 1332 insertions, 641 deletions
diff --git a/contrib/atf/atf-c/Makefile.am.inc b/contrib/atf/atf-c/Makefile.am.inc
deleted file mode 100644
index b813ec4..0000000
--- a/contrib/atf/atf-c/Makefile.am.inc
+++ /dev/null
@@ -1,157 +0,0 @@
-#
-# Automated Testing Framework (atf)
-#
-# Copyright (c) 2007 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.
-#
-
-lib_LTLIBRARIES += libatf-c.la
-libatf_c_la_SOURCES = atf-c/build.c \
- atf-c/build.h \
- atf-c/check.c \
- atf-c/check.h \
- atf-c/config.c \
- atf-c/config.h \
- atf-c/error.c \
- atf-c/error.h \
- atf-c/error_fwd.h \
- atf-c/macros.h \
- atf-c/tc.c \
- atf-c/tc.h \
- atf-c/tp.c \
- atf-c/tp.h \
- atf-c/utils.c \
- atf-c/utils.h
-nodist_libatf_c_la_SOURCES = atf-c/defs.h
-libatf_c_la_CPPFLAGS = "-DATF_ARCH=\"$(atf_arch)\"" \
- "-DATF_BUILD_CC=\"$(ATF_BUILD_CC)\"" \
- "-DATF_BUILD_CFLAGS=\"$(ATF_BUILD_CFLAGS)\"" \
- "-DATF_BUILD_CPP=\"$(ATF_BUILD_CPP)\"" \
- "-DATF_BUILD_CPPFLAGS=\"$(ATF_BUILD_CPPFLAGS)\"" \
- "-DATF_BUILD_CXX=\"$(ATF_BUILD_CXX)\"" \
- "-DATF_BUILD_CXXFLAGS=\"$(ATF_BUILD_CXXFLAGS)\"" \
- "-DATF_CONFDIR=\"$(atf_confdir)\"" \
- "-DATF_INCLUDEDIR=\"$(includedir)\"" \
- "-DATF_LIBDIR=\"$(libdir)\"" \
- "-DATF_LIBEXECDIR=\"$(libexecdir)\"" \
- "-DATF_MACHINE=\"$(atf_machine)\"" \
- "-DATF_M4=\"$(ATF_M4)\"" \
- "-DATF_PKGDATADIR=\"$(pkgdatadir)\"" \
- "-DATF_SHELL=\"$(ATF_SHELL)\"" \
- "-DATF_WORKDIR=\"$(ATF_WORKDIR)\"" \
- -I$(srcdir)/atf-c
-libatf_c_la_LDFLAGS = -version-info 0:0:0
-
-# XXX For some reason, the nodist line above does not work as expected.
-# Work this problem around.
-dist-hook: kill-defs-h
-kill-defs-h:
- rm -f $(distdir)/atf-c/defs.h
-
-include_HEADERS += atf-c.h
-atf_c_HEADERS = atf-c/build.h \
- atf-c/check.h \
- atf-c/config.h \
- atf-c/defs.h \
- atf-c/error.h \
- atf-c/error_fwd.h \
- atf-c/macros.h \
- atf-c/tc.h \
- atf-c/tp.h \
- atf-c/utils.h
-atf_cdir = $(includedir)/atf-c
-
-dist_man_MANS += atf-c/atf-c-api.3
-
-atf_aclocal_DATA += atf-c/atf-common.m4 atf-c/atf-c.m4
-EXTRA_DIST += atf-c/atf-common.m4 atf-c/atf-c.m4
-
-atf_cpkgconfigdir = $(atf_pkgconfigdir)
-atf_cpkgconfig_DATA = atf-c/atf-c.pc
-CLEANFILES += atf-c/atf-c.pc
-EXTRA_DIST += atf-c/atf-c.pc.in
-atf-c/atf-c.pc: $(srcdir)/atf-c/atf-c.pc.in Makefile
- test -d atf-c || mkdir -p atf-c
- sed -e 's#__ATF_VERSION__#$(PACKAGE_VERSION)#g' \
- -e 's#__CC__#$(CC)#g' \
- -e 's#__INCLUDEDIR__#$(includedir)#g' \
- -e 's#__LIBDIR__#$(libdir)#g' \
- <$(srcdir)/atf-c/atf-c.pc.in >atf-c/atf-c.pc.tmp
- mv atf-c/atf-c.pc.tmp atf-c/atf-c.pc
-
-tests_atf_c_DATA = atf-c/Atffile \
- atf-c/Kyuafile \
- atf-c/macros_h_test.c \
- atf-c/unused_test.c
-tests_atf_cdir = $(pkgtestsdir)/atf-c
-EXTRA_DIST += $(tests_atf_c_DATA)
-
-tests_atf_c_PROGRAMS = atf-c/atf_c_test
-atf_c_atf_c_test_SOURCES = atf-c/atf_c_test.c
-atf_c_atf_c_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_PROGRAMS += atf-c/build_test
-atf_c_build_test_SOURCES = atf-c/build_test.c atf-c/h_build.h
-atf_c_build_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_PROGRAMS += atf-c/check_test
-atf_c_check_test_SOURCES = atf-c/check_test.c
-atf_c_check_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_PROGRAMS += atf-c/config_test
-atf_c_config_test_SOURCES = atf-c/config_test.c
-atf_c_config_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_PROGRAMS += atf-c/error_test
-atf_c_error_test_SOURCES = atf-c/error_test.c
-atf_c_error_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_PROGRAMS += atf-c/macros_test
-atf_c_macros_test_SOURCES = atf-c/macros_test.c
-atf_c_macros_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_SCRIPTS = atf-c/pkg_config_test
-CLEANFILES += atf-c/pkg_config_test
-EXTRA_DIST += atf-c/pkg_config_test.sh
-atf-c/pkg_config_test: $(srcdir)/atf-c/pkg_config_test.sh
- test -d atf-c || mkdir -p atf-c
- @src="$(srcdir)/atf-c/pkg_config_test.sh"; \
- dst="atf-c/pkg_config_test"; $(BUILD_SH_TP)
-
-tests_atf_c_PROGRAMS += atf-c/tc_test
-atf_c_tc_test_SOURCES = atf-c/tc_test.c
-atf_c_tc_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_PROGRAMS += atf-c/tp_test
-atf_c_tp_test_SOURCES = atf-c/tp_test.c
-atf_c_tp_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_PROGRAMS += atf-c/utils_test
-atf_c_utils_test_SOURCES = atf-c/utils_test.c atf-c/h_build.h
-atf_c_utils_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-include atf-c/detail/Makefile.am.inc
-
-# vim: syntax=make:noexpandtab:shiftwidth=8:softtabstop=8
diff --git a/contrib/atf/atf-c/atf-c-api.3 b/contrib/atf/atf-c/atf-c-api.3
index 548db4f..366caec 100644
--- a/contrib/atf/atf-c/atf-c-api.3
+++ b/contrib/atf/atf-c/atf-c-api.3
@@ -26,14 +26,17 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd December 26, 2010
+.Dd November 15, 2013
.Dt ATF-C-API 3
.Os
.Sh NAME
+.Nm atf-c-api ,
.Nm ATF_CHECK ,
.Nm ATF_CHECK_MSG ,
.Nm ATF_CHECK_EQ ,
.Nm ATF_CHECK_EQ_MSG ,
+.Nm ATF_CHECK_MATCH ,
+.Nm ATF_CHECK_MATCH_MSG ,
.Nm ATF_CHECK_STREQ ,
.Nm ATF_CHECK_STREQ_MSG ,
.Nm ATF_CHECK_ERRNO ,
@@ -41,6 +44,8 @@
.Nm ATF_REQUIRE_MSG ,
.Nm ATF_REQUIRE_EQ ,
.Nm ATF_REQUIRE_EQ_MSG ,
+.Nm ATF_REQUIRE_MATCH ,
+.Nm ATF_REQUIRE_MATCH_MSG ,
.Nm ATF_REQUIRE_STREQ ,
.Nm ATF_REQUIRE_STREQ_MSG ,
.Nm ATF_REQUIRE_ERRNO ,
@@ -72,7 +77,19 @@
.Nm atf_tc_fail ,
.Nm atf_tc_fail_nonfatal ,
.Nm atf_tc_pass ,
-.Nm atf_tc_skip
+.Nm atf_tc_skip ,
+.Nm atf_utils_cat_file ,
+.Nm atf_utils_compare_file ,
+.Nm atf_utils_copy_file ,
+.Nm atf_utils_create_file ,
+.Nm atf_utils_file_exists ,
+.Nm atf_utils_fork ,
+.Nm atf_utils_free_charpp ,
+.Nm atf_utils_grep_file ,
+.Nm atf_utils_grep_string ,
+.Nm atf_utils_readline ,
+.Nm atf_utils_redirect ,
+.Nm atf_utils_wait
.Nd C API to write ATF-based test programs
.Sh SYNOPSIS
.In atf-c.h
@@ -80,6 +97,8 @@
.Fn ATF_CHECK_MSG "expression" "fail_msg_fmt" ...
.Fn ATF_CHECK_EQ "expression_1" "expression_2"
.Fn ATF_CHECK_EQ_MSG "expression_1" "expression_2" "fail_msg_fmt" ...
+.Fn ATF_CHECK_MATCH "regexp" "string"
+.Fn ATF_CHECK_MATCH_MSG "regexp" "string" "fail_msg_fmt" ...
.Fn ATF_CHECK_STREQ "string_1" "string_2"
.Fn ATF_CHECK_STREQ_MSG "string_1" "string_2" "fail_msg_fmt" ...
.Fn ATF_CHECK_ERRNO "exp_errno" "bool_expression"
@@ -87,6 +106,8 @@
.Fn ATF_REQUIRE_MSG "expression" "fail_msg_fmt" ...
.Fn ATF_REQUIRE_EQ "expression_1" "expression_2"
.Fn ATF_REQUIRE_EQ_MSG "expression_1" "expression_2" "fail_msg_fmt" ...
+.Fn ATF_REQUIRE_MATCH "regexp" "string"
+.Fn ATF_REQUIRE_MATCH_MSG "regexp" "string" "fail_msg_fmt" ...
.Fn ATF_REQUIRE_STREQ "string_1" "string_2"
.Fn ATF_REQUIRE_STREQ_MSG "string_1" "string_2" "fail_msg_fmt" ...
.Fn ATF_REQUIRE_ERRNO "exp_errno" "bool_expression"
@@ -119,10 +140,70 @@
.Fn atf_tc_fail_nonfatal "reason"
.Fn atf_tc_pass
.Fn atf_tc_skip "reason"
+.Ft void
+.Fo atf_utils_cat_file
+.Fa "const char *file"
+.Fa "const char *prefix"
+.Fc
+.Ft bool
+.Fo atf_utils_compare_file
+.Fa "const char *file"
+.Fa "const char *contents"
+.Fc
+.Ft void
+.Fo atf_utils_copy_file
+.Fa "const char *source"
+.Fa "const char *destination"
+.Fc
+.Ft void
+.Fo atf_utils_create_file
+.Fa "const char *file"
+.Fa "const char *contents"
+.Fa "..."
+.Fc
+.Ft void
+.Fo atf_utils_file_exists
+.Fa "const char *file"
+.Fc
+.Ft pid_t
+.Fo atf_utils_fork
+.Fa "void"
+.Fc
+.Ft void
+.Fo atf_utils_free_charpp
+.Fa "char **argv"
+.Fc
+.Ft bool
+.Fo atf_utils_grep_file
+.Fa "const char *regexp"
+.Fa "const char *file"
+.Fa "..."
+.Fc
+.Ft bool
+.Fo atf_utils_grep_string
+.Fa "const char *regexp"
+.Fa "const char *str"
+.Fa "..."
+.Fc
+.Ft char *
+.Fo atf_utils_readline
+.Fa "int fd"
+.Fc
+.Ft void
+.Fo atf_utils_redirect
+.Fa "const int fd"
+.Fa "const char *file"
+.Fc
+.Ft void
+.Fo atf_utils_wait
+.Fa "const pid_t pid"
+.Fa "const int expected_exit_status"
+.Fa "const char *expected_stdout"
+.Fa "const char *expected_stderr"
+.Fc
.Sh DESCRIPTION
-The ATF
-.Pp
-C-based test programs always follow this template:
+ATF provides a C programming interface to implement test programs.
+C-based test programs follow this template:
.Bd -literal -offset indent
.Ns ... C-specific includes go here ...
@@ -382,7 +463,7 @@ variant of the macros immediately abort the test case as soon as an error
condition is detected by calling the
.Fn atf_tc_fail
function.
-Use this variant whenever it makes now sense to continue the execution of a
+Use this variant whenever it makes no sense to continue the execution of a
test case when the checked condition is not met.
The
.Sq CHECK
@@ -417,6 +498,16 @@ and
.Fn ATF_REQUIRE_EQ_MSG
take two expressions and fail if the two evaluated values are not equal.
.Pp
+.Fn ATF_CHECK_MATCH ,
+.Fn ATF_CHECK_MATCH_MSG ,
+.Fn ATF_REQUIRE_MATCH
+and
+.Fn ATF_REQUIRE_MATCH_MSG
+take a regular expression and a string and fail if the regular expression does
+not match the given string.
+Note that the regular expression is not anchored, so it will match anywhere in
+the string.
+.Pp
.Fn ATF_CHECK_STREQ ,
.Fn ATF_CHECK_STREQ_MSG ,
.Fn ATF_REQUIRE_STREQ
@@ -433,6 +524,180 @@ variable and, second, a boolean expression that, if evaluates to true,
means that a call failed and
.Va errno
has to be checked against the first value.
+.Ss Utility functions
+The following functions are provided as part of the
+.Nm
+API to simplify the creation of a variety of tests.
+In particular, these are useful to write tests for command-line interfaces.
+.Pp
+.Ft void
+.Fo atf_utils_cat_file
+.Fa "const char *file"
+.Fa "const char *prefix"
+.Fc
+.Bd -ragged -offset indent
+Prints the contents of
+.Fa file
+to the standard output, prefixing every line with the string in
+.Fa prefix .
+.Ed
+.Pp
+.Ft bool
+.Fo atf_utils_compare_file
+.Fa "const char *file"
+.Fa "const char *contents"
+.Fc
+.Bd -ragged -offset indent
+Returns true if the given
+.Fa file
+matches exactly the expected inlined
+.Fa contents .
+.Ed
+.Pp
+.Ft void
+.Fo atf_utils_copy_file
+.Fa "const char *source"
+.Fa "const char *destination"
+.Fc
+.Bd -ragged -offset indent
+Copies the file
+.Fa source
+to
+.Fa destination .
+The permissions of the file are preserved during the code.
+.Ed
+.Pp
+.Ft void
+.Fo atf_utils_create_file
+.Fa "const char *file"
+.Fa "const char *contents"
+.Fa "..."
+.Fc
+.Bd -ragged -offset indent
+Creates
+.Fa file
+with the text given in
+.Fa contents ,
+which is a formatting string that uses the rest of the variable arguments.
+.Ed
+.Pp
+.Ft void
+.Fo atf_utils_file_exists
+.Fa "const char *file"
+.Fc
+.Bd -ragged -offset indent
+Checks if
+.Fa file
+exists.
+.Ed
+.Pp
+.Ft pid_t
+.Fo atf_utils_fork
+.Fa "void"
+.Fc
+.Bd -ragged -offset indent
+Forks a process and redirects the standard output and standard error of the
+child to files for later validation with
+.Fn atf_utils_wait .
+Fails the test case if the fork fails, so this does not return an error.
+.Ed
+.Pp
+.Ft void
+.Fo atf_utils_free_charpp
+.Fa "char **argv"
+.Fc
+.Bd -ragged -offset indent
+Frees a dynamically-allocated array of dynamically-allocated strings.
+.Ed
+.Pp
+.Ft bool
+.Fo atf_utils_grep_file
+.Fa "const char *regexp"
+.Fa "const char *file"
+.Fa "..."
+.Fc
+.Bd -ragged -offset indent
+Searches for the
+.Fa regexp ,
+which is a formatting string representing the regular expression,
+in the
+.Fa file .
+The variable arguments are used to construct the regular expression.
+.Ed
+.Pp
+.Ft bool
+.Fo atf_utils_grep_string
+.Fa "const char *regexp"
+.Fa "const char *str"
+.Fa "..."
+.Fc
+.Bd -ragged -offset indent
+Searches for the
+.Fa regexp ,
+which is a formatting string representing the regular expression,
+in the literal string
+.Fa str .
+The variable arguments are used to construct the regular expression.
+.Ed
+.Pp
+.Ft char *
+.Fo atf_utils_readline
+.Fa "int fd"
+.Fc
+.Bd -ragged -offset indent
+Reads a line from the file descriptor
+.Fa fd .
+The line, if any, is returned as a dynamically-allocated buffer that must be
+released with
+.Xr free 3 .
+If there was nothing to read, returns
+.Sq NULL .
+.Ed
+.Pp
+.Ft void
+.Fo atf_utils_redirect
+.Fa "const int fd"
+.Fa "const char *file"
+.Fc
+.Bd -ragged -offset indent
+Redirects the given file descriptor
+.Fa fd
+to
+.Fa file .
+This function exits the process in case of an error and does not properly mark
+the test case as failed.
+As a result, it should only be used in subprocesses of the test case; specially
+those spawned by
+.Fn atf_utils_fork .
+.Ed
+.Pp
+.Ft void
+.Fo atf_utils_wait
+.Fa "const pid_t pid"
+.Fa "const int expected_exit_status"
+.Fa "const char *expected_stdout"
+.Fa "const char *expected_stderr"
+.Fc
+.Bd -ragged -offset indent
+Waits and validates the result of a subprocess spawned with
+.Fn atf_utils_wait .
+The validation involves checking that the subprocess exited cleanly and returned
+the code specified in
+.Fa expected_exit_status
+and that its standard output and standard error match the strings given in
+.Fa expected_stdout
+and
+.Fa expected_stderr .
+.Pp
+If any of the
+.Fa expected_stdout
+or
+.Fa expected_stderr
+strings are prefixed with
+.Sq save: ,
+then they specify the name of the file into which to store the stdout or stderr
+of the subprocess, and no comparison is performed.
+.Ed
.Sh EXAMPLES
The following shows a complete test program with a single test case that
validates the addition operator:
diff --git a/contrib/atf/atf-c/check_test.c b/contrib/atf/atf-c/check_test.c
index b36dd73..a26e032 100644
--- a/contrib/atf/atf-c/check_test.c
+++ b/contrib/atf/atf-c/check_test.c
@@ -90,14 +90,10 @@ static
void
check_line(int fd, const char *exp)
{
- atf_dynstr_t line;
-
- atf_dynstr_init(&line);
- ATF_CHECK(!read_line(fd, &line));
- ATF_CHECK_MSG(atf_equal_dynstr_cstring(&line, exp),
- "read: '%s', expected: '%s'",
- atf_dynstr_cstring(&line), exp);
- atf_dynstr_fini(&line);
+ char *line = atf_utils_readline(fd);
+ ATF_CHECK(line != NULL);
+ ATF_CHECK_STREQ_MSG(exp, line, "read: '%s', expected: '%s'", line, exp);
+ free(line);
}
/* ---------------------------------------------------------------------
@@ -246,15 +242,15 @@ ATF_TC_BODY(build_c_o, tc)
{
init_and_run_h_tc(&ATF_TC_NAME(h_build_c_o_ok),
&ATF_TC_PACK_NAME(h_build_c_o_ok), "stdout", "stderr");
- ATF_CHECK(grep_file("stdout", "-o test.o"));
- ATF_CHECK(grep_file("stdout", "-c test.c"));
+ ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("-c test.c", "stdout"));
init_and_run_h_tc(&ATF_TC_NAME(h_build_c_o_fail),
&ATF_TC_PACK_NAME(h_build_c_o_fail), "stdout", "stderr");
- ATF_CHECK(grep_file("stdout", "-o test.o"));
- ATF_CHECK(grep_file("stdout", "-c test.c"));
- ATF_CHECK(grep_file("stderr", "test.c"));
- ATF_CHECK(grep_file("stderr", "UNDEFINED_SYMBOL"));
+ ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("-c test.c", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("test.c", "stderr"));
+ ATF_CHECK(atf_utils_grep_file("UNDEFINED_SYMBOL", "stderr"));
}
ATF_TC(build_cpp);
@@ -267,16 +263,16 @@ ATF_TC_BODY(build_cpp, tc)
{
init_and_run_h_tc(&ATF_TC_NAME(h_build_cpp_ok),
&ATF_TC_PACK_NAME(h_build_cpp_ok), "stdout", "stderr");
- ATF_CHECK(grep_file("stdout", "-o.*test.p"));
- ATF_CHECK(grep_file("stdout", "test.c"));
- ATF_CHECK(grep_file("test.p", "foo bar"));
+ ATF_CHECK(atf_utils_grep_file("-o.*test.p", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("test.c", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("foo bar", "test.p"));
init_and_run_h_tc(&ATF_TC_NAME(h_build_cpp_fail),
&ATF_TC_PACK_NAME(h_build_cpp_fail), "stdout", "stderr");
- ATF_CHECK(grep_file("stdout", "-o test.p"));
- ATF_CHECK(grep_file("stdout", "test.c"));
- ATF_CHECK(grep_file("stderr", "test.c"));
- ATF_CHECK(grep_file("stderr", "non-existent.h"));
+ ATF_CHECK(atf_utils_grep_file("-o test.p", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("test.c", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("test.c", "stderr"));
+ ATF_CHECK(atf_utils_grep_file("non-existent.h", "stderr"));
}
ATF_TC(build_cxx_o);
@@ -289,15 +285,15 @@ ATF_TC_BODY(build_cxx_o, tc)
{
init_and_run_h_tc(&ATF_TC_NAME(h_build_cxx_o_ok),
&ATF_TC_PACK_NAME(h_build_cxx_o_ok), "stdout", "stderr");
- ATF_CHECK(grep_file("stdout", "-o test.o"));
- ATF_CHECK(grep_file("stdout", "-c test.cpp"));
+ ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("-c test.cpp", "stdout"));
init_and_run_h_tc(&ATF_TC_NAME(h_build_cxx_o_fail),
&ATF_TC_PACK_NAME(h_build_cxx_o_fail), "stdout", "stderr");
- ATF_CHECK(grep_file("stdout", "-o test.o"));
- ATF_CHECK(grep_file("stdout", "-c test.cpp"));
- ATF_CHECK(grep_file("stderr", "test.cpp"));
- ATF_CHECK(grep_file("stderr", "UNDEFINED_SYMBOL"));
+ ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("-c test.cpp", "stdout"));
+ ATF_CHECK(atf_utils_grep_file("test.cpp", "stderr"));
+ ATF_CHECK(atf_utils_grep_file("UNDEFINED_SYMBOL", "stderr"));
}
ATF_TC(exec_array);
diff --git a/contrib/atf/atf-c/detail/Atffile b/contrib/atf/atf-c/detail/Atffile
index f715c98..5fd8593 100644
--- a/contrib/atf/atf-c/detail/Atffile
+++ b/contrib/atf/atf-c/detail/Atffile
@@ -9,6 +9,5 @@ tp: list_test
tp: map_test
tp: process_test
tp: sanity_test
-tp: test_helpers_test
tp: text_test
tp: user_test
diff --git a/contrib/atf/atf-c/detail/Kyuafile b/contrib/atf/atf-c/detail/Kyuafile
index 3f4901d..bb741da 100644
--- a/contrib/atf/atf-c/detail/Kyuafile
+++ b/contrib/atf/atf-c/detail/Kyuafile
@@ -9,6 +9,5 @@ atf_test_program{name="list_test"}
atf_test_program{name="map_test"}
atf_test_program{name="process_test"}
atf_test_program{name="sanity_test"}
-atf_test_program{name="test_helpers_test"}
atf_test_program{name="text_test"}
atf_test_program{name="user_test"}
diff --git a/contrib/atf/atf-c/detail/Makefile.am.inc b/contrib/atf/atf-c/detail/Makefile.am.inc
deleted file mode 100644
index d3c325b..0000000
--- a/contrib/atf/atf-c/detail/Makefile.am.inc
+++ /dev/null
@@ -1,104 +0,0 @@
-#
-# Automated Testing Framework (atf)
-#
-# Copyright (c) 2007 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.
-#
-
-libatf_c_la_SOURCES += atf-c/detail/dynstr.c \
- atf-c/detail/dynstr.h \
- atf-c/detail/env.c \
- atf-c/detail/env.h \
- atf-c/detail/fs.c \
- atf-c/detail/fs.h \
- atf-c/detail/list.c \
- atf-c/detail/list.h \
- atf-c/detail/map.c \
- atf-c/detail/map.h \
- atf-c/detail/process.c \
- atf-c/detail/process.h \
- atf-c/detail/sanity.c \
- atf-c/detail/sanity.h \
- atf-c/detail/text.c \
- atf-c/detail/text.h \
- atf-c/detail/tp_main.c \
- atf-c/detail/user.c \
- atf-c/detail/user.h
-
-tests_atf_c_detail_DATA = atf-c/detail/Atffile \
- atf-c/detail/Kyuafile
-tests_atf_c_detaildir = $(pkgtestsdir)/atf-c/detail
-EXTRA_DIST += $(tests_atf_c_detail_DATA)
-
-noinst_LTLIBRARIES += atf-c/detail/libtest_helpers.la
-atf_c_detail_libtest_helpers_la_SOURCES = atf-c/detail/test_helpers.c \
- atf-c/detail/test_helpers.h
-atf_c_detail_libtest_helpers_la_CPPFLAGS = -I$(srcdir)/atf-c
-
-tests_atf_c_detail_PROGRAMS = atf-c/detail/dynstr_test
-atf_c_detail_dynstr_test_SOURCES = atf-c/detail/dynstr_test.c
-atf_c_detail_dynstr_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/env_test
-atf_c_detail_env_test_SOURCES = atf-c/detail/env_test.c
-atf_c_detail_env_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/fs_test
-atf_c_detail_fs_test_SOURCES = atf-c/detail/fs_test.c
-atf_c_detail_fs_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/test_helpers_test
-atf_c_detail_test_helpers_test_SOURCES = atf-c/detail/test_helpers_test.c
-atf_c_detail_test_helpers_test_LDADD = atf-c/detail/libtest_helpers.la \
- libatf-c.la
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/list_test
-atf_c_detail_list_test_SOURCES = atf-c/detail/list_test.c
-atf_c_detail_list_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/map_test
-atf_c_detail_map_test_SOURCES = atf-c/detail/map_test.c
-atf_c_detail_map_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/process_helpers
-atf_c_detail_process_helpers_SOURCES = atf-c/detail/process_helpers.c
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/process_test
-atf_c_detail_process_test_SOURCES = atf-c/detail/process_test.c
-atf_c_detail_process_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/sanity_test
-atf_c_detail_sanity_test_SOURCES = atf-c/detail/sanity_test.c
-atf_c_detail_sanity_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/text_test
-atf_c_detail_text_test_SOURCES = atf-c/detail/text_test.c
-atf_c_detail_text_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-tests_atf_c_detail_PROGRAMS += atf-c/detail/user_test
-atf_c_detail_user_test_SOURCES = atf-c/detail/user_test.c
-atf_c_detail_user_test_LDADD = atf-c/detail/libtest_helpers.la libatf-c.la
-
-# vim: syntax=make:noexpandtab:shiftwidth=8:softtabstop=8
diff --git a/contrib/atf/atf-c/detail/process_test.c b/contrib/atf/atf-c/detail/process_test.c
index 229593b..9e55f70 100644
--- a/contrib/atf/atf-c/detail/process_test.c
+++ b/contrib/atf/atf-c/detail/process_test.c
@@ -95,12 +95,12 @@ check_file(const enum out_type type)
{
switch (type) {
case stdout_type:
- ATF_CHECK(grep_file("stdout", "stdout: msg"));
- ATF_CHECK(!grep_file("stdout", "stderr: msg"));
+ ATF_CHECK(atf_utils_grep_file("stdout: msg", "stdout"));
+ ATF_CHECK(!atf_utils_grep_file("stderr: msg", "stdout"));
break;
case stderr_type:
- ATF_CHECK(grep_file("stderr", "stderr: msg"));
- ATF_CHECK(!grep_file("stderr", "stdout: msg"));
+ ATF_CHECK(atf_utils_grep_file("stderr: msg", "stderr"));
+ ATF_CHECK(!atf_utils_grep_file("stdout: msg", "stderr"));
break;
default:
UNREACHABLE;
@@ -110,7 +110,7 @@ check_file(const enum out_type type)
struct capture_stream {
struct base_stream m_base;
- atf_dynstr_t m_msg;
+ char *m_msg;
};
#define CAPTURE_STREAM(type) \
{ .m_base = BASE_STREAM(capture_stream_init, \
@@ -126,7 +126,7 @@ capture_stream_init(void *v)
s->m_base.m_sb_ptr = &s->m_base.m_sb;
RE(atf_process_stream_init_capture(&s->m_base.m_sb));
- RE(atf_dynstr_init(&s->m_msg));
+ s->m_msg = NULL;
}
static
@@ -137,10 +137,10 @@ capture_stream_process(void *v, atf_process_child_t *c)
switch (s->m_base.m_type) {
case stdout_type:
- (void)read_line(atf_process_child_stdout(c), &s->m_msg);
+ s->m_msg = atf_utils_readline(atf_process_child_stdout(c));
break;
case stderr_type:
- (void)read_line(atf_process_child_stderr(c), &s->m_msg);
+ s->m_msg = atf_utils_readline(atf_process_child_stderr(c));
break;
default:
UNREACHABLE;
@@ -155,18 +155,18 @@ capture_stream_fini(void *v)
switch (s->m_base.m_type) {
case stdout_type:
- ATF_CHECK(grep_string(&s->m_msg, "stdout: msg"));
- ATF_CHECK(!grep_string(&s->m_msg, "stderr: msg"));
+ ATF_CHECK(atf_utils_grep_string("stdout: msg", s->m_msg));
+ ATF_CHECK(!atf_utils_grep_string("stderr: msg", s->m_msg));
break;
case stderr_type:
- ATF_CHECK(!grep_string(&s->m_msg, "stdout: msg"));
- ATF_CHECK(grep_string(&s->m_msg, "stderr: msg"));
+ ATF_CHECK(!atf_utils_grep_string("stdout: msg", s->m_msg));
+ ATF_CHECK(atf_utils_grep_string("stderr: msg", s->m_msg));
break;
default:
UNREACHABLE;
}
- atf_dynstr_fini(&s->m_msg);
+ free(s->m_msg);
atf_process_stream_fini(&s->m_base.m_sb);
}
@@ -881,16 +881,10 @@ static
void
check_line(int fd, const char *exp)
{
- atf_dynstr_t line;
- bool eof;
-
- atf_dynstr_init(&line);
- eof = read_line(fd, &line);
- ATF_CHECK(!eof);
- ATF_CHECK_MSG(atf_equal_dynstr_cstring(&line, exp),
- "read: '%s', expected: '%s'",
- atf_dynstr_cstring(&line), exp);
- atf_dynstr_fini(&line);
+ char *line = atf_utils_readline(fd);
+ ATF_CHECK(line != NULL);
+ ATF_CHECK_STREQ_MSG(exp, line, "read: '%s', expected: '%s'", line, exp);
+ free(line);
}
ATF_TC(exec_failure);
diff --git a/contrib/atf/atf-c/detail/sanity_test.c b/contrib/atf/atf-c/detail/sanity_test.c
index af2bbc0..7c8285b 100644
--- a/contrib/atf/atf-c/detail/sanity_test.c
+++ b/contrib/atf/atf-c/detail/sanity_test.c
@@ -53,21 +53,6 @@
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;
-}
-
struct test_data {
enum type m_type;
bool m_cond;
@@ -109,9 +94,8 @@ do_test(enum type t, bool cond)
{
atf_process_child_t child;
atf_process_status_t status;
- bool eof;
int nlines;
- atf_dynstr_t lines[3];
+ char *lines[3];
{
atf_process_stream_t outsb, errsb;
@@ -125,13 +109,9 @@ do_test(enum type t, bool cond)
}
nlines = 0;
- eof = false;
- do {
- RE(atf_dynstr_init(&lines[nlines]));
- if (!eof)
- eof = read_line(atf_process_child_stderr(&child), &lines[nlines]);
+ while (nlines < 3 && (lines[nlines] =
+ atf_utils_readline(atf_process_child_stderr(&child))) != NULL)
nlines++;
- } while (nlines < 3);
ATF_REQUIRE(nlines == 0 || nlines == 3);
RE(atf_process_child_wait(&child, &status));
@@ -147,29 +127,29 @@ do_test(enum type t, bool cond)
if (!cond) {
switch (t) {
case inv:
- ATF_REQUIRE(grep(&lines[0], "Invariant"));
+ ATF_REQUIRE(atf_utils_grep_string("Invariant", lines[0]));
break;
case pre:
- ATF_REQUIRE(grep(&lines[0], "Precondition"));
+ ATF_REQUIRE(atf_utils_grep_string("Precondition", lines[0]));
break;
case post:
- ATF_REQUIRE(grep(&lines[0], "Postcondition"));
+ ATF_REQUIRE(atf_utils_grep_string("Postcondition", lines[0]));
break;
case unreachable:
- ATF_REQUIRE(grep(&lines[0], "Invariant"));
+ ATF_REQUIRE(atf_utils_grep_string("Invariant", lines[0]));
break;
}
- ATF_REQUIRE(grep(&lines[0], __FILE__));
- ATF_REQUIRE(grep(&lines[2], PACKAGE_BUGREPORT));
+ ATF_REQUIRE(atf_utils_grep_string(__FILE__, lines[0]));
+ ATF_REQUIRE(atf_utils_grep_string(PACKAGE_BUGREPORT, lines[2]));
}
while (nlines > 0) {
nlines--;
- atf_dynstr_fini(&lines[nlines]);
+ free(lines[nlines]);
}
}
diff --git a/contrib/atf/atf-c/detail/test_helpers.c b/contrib/atf/atf-c/detail/test_helpers.c
index b20a849..aa64c12 100644
--- a/contrib/atf/atf-c/detail/test_helpers.c
+++ b/contrib/atf/atf-c/detail/test_helpers.c
@@ -30,7 +30,6 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
-#include <regex.h>
#include <unistd.h>
#include "atf-c/build.h"
@@ -106,72 +105,6 @@ get_process_helpers_path(const atf_tc_t *tc, const bool is_detail,
is_detail ? "" : "detail/"));
}
-bool
-grep_string(const atf_dynstr_t *str, const char *regex)
-{
- int res;
- regex_t preg;
-
- printf("Looking for '%s' in '%s'\n", regex, atf_dynstr_cstring(str));
- ATF_REQUIRE(regcomp(&preg, regex, REG_EXTENDED) == 0);
-
- res = regexec(&preg, atf_dynstr_cstring(str), 0, NULL, 0);
- ATF_REQUIRE(res == 0 || res == REG_NOMATCH);
-
- regfree(&preg);
-
- return res == 0;
-}
-
-bool
-grep_file(const char *file, const char *regex, ...)
-{
- bool done, found;
- int fd;
- va_list ap;
- atf_dynstr_t formatted;
-
- va_start(ap, regex);
- RE(atf_dynstr_init_ap(&formatted, regex, ap));
- va_end(ap);
-
- done = false;
- found = false;
- ATF_REQUIRE((fd = open(file, O_RDONLY)) != -1);
- do {
- atf_dynstr_t line;
-
- RE(atf_dynstr_init(&line));
-
- done = read_line(fd, &line);
- if (!done)
- found = grep_string(&line, atf_dynstr_cstring(&formatted));
-
- atf_dynstr_fini(&line);
- } while (!found && !done);
- close(fd);
-
- atf_dynstr_fini(&formatted);
-
- return found;
-}
-
-bool
-read_line(int fd, atf_dynstr_t *dest)
-{
- char ch;
- ssize_t cnt;
-
- while ((cnt = read(fd, &ch, sizeof(ch))) == sizeof(ch) &&
- ch != '\n') {
- const atf_error_t err = atf_dynstr_append_fmt(dest, "%c", ch);
- ATF_REQUIRE(!atf_is_error(err));
- }
- ATF_REQUIRE(cnt != -1);
-
- return cnt == 0;
-}
-
struct run_h_tc_data {
atf_tc_t *m_tc;
const char *m_resname;
diff --git a/contrib/atf/atf-c/detail/test_helpers.h b/contrib/atf/atf-c/detail/test_helpers.h
index b0ce6cc..5df034f 100644
--- a/contrib/atf/atf-c/detail/test_helpers.h
+++ b/contrib/atf/atf-c/detail/test_helpers.h
@@ -81,7 +81,5 @@ void build_check_c_o(const atf_tc_t *, const char *, const char *, const bool);
void header_check(const char *);
void get_process_helpers_path(const atf_tc_t *, const bool,
struct atf_fs_path *);
-bool grep_string(const struct atf_dynstr *, const char *);
-bool grep_file(const char *, const char *, ...);
bool read_line(int, struct atf_dynstr *);
void run_h_tc(atf_tc_t *, const char *, const char *, const char *);
diff --git a/contrib/atf/atf-c/detail/test_helpers_test.c b/contrib/atf/atf-c/detail/test_helpers_test.c
deleted file mode 100644
index 52d8608..0000000
--- a/contrib/atf/atf-c/detail/test_helpers_test.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Automated Testing Framework (atf)
- *
- * Copyright (c) 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.
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <atf-c.h>
-
-#include "dynstr.h"
-#include "test_helpers.h"
-
-/* ---------------------------------------------------------------------
- * Test cases for the free functions.
- * --------------------------------------------------------------------- */
-
-/* TODO: Add checks for build_check_c_o and the macros defined in the
- * header file. */
-
-ATF_TC(grep_string);
-ATF_TC_HEAD(grep_string, tc)
-{
- atf_tc_set_md_var(tc, "descr", "Tests the grep_string helper "
- "function");
-}
-ATF_TC_BODY(grep_string, tc)
-{
- atf_dynstr_t str;
-
- atf_dynstr_init_fmt(&str, "a string - aaaabbbb");
- ATF_CHECK(grep_string(&str, "a string"));
- ATF_CHECK(grep_string(&str, "^a string"));
- ATF_CHECK(grep_string(&str, "aaaabbbb$"));
- ATF_CHECK(grep_string(&str, "aa.*bb"));
- ATF_CHECK(!grep_string(&str, "foo"));
- ATF_CHECK(!grep_string(&str, "bar"));
- ATF_CHECK(!grep_string(&str, "aaaaa"));
-
- atf_dynstr_fini(&str);
-}
-
-
-ATF_TC(grep_file);
-ATF_TC_HEAD(grep_file, tc)
-{
- atf_tc_set_md_var(tc, "descr", "Tests the grep_file helper function");
-}
-ATF_TC_BODY(grep_file, tc)
-{
- FILE *f;
-
- f = fopen("test.txt", "w");
- ATF_CHECK(f != NULL);
- fprintf(f, "line1\n");
- fprintf(f, "the second line\n");
- fprintf(f, "aaaabbbb\n");
- fclose(f);
-
- ATF_CHECK(grep_file("test.txt", "line1"));
- ATF_CHECK(grep_file("test.txt", "line%d", 1));
- ATF_CHECK(grep_file("test.txt", "second line"));
- ATF_CHECK(grep_file("test.txt", "aa.*bb"));
- ATF_CHECK(!grep_file("test.txt", "foo"));
- ATF_CHECK(!grep_file("test.txt", "bar"));
- ATF_CHECK(!grep_file("test.txt", "aaaaa"));
-}
-
-ATF_TC(read_line);
-ATF_TC_HEAD(read_line, tc)
-{
- atf_tc_set_md_var(tc, "descr", "Tests the read_line function");
-}
-ATF_TC_BODY(read_line, tc)
-{
- const char *l1 = "First line with % formatting % characters %";
- const char *l2 = "Second line; much longer than the first one";
- const char *l3 = "Last line, without terminator";
-
- {
- FILE *f;
-
- f = fopen("test", "w");
- ATF_REQUIRE(f != NULL);
- fclose(f);
- }
-
- {
- int fd;
- atf_dynstr_t dest;
- bool eof;
-
- fd = open("test", O_RDONLY);
- ATF_REQUIRE(fd != -1);
-
- RE(atf_dynstr_init(&dest));
- eof = read_line(fd, &dest);
- ATF_REQUIRE(eof);
- atf_dynstr_fini(&dest);
- }
-
- {
- FILE *f;
-
- f = fopen("test", "w");
- ATF_REQUIRE(f != NULL);
-
- fprintf(f, "%s\n", l1);
- fprintf(f, "%s\n", l2);
- fprintf(f, "%s", l3);
-
- fclose(f);
- }
-
- {
- int fd;
- atf_dynstr_t dest;
- bool eof;
-
- fd = open("test", O_RDONLY);
- ATF_REQUIRE(fd != -1);
-
- RE(atf_dynstr_init(&dest));
- eof = read_line(fd, &dest);
- ATF_REQUIRE(!eof);
- printf("1st line: >%s<\n", atf_dynstr_cstring(&dest));
- ATF_REQUIRE(atf_equal_dynstr_cstring(&dest, l1));
- atf_dynstr_fini(&dest);
-
- RE(atf_dynstr_init(&dest));
- eof = read_line(fd, &dest);
- ATF_REQUIRE(!eof);
- printf("2nd line: >%s<\n", atf_dynstr_cstring(&dest));
- ATF_REQUIRE(atf_equal_dynstr_cstring(&dest, l2));
- atf_dynstr_fini(&dest);
-
- RE(atf_dynstr_init(&dest));
- eof = read_line(fd, &dest);
- ATF_REQUIRE(eof);
- printf("3rd line: >%s<\n", atf_dynstr_cstring(&dest));
- ATF_REQUIRE(atf_equal_dynstr_cstring(&dest, l3));
- atf_dynstr_fini(&dest);
-
- close(fd);
- }
-}
-
-/* ---------------------------------------------------------------------
- * Main.
- * --------------------------------------------------------------------- */
-
-ATF_TP_ADD_TCS(tp)
-{
- /* Add the tests for the free functions. */
- ATF_TP_ADD_TC(tp, grep_string);
- ATF_TP_ADD_TC(tp, grep_file);
- ATF_TP_ADD_TC(tp, read_line);
-
- return atf_no_error();
-}
diff --git a/contrib/atf/atf-c/macros.h b/contrib/atf/atf-c/macros.h
index 7afe9e8..7c33ccb 100644
--- a/contrib/atf/atf-c/macros.h
+++ b/contrib/atf/atf-c/macros.h
@@ -80,7 +80,7 @@
#define ATF_TC_HEAD(tc, tcptr) \
static \
void \
- atfu_ ## tc ## _head(atf_tc_t *tcptr)
+ atfu_ ## tc ## _head(atf_tc_t *tcptr ATF_DEFS_ATTRIBUTE_UNUSED)
#define ATF_TC_HEAD_NAME(tc) \
(atfu_ ## tc ## _head)
@@ -181,6 +181,24 @@
ATF_CHECK_MSG(strcmp(x, y) == 0, "%s != %s (%s != %s): " fmt, \
#x, #y, x, y, ##__VA_ARGS__)
+#define ATF_REQUIRE_MATCH(regexp, string) \
+ ATF_REQUIRE_MSG(atf_utils_grep_string("%s", string, regexp), \
+ "'%s' not matched in '%s'", regexp, string);
+
+#define ATF_CHECK_MATCH(regexp, string) \
+ ATF_CHECK_MSG(atf_utils_grep_string("%s", string, regexp), \
+ "'%s' not matched in '%s'", regexp, string);
+
+#define ATF_REQUIRE_MATCH_MSG(regexp, string, fmt, ...) \
+ ATF_REQUIRE_MSG(atf_utils_grep_string("%s", string, regexp), \
+ "'%s' not matched in '%s': " fmt, regexp, string, \
+ ##__VA_ARGS__);
+
+#define ATF_CHECK_MATCH_MSG(regexp, string, fmt, ...) \
+ ATF_CHECK_MSG(atf_utils_grep_string("%s", string, regexp), \
+ "'%s' not matched in '%s': " fmt, regexp, string, \
+ ##__VA_ARGS__);
+
#define ATF_CHECK_ERRNO(exp_errno, bool_expr) \
atf_tc_check_errno(__FILE__, __LINE__, exp_errno, #bool_expr, bool_expr)
diff --git a/contrib/atf/atf-c/macros_test.c b/contrib/atf/atf-c/macros_test.c
index 9cf0525..f077a27 100644
--- a/contrib/atf/atf-c/macros_test.c
+++ b/contrib/atf/atf-c/macros_test.c
@@ -125,6 +125,11 @@ init_and_run_h_tc(const char *name, void (*head)(atf_tc_t *),
#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) \
@@ -139,6 +144,13 @@ init_and_run_h_tc(const char *name, void (*head)(atf_tc_t *),
#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) \
@@ -164,6 +176,11 @@ init_and_run_h_tc(const char *name, void (*head)(atf_tc_t *),
#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) \
@@ -178,6 +195,13 @@ init_and_run_h_tc(const char *name, void (*head)(atf_tc_t *),
#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) \
@@ -240,11 +264,11 @@ ATF_TC_BODY(check_errno, tc)
ATF_REQUIRE(exists("after"));
if (t->ok) {
- ATF_REQUIRE(grep_file("result", "^passed"));
+ ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
} else {
- ATF_REQUIRE(grep_file("result", "^failed"));
- ATF_REQUIRE(grep_file("error", "macros_test.c:[0-9]+: %s$",
- t->exp_regex));
+ 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);
@@ -282,11 +306,12 @@ ATF_TC_BODY(require_errno, tc)
ATF_REQUIRE(exists("before"));
if (t->ok) {
- ATF_REQUIRE(grep_file("result", "^passed"));
+ ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
ATF_REQUIRE(exists("after"));
} else {
- ATF_REQUIRE(grep_file("result", "^failed: .*macros_test.c:[0-9]+: "
- "%s$", t->exp_regex));
+ ATF_REQUIRE(atf_utils_grep_file(
+ "^failed: .*macros_test.c:[0-9]+: %s$", "result",
+ t->exp_regex));
ATF_REQUIRE(!exists("after"));
}
@@ -340,11 +365,11 @@ ATF_TC_BODY(check, tc)
ATF_REQUIRE(exists("after"));
if (t->ok) {
- ATF_REQUIRE(grep_file("result", "^passed"));
+ ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
} else {
- ATF_REQUIRE(grep_file("result", "^failed"));
- ATF_REQUIRE(grep_file("error", "Check failed: .*"
- "macros_test.c:[0-9]+: %s$", t->msg));
+ 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);
@@ -381,11 +406,11 @@ do_check_eq_tests(const struct check_eq_test *tests)
ATF_CHECK(exists("after"));
if (t->ok) {
- ATF_REQUIRE(grep_file("result", "^passed"));
+ ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
} else {
- ATF_REQUIRE(grep_file("result", "^failed"));
- ATF_CHECK(grep_file("error", "Check failed: .*"
- "macros_test.c:[0-9]+: %s$", t->msg));
+ 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);
@@ -442,8 +467,8 @@ 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 const char *check_streq_var1 = CHECK_STREQ_VAR1;
-const const char *check_streq_var2 = CHECK_STREQ_VAR2;
+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);
@@ -485,6 +510,40 @@ ATF_TC_BODY(check_streq, tc)
}
/* ---------------------------------------------------------------------
+ * 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.
* --------------------------------------------------------------------- */
@@ -526,11 +585,11 @@ ATF_TC_BODY(require, tc)
ATF_REQUIRE(exists("before"));
if (t->ok) {
- ATF_REQUIRE(grep_file("result", "^passed"));
+ ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
ATF_REQUIRE(exists("after"));
} else {
- ATF_REQUIRE(grep_file("result", "^failed: .*macros_test.c:[0-9]+: "
- "%s$", t->msg));
+ ATF_REQUIRE(atf_utils_grep_file(
+ "^failed: .*macros_test.c:[0-9]+: %s$", "result", t->msg));
ATF_REQUIRE(!exists("after"));
}
@@ -567,11 +626,11 @@ do_require_eq_tests(const struct require_eq_test *tests)
ATF_REQUIRE(exists("before"));
if (t->ok) {
- ATF_REQUIRE(grep_file("result", "^passed"));
+ ATF_REQUIRE(atf_utils_grep_file("^passed", "result"));
ATF_REQUIRE(exists("after"));
} else {
- ATF_REQUIRE(grep_file("result", "^failed: .*macros_test.c"
- ":[0-9]+: %s$", t->msg));
+ ATF_REQUIRE(atf_utils_grep_file("^failed: .*macros_test.c"
+ ":[0-9]+: %s$", "result", t->msg));
ATF_REQUIRE(!exists("after"));
}
@@ -630,8 +689,8 @@ 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 const char *require_streq_var1 = REQUIRE_STREQ_VAR1;
-const const char *require_streq_var2 = REQUIRE_STREQ_VAR2;
+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);
@@ -673,6 +732,41 @@ ATF_TC_BODY(require_streq, tc)
}
/* ---------------------------------------------------------------------
+ * 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.
* --------------------------------------------------------------------- */
@@ -728,12 +822,12 @@ ATF_TC_BODY(msg_embedded_fmt, tc)
if (t->fatal) {
bool matched =
- grep_file("result", "^failed: .*macros_test.c:[0-9]+: "
- "%s$", t->msg);
+ 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 = grep_file("error", "Check failed: .*"
- "macros_test.c:[0-9]+: %s$", t->msg);
+ 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");
}
}
@@ -765,11 +859,13 @@ ATF_TP_ADD_TCS(tp)
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);
diff --git a/contrib/atf/atf-c/pkg_config_test.sh b/contrib/atf/atf-c/pkg_config_test.sh
index 8770808..efeae83 100644
--- a/contrib/atf/atf-c/pkg_config_test.sh
+++ b/contrib/atf/atf-c/pkg_config_test.sh
@@ -59,7 +59,7 @@ atf_test_case version
version_head()
{
atf_set "descr" "Checks that the version in atf-c is correct"
- atf_set "require.progs" "pkg-config"
+ atf_set "require.progs" "atf-version pkg-config"
}
version_body()
{
diff --git a/contrib/atf/atf-c/utils.c b/contrib/atf/atf-c/utils.c
index c332703..4409f7a 100644
--- a/contrib/atf/atf-c/utils.c
+++ b/contrib/atf/atf-c/utils.c
@@ -27,10 +27,221 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "atf-c/utils.h"
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <regex.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
-#include "atf-c/utils.h"
+#include <atf-c.h>
+
+#include "detail/dynstr.h"
+
+/** Searches for a regexp in a string.
+ *
+ * \param regex The regexp to look for.
+ * \param str The string in which to look for the expression.
+ *
+ * \return True if there is a match; false otherwise. */
+static
+bool
+grep_string(const char *regex, const char *str)
+{
+ int res;
+ regex_t preg;
+
+ printf("Looking for '%s' in '%s'\n", regex, str);
+ ATF_REQUIRE(regcomp(&preg, regex, REG_EXTENDED) == 0);
+
+ res = regexec(&preg, str, 0, NULL, 0);
+ ATF_REQUIRE(res == 0 || res == REG_NOMATCH);
+
+ regfree(&preg);
+
+ return res == 0;
+}
+
+/** Prints the contents of a file to stdout.
+ *
+ * \param name The name of the file to be printed.
+ * \param prefix An string to be prepended to every line of the printed
+ * file. */
+void
+atf_utils_cat_file(const char *name, const char *prefix)
+{
+ const int fd = open(name, O_RDONLY);
+ ATF_REQUIRE_MSG(fd != -1, "Cannot open %s", name);
+
+ char buffer[1024];
+ ssize_t count;
+ bool continued = false;
+ while ((count = read(fd, buffer, sizeof(buffer) - 1)) > 0) {
+ buffer[count] = '\0';
+
+ if (!continued)
+ printf("%s", prefix);
+
+ char *iter = buffer;
+ char *end;
+ while ((end = strchr(iter, '\n')) != NULL) {
+ *end = '\0';
+ printf("%s\n", iter);
+
+ iter = end + 1;
+ if (iter != buffer + count)
+ printf("%s", prefix);
+ else
+ continued = false;
+ }
+ if (iter < buffer + count) {
+ printf("%s", iter);
+ continued = true;
+ }
+ }
+ ATF_REQUIRE(count == 0);
+}
+
+/** Compares a file against the given golden contents.
+ *
+ * \param name Name of the file to be compared.
+ * \param contents Expected contents of the file.
+ *
+ * \return True if the file matches the contents; false otherwise. */
+bool
+atf_utils_compare_file(const char *name, const char *contents)
+{
+ const int fd = open(name, O_RDONLY);
+ ATF_REQUIRE_MSG(fd != -1, "Cannot open %s", name);
+
+ const char *pos = contents;
+ ssize_t remaining = strlen(contents);
+
+ char buffer[1024];
+ ssize_t count;
+ while ((count = read(fd, buffer, sizeof(buffer))) > 0 &&
+ count <= remaining) {
+ if (memcmp(pos, buffer, count) != 0) {
+ close(fd);
+ return false;
+ }
+ remaining -= count;
+ pos += count;
+ }
+ close(fd);
+ return count == 0 && remaining == 0;
+}
+
+/** Copies a file.
+ *
+ * \param source Path to the source file.
+ * \param destination Path to the destination file. */
+void
+atf_utils_copy_file(const char *source, const char *destination)
+{
+ const int input = open(source, O_RDONLY);
+ ATF_REQUIRE_MSG(input != -1, "Failed to open source file during "
+ "copy (%s)", source);
+
+ const int output = open(destination, O_WRONLY | O_CREAT | O_TRUNC, 0777);
+ ATF_REQUIRE_MSG(output != -1, "Failed to open destination file during "
+ "copy (%s)", destination);
+
+ char buffer[1024];
+ ssize_t length;
+ while ((length = read(input, buffer, sizeof(buffer))) > 0)
+ ATF_REQUIRE_MSG(write(output, buffer, length) == length,
+ "Failed to write to %s during copy", destination);
+ ATF_REQUIRE_MSG(length != -1, "Failed to read from %s during copy", source);
+
+ struct stat sb;
+ ATF_REQUIRE_MSG(fstat(input, &sb) != -1,
+ "Failed to stat source file %s during copy", source);
+ ATF_REQUIRE_MSG(fchmod(output, sb.st_mode) != -1,
+ "Failed to chmod destination file %s during copy",
+ destination);
+
+ close(output);
+ close(input);
+}
+/** Creates a file.
+ *
+ * \param name Name of the file to create.
+ * \param contents Text to write into the created file.
+ * \param ... Positional parameters to the contents. */
+void
+atf_utils_create_file(const char *name, const char *contents, ...)
+{
+ va_list ap;
+ atf_dynstr_t formatted;
+ atf_error_t error;
+
+ va_start(ap, contents);
+ error = atf_dynstr_init_ap(&formatted, contents, ap);
+ va_end(ap);
+ ATF_REQUIRE(!atf_is_error(error));
+
+ const int fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ ATF_REQUIRE_MSG(fd != -1, "Cannot create file %s", name);
+ ATF_REQUIRE(write(fd, atf_dynstr_cstring(&formatted),
+ atf_dynstr_length(&formatted)) != -1);
+ close(fd);
+
+ atf_dynstr_fini(&formatted);
+}
+
+/** Checks if a file exists.
+ *
+ * \param path Location of the file to check for.
+ *
+ * \return True if the file exists, false otherwise. */
+bool
+atf_utils_file_exists(const char *path)
+{
+ const int ret = access(path, F_OK);
+ if (ret == -1) {
+ if (errno != ENOENT)
+ atf_tc_fail("Failed to check the existence of %s: %s", path,
+ strerror(errno));
+ else
+ return false;
+ } else
+ return true;
+}
+
+/** Spawns a subprocess and redirects its output to files.
+ *
+ * Use the atf_utils_wait() function to wait for the completion of the spawned
+ * subprocess and validate its exit conditions.
+ *
+ * \return 0 in the new child; the PID of the new child in the parent. Does
+ * not return in error conditions. */
+pid_t
+atf_utils_fork(void)
+{
+ const pid_t pid = fork();
+ if (pid == -1)
+ atf_tc_fail("fork failed");
+
+ if (pid == 0) {
+ atf_utils_redirect(STDOUT_FILENO, "atf_utils_fork_out.txt");
+ atf_utils_redirect(STDERR_FILENO, "atf_utils_fork_err.txt");
+ }
+ return pid;
+}
+
+/** Frees an dynamically-allocated "argv" array.
+ *
+ * \param argv A dynamically-allocated array of dynamically-allocated
+ * strings. */
void
atf_utils_free_charpp(char **argv)
{
@@ -41,3 +252,164 @@ atf_utils_free_charpp(char **argv)
free(argv);
}
+
+/** Searches for a regexp in a file.
+ *
+ * \param regex The regexp to look for.
+ * \param file The file in which to look for the expression.
+ * \param ... Positional parameters to the regex.
+ *
+ * \return True if there is a match; false otherwise. */
+bool
+atf_utils_grep_file(const char *regex, const char *file, ...)
+{
+ int fd;
+ va_list ap;
+ atf_dynstr_t formatted;
+ atf_error_t error;
+
+ va_start(ap, file);
+ error = atf_dynstr_init_ap(&formatted, regex, ap);
+ va_end(ap);
+ ATF_REQUIRE(!atf_is_error(error));
+
+ ATF_REQUIRE((fd = open(file, O_RDONLY)) != -1);
+ bool found = false;
+ char *line = NULL;
+ while (!found && (line = atf_utils_readline(fd)) != NULL) {
+ found = grep_string(atf_dynstr_cstring(&formatted), line);
+ free(line);
+ }
+ close(fd);
+
+ atf_dynstr_fini(&formatted);
+
+ return found;
+}
+
+/** Searches for a regexp in a string.
+ *
+ * \param regex The regexp to look for.
+ * \param str The string in which to look for the expression.
+ * \param ... Positional parameters to the regex.
+ *
+ * \return True if there is a match; false otherwise. */
+bool
+atf_utils_grep_string(const char *regex, const char *str, ...)
+{
+ bool res;
+ va_list ap;
+ atf_dynstr_t formatted;
+ atf_error_t error;
+
+ va_start(ap, str);
+ error = atf_dynstr_init_ap(&formatted, regex, ap);
+ va_end(ap);
+ ATF_REQUIRE(!atf_is_error(error));
+
+ res = grep_string(atf_dynstr_cstring(&formatted), str);
+
+ atf_dynstr_fini(&formatted);
+
+ return res;
+}
+
+/** Reads a line of arbitrary length.
+ *
+ * \param fd The descriptor from which to read the line.
+ *
+ * \return A pointer to the read line, which must be released with free(), or
+ * NULL if there was nothing to read from the file. */
+char *
+atf_utils_readline(const int fd)
+{
+ char ch;
+ ssize_t cnt;
+ atf_dynstr_t temp;
+ atf_error_t error;
+
+ error = atf_dynstr_init(&temp);
+ ATF_REQUIRE(!atf_is_error(error));
+
+ while ((cnt = read(fd, &ch, sizeof(ch))) == sizeof(ch) &&
+ ch != '\n') {
+ error = atf_dynstr_append_fmt(&temp, "%c", ch);
+ ATF_REQUIRE(!atf_is_error(error));
+ }
+ ATF_REQUIRE(cnt != -1);
+
+ if (cnt == 0 && atf_dynstr_length(&temp) == 0) {
+ atf_dynstr_fini(&temp);
+ return NULL;
+ } else
+ return atf_dynstr_fini_disown(&temp);
+}
+
+/** Redirects a file descriptor to a file.
+ *
+ * \param target_fd The file descriptor to be replaced.
+ * \param name The name of the file to direct the descriptor to.
+ *
+ * \pre Should only be called from the process spawned by fork_for_testing
+ * because this exits uncontrolledly.
+ * \post Terminates execution if the redirection fails. */
+void
+atf_utils_redirect(const int target_fd, const char *name)
+{
+ if (target_fd == STDOUT_FILENO)
+ fflush(stdout);
+ else if (target_fd == STDERR_FILENO)
+ fflush(stderr);
+
+ const int new_fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (new_fd == -1)
+ err(EXIT_FAILURE, "Cannot create %s", name);
+ if (new_fd != target_fd) {
+ if (dup2(new_fd, target_fd) == -1)
+ err(EXIT_FAILURE, "Cannot redirect to fd %d", target_fd);
+ }
+ close(new_fd);
+}
+
+/** Waits for a subprocess and validates its exit condition.
+ *
+ * \param pid The process to be waited for. Must have been started by
+ * testutils_fork().
+ * \param exitstatus Expected exit status.
+ * \param expout Expected contents of stdout.
+ * \param experr Expected contents of stderr. */
+void
+atf_utils_wait(const pid_t pid, const int exitstatus, const char *expout,
+ const char *experr)
+{
+ int status;
+ ATF_REQUIRE(waitpid(pid, &status, 0) != -1);
+
+ atf_utils_cat_file("atf_utils_fork_out.txt", "subprocess stdout: ");
+ atf_utils_cat_file("atf_utils_fork_err.txt", "subprocess stderr: ");
+
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(exitstatus, WEXITSTATUS(status));
+
+ const char *save_prefix = "save:";
+ const size_t save_prefix_length = strlen(save_prefix);
+
+ if (strlen(expout) > save_prefix_length &&
+ strncmp(expout, save_prefix, save_prefix_length) == 0) {
+ atf_utils_copy_file("atf_utils_fork_out.txt",
+ expout + save_prefix_length);
+ } else {
+ ATF_REQUIRE(atf_utils_compare_file("atf_utils_fork_out.txt", expout));
+ }
+
+ if (strlen(experr) > save_prefix_length &&
+ strncmp(experr, save_prefix, save_prefix_length) == 0) {
+ atf_utils_copy_file("atf_utils_fork_err.txt",
+ experr + save_prefix_length);
+ } else {
+ ATF_REQUIRE(atf_utils_compare_file("atf_utils_fork_err.txt", experr));
+ }
+
+ ATF_REQUIRE(unlink("atf_utils_fork_out.txt") != -1);
+ ATF_REQUIRE(unlink("atf_utils_fork_err.txt") != -1);
+}
diff --git a/contrib/atf/atf-c/utils.h b/contrib/atf/atf-c/utils.h
index dc4c5ae..666804d 100644
--- a/contrib/atf/atf-c/utils.h
+++ b/contrib/atf/atf-c/utils.h
@@ -30,6 +30,25 @@
#if !defined(ATF_C_UTILS_H)
#define ATF_C_UTILS_H
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <atf-c/defs.h>
+
+void atf_utils_cat_file(const char *, const char *);
+bool atf_utils_compare_file(const char *, const char *);
+void atf_utils_copy_file(const char *, const char *);
+void atf_utils_create_file(const char *, const char *, ...)
+ ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 3);
+bool atf_utils_file_exists(const char *);
+pid_t atf_utils_fork(void);
void atf_utils_free_charpp(char **);
+bool atf_utils_grep_file(const char *, const char *, ...)
+ ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 3);
+bool atf_utils_grep_string(const char *, const char *, ...)
+ ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 3);
+char *atf_utils_readline(int);
+void atf_utils_redirect(const int, const char *);
+void atf_utils_wait(const pid_t, const int, const char *, const char *);
#endif /* ATF_C_UTILS_H */
diff --git a/contrib/atf/atf-c/utils_test.c b/contrib/atf/atf-c/utils_test.c
index 146272a..57d6af8 100644
--- a/contrib/atf/atf-c/utils_test.c
+++ b/contrib/atf/atf-c/utils_test.c
@@ -27,8 +27,15 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <atf-c.h>
@@ -36,8 +43,218 @@
#include "detail/test_helpers.h"
-ATF_TC_WITHOUT_HEAD(free_charpp_empty);
-ATF_TC_BODY(free_charpp_empty, tc)
+/** Reads the contents of a file into a buffer.
+ *
+ * Up to buflen-1 characters are read into buffer. If this function returns,
+ * the contents read into the buffer are guaranteed to be nul-terminated.
+ * Note, however, that if the file contains any nul characters itself,
+ * comparing it "as a string" will not work.
+ *
+ * \param path The file to be read, which must exist.
+ * \param buffer Buffer into which to store the file contents.
+ * \param buflen Size of the target buffer.
+ *
+ * \return The count of bytes read. */
+static ssize_t
+read_file(const char *path, void *const buffer, const size_t buflen)
+{
+ const int fd = open(path, O_RDONLY);
+ ATF_REQUIRE_MSG(fd != -1, "Cannot open %s", path);
+ const ssize_t length = read(fd, buffer, buflen - 1);
+ close(fd);
+ ATF_REQUIRE(length != -1);
+ ((char *)buffer)[length] = '\0';
+ return length;
+}
+
+ATF_TC_WITHOUT_HEAD(cat_file__empty);
+ATF_TC_BODY(cat_file__empty, tc)
+{
+ atf_utils_create_file("file.txt", "%s", "");
+ atf_utils_redirect(STDOUT_FILENO, "captured.txt");
+ atf_utils_cat_file("file.txt", "PREFIX");
+ fflush(stdout);
+ close(STDOUT_FILENO);
+
+ char buffer[1024];
+ read_file("captured.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ("", buffer);
+}
+
+ATF_TC_WITHOUT_HEAD(cat_file__one_line);
+ATF_TC_BODY(cat_file__one_line, tc)
+{
+ atf_utils_create_file("file.txt", "This is a single line\n");
+ atf_utils_redirect(STDOUT_FILENO, "captured.txt");
+ atf_utils_cat_file("file.txt", "PREFIX");
+ fflush(stdout);
+ close(STDOUT_FILENO);
+
+ char buffer[1024];
+ read_file("captured.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ("PREFIXThis is a single line\n", buffer);
+}
+
+ATF_TC_WITHOUT_HEAD(cat_file__several_lines);
+ATF_TC_BODY(cat_file__several_lines, tc)
+{
+ atf_utils_create_file("file.txt", "First\nSecond line\nAnd third\n");
+ atf_utils_redirect(STDOUT_FILENO, "captured.txt");
+ atf_utils_cat_file("file.txt", ">");
+ fflush(stdout);
+ close(STDOUT_FILENO);
+
+ char buffer[1024];
+ read_file("captured.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ(">First\n>Second line\n>And third\n", buffer);
+}
+
+ATF_TC_WITHOUT_HEAD(cat_file__no_newline_eof);
+ATF_TC_BODY(cat_file__no_newline_eof, tc)
+{
+ atf_utils_create_file("file.txt", "Foo\n bar baz");
+ atf_utils_redirect(STDOUT_FILENO, "captured.txt");
+ atf_utils_cat_file("file.txt", "PREFIX");
+ fflush(stdout);
+ close(STDOUT_FILENO);
+
+ char buffer[1024];
+ read_file("captured.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ("PREFIXFoo\nPREFIX bar baz", buffer);
+}
+
+ATF_TC_WITHOUT_HEAD(compare_file__empty__match);
+ATF_TC_BODY(compare_file__empty__match, tc)
+{
+ atf_utils_create_file("test.txt", "%s", "");
+ ATF_REQUIRE(atf_utils_compare_file("test.txt", ""));
+}
+
+ATF_TC_WITHOUT_HEAD(compare_file__empty__not_match);
+ATF_TC_BODY(compare_file__empty__not_match, tc)
+{
+ atf_utils_create_file("test.txt", "%s", "");
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n"));
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", "foo"));
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", " "));
+}
+
+ATF_TC_WITHOUT_HEAD(compare_file__short__match);
+ATF_TC_BODY(compare_file__short__match, tc)
+{
+ atf_utils_create_file("test.txt", "this is a short file");
+ ATF_REQUIRE(atf_utils_compare_file("test.txt", "this is a short file"));
+}
+
+ATF_TC_WITHOUT_HEAD(compare_file__short__not_match);
+ATF_TC_BODY(compare_file__short__not_match, tc)
+{
+ atf_utils_create_file("test.txt", "this is a short file");
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", ""));
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n"));
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a Short file"));
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short fil"));
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short file "));
+}
+
+ATF_TC_WITHOUT_HEAD(compare_file__long__match);
+ATF_TC_BODY(compare_file__long__match, tc)
+{
+ char long_contents[3456];
+ size_t i = 0;
+ for (; i < sizeof(long_contents) - 1; i++)
+ long_contents[i] = '0' + (i % 10);
+ long_contents[i] = '\0';
+ atf_utils_create_file("test.txt", "%s", long_contents);
+
+ ATF_REQUIRE(atf_utils_compare_file("test.txt", long_contents));
+}
+
+ATF_TC_WITHOUT_HEAD(compare_file__long__not_match);
+ATF_TC_BODY(compare_file__long__not_match, tc)
+{
+ char long_contents[3456];
+ size_t i = 0;
+ for (; i < sizeof(long_contents) - 1; i++)
+ long_contents[i] = '0' + (i % 10);
+ long_contents[i] = '\0';
+ atf_utils_create_file("test.txt", "%s", long_contents);
+
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", ""));
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n"));
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", "0123456789"));
+ long_contents[i - 1] = 'Z';
+ ATF_REQUIRE(!atf_utils_compare_file("test.txt", long_contents));
+}
+
+ATF_TC_WITHOUT_HEAD(copy_file__empty);
+ATF_TC_BODY(copy_file__empty, tc)
+{
+ atf_utils_create_file("src.txt", "%s", "");
+ ATF_REQUIRE(chmod("src.txt", 0520) != -1);
+
+ atf_utils_copy_file("src.txt", "dest.txt");
+ ATF_REQUIRE(atf_utils_compare_file("dest.txt", ""));
+ struct stat sb;
+ ATF_REQUIRE(stat("dest.txt", &sb) != -1);
+ ATF_REQUIRE_EQ(0520, sb.st_mode & 0xfff);
+}
+
+ATF_TC_WITHOUT_HEAD(copy_file__some_contents);
+ATF_TC_BODY(copy_file__some_contents, tc)
+{
+ atf_utils_create_file("src.txt", "This is a\ntest file\n");
+ atf_utils_copy_file("src.txt", "dest.txt");
+ ATF_REQUIRE(atf_utils_compare_file("dest.txt", "This is a\ntest file\n"));
+}
+
+ATF_TC_WITHOUT_HEAD(create_file);
+ATF_TC_BODY(create_file, tc)
+{
+ atf_utils_create_file("test.txt", "This is a test with %d", 12345);
+
+ char buffer[128];
+ read_file("test.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ("This is a test with 12345", buffer);
+}
+
+ATF_TC_WITHOUT_HEAD(file_exists);
+ATF_TC_BODY(file_exists, tc)
+{
+ atf_utils_create_file("test.txt", "foo");
+
+ ATF_REQUIRE( atf_utils_file_exists("test.txt"));
+ ATF_REQUIRE( atf_utils_file_exists("./test.txt"));
+ ATF_REQUIRE(!atf_utils_file_exists("./test.tx"));
+ ATF_REQUIRE(!atf_utils_file_exists("test.txt2"));
+}
+
+ATF_TC_WITHOUT_HEAD(fork);
+ATF_TC_BODY(fork, tc)
+{
+ fprintf(stdout, "Should not get into child\n");
+ fprintf(stderr, "Should not get into child\n");
+ pid_t pid = atf_utils_fork();
+ if (pid == 0) {
+ fprintf(stdout, "Child stdout\n");
+ fprintf(stderr, "Child stderr\n");
+ exit(EXIT_SUCCESS);
+ }
+
+ int status;
+ ATF_REQUIRE(waitpid(pid, &status, 0) != -1);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
+
+ char buffer[1024];
+ read_file("atf_utils_fork_out.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ("Child stdout\n", buffer);
+ read_file("atf_utils_fork_err.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ("Child stderr\n", buffer);
+}
+
+ATF_TC_WITHOUT_HEAD(free_charpp__empty);
+ATF_TC_BODY(free_charpp__empty, tc)
{
char **array = malloc(sizeof(char *) * 1);
array[0] = NULL;
@@ -45,8 +262,8 @@ ATF_TC_BODY(free_charpp_empty, tc)
atf_utils_free_charpp(array);
}
-ATF_TC_WITHOUT_HEAD(free_charpp_some);
-ATF_TC_BODY(free_charpp_some, tc)
+ATF_TC_WITHOUT_HEAD(free_charpp__some);
+ATF_TC_BODY(free_charpp__some, tc)
{
char **array = malloc(sizeof(char *) * 4);
array[0] = strdup("first");
@@ -57,12 +274,263 @@ ATF_TC_BODY(free_charpp_some, tc)
atf_utils_free_charpp(array);
}
+ATF_TC_WITHOUT_HEAD(grep_file);
+ATF_TC_BODY(grep_file, tc)
+{
+ atf_utils_create_file("test.txt", "line1\nthe second line\naaaabbbb\n");
+
+ ATF_CHECK(atf_utils_grep_file("line1", "test.txt"));
+ ATF_CHECK(atf_utils_grep_file("line%d", "test.txt", 1));
+ ATF_CHECK(atf_utils_grep_file("second line", "test.txt"));
+ ATF_CHECK(atf_utils_grep_file("aa.*bb", "test.txt"));
+ ATF_CHECK(!atf_utils_grep_file("foo", "test.txt"));
+ ATF_CHECK(!atf_utils_grep_file("bar", "test.txt"));
+ ATF_CHECK(!atf_utils_grep_file("aaaaa", "test.txt"));
+}
+
+ATF_TC_WITHOUT_HEAD(grep_string);
+ATF_TC_BODY(grep_string, tc)
+{
+ const char *str = "a string - aaaabbbb";
+ ATF_CHECK(atf_utils_grep_string("a string", str));
+ ATF_CHECK(atf_utils_grep_string("^a string", str));
+ ATF_CHECK(atf_utils_grep_string("aaaabbbb$", str));
+ ATF_CHECK(atf_utils_grep_string("a%s*bb", str, "a."));
+ ATF_CHECK(!atf_utils_grep_string("foo", str));
+ ATF_CHECK(!atf_utils_grep_string("bar", str));
+ ATF_CHECK(!atf_utils_grep_string("aaaaa", str));
+}
+
+ATF_TC_WITHOUT_HEAD(readline__none);
+ATF_TC_BODY(readline__none, tc)
+{
+ atf_utils_create_file("empty.txt", "%s", "");
+
+ const int fd = open("empty.txt", O_RDONLY);
+ ATF_REQUIRE(fd != -1);
+ ATF_REQUIRE(atf_utils_readline(fd) == NULL);
+ close(fd);
+}
+
+ATF_TC_WITHOUT_HEAD(readline__some);
+ATF_TC_BODY(readline__some, tc)
+{
+ const char *l1 = "First line with % formatting % characters %";
+ const char *l2 = "Second line; much longer than the first one";
+ const char *l3 = "Last line, without terminator";
+
+ atf_utils_create_file("test.txt", "%s\n%s\n%s", l1, l2, l3);
+
+ const int fd = open("test.txt", O_RDONLY);
+ ATF_REQUIRE(fd != -1);
+
+ char *line;
+
+ line = atf_utils_readline(fd);
+ ATF_REQUIRE_STREQ(l1, line);
+ free(line);
+
+ line = atf_utils_readline(fd);
+ ATF_REQUIRE_STREQ(l2, line);
+ free(line);
+
+ line = atf_utils_readline(fd);
+ ATF_REQUIRE_STREQ(l3, line);
+ free(line);
+
+ close(fd);
+}
+
+ATF_TC_WITHOUT_HEAD(redirect__stdout);
+ATF_TC_BODY(redirect__stdout, tc)
+{
+ printf("Buffer this");
+ atf_utils_redirect(STDOUT_FILENO, "captured.txt");
+ printf("The printed message");
+ fflush(stdout);
+
+ char buffer[1024];
+ read_file("captured.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ("The printed message", buffer);
+}
+
+ATF_TC_WITHOUT_HEAD(redirect__stderr);
+ATF_TC_BODY(redirect__stderr, tc)
+{
+ fprintf(stderr, "Buffer this");
+ atf_utils_redirect(STDERR_FILENO, "captured.txt");
+ fprintf(stderr, "The printed message");
+ fflush(stderr);
+
+ char buffer[1024];
+ read_file("captured.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ("The printed message", buffer);
+}
+
+ATF_TC_WITHOUT_HEAD(redirect__other);
+ATF_TC_BODY(redirect__other, tc)
+{
+ const char *message = "Foo bar\nbaz\n";
+ atf_utils_redirect(15, "captured.txt");
+ ATF_REQUIRE(write(15, message, strlen(message)) != -1);
+ close(15);
+
+ char buffer[1024];
+ read_file("captured.txt", buffer, sizeof(buffer));
+ ATF_REQUIRE_STREQ(message, buffer);
+}
+
+static void
+fork_and_wait(const int exitstatus, const char* expout, const char* experr)
+{
+ const pid_t pid = atf_utils_fork();
+ if (pid == 0) {
+ fprintf(stdout, "Some output\n");
+ fprintf(stderr, "Some error\n");
+ exit(123);
+ }
+ atf_utils_wait(pid, exitstatus, expout, experr);
+ exit(EXIT_SUCCESS);
+}
+
+ATF_TC_WITHOUT_HEAD(wait__ok);
+ATF_TC_BODY(wait__ok, tc)
+{
+ const pid_t control = fork();
+ ATF_REQUIRE(control != -1);
+ if (control == 0)
+ fork_and_wait(123, "Some output\n", "Some error\n");
+ else {
+ int status;
+ ATF_REQUIRE(waitpid(control, &status, 0) != -1);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(wait__invalid_exitstatus);
+ATF_TC_BODY(wait__invalid_exitstatus, tc)
+{
+ const pid_t control = fork();
+ ATF_REQUIRE(control != -1);
+ if (control == 0)
+ fork_and_wait(120, "Some output\n", "Some error\n");
+ else {
+ int status;
+ ATF_REQUIRE(waitpid(control, &status, 0) != -1);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status));
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(wait__invalid_stdout);
+ATF_TC_BODY(wait__invalid_stdout, tc)
+{
+ const pid_t control = fork();
+ ATF_REQUIRE(control != -1);
+ if (control == 0)
+ fork_and_wait(123, "Some output foo\n", "Some error\n");
+ else {
+ int status;
+ ATF_REQUIRE(waitpid(control, &status, 0) != -1);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status));
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(wait__invalid_stderr);
+ATF_TC_BODY(wait__invalid_stderr, tc)
+{
+ const pid_t control = fork();
+ ATF_REQUIRE(control != -1);
+ if (control == 0)
+ fork_and_wait(123, "Some output\n", "Some error foo\n");
+ else {
+ int status;
+ ATF_REQUIRE(waitpid(control, &status, 0) != -1);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status));
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(wait__save_stdout);
+ATF_TC_BODY(wait__save_stdout, tc)
+{
+ const pid_t control = fork();
+ ATF_REQUIRE(control != -1);
+ if (control == 0)
+ fork_and_wait(123, "save:my-output.txt", "Some error\n");
+ else {
+ int status;
+ ATF_REQUIRE(waitpid(control, &status, 0) != -1);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
+
+ ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some output\n"));
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(wait__save_stderr);
+ATF_TC_BODY(wait__save_stderr, tc)
+{
+ const pid_t control = fork();
+ ATF_REQUIRE(control != -1);
+ if (control == 0)
+ fork_and_wait(123, "Some output\n", "save:my-output.txt");
+ else {
+ int status;
+ ATF_REQUIRE(waitpid(control, &status, 0) != -1);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
+
+ ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some error\n"));
+ }
+}
+
HEADER_TC(include, "atf-c/utils.h");
ATF_TP_ADD_TCS(tp)
{
- ATF_TP_ADD_TC(tp, free_charpp_empty);
- ATF_TP_ADD_TC(tp, free_charpp_some);
+ ATF_TP_ADD_TC(tp, cat_file__empty);
+ ATF_TP_ADD_TC(tp, cat_file__one_line);
+ ATF_TP_ADD_TC(tp, cat_file__several_lines);
+ ATF_TP_ADD_TC(tp, cat_file__no_newline_eof);
+
+ ATF_TP_ADD_TC(tp, compare_file__empty__match);
+ ATF_TP_ADD_TC(tp, compare_file__empty__not_match);
+ ATF_TP_ADD_TC(tp, compare_file__short__match);
+ ATF_TP_ADD_TC(tp, compare_file__short__not_match);
+ ATF_TP_ADD_TC(tp, compare_file__long__match);
+ ATF_TP_ADD_TC(tp, compare_file__long__not_match);
+
+ ATF_TP_ADD_TC(tp, copy_file__empty);
+ ATF_TP_ADD_TC(tp, copy_file__some_contents);
+
+ ATF_TP_ADD_TC(tp, create_file);
+
+ ATF_TP_ADD_TC(tp, file_exists);
+
+ ATF_TP_ADD_TC(tp, fork);
+
+ ATF_TP_ADD_TC(tp, free_charpp__empty);
+ ATF_TP_ADD_TC(tp, free_charpp__some);
+
+ ATF_TP_ADD_TC(tp, grep_file);
+ ATF_TP_ADD_TC(tp, grep_string);
+
+ ATF_TP_ADD_TC(tp, readline__none);
+ ATF_TP_ADD_TC(tp, readline__some);
+
+ ATF_TP_ADD_TC(tp, redirect__stdout);
+ ATF_TP_ADD_TC(tp, redirect__stderr);
+ ATF_TP_ADD_TC(tp, redirect__other);
+
+ ATF_TP_ADD_TC(tp, wait__ok);
+ ATF_TP_ADD_TC(tp, wait__save_stdout);
+ ATF_TP_ADD_TC(tp, wait__save_stderr);
+ ATF_TP_ADD_TC(tp, wait__invalid_exitstatus);
+ ATF_TP_ADD_TC(tp, wait__invalid_stdout);
+ ATF_TP_ADD_TC(tp, wait__invalid_stderr);
ATF_TP_ADD_TC(tp, include);
OpenPOWER on IntegriCloud