Subject: bug#10427: New testsuite driver and extra trailing backslash in recipes (was: Re: bug#10427: coreutils-8.14.116-1e18d: testsuite failures on NetBSD 5.1)

From: Stefano Lattarini <[email-masked]>
Date: Thu, 05 Jan 2012 13:47:36 +0100

[adding bug-automake in CC:]

Reference: <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=10427#8>

Hi Paul, thanks for the report and diagnosis.

On 01/05/2012 10:00 AM, Paul Eggert wrote:
> I'm sending this to bug-automake because I think it's an automake
> issue.  However, the problem causes the latest coreutils snapshot
> to fail to build, so I'm CC'ing to bug-coreutils.
> 
>> On 01/03/2012 06:10 PM, Jim Meyering wrote:
>>> FYI, here's a snapshot of what will soon be coreutils-8.15,
>>> expected on Thursday or Friday.
>>>
>>> coreutils snapshot:
>>>   http://meyering.net/cu/coreutils-ss.tar.xz      5.2 MB
>>>   http://meyering.net/cu/coreutils-ss.tar.xz.sig
>>>   http://meyering.net/cu/coreutils-8.14.116-1e18d.tar.xz
> 
> This snapshot doesn't build on Solaris 8 (sparc) with native tools,
> for a couple of reasons.  I don't expect Solaris 8 is an active
> porting target any more, but these problems could well happen on
> active targets.
>
I agree that this issues might prove a liability on some modern systems
too, and that we should fix them.  (BTW, if you feel like running the
whole automake testsuite on Solaris 8 to find more similar issues, I
wouldn't object ;-)

> First, there's code like this in tests/Makefile.in:
> 
> 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) "$$tst" \
> 	$(AM_TESTS_FD_REDIRECT)
> 
> This code is generated by Automake.  Here, AM_TESTS_FD_REDIRECT
> is empty.  Solaris 8 'make' executes the above as follows:
> 
>    bash -c '[expansion of previous line] \'
> 
> and Bash complains about a syntax error with the trailing backslash.
>
I can reproduce this with bash 2.05b on Debian.

Attached is a fix for this bug, with a testcase.  The test is quite
elaborate and somewhat hacky, but I'd rather keep it anyway, since
I'm planning to refactor it into an external helper script that will
be used to guard against other unwanted trailing `\' in *all* the
make recipes run in the automake testsuite (that's for a follow-up
patch obviously).

> How about changing Automake to generate something like this instead,
> with no backslash-newline?
> 
> 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) "$$tst" $(AM_TESTS_FD_REDIRECT)
> 
> This should avoid the problem.
>
I ended up breaking the line in a "safer" place instead.  It is enough
to fix the bug.

Regards,
  Stefano
>From 7902852607b596d1a341501d1823da826fb4b4ed Mon Sep 17 00:00:00 2001
Message-Id: <790285260[email-masked]>
From: Stefano Lattarini <[email-masked]>
Date: Thu, 5 Jan 2012 13:41:13 +0100
Subject: [PATCH] parallel-tests: avoid trailing backslashes in make recipes

The new testsuite-harness could generate recipes with a trailing
backslash character (possibly followed by blank characters only),
in the very common case where the user hadn't defined the special
$(AM_TESTS_FD_REDIRECT) variable.  This caused spurious syntax
errors with at least older bash versions (e.g., bash 2.05b), and
could be potentially unportable to other weaker shells.

See automake bug#xxx:
  <xxx>
and coreutils bug#10427:
  <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=10427#8>

* lib/am/check2.am: Rework line breaks so that no backslash can
be at the end of a line.
* tests/parallel-tests-trailing-bslash.test: New test.
* tests/list-of-tests.mk: Add it.
---
 lib/am/check2.am                          |   10 +-
 tests/list-of-tests.mk                    |    1 +
 tests/parallel-tests-trailing-bslash.test |  115 +++++++++++++++++++++++++++++
 3 files changed, 121 insertions(+), 5 deletions(-)
 create mode 100755 tests/parallel-tests-trailing-bslash.test

diff --git a/lib/am/check2.am b/lib/am/check2.am
index ad0a4aa..9a0fe9d 100644
--- a/lib/am/check2.am
+++ b/lib/am/check2.am
@@ -1,5 +1,5 @@
 ## automake - create Makefile.in from Makefile.am
-## Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
+## Copyright (C) 2008, 2009, 2011, 2012 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
@@ -19,8 +19,8 @@
 ?!GENERIC?%OBJ%: %SOURCE%
 	@p='%SOURCE%'; $(am__check_pre) %DRIVER% --test-name "$$f" \
 	--log-file '%BASE%.log' --trs-file '%BASE%.trs' \
-	$(am__common_driver_flags) %DRIVER_FLAGS% -- %COMPILE% "$$tst" \
-	$(AM_TESTS_FD_REDIRECT)
+	$(am__common_driver_flags) %DRIVER_FLAGS% -- %COMPILE% \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 
 ## If no programs are built in this package, then this rule is removed
 ## at automake time.  Otherwise, %am__EXEEXT% expands to a configure time
@@ -30,6 +30,6 @@ if %am__EXEEXT%
 ?GENERIC?%EXT%$(EXEEXT).log:
 	@p='%SOURCE%'; $(am__check_pre) %DRIVER% --test-name "$$f" \
 	--log-file '%BASE%.log' --trs-file '%BASE%.trs' \
-	$(am__common_driver_flags) %DRIVER_FLAGS% -- %COMPILE% "$$tst" \
-	$(AM_TESTS_FD_REDIRECT)
+	$(am__common_driver_flags) %DRIVER_FLAGS% -- %COMPILE% \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 endif %am__EXEEXT%
diff --git a/tests/list-of-tests.mk b/tests/list-of-tests.mk
index 8b4f2ca..dbadfdc 100644
--- a/tests/list-of-tests.mk
+++ b/tests/list-of-tests.mk
@@ -709,6 +709,7 @@ parallel-tests-no-spurious-summary.test \
 parallel-tests-exit-statuses.test \
 parallel-tests-console-output.test \
 parallel-tests-once.test \
+parallel-tests-trailing-bslash.test \
 tests-environment.test \
 am-tests-environment.test \
 tests-environment-backcompat.test \
diff --git a/tests/parallel-tests-trailing-bslash.test b/tests/parallel-tests-trailing-bslash.test
new file mode 100755
index 0000000..cd15600
--- /dev/null
+++ b/tests/parallel-tests-trailing-bslash.test
@@ -0,0 +1,115 @@
+#! /bin/sh
+# Copyright (C) 2012 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 2, 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/>.
+
+# Check that the new testsuite-harness do not generate recipes that can
+# have a trailing `\', since that can cause spurious syntax errors with
+# older bash versions (e.g., bash 2.05b).
+# See automake bug#xxx.
+
+am_parallel_tests=yes
+. ./defs || Exit 1
+
+echo AC_OUTPUT >> configure.in
+
+cat > Makefile.am <<'END'
+TESTS = foo.test
+EXTRA_DIST = $(TESTS)
+am__backslash = \\ # foo
+.PHONY: bad-recipe
+bad-recipe:
+	@printf '%s\n' $(am__backslash)
+END
+
+cat > foo.test <<'END'
+#!/bin/sh
+exit 0
+END
+chmod +x foo.test
+
+am__SHELL=$SHELL; export am__SHELL
+am__PERL=$PERL; export am__PERL
+
+cat > my-shell <<'END'
+#!/bin/sh -e
+set -u
+tab='	'
+nl='
+'
+am__shell_flags=
+am__shell_command=; unset am__shell_command
+while test $# -gt 0; do
+  case $1 in
+    # If the shell is invoked by make e.g. as "sh -ec" (seen on
+    # GNU make in POSIX mode) or "sh -ce" (seen on Solaris make).
+    -*c*)
+        flg=`echo x"$1" | sed -e 's/^x-//' -e 's/c//g'`
+        if test x"$flg" != x; then
+          am__shell_flags="$am__shell_flags -$flg"
+        fi
+        am__shell_command=$2
+        shift
+        ;;
+    -?*)
+        am__shell_flags="$am__shell_flags $1"
+        ;;
+      *)
+        break
+        ;;
+  esac
+  shift
+done
+if test x${am__shell_command+"set"} != x"set"; then
+  # Some make implementations, like *BSD's, pass the recipes to the shell
+  # through its standard input.  Trying to run our extra checks in this
+  # case would be too tricky, so we just skip them.
+  exec $am__SHELL $am__shell_flags ${1+"$@"}
+else
+  am__tweaked_shell_command=`printf '%s\n' "$am__shell_command" \
+    | tr -d " $tab$nl"`
+  case ${am__tweaked_shell_command-} in
+    *\\)
+      echo "my-shell: recipe ends with backslash character" >&2
+      printf '%s\n' "=== BEGIN recipe" >&2
+      printf '%s\n' "${am__shell_command-}" >&2
+      printf '%s\n' "=== END recipe" >&2
+      exit 99
+      ;;
+  esac
+  exec $am__SHELL $am__shell_flags -c "$am__shell_command" ${1+"$@"}
+fi
+END
+chmod a+x my-shell
+
+cat my-shell
+
+CONFIG_SHELL=`pwd`/my-shell; export CONFIG_SHELL
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE -a
+
+./configure CONFIG_SHELL="$CONFIG_SHELL"
+
+# Sanity check.
+st=0
+$MAKE bad-recipe 2>stderr && st=1
+cat stderr >&2
+$FGREP "my-shell: recipe ends with backslash character" stderr || st=1
+test $st -eq 0 || skip_ "can't catch trailing backslashes in make recipes"
+
+$MAKE check
+
+:
-- 
1.7.7.3