summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--doc/autoconf.texi35
-rw-r--r--lib/autotest/general.m4115
-rw-r--r--tests/autotest.at66
-rw-r--r--tests/base.at13
-rw-r--r--tests/compile.at10
-rw-r--r--tests/local.at42
-rw-r--r--tests/m4sh.at4
-rw-r--r--tests/torture.at5
9 files changed, 221 insertions, 74 deletions
diff --git a/NEWS b/NEWS
index 42095344..a0258956 100644
--- a/NEWS
+++ b/NEWS
@@ -363,6 +363,11 @@ GNU Autoconf NEWS - User visible changes.
*** AT_TESTED arguments can use variable or command substitutions, including
in particular $EXEEXT
+*** New macros AT_PREPARE_TESTS, AT_PREPARE_EACH_TEST, and AT_TEST_HELPER_FN.
+
+ These provide an official way to define testsuite-specific
+ initialization code and shell functions.
+
* Noteworthy changes in release 2.69 (2012-04-24) [stable]
** Autoconf now requires perl 5.6 or better (but generated configure
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index acc290b0..f1eff146 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -25463,6 +25463,41 @@ will still use shell variable expansion (@samp{$}), command substitution
via @file{atlocal} or @file{atconfig}.
@end defmac
+@defmac AT_PREPARE_TESTS (@var{shell-code})
+@atindex{PREPARE_TESTS}
+Execute @var{shell-code} in the main testsuite process,
+after initializing the test suite and processing command-line options,
+but before running any tests. If this macro is used several times,
+all of the @var{shell-code}s will be executed,
+in the order they appeared in @file{testsuite.at}.
+
+One reason to use @code{AT_PREPARE_TESTS} is when the programs under
+test are sensitive to environment variables: you can unset all these
+variables or reset them to safe values in @var{shell-code}.
+
+@var{shell-code} is only executed if at least one test is going to be
+run. In particular, it will not be executed if any of the @option{--help},
+@option{--version}, @option{--list}, or @option{--clean} options are
+given to @command{testsuite} (@pxref{testsuite Invocation}).
+@end defmac
+
+@defmac AT_PREPARE_EACH_TEST (@var{shell-code})
+@atindex{AT_PREPARE_EACH_TEST}
+Execute @var{shell-code} in each test group's subshell, at the point of
+the @code{AT_SETUP} that starts the test group.
+@end defmac
+
+@defmac AT_TEST_HELPER_FN (@var{name}, @var{args}, @var{description}, @var{code})
+Define a shell function that will be available to the code for each test
+group. Its name will be @code{ath_fn_@var{name}}, and its body will be
+@var{code}. (The prefix prevents name conflicts with shell functions
+defined by M4sh and Autotest.)
+
+@var{args} should describe the function's arguments and @var{description}
+what it does; these are used only for documentation comments in the
+generated testsuite script.
+@end defmac
+
@sp 1
@defmac AT_BANNER (@var{test-category-name})
diff --git a/lib/autotest/general.m4 b/lib/autotest/general.m4
index f29ce490..955ed0d9 100644
--- a/lib/autotest/general.m4
+++ b/lib/autotest/general.m4
@@ -429,9 +429,6 @@ m4_divert_text([DEFAULTS],
[
# Whether to enable colored test results.
at_color=m4_ifdef([AT_color], [AT_color], [no])
-# List of the tested programs.
-at_tested='m4_ifdef([AT_tested],
- [m4_translit(m4_dquote(m4_defn([AT_tested])), [ ], m4_newline)])'
# As many question marks as there are digits in the last test group number.
# Used to normalize the test group numbers so that `ls' lists them in
# numerical order.
@@ -992,33 +989,7 @@ AS_BOX(m4_defn([AT_TESTSUITE_NAME])[.])
} >&AS_MESSAGE_LOG_FD
m4_divert_pop([TESTS_BEGIN])dnl
-m4_divert_push([PREPARE_TESTS])dnl
-{
- AS_BOX([Tested programs.])
- echo
-} >&AS_MESSAGE_LOG_FD
-
-# Report what programs are being tested.
-for at_program in : `eval echo $at_tested`
-do
- test "$at_program" = : && continue
- case $at_program in
- [[\\/]* | ?:[\\/]* ) $at_program_=$at_program ;;]
- * )
- _AS_PATH_WALK([$PATH], [test -f "$as_dir$at_program" && break])
- at_program_=$as_dir$at_program ;;
- esac
- if test -f "$at_program_"; then
- {
- AS_ECHO(["$at_srcdir/AT_LINE: $at_program_ --version"])
- "$at_program_" --version </dev/null
- echo
- } >&AS_MESSAGE_LOG_FD 2>&1
- else
- AS_ERROR([cannot find $at_program])
- fi
-done
-
+m4_divert_push([TESTS])dnl
{
AS_BOX([Running the tests.])
} >&AS_MESSAGE_LOG_FD
@@ -1026,8 +997,6 @@ done
at_start_date=`date`
at_start_time=`date +%s 2>/dev/null`
AS_ECHO(["$as_me: starting at: $at_start_date"]) >&AS_MESSAGE_LOG_FD
-m4_divert_pop([PREPARE_TESTS])dnl
-m4_divert_push([TESTS])dnl
# Create the master directory if it doesn't already exist.
AS_MKDIR_P(["$at_suite_dir"]) ||
@@ -1794,10 +1763,88 @@ m4_defun([AT_ARG_OPTION_ARG],[_AT_ARG_OPTION([$1],[$2],1,[$3],[$4])])
# versions are logged, and in the case of embedded test suite, they
# must correspond to the version of the package. PATH should be
# already preset so the proper executable will be selected.
-m4_define([AT_TESTED],
+m4_defun([AT_TESTED],
+[m4_require([_AT_TESTED])]dnl
[m4_foreach_w([AT_test], [$1],
[m4_append_uniq([AT_tested], "m4_defn([AT_test])", [ ])])])
+m4_defun([_AT_TESTED],
+[m4_wrap([m4_divert_text([DEFAULTS],
+[# List of the tested programs.
+at_tested='m4_translit(m4_dquote(m4_defn([AT_tested])), [ ], m4_newline)'
+])]dnl
+[m4_divert_text([PREPARE_TESTS],
+[{
+ AS_BOX([Tested programs.])
+ echo
+} >&AS_MESSAGE_LOG_FD
+
+# Report what programs are being tested.
+for at_program in : `eval echo $at_tested`
+do
+ AS_CASE([$at_program],
+ [:], [continue],
+ [[[\\/]* | ?:[\\/]*]], [$at_program_=$at_program],
+ [_AS_PATH_WALK([$PATH], [test -f "$as_dir$at_program" && break])
+ at_program_=$as_dir$at_program])
+
+ if test -f "$at_program_"; then
+ {
+ AS_ECHO(["$at_srcdir/AT_LINE: $at_program_ --version"])
+ "$at_program_" --version </dev/null
+ echo
+ } >&AS_MESSAGE_LOG_FD 2>&1
+ else
+ AS_ERROR([cannot find $at_program])
+ fi
+done
+])])])
+
+
+# AT_PREPARE_TESTS(SHELL-CODE)
+# ----------------------------
+# Execute @var{shell-code} in the main testsuite process,
+# after initializing the test suite and processing command-line options,
+# but before running any tests.
+m4_define([AT_PREPARE_TESTS],
+[m4_divert_once([PREPARE_TESTS],
+[m4_text_box([Prepare for this testsuite.])
+])]dnl
+[m4_divert_text([PREPARE_TESTS], [$1])])
+
+
+# AT_PREPARE_EACH_TEST([SHELL-CODE])
+# ----------------------------------
+# Execute @var{shell-code} in each test group's subshell,
+# at the point of the AT_SETUP that starts each test group.
+m4_define([AT_PREPARE_EACH_TEST],
+[m4_append([AT_prepare_each_test], [$1], [
+])])
+
+
+# AT_TEST_HELPER_FN(NAME, ARGS, DESCRIPTION, CODE)
+# ------------------------------------------------
+# Define a shell function that will be available to the code for each test
+# group. Its name will be ath_fn_NAME, and its body will be CODE.
+#
+# Implementation note: you might think this would use AT_PREPARE_EACH_TEST,
+# but shell functions defined in AT_PREPARE_TESTS *are* (currently) available
+# to test group subshells, and this way the code is only emitted once, not
+# once for each test group.
+m4_define([AT_TEST_HELPER_FN],
+[AS_LITERAL_WORD_IF([$1], [],
+ [m4_fatal([invalid shell function name "$1"])])]dnl
+[m4_ifdef([ATH_fn_$1_defined],
+ [m4_fatal([helper function "$1" defined twice])])]dnl
+[m4_define([ATH_fn_$1_defined])]dnl
+[AT_PREPARE_TESTS([
+AS_FUNCTION_DESCRIBE([ath_fn_$1], [$2], [$3])
+ath_fn_$1 ()
+{
+ $4
+}
+])])
+
# AT_COPYRIGHT(TEXT, [FILTER = m4_newline])
# -----------------------------------------
@@ -1837,6 +1884,8 @@ at_fn_group_banner AT_ordinal 'm4_defn([AT_line])' \
"AS_ESCAPE(m4_dquote(m4_defn([AT_description])))" m4_format(["%*s"],
m4_max(0, m4_eval(47 - m4_qlen(m4_defn([AT_description])))), [])m4_if(
AT_banner_ordinal, [0], [], [ AT_banner_ordinal])
+m4_ifset([AT_prepare_each_test], [AT_prepare_each_test
+])dnl
m4_divert_push([TEST_SCRIPT])dnl
])
diff --git a/tests/autotest.at b/tests/autotest.at
index 2892b1dd..6b4302c9 100644
--- a/tests/autotest.at
+++ b/tests/autotest.at
@@ -195,6 +195,46 @@ AT_CHECK([echo file2 > file3])
AT_CHECK([cmp file2 file3])
])
+## ----------------------------------------------------------- ##
+## AT_PREPARE_TESTS, AT_PREPARE_EACH_TEST, AT_TEST_HELPER_FN. ##
+## ----------------------------------------------------------- ##
+
+AT_CHECK_AT([AT@&t@_PREPARE_TESTS],
+[[
+AT_INIT([artificial test suite])
+AT_PREPARE_TESTS([FOO=foo; export FOO])
+AT_SETUP([my only test])
+AT_CHECK([test x"$FOO" = xfoo])
+AT_CLEANUP
+]])
+
+AT_CHECK_AT([AT@&t@_PREPARE_EACH_TEST],
+[[
+AT_INIT([artificial test suite])
+AT_PREPARE_EACH_TEST([
+if test -z "$at_test_counter"
+then at_test_counter=1
+else at_test_counter=`expr $at_test_counter + 1`
+fi
+])
+AT_SETUP([test one])
+AT_CHECK([test "$at_test_counter" -eq 1])
+AT_CLEANUP
+AT_SETUP([test two])
+AT_CHECK([test "$at_test_counter" -eq 2])
+AT_CLEANUP
+]])
+
+AT_CHECK_AT([AT@&t@_TEST_HELPER_FN],
+[[
+AT_INIT([artificial test suite])
+AT_TEST_HELPER_FN([helper], [], [], [test x"$][1" = x"$][2"])
+AT_SETUP([my only test])
+AT_CHECK([ath_fn_helper same same])
+AT_CHECK([ath_fn_helper same other], [1])
+AT_CLEANUP
+]])
+
## ------------------ ##
## Empty test suite. ##
@@ -296,6 +336,32 @@ AT_CHECK_AT_SYNTAX([Multiple AT@&t@_INIT],
AT_INIT([repeat])
]], [AT@&t@_INIT: invoked multiple times])
+AT_CHECK_AT_SYNTAX([Invalid AT@&t@_TEST_HELPER_FN (spaces)],
+[[AT_INIT([buggy test suite])
+AT_TEST_HELPER_FN([bad name], [], [], [:])
+AT_SETUP([only test])
+AT_CHECK([:])
+AT_CLEANUP
+]], [invalid shell function name "bad name"])
+
+AT_CHECK_AT_SYNTAX([Invalid AT@&t@_TEST_HELPER_FN (substitutions)],
+[[AT_INIT([buggy test suite])
+AT_TEST_HELPER_FN([variable_${name}], [], [], [:])
+AT_SETUP([only test])
+AT_CHECK([:])
+AT_CLEANUP
+]], [invalid shell function name "variable_${name}"])
+
+AT_CHECK_AT_SYNTAX([Multiple AT@&t@_TEST_HELPER_FN],
+[[AT_INIT([buggy test suite])
+AT_TEST_HELPER_FN([repeated], [], [], [AS_ECHO([repeated 1])])
+# The duplicate check only cares about the name.
+AT_TEST_HELPER_FN([repeated], [args], [desc], [AS_ECHO([repeated 2])])
+AT_SETUP([only test])
+AT_CHECK([:])
+AT_CLEANUP
+]], [helper function "repeated" defined twice])
+
# Check for tested programs. autoconf should only appear once.
AT_CHECK_AT([Tested programs],
[[AT_INIT([programs test suite])
diff --git a/tests/base.at b/tests/base.at
index 6a1d9742..48df3597 100644
--- a/tests/base.at
+++ b/tests/base.at
@@ -393,9 +393,6 @@ AT_CLEANUP
AT_SETUP([AC_CACHE_CHECK])
AT_KEYWORDS([CONFIG_SITE])
-# Don't let a config.site file affect this test.
-AS_UNSET([CONFIG_SITE])
-
AT_DATA([configure.ac],
[[AC_INIT
# m4_define([ac_nothing], [ac_cv_absolutely_nothing])
@@ -669,9 +666,12 @@ cat <&AS@&t@_ORIGINAL_STDIN_FD >&AS@&t@_MESSAGE_FD
AC_OUTPUT
]])
AT_CHECK_AUTOCONF
-AT_CHECK([echo Hello | CONFIG_SITE=/dev/null ./configure $configure_options | grep -v '^configure: '],, [Hello
+AT_CHECK([echo Hello |
+ ./configure $configure_options |
+ grep -v '^configure: '],,
+[Hello
])
-AT_CHECK([echo Hello | CONFIG_SITE=/dev/null ./configure $configure_options --silent])
+AT_CHECK([echo Hello | ./configure $configure_options --silent])
AT_CLEANUP
@@ -758,9 +758,6 @@ AT_CLEANUP
AT_SETUP([configure directories])
-CONFIG_SITE=/dev/null
-export CONFIG_SITE
-
AT_DATA([foo.in],
[[prefix=@prefix@
exec_prefix=@exec_prefix@
diff --git a/tests/compile.at b/tests/compile.at
index c93722b9..9ebe782e 100644
--- a/tests/compile.at
+++ b/tests/compile.at
@@ -175,11 +175,6 @@ AT_CLEANUP
AT_SETUP([AC_LANG_SOURCE example])
-# Set CONFIG_SITE to a nonexistent file, so that there are
-# no worries about configure output caused by sourcing a config.site.
-CONFIG_SITE=no-such-file
-export CONFIG_SITE
-
AT_DATA([configure.ac],
[[# Taken from autoconf.texi:Generating Sources.
# The only change is to not fail if gcc doesn't work.
@@ -221,11 +216,6 @@ AT_CLEANUP
AT_SETUP([AC_LANG_PROGRAM example])
-# Set CONFIG_SITE to a nonexistent file, so that there are
-# no worries about configure output caused by sourcing a config.site.
-CONFIG_SITE=no-such-file
-export CONFIG_SITE
-
AT_DATA([configure.ac],
[[# Taken from autoconf.texi:Generating Sources.
# The only change is to not fail if gcc doesn't work.
diff --git a/tests/local.at b/tests/local.at
index 374e530c..a7fdbb16 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -27,6 +27,22 @@ AT_TESTED([autom4te autoconf autoheader autoupdate autoreconf ifnames])
# Enable colored test output.
AT_COLOR_TESTS
+# Sanitize the environment used for tests.
+AT_PREPARE_TESTS(
+[# These variables should not be inherited from the
+# parent environment.
+AS_UNSET([CONFIG_SITE])
+AS_UNSET([MAKEFLAGS])
+
+# Ensure MAKE is set to a useful value. Unlike the above, we *do*
+# want to inherit this variable from the parent environment and/or
+# our command line.
+: "${MAKE=make}"
+export MAKE
+])
+
+
+
## ---------------- ##
## Utility macros. ##
## ---------------- ##
@@ -334,16 +350,15 @@ m4_define([AT_CHECK_CONFIGURE],
# | '#'=0
# | '$'=6908
#
-m4_define([AT_CHECK_ENV],
-[m4_divert_once([PREPARE_TESTS], [_AT_CHECK_ENV])dnl
-AT_CHECK([at_check_env])])
-m4_define([_AT_CHECK_ENV],
-[AS_FUNCTION_DESCRIBE([at_check_env], [],
+m4_defun([AT_CHECK_ENV],
+[m4_require([_AT_CHECK_ENV])]dnl
+[AT_CHECK([ath_fn_check_env])])
+
+m4_defun([_AT_CHECK_ENV],
+[AT_TEST_HELPER_FN([check_env], [],
[Compare the directory and environment state both before and after a run,
-and return non-zero status if they differ inappropriately.])
-at_check_env ()
-{
-# Compare directory listings.
+and return non-zero status if they differ inappropriately.],
+[# Compare directory listings.
test -f state-ls.before ||
AS_ERROR([state-ls.before not present])
test -f state-ls.after \
@@ -377,7 +392,7 @@ if test -f state-env.before && test -f state-env.after; then
[ALLOCA|GETLOADAVG_LIBS|KMEM_GROUP|NEED_SETGID|POW_LIB],
[AWK|LEX|LEXLIB|LEX_OUTPUT_ROOT|LN_S|M4|MKDIR_P|RANLIB|SET_MAKE|YACC],
[GREP|[EF]GREP|SED],
- [[_@]|.[*#?$].],
+ [[_@]|.[*@%:@?$].],
[argv|ARGC|LINENO|BASH_ARGC|BASH_ARGV|OLDPWD|PIPESTATUS|RANDOM],
[SECONDS|START_TIME|ToD|_AST_FEATURES]))=' \
$act_file ||
@@ -391,7 +406,7 @@ if test -f state-env.before && test -f state-env.after; then
$at_traceon
$grep_failed || $at_diff clean-state-env.before clean-state-env.after
fi
-} [#]at_check_env])
+])])
# AT_CONFIG_CMP(VAR-FILE-A, VAR-FILE-B)
@@ -496,10 +511,7 @@ m4_define([AT_CHECK_AUTOUPDATE],
# an acceptable result, because there are situations where BSD make will
# exit with status 1 but GNU make will instead exit with status 2.
m4_define([AT_CHECK_MAKE],
-[: "${MAKE=make}"
-export MAKE
-unset MAKEFLAGS
-AT_CHECK(
+[AT_CHECK(
m4_if(m4_default([$2], [.]), [.], [],
[cd "$2" && ])[$][MAKE]m4_ifnblank([$1],[ $1])[]m4_if([$3], [1], [[
dnl pacify editors that don't understand sh case: ((
diff --git a/tests/m4sh.at b/tests/m4sh.at
index 633becdd..a330fec4 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -125,9 +125,7 @@ exec sh "@S|@@"
chmod a+x cfg-sh
AT_CAPTURE_FILE([config.log])
-# Export CONFIG_SITE to /dev/null to avoid spurious diffs in expected
-# stdout/stderr.
-AT_CHECK([env CONFIG_SITE=/dev/null CONFIG_SHELL=./cfg-sh ./configure],
+AT_CHECK([env CONFIG_SHELL=./cfg-sh ./configure],
[0],
[[configure: creating ./config.status
]], [])
diff --git a/tests/torture.at b/tests/torture.at
index 6ae6bfdf..002b75d5 100644
--- a/tests/torture.at
+++ b/tests/torture.at
@@ -1463,11 +1463,6 @@ AT_CHECK([[grep '[1-9]\.[0-9]' stdout || exit 77]], [], [ignore])
# It should understand configure.ac.
AT_CHECK([[grep '[^0-9]1\.[01234][^0-9]' stdout && exit 77]], [1], [ignore])
-# Set CONFIG_SITE to a nonexistent file, so that there are
-# no worries about nonstandard values for 'prefix'.
-CONFIG_SITE=no-such-file
-export CONFIG_SITE
-
# The contents of `inner/', and `inner/innermost/'.
AS_MKDIR_P([inner/innermost])