tests: make test runner a script, not a shell function
authorStefano Lattarini <stefano.lattarini@gmail.com>
Sat, 18 Jun 2011 08:26:15 +0000 (10:26 +0200)
committerJim Meyering <meyering@redhat.com>
Sun, 19 Jun 2011 19:57:43 +0000 (21:57 +0200)
This change implements a more correct and idiomatic use of the
features of the Automake-provided 'parallel-tests' harness.
Moreover, this change is required in order for the testsuite to
continue to work with the new testsuite harness that is planned
to be introduced in Automake 1.12 (which, as of the writing date,
is still under development and in alpha state).

* tests/shell-or-perl: New auxiliary script.
* tests/Makefile.am (EXTRA_DIST): Distribute it.
* tests/check.mk (TESTS_ENVIRONMENT): Remove definition of the
`shell_or_perl_' shell function, whose code has been moved in
the new script above (with a few improvements and extensions).
Do not use it to run the test scripts.
(LOG_COMPILER): New, properly invoking `shell-or-perl'.

tests/Makefile.am
tests/check.mk
tests/shell-or-perl [new file with mode: 0644]

index a324dc1..f8fbd38 100644 (file)
@@ -20,6 +20,7 @@ EXTRA_DIST =          \
   other-fs-tmpdir      \
   require-perl         \
   sample-test          \
+  shell-or-perl                \
   $(pr_data)
 
 root_tests =                                   \
index 9db96af..d45c288 100644 (file)
@@ -48,6 +48,16 @@ check-am: .built-programs
             && MAKEFLAGS= $(MAKE) -s built_programs.list)              \
           > $@-t && mv $@-t $@
 
+## `$f' is set by the Automake-generated test harness to the path of the
+## current test script stripped of VPATH components, and is used by the
+## shell-or-perl script to determine the name of the temporary files to be
+## used.  Note that $f is a shell variable, not a make macro, so the use of
+## `$$f' below is correct, and not a typo.
+LOG_COMPILER = \
+  $(SHELL) $(srcdir)/shell-or-perl \
+  --test-name "$$f" --srcdir '$(srcdir)' \
+  --shell '$(SHELL)' --perl '$(PERL)' --
+
 # Note that the first lines are statements.  They ensure that environment
 # variables that can perturb tests are unset or set to expected values.
 # The rest are envvar settings that propagate build-related Makefile
@@ -58,21 +68,6 @@ TESTS_ENVIRONMENT =                          \
   test -d "$$tmp__" && test -w "$$tmp__" || tmp__=.;   \
   . $(srcdir)/envvar-check;                    \
   TMPDIR=$$tmp__; export TMPDIR;               \
-  shell_or_perl_() {                           \
-    if grep '^\#!/usr/bin/perl' "$$1" > /dev/null; then                        \
-      if $(PERL) -e 'use warnings' > /dev/null 2>&1; then              \
-       grep '^\#!/usr/bin/perl -T' "$$1" > /dev/null && T_=T || T_=;   \
-        $(PERL) -w$$T_ -I$(srcdir) -MCoreutils -MCuSkip                        \
-             -M"CuTmpdir qw($$f)" -- "$$1";    \
-      else                                     \
-       echo 1>&2 "$$tst: configure did not find a usable version of Perl," \
-         "so skipping this test";              \
-       (exit 77);                              \
-      fi;                                      \
-    else                                       \
-      $(SHELL) "$$1";                          \
-    fi;                                                \
-  };                                           \
   export                                       \
   VERSION='$(VERSION)'                         \
   LOCALE_FR='$(LOCALE_FR)'                     \
@@ -99,6 +94,6 @@ TESTS_ENVIRONMENT =                           \
   REPLACE_GETCWD=$(REPLACE_GETCWD)             \
   ; test -d /usr/xpg4/bin && PATH='/usr/xpg4/bin$(PATH_SEPARATOR)'"$$PATH"; \
   PATH='$(abs_top_builddir)/src$(PATH_SEPARATOR)'"$$PATH" \
-  ; shell_or_perl_ 9>&2
+  ; 9>&2
 
 VERBOSE = yes
diff --git a/tests/shell-or-perl b/tests/shell-or-perl
new file mode 100644 (file)
index 0000000..08604eb
--- /dev/null
@@ -0,0 +1,111 @@
+#! /bin/sh
+# Run a test script of the coreutils test scripts, picking up the right
+# interpreter (i.e., perl or the shell) and the right flags for it (e.g.,
+# perl `-T' flag for perl scripts that must run in tainted mode).
+#
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# ---------------------------------- #
+#  Readonly variables and functions  #
+# ---------------------------------- #
+
+# Help to avoid typo-related bugs.
+set -u
+
+me=shell-or-perl
+
+error_ ()
+{
+  echo "$me: $*" >&2
+  exit 99
+}
+
+print_help_ ()
+{
+  cat <<EOH
+Usage: $me [--help] [--srcdir DIR] [--shell SHELL-CMD] [--perl PERL-CMD]
+       [--test-name NAME-WITHOUT-VPATH] TEST-SCRIPT [ARGS..]
+EOH
+}
+
+# ---------------- #
+#  Option parsing  #
+# ---------------- #
+
+assign_optarg_to_var='
+  test $# -gt 1 || error_ "option '\''$1'\'' requires an argument"
+  eval "$var=\$2"
+  shift'
+
+srcdir=${srcdir-.}
+cu_PERL=${PERL-perl}
+cu_SHELL=/bin/sh # Getting $SHELL from the environment is dangerous.
+test_name=
+while test $# -gt 0; do
+  var=
+  case $1 in
+    --help) print_help_; exit $?;;
+    --shell) var=cu_SHELL;;
+    --perl) var=cu_PERL;;
+    --srcdir) var=srcdir;;
+    --test-name) var=test_name;;
+    --) shift; break;;
+    -*) error_ "unknown option '$1'";;
+    *) break;;
+  esac
+  test -z "$var" || eval "$assign_optarg_to_var"
+  shift
+done
+
+unset assign_optarg_to_var var
+
+case $# in
+  0) error_ "missing argument";;
+  *) test_script=$1; shift;;
+esac
+
+test -z "$test_name" && test_name=$test_script
+
+# --------------------- #
+#  Run the test script  #
+# --------------------- #
+
+if grep '^#!/usr/bin/perl' "$test_script" >/dev/null; then
+  # The test is a perl script.
+  if $cu_PERL -e 'use warnings' > /dev/null 2>&1; then
+    # Perl is available, see if we must run the test with taint
+    # mode on or not.
+    grep '^#!/usr/bin/perl -T' "$test_script" >/dev/null && T_=T || T_=
+    # Now run it.
+    exec $cu_PERL -w$T_ -I"$srcdir" -MCoreutils -MCuSkip \
+                  -M"CuTmpdir qw($test_name)" \
+                  -- "$test_script" ${1+"$@"}
+  else
+    # Perl is not available, skip the test.
+    echo "$test_name: skip: no usable version of Perl found"
+    exit 77
+  fi
+else
+  # Assume the test is a shell script.
+  exec $cu_SHELL "$test_script" ${1+"$@"}
+fi
+
+# ------------- #
+#  Not reached  #
+# ------------- #
+
+error_ "dead code reached"