diff options
author | ngie <ngie@FreeBSD.org> | 2014-12-21 08:30:18 +0000 |
---|---|---|
committer | ngie <ngie@FreeBSD.org> | 2014-12-21 08:30:18 +0000 |
commit | dc3ad5131fa6525673d58aa537f9d67ba69edb94 (patch) | |
tree | 1473124a62111de8a694012ddb628f25f249137d /contrib/atf/atf-sh | |
parent | 1a3934911c5c7b282bc36336bafe16e321f63922 (diff) | |
download | FreeBSD-src-dc3ad5131fa6525673d58aa537f9d67ba69edb94.zip FreeBSD-src-dc3ad5131fa6525673d58aa537f9d67ba69edb94.tar.gz |
MFC r273929:
r273929 (by jmmv):
MFV: Import atf-0.21.
Diffstat (limited to 'contrib/atf/atf-sh')
-rw-r--r-- | contrib/atf/atf-sh/atf-check.1 | 35 | ||||
-rw-r--r-- | contrib/atf/atf-sh/atf-check.cpp | 24 | ||||
-rw-r--r-- | contrib/atf/atf-sh/atf-check_test.sh | 26 | ||||
-rw-r--r-- | contrib/atf/atf-sh/atf-sh.1 | 64 | ||||
-rw-r--r-- | contrib/atf/atf-sh/atf-sh.3 | 372 | ||||
-rw-r--r-- | contrib/atf/atf-sh/atf-sh.cpp | 59 | ||||
-rw-r--r-- | contrib/atf/atf-sh/atf_check_test.sh | 4 | ||||
-rw-r--r-- | contrib/atf/atf-sh/config_test.sh | 4 | ||||
-rw-r--r-- | contrib/atf/atf-sh/integration_test.sh | 89 | ||||
-rw-r--r-- | contrib/atf/atf-sh/libatf-sh.subr | 23 | ||||
-rw-r--r-- | contrib/atf/atf-sh/misc_helpers.sh | 4 | ||||
-rw-r--r-- | contrib/atf/atf-sh/normalize_test.sh | 4 | ||||
-rw-r--r-- | contrib/atf/atf-sh/tc_test.sh | 4 | ||||
-rw-r--r-- | contrib/atf/atf-sh/tp_test.sh | 4 |
14 files changed, 583 insertions, 133 deletions
diff --git a/contrib/atf/atf-sh/atf-check.1 b/contrib/atf/atf-sh/atf-check.1 index 66f9318..a3bd379 100644 --- a/contrib/atf/atf-sh/atf-check.1 +++ b/contrib/atf/atf-sh/atf-check.1 @@ -1,6 +1,3 @@ -.\" -.\" Automated Testing Framework (atf) -.\" .\" Copyright (c) 2008 The NetBSD Foundation, Inc. .\" All rights reserved. .\" @@ -25,8 +22,7 @@ .\" 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. -.\" -.Dd March 2, 2014 +.Dd October 5, 2014 .Dt ATF-CHECK 1 .Os .Sh NAME @@ -39,13 +35,16 @@ .Op Fl e Ar action:arg ... .Op Fl x .Ar command -.Nm -.Fl h .Sh DESCRIPTION .Nm executes a given command and analyzes its results, including exit code, stdout and stderr. .Pp +.Em Test cases must use +.Em Xr atf-sh 3 Ns ' Ns s +.Em Nm atf_check +.Em builtin function instead of calling this utility directly. +.Pp In the first synopsis form, .Nm will execute the provided command and apply checks specified @@ -67,8 +66,6 @@ will print information about all supported options and their purpose. .Pp The following options are available: .Bl -tag -width XqualXvalueXX -.It Fl h -Shows a short summary of all available options and their purpose. .It Fl s Ar qual:value Analyzes termination status. Must be one of: @@ -133,21 +130,31 @@ Path to the system shell to be used when the is given to run commands. .El .Sh EXAMPLES +The following are sample invocations from within a test case. +Note that we use the +.Nm atf_check +function provided by +.Xr atf-sh 3 +instead of executing +.Nm +directly: .Bd -literal -offset indent # Exit code 0, nothing on stdout/stderr -atf-check 'true' +atf_check 'true' # Typical usage if failure is expected -atf-check -s not-exit:0 'false' +atf_check -s not-exit:0 'false' # Checking stdout/stderr echo foobar >expout -atf-check -o file:expout -e inline:"xx\etyy\en" \e +atf_check -o file:expout -e inline:"xx\etyy\en" \e 'echo foobar ; printf "xx\etyy\en" >&2' # Checking for a crash -atf-check -s signal:sigsegv my_program +atf_check -s signal:sigsegv my_program # Combined checks -atf-check -o match:foo -o not-match:bar echo foo baz +atf_check -o match:foo -o not-match:bar echo foo baz .Ed +.Sh SEE ALSO +.Xr atf-sh 1 diff --git a/contrib/atf/atf-sh/atf-check.cpp b/contrib/atf/atf-sh/atf-check.cpp index b08c020..866b7bb 100644 --- a/contrib/atf/atf-sh/atf-check.cpp +++ b/contrib/atf/atf-sh/atf-check.cpp @@ -1,6 +1,3 @@ -// -// Automated Testing Framework (atf) -// // Copyright (c) 2008 The NetBSD Foundation, Inc. // All rights reserved. // @@ -25,7 +22,6 @@ // 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. -// extern "C" { #include <sys/types.h> @@ -48,10 +44,9 @@ extern "C" { #include <utility> #include "atf-c++/check.hpp" -#include "atf-c++/config.hpp" - #include "atf-c++/detail/application.hpp" #include "atf-c++/detail/auto_array.hpp" +#include "atf-c++/detail/env.hpp" #include "atf-c++/detail/exceptions.hpp" #include "atf-c++/detail/fs.hpp" #include "atf-c++/detail/process.hpp" @@ -112,17 +107,20 @@ class temp_file : public std::ostream { int m_fd; public: - temp_file(const atf::fs::path& p) : + temp_file(const char* pattern) : std::ostream(NULL), m_fd(-1) { - atf::auto_array< char > buf(new char[p.str().length() + 1]); - std::strcpy(buf.get(), p.c_str()); + const atf::fs::path file = atf::fs::path( + atf::env::get("TMPDIR", "/tmp")) / pattern; + + atf::auto_array< char > buf(new char[file.str().length() + 1]); + std::strcpy(buf.get(), file.c_str()); m_fd = ::mkstemp(buf.get()); if (m_fd == -1) throw atf::system_error("atf_check::temp_file::temp_file(" + - p.str() + ")", "mkstemp(3) failed", + file.str() + ")", "mkstemp(3) failed", errno); m_path.reset(new atf::fs::path(buf.get())); @@ -350,7 +348,7 @@ execute_with_shell(char* const* argv) const std::string cmd = flatten_argv(argv); const char* sh_argv[4]; - sh_argv[0] = atf::config::get("atf_shell").c_str(); + sh_argv[0] = atf::env::get("ATF_SHELL", ATF_SHELL).c_str(); sh_argv[1] = "-c"; sh_argv[2] = cmd.c_str(); sh_argv[3] = NULL; @@ -623,9 +621,7 @@ run_output_check(const output_check oc, const atf::fs::path& path, } else if (oc.type == oc_ignore) { result = true; } else if (oc.type == oc_inline) { - atf::fs::path path2 = atf::fs::path(atf::config::get("atf_workdir")) - / "inline.XXXXXX"; - temp_file temp(path2); + temp_file temp("atf-check.XXXXXX"); temp.write(decode(oc.value)); temp.close(); diff --git a/contrib/atf/atf-sh/atf-check_test.sh b/contrib/atf/atf-sh/atf-check_test.sh index 7319a2b..9542dfb 100644 --- a/contrib/atf/atf-sh/atf-check_test.sh +++ b/contrib/atf/atf-sh/atf-check_test.sh @@ -1,6 +1,3 @@ -# -# Automated Testing Framework (atf) -# # Copyright (c) 2008 The NetBSD Foundation, Inc. # All rights reserved. # @@ -25,7 +22,6 @@ # 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. -# # The Atf_Check and Atf-Shell variables are set by atf-sh. @@ -211,16 +207,7 @@ oflag_inline_body() h_pass "echo foo bar" -o inline:"foo bar\n" h_pass "printf 'foo bar'" -o inline:"foo bar" h_pass "printf '\t\n\t\n'" -o inline:"\t\n\t\n" - # XXX Ugly hack to workaround the lack of \e in FreeBSD. Also, \e doesn't - # seem to work as expected in Linux. Look for a nicer solution. - case $(uname) in - Darwin|FreeBSD|Linux) - h_pass "printf '\a\b\f\n\r\t\v'" -o inline:"\a\b\f\n\r\t\v" - ;; - *) - h_pass "printf '\a\b\e\f\n\r\t\v'" -o inline:"\a\b\e\f\n\r\t\v" - ;; - esac + h_pass "printf '\a\b\033\f\n\r\t\v'" -o inline:"\a\b\e\f\n\r\t\v" h_pass "printf '\011\022\033\012'" -o inline:"\011\022\033\012" h_fail "echo foo bar" -o inline:"foo bar" @@ -331,16 +318,7 @@ eflag_inline_body() h_pass "echo foo bar 1>&2" -e inline:"foo bar\n" h_pass "printf 'foo bar' 1>&2" -e inline:"foo bar" h_pass "printf '\t\n\t\n' 1>&2" -e inline:"\t\n\t\n" - # XXX Ugly hack to workaround the lack of \e in FreeBSD. Also, \e doesn't - # seem to work as expected in Linux. Look for a nicer solution. - case $(uname) in - Darwin|FreeBSD|Linux) - h_pass "printf '\a\b\f\n\r\t\v' 1>&2" -e inline:"\a\b\f\n\r\t\v" - ;; - *) - h_pass "printf '\a\b\e\f\n\r\t\v' 1>&2" -e inline:"\a\b\e\f\n\r\t\v" - ;; - esac + h_pass "printf '\a\b\033\f\n\r\t\v' 1>&2" -e inline:"\a\b\e\f\n\r\t\v" h_pass "printf '\011\022\033\012' 1>&2" -e inline:"\011\022\033\012" h_fail "echo foo bar 1>&2" -e inline:"foo bar" diff --git a/contrib/atf/atf-sh/atf-sh.1 b/contrib/atf/atf-sh/atf-sh.1 index ad77f04..ac4a135 100644 --- a/contrib/atf/atf-sh/atf-sh.1 +++ b/contrib/atf/atf-sh/atf-sh.1 @@ -1,6 +1,3 @@ -.\" -.\" Automated Testing Framework (atf) -.\" .\" Copyright (c) 2010 The NetBSD Foundation, Inc. .\" All rights reserved. .\" @@ -25,24 +22,22 @@ .\" 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. -.\" -.Dd March 2, 2014 +.Dd September 27, 2014 .Dt ATF-SH 1 .Os .Sh NAME .Nm atf-sh +.Op Fl s Ar shell .Nd interpreter for shell-based test programs .Sh SYNOPSIS .Nm .Ar script -.Nm -.Fl h .Sh DESCRIPTION .Nm is an interpreter that runs the test program given in .Ar script after loading the -.Xr atf-sh-api 3 +.Xr atf-sh 3 library. .Pp .Nm @@ -51,25 +46,62 @@ the system-wide shell defined by .Va ATF_SHELL . .Nm executes the interpreter, loads the -.Xr atf-sh-api 3 +.Xr atf-sh 3 library and then runs the script. +You must consider +.Nm atf-sh +to be a POSIX shell by default and thus should not use any non-standard +extensions. .Pp +The following options are available: +.Bl -tag -width XsXshellXXX +.It Fl s Ar shell +Specifies the shell to use instead of the value provided by +.Va ATF_SHELL . +.El +.Sh ENVIRONMENT +.Bl -tag -width ATFXLIBEXECDIRXX -compact +.It Va ATF_LIBEXECDIR +Overrides the builtin directory where +.Nm +is located. +Should not be overridden other than for testing purposes. +.It Va ATF_PKGDATADIR +Overrides the builtin directory where +.Pa libatf-sh.subr +is located. +Should not be overridden other than for testing purposes. +.It Va ATF_SHELL +Path to the system shell to be used in the generated scripts. +Scripts must not rely on this variable being set to select a specific +interpreter. +.El +.Sh EXAMPLES Scripts using -.Xr atf-sh-api 3 +.Xr atf-sh 3 should start with: .Bd -literal -offset indent #! /usr/bin/env atf-sh .Ed .Pp -The following options are available: -.Bl -tag -width XhXX -.It Fl h -Shows a short summary of all available options and their purpose. -.El +Alternatively, if you want to explicitly choose a shell interpreter, you cannot +rely on +.Xr env 1 +to find +.Nm . +Instead, you have to hardcode the path to +.Nm +in the script and then use the +.Fl s +option afterwards as a +.Em single parameter : +.Bd -literal -offset indent +#! /path/to/bin/atf-sh -s/bin/bash +.Ed .Sh ENVIRONMENT .Bl -tag -width ATFXSHELLXX -compact .It Va ATF_SHELL Path to the system shell to be used in the generated scripts. .El .Sh SEE ALSO -.Xr atf-sh-api 3 +.Xr atf-sh 3 diff --git a/contrib/atf/atf-sh/atf-sh.3 b/contrib/atf/atf-sh/atf-sh.3 new file mode 100644 index 0000000..be56539 --- /dev/null +++ b/contrib/atf/atf-sh/atf-sh.3 @@ -0,0 +1,372 @@ +.\" 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. +.Dd October 13, 2014 +.Dt ATF-SH 3 +.Os +.Sh NAME +.Nm atf_add_test_case , +.Nm atf_check , +.Nm atf_check_equal , +.Nm atf_config_get , +.Nm atf_config_has , +.Nm atf_expect_death , +.Nm atf_expect_exit , +.Nm atf_expect_fail , +.Nm atf_expect_pass , +.Nm atf_expect_signal , +.Nm atf_expect_timeout , +.Nm atf_fail , +.Nm atf_get , +.Nm atf_get_srcdir , +.Nm atf_pass , +.Nm atf_require_prog , +.Nm atf_set , +.Nm atf_skip , +.Nm atf_test_case +.Nd POSIX shell API to write ATF-based test programs +.Sh SYNOPSIS +.Nm atf_add_test_case +.Qq name +.Nm atf_check +.Qq command +.Nm atf_check_equal +.Qq expected_expression +.Qq actual_expression +.Nm atf_config_get +.Qq var_name +.Nm atf_config_has +.Qq var_name +.Nm atf_expect_death +.Qq reason +.Qq ... +.Nm atf_expect_exit +.Qq exitcode +.Qq reason +.Qq ... +.Nm atf_expect_fail +.Qq reason +.Qq ... +.Nm atf_expect_pass +.Qq +.Nm atf_expect_signal +.Qq signo +.Qq reason +.Qq ... +.Nm atf_expect_timeout +.Qq reason +.Qq ... +.Nm atf_fail +.Qq reason +.Nm atf_get +.Qq var_name +.Nm atf_get_srcdir +.Nm atf_pass +.Nm atf_require_prog +.Qq prog_name +.Nm atf_set +.Qq var_name +.Qq value +.Nm atf_skip +.Qq reason +.Nm atf_test_case +.Qq name +.Qq cleanup +.Sh DESCRIPTION +ATF +provides a simple but powerful interface to easily write test programs in +the POSIX shell language. +These are extremely helpful given that they are trivial to write due to the +language simplicity and the great deal of available external tools, so they +are often ideal to test other applications at the user level. +.Pp +Test programs written using this library must be run using the +.Xr atf-sh 1 +interpreter by putting the following on their very first line: +.Bd -literal -offset indent +#! /usr/bin/env atf-sh +.Ed +.Pp +Shell-based test programs always follow this template: +.Bd -literal -offset indent +atf_test_case tc1 +tc1_head() { + ... first test case's header ... +} +tc1_body() { + ... first test case's body ... +} + +atf_test_case tc2 cleanup +tc2_head() { + ... second test case's header ... +} +tc2_body() { + ... second test case's body ... +} +tc2_cleanup() { + ... second test case's cleanup ... +} + +.Ns ... additional test cases ... + +atf_init_test_cases() { + atf_add_test_case tc1 + atf_add_test_case tc2 + ... add additional test cases ... +} +.Ed +.Ss Definition of test cases +Test cases have an identifier and are composed of three different parts: +the header, the body and an optional cleanup routine, all of which are +described in +.Xr atf-test-case 4 . +To define test cases, one can use the +.Nm atf_test_case +function, which takes a first parameter specifiying the test case's +name and instructs the library to set things up to accept it as a valid +test case. +The second parameter is optional and, if provided, must be +.Sq cleanup ; +providing this parameter allows defining a cleanup routine for the test +case. +It is important to note that this function +.Em does not +set the test case up for execution when the program is run. +In order to do so, a later registration is needed through the +.Nm atf_add_test_case +function detailed in +.Sx Program initialization . +.Pp +Later on, one must define the three parts of the body by providing two +or three functions (remember that the cleanup routine is optional). +These functions are named after the test case's identifier, and are +.Nm \*(Ltid\*(Gt_head , +.Nm \*(Ltid\*(Gt_body +and +.Nm \*(Ltid\*(Gt_cleanup . +None of these take parameters when executed. +.Ss Program initialization +The test program must define an +.Nm atf_init_test_cases +function, which is in charge of registering the test cases that will be +executed at run time by using the +.Nm atf_add_test_case +function, which takes the name of a test case as its single parameter. +This main function should not do anything else, except maybe sourcing +auxiliary source files that define extra variables and functions. +.Ss Configuration variables +The test case has read-only access to the current configuration variables +through the +.Nm atf_config_has +and +.Nm atf_config_get +methods. +The former takes a single parameter specifying a variable name and returns +a boolean indicating whether the variable is defined or not. +The latter can take one or two parameters. +If it takes only one, it specifies the variable from which to get the +value, and this variable must be defined. +If it takes two, the second one specifies a default value to be returned +if the variable is not available. +.Ss Access to the source directory +It is possible to get the path to the test case's source directory from +anywhere in the test program by using the +.Nm atf_get_srcdir +function. +It is interesting to note that this can be used inside +.Nm atf_init_test_cases +to silently include additional helper files from the source directory. +.Ss Requiring programs +Aside from the +.Va require.progs +meta-data variable available in the header only, one can also check for +additional programs in the test case's body by using the +.Nm atf_require_prog +function, which takes the base name or full path of a single binary. +Relative paths are forbidden. +If it is not found, the test case will be automatically skipped. +.Ss Test case finalization +The test case finalizes either when the body reaches its end, at which +point the test is assumed to have +.Em passed , +or at any explicit call to +.Nm atf_pass , +.Nm atf_fail +or +.Nm atf_skip . +These three functions terminate the execution of the test case immediately. +The cleanup routine will be processed afterwards in a completely automated +way, regardless of the test case's termination reason. +.Pp +.Nm atf_pass +does not take any parameters. +.Nm atf_fail +and +.Nm atf_skip +take a single string parameter that describes why the test case failed or +was skipped, respectively. +It is very important to provide a clear error message in both cases so that +the user can quickly know why the test did not pass. +.Ss Expectations +Everything explained in the previous section changes when the test case +expectations are redefined by the programmer. +.Pp +Each test case has an internal state called +.Sq expect +that describes what the test case expectations are at any point in time. +The value of this property can change during execution by any of: +.Bl -tag -width indent +.It Nm atf_expect_death Qo reason Qc Qo ... Qc +Expects the test case to exit prematurely regardless of the nature of the +exit. +.It Nm atf_expect_exit Qo exitcode Qc Qo reason Qc Qo ... Qc +Expects the test case to exit cleanly. +If +.Va exitcode +is not +.Sq -1 , +the runtime engine will validate that the exit code of the test case +matches the one provided in this call. +Otherwise, the exact value will be ignored. +.It Nm atf_expect_fail Qo reason Qc +Any failure raised in this mode is recorded, but such failures do not report +the test case as failed; instead, the test case finalizes cleanly and is +reported as +.Sq expected failure ; +this report includes the provided +.Fa reason +as part of it. +If no error is raised while running in this mode, then the test case is +reported as +.Sq failed . +.Pp +This mode is useful to reproduce actual known bugs in tests. +Whenever the developer fixes the bug later on, the test case will start +reporting a failure, signaling the developer that the test case must be +adjusted to the new conditions. +In this situation, it is useful, for example, to set +.Fa reason +as the bug number for tracking purposes. +.It Nm atf_expect_pass +This is the normal mode of execution. +In this mode, any failure is reported as such to the user and the test case +is marked as +.Sq failed . +.It Nm atf_expect_signal Qo signo Qc Qo reason Qc Qo ... Qc +Expects the test case to terminate due to the reception of a signal. +If +.Va signo +is not +.Sq -1 , +the runtime engine will validate that the signal that terminated the test +case matches the one provided in this call. +Otherwise, the exact value will be ignored. +.It Nm atf_expect_timeout Qo reason Qc Qo ... Qc +Expects the test case to execute for longer than its timeout. +.El +.Ss Helper functions for common checks +.Bl -tag -width indent +.It Nm atf_check Qo [options] Qc Qo command Qc Qo [args] Qc +Executes a command, performs checks on its exit code and its output, and +fails the test case if any of the checks is not successful. +This function is particularly useful in integration tests that verify the +correct functioning of a binary. +.Pp +Internally, this function is just a wrapper over the +.Xr atf-check 1 +tool (whose manual page provides all details on the calling syntax). +You should always use the +.Nm atf_check +function instead of the +.Xr atf-check 1 +tool in your scripts; the latter is not even in the path. +.It Nm atf_check_equal Qo expected_expression Qc Qo actual_expression Qc +This function takes two expressions, evaluates them and, if their +results differ, aborts the test case with an appropriate failure message. +The common style is to put the expected value in the first parameter and the +actual value in the second parameter. +.El +.Sh EXAMPLES +The following shows a complete test program with a single test case that +validates the addition operator: +.Bd -literal -offset indent +atf_test_case addition +addition_head() { + atf_set "descr" "Sample tests for the addition operator" +} +addition_body() { + atf_check_equal 0 $((0 + 0)) + atf_check_equal 1 $((0 + 1)) + atf_check_equal 1 $((1 + 0)) + + atf_check_equal 2 $((1 + 1)) + + atf_check_equal 300 $((100 + 200)) +} + +atf_init_test_cases() { + atf_add_test_case addition +} +.Ed +.Pp +This other example shows how to include a file with extra helper functions +in the test program: +.Bd -literal -offset indent +.Ns ... definition of test cases ... + +atf_init_test_cases() { + . $(atf_get_srcdir)/helper_functions.sh + + atf_add_test_case foo1 + atf_add_test_case foo2 +} +.Ed +.Pp +This example demonstrates the use of the very useful +.Nm atf_check +function: +.Bd -literal -offset indent +# Check for silent output +atf_check -s exit:0 -o empty -e empty 'true' + +# Check for silent output and failure +atf_check -s exit:1 -o empty -e empty 'false' + +# Check for known stdout and silent stderr +echo foo >expout +atf_check -s exit:0 -o file:expout -e empty 'echo foo' + +# Generate a file for later inspection +atf_check -s exit:0 -o save:stdout -e empty 'ls' +grep foo ls || atf_fail "foo file not found in listing" + +# Or just do the match along the way +atf_check -s exit:0 -o match:"^foo$" -e empty 'ls' +.Ed +.Sh SEE ALSO +.Xr atf-check 1 , +.Xr atf-sh 1 , +.Xr atf-test-program 1 , +.Xr atf-test-case 4 diff --git a/contrib/atf/atf-sh/atf-sh.cpp b/contrib/atf/atf-sh/atf-sh.cpp index e985e79..9975573 100644 --- a/contrib/atf/atf-sh/atf-sh.cpp +++ b/contrib/atf/atf-sh/atf-sh.cpp @@ -1,6 +1,3 @@ -// -// Automated Testing Framework (atf) -// // Copyright (c) 2010 The NetBSD Foundation, Inc. // All rights reserved. // @@ -25,7 +22,6 @@ // 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. -// extern "C" { #include <unistd.h> @@ -36,9 +32,8 @@ extern "C" { #include <cstring> #include <iostream> -#include "atf-c++/config.hpp" - #include "atf-c++/detail/application.hpp" +#include "atf-c++/detail/env.hpp" #include "atf-c++/detail/fs.hpp" #include "atf-c++/detail/sanity.hpp" @@ -63,9 +58,11 @@ static std::string* construct_script(const char* filename) { - const std::string libexecdir = atf::config::get("atf_libexecdir"); - const std::string pkgdatadir = atf::config::get("atf_pkgdatadir"); - const std::string shell = atf::config::get("atf_shell"); + const std::string libexecdir = atf::env::get( + "ATF_LIBEXECDIR", ATF_LIBEXECDIR); + const std::string pkgdatadir = atf::env::get( + "ATF_PKGDATADIR", ATF_PKGDATADIR); + const std::string shell = atf::env::get("ATF_SHELL", ATF_SHELL); std::string* command = new std::string(); command->reserve(512); @@ -111,6 +108,11 @@ construct_argv(const std::string& shell, const int interpreter_argc, class atf_sh : public atf::application::app { static const char* m_description; + atf::fs::path m_shell; + + options_set specific_options(void) const; + void process_option(int, const char*); + public: atf_sh(void); @@ -122,8 +124,36 @@ const char* atf_sh::m_description = "system sh(1) with the atf-sh library."; atf_sh::atf_sh(void) : - app(m_description, "atf-sh(1)") + app(m_description, "atf-sh(1)"), + m_shell(atf::fs::path(atf::env::get("ATF_SHELL", ATF_SHELL))) +{ +} + +atf_sh::options_set +atf_sh::specific_options(void) + const +{ + using atf::application::option; + options_set opts; + + INV(m_shell == atf::fs::path(atf::env::get("ATF_SHELL", ATF_SHELL))); + opts.insert(option('s', "shell", "Path to the shell interpreter to use; " + "default: " + m_shell.str())); + + return opts; +} + +void +atf_sh::process_option(int ch, const char* arg) { + switch (ch) { + case 's': + m_shell = atf::fs::path(arg); + break; + + default: + UNREACHABLE; + } } int @@ -137,15 +167,14 @@ atf_sh::main(void) throw std::runtime_error("The test program '" + script.str() + "' " "does not exist"); - const std::string shell = atf::config::get("atf_shell"); - const char** argv = construct_argv(shell, m_argc, m_argv); + const char** argv = construct_argv(m_shell.str(), m_argc, m_argv); // Don't bother keeping track of the memory allocated by construct_argv: // we are going to exec or die immediately. - const int ret = execv(shell.c_str(), const_cast< char** >(argv)); + const int ret = execv(m_shell.c_str(), const_cast< char** >(argv)); INV(ret == -1); - std::cerr << "Failed to execute " << shell << ": " << std::strerror(errno) - << "\n"; + std::cerr << "Failed to execute " << m_shell.str() << ": " + << std::strerror(errno) << "\n"; return EXIT_FAILURE; } diff --git a/contrib/atf/atf-sh/atf_check_test.sh b/contrib/atf/atf-sh/atf_check_test.sh index a43a952..163e905 100644 --- a/contrib/atf/atf-sh/atf_check_test.sh +++ b/contrib/atf/atf-sh/atf_check_test.sh @@ -1,6 +1,3 @@ -# -# Automated Testing Framework (atf) -# # Copyright (c) 2007 The NetBSD Foundation, Inc. # All rights reserved. # @@ -25,7 +22,6 @@ # 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. -# # TODO: Bring in the checks in the bootstrap testsuite for atf_check. diff --git a/contrib/atf/atf-sh/config_test.sh b/contrib/atf/atf-sh/config_test.sh index f7f57f0..048834c 100644 --- a/contrib/atf/atf-sh/config_test.sh +++ b/contrib/atf/atf-sh/config_test.sh @@ -1,6 +1,3 @@ -# -# Automated Testing Framework (atf) -# # Copyright (c) 2007 The NetBSD Foundation, Inc. # All rights reserved. # @@ -25,7 +22,6 @@ # 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. -# atf_test_case has has_head() diff --git a/contrib/atf/atf-sh/integration_test.sh b/contrib/atf/atf-sh/integration_test.sh index 452c958..1150966 100644 --- a/contrib/atf/atf-sh/integration_test.sh +++ b/contrib/atf/atf-sh/integration_test.sh @@ -1,6 +1,3 @@ -# -# Automated Testing Framework (atf) -# # Copyright (c) 2010 The NetBSD Foundation, Inc. # All rights reserved. # @@ -25,12 +22,14 @@ # 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. -# + +: ${ATF_SH:="__ATF_SH__"} create_test_program() { - echo '#! /usr/bin/env atf-sh' >"${1}" - cat >>"${1}" - chmod +x "${1}" + local output="${1}"; shift + echo "#! ${ATF_SH} ${*}" >"${output}" + cat >>"${output}" + chmod +x "${output}" } atf_test_case no_args @@ -40,7 +39,7 @@ no_args_body() atf-sh: ERROR: No test program provided atf-sh: See atf-sh(1) for usage details. EOF - atf_check -s eq:1 -o ignore -e file:experr atf-sh + atf_check -s eq:1 -o ignore -e file:experr "${ATF_SH}" } atf_test_case missing_script @@ -49,7 +48,7 @@ missing_script_body() cat >experr <<EOF atf-sh: ERROR: The test program 'non-existent' does not exist EOF - atf_check -s eq:1 -o ignore -e file:experr atf-sh non-existent + atf_check -s eq:1 -o ignore -e file:experr "${ATF_SH}" non-existent } atf_test_case arguments @@ -78,7 +77,74 @@ EOF >>> hello bye <<< >>>foo bar<<< EOF - atf_check -s eq:0 -o file:expout -e empty atf-sh tp ' hello bye ' 'foo bar' + atf_check -s eq:0 -o file:expout -e empty "${ATF_SH}" tp \ + ' hello bye ' 'foo bar' +} + +atf_test_case custom_shell__command_line +custom_shell__command_line_body() +{ + cat >expout <<EOF +This is the custom shell +This is the test program +EOF + + cat >custom-shell <<EOF +#! /bin/sh +echo "This is the custom shell" +exec /bin/sh "\${@}" +EOF + chmod +x custom-shell + + echo 'main() { echo "This is the test program"; }' | create_test_program tp + atf_check -s eq:0 -o file:expout -e empty "${ATF_SH}" -s ./custom-shell tp +} + +atf_test_case custom_shell__shebang +custom_shell__shebang_body() +{ + cat >expout <<EOF +This is the custom shell +This is the test program +EOF + + cat >custom-shell <<EOF +#! /bin/sh +echo "This is the custom shell" +exec /bin/sh "\${@}" +EOF + chmod +x custom-shell + + echo 'main() { echo "This is the test program"; }' | create_test_program \ + tp "-s$(pwd)/custom-shell" + atf_check -s eq:0 -o file:expout -e empty ./tp +} + +atf_test_case set_e +set_e_head() +{ + atf_set "descr" "Simple test to validate that atf-sh works even when" \ + "set -e is enabled" +} +set_e_body() +{ + cat >custom-shell <<EOF +#! /bin/sh +exec /bin/sh -e "\${@}" +EOF + chmod +x custom-shell + + cat >tp <<EOF +atf_test_case helper +helper_body() { + atf_skip "reached" +} +atf_init_test_cases() { + atf_add_test_case helper +} +EOF + atf_check -s eq:0 -o match:skipped.*reached \ + "${ATF_SH}" -s ./custom-shell tp helper } atf_init_test_cases() @@ -86,6 +152,9 @@ atf_init_test_cases() atf_add_test_case no_args atf_add_test_case missing_script atf_add_test_case arguments + atf_add_test_case custom_shell__command_line + atf_add_test_case custom_shell__shebang + atf_add_test_case set_e } # vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/contrib/atf/atf-sh/libatf-sh.subr b/contrib/atf/atf-sh/libatf-sh.subr index 8525b22..a078975 100644 --- a/contrib/atf/atf-sh/libatf-sh.subr +++ b/contrib/atf/atf-sh/libatf-sh.subr @@ -1,6 +1,3 @@ -# -# Automated Testing Framework (atf) -# # Copyright (c) 2007 The NetBSD Foundation, Inc. # All rights reserved. # @@ -25,9 +22,6 @@ # 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. -# - -set -e # ------------------------------------------------------------------------ # GLOBAL VARIABLES @@ -90,12 +84,13 @@ atf_check() } # -# atf_check_equal expr1 expr2 +# atf_check_equal expected_expression actual_expression # -# Checks that expr1's value matches expr2's and, if not, raises an -# error. Ideally expr1 and expr2 should be provided quoted (not -# expanded) so that the error message is helpful; otherwise it will -# only show the values, not the expressions themselves. +# Checks that expected_expression's value matches actual_expression's +# and, if not, raises an error. Ideally expected_expression and +# actual_expression should be provided quoted (not expanded) so that +# the error message is helpful; otherwise it will only show the values, +# not the expressions themselves. # atf_check_equal() { @@ -595,7 +590,7 @@ _atf_run_tc() _atf_has_tc "${_tcname}" || _atf_syntax_error "Unknown test case \`${1}'" if [ "${__RUNNING_INSIDE_ATF_RUN}" != "internal-yes-value" ]; then - _atf_warning "Running test cases without atf-run(1) is unsupported" + _atf_warning "Running test cases outside of kyua(1) is unsupported" _atf_warning "No isolation nor timeout control is being applied;" \ "you may get unexpected failures; see atf-test-case(4)" fi @@ -741,10 +736,6 @@ main() done shift `expr ${OPTIND} - 1` - # First of all, make sure that the source directory is correct. It - # doesn't matter if the user did not change it, because the default - # value may not work. (TODO: It possibly should, even though it is - # not a big deal because atf-run deals with this.) case ${Source_Dir} in /*) ;; diff --git a/contrib/atf/atf-sh/misc_helpers.sh b/contrib/atf/atf-sh/misc_helpers.sh index 1f83688..62d6580 100644 --- a/contrib/atf/atf-sh/misc_helpers.sh +++ b/contrib/atf/atf-sh/misc_helpers.sh @@ -1,6 +1,3 @@ -# -# Automated Testing Framework (atf) -# # Copyright (c) 2007 The NetBSD Foundation, Inc. # All rights reserved. # @@ -25,7 +22,6 @@ # 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. -# # ------------------------------------------------------------------------- # Helper tests for "t_atf_check". diff --git a/contrib/atf/atf-sh/normalize_test.sh b/contrib/atf/atf-sh/normalize_test.sh index 0f59da0..0419db36 100644 --- a/contrib/atf/atf-sh/normalize_test.sh +++ b/contrib/atf/atf-sh/normalize_test.sh @@ -1,6 +1,3 @@ -# -# Automated Testing Framework (atf) -# # Copyright (c) 2007 The NetBSD Foundation, Inc. # All rights reserved. # @@ -25,7 +22,6 @@ # 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. -# atf_test_case main main_head() diff --git a/contrib/atf/atf-sh/tc_test.sh b/contrib/atf/atf-sh/tc_test.sh index 5bece42..1117047 100644 --- a/contrib/atf/atf-sh/tc_test.sh +++ b/contrib/atf/atf-sh/tc_test.sh @@ -1,6 +1,3 @@ -# -# Automated Testing Framework (atf) -# # Copyright (c) 2007 The NetBSD Foundation, Inc. # All rights reserved. # @@ -25,7 +22,6 @@ # 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. -# atf_test_case default_status default_status_head() diff --git a/contrib/atf/atf-sh/tp_test.sh b/contrib/atf/atf-sh/tp_test.sh index c159813..a9f1b96 100644 --- a/contrib/atf/atf-sh/tp_test.sh +++ b/contrib/atf/atf-sh/tp_test.sh @@ -1,6 +1,3 @@ -# -# Automated Testing Framework (atf) -# # Copyright (c) 2007 The NetBSD Foundation, Inc. # All rights reserved. # @@ -25,7 +22,6 @@ # 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. -# atf_test_case srcdir srcdir_head() |