Subject: [PATCH 2/2] preproc: enhance and extend tests

From: Peter Rosin <[email-masked]>
Date: Fri, 8 Feb 2013 09:45:26 +0100

From: Stefano Lattarini <[email-masked]>

* t/preproc-demo.sh: New test, a "demo" of how the new pre-processing
feature could be used in a real-world package.
* t/preproc-errmsg.sh: New test, check that error messages remain
useful when the new pre-processing features are involved.
* t/preproc-reldir.sh: Split up ...
* t/preproc-basics.sh, t/preproc-c-compile.sh: ... into these two
tests, with some refactorings, clean-up and enhancements.
* t/list-of-tests.mk: Adjust.

Signed-off-by: Stefano Lattarini <[email-masked]>
---
 t/list-of-tests.mk     |    5 +-
 t/preproc-basics.sh    |  106 +++++++++++++++++++++++
 t/preproc-c-compile.sh |  118 +++++++++++++++++++++++++
 t/preproc-demo.sh      |  222 ++++++++++++++++++++++++++++++++++++++++++++++++
 t/preproc-errmsg.sh    |   75 ++++++++++++++++
 t/preproc-reldir.sh    |  129 ----------------------------
 6 files changed, 525 insertions(+), 130 deletions(-)
 create mode 100755 t/preproc-basics.sh
 create mode 100755 t/preproc-c-compile.sh
 create mode 100755 t/preproc-demo.sh
 create mode 100755 t/preproc-errmsg.sh
 delete mode 100755 t/preproc-reldir.sh

diff --git a/t/list-of-tests.mk b/t/list-of-tests.mk
index 72c99ee..679fe5d 100644
--- a/t/list-of-tests.mk
+++ b/t/list-of-tests.mk
@@ -865,7 +865,10 @@ t/pr401.sh \
 t/pr401b.sh \
 t/pr401c.sh \
 t/prefix.sh \
-t/preproc-reldir.sh \
+t/preproc-basics.sh \
+t/preproc-c-compile.sh \
+t/preproc-demo.sh \
+t/preproc-errmsg.sh \
 t/primary.sh \
 t/primary2.sh \
 t/primary3.sh \
diff --git a/t/preproc-basics.sh b/t/preproc-basics.sh
new file mode 100755
index 0000000..6000d88
--- /dev/null
+++ b/t/preproc-basics.sh
@@ -0,0 +1,106 @@
+#! /bin/sh
+# Copyright (C) 2013 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/>.
+
+# Basic tests for '%...%' preprocessing in included Makefile fragments:
+#   %reldir%        a.k.a.  %D%
+#   %canon_reldir%  a.k.a.  %C%
+
+. test-init.sh
+
+cat >> configure.ac << 'END'
+AC_CONFIG_FILES([zot/Makefile])
+AC_OUTPUT
+END
+
+mkdir foo foo/bar foo/foobar zot
+
+cat > Makefile.am << 'END'
+include $(top_srcdir)/foo/local.mk
+include $(srcdir)/foo/foobar/local.mk
+include local.mk
+END
+
+cat > zot/Makefile.am << 'END'
+include $(top_srcdir)/zot/local.mk
+
+## Check that '%canon_reldir%' doesn't remain overridden
+## by the previous include.
+%canon_reldir%_zot_whoami:
+	echo "I am %reldir%/Makefile.am" >$@
+
+include $(top_srcdir)/top.mk
+include ../reltop.mk
+END
+
+cat > local.mk << 'END'
+%canon_reldir%_whoami:
+	echo "I am %reldir%/local.mk" >$@
+END
+
+cat > top.mk << 'END'
+%canon_reldir%_top_whoami:
+	echo "I am %reldir%/top.mk" >$@
+END
+
+cat > reltop.mk << 'END'
+%C%_reltop_whoami:
+	echo "I am %D%/reltop.mk" >$@
+END
+
+cp local.mk foo
+cp local.mk foo/bar
+cp local.mk foo/foobar
+cp local.mk zot
+
+cat >> foo/local.mk << 'END'
+include %reldir%/bar/local.mk
+## Check that '%canon_reldir%' doesn't remain overridden by the
+## previous include.  The duplicated checks are done to ensure that
+## Automake substitutes all pre-processing occurrences on a line,
+## not just the first one.
+test-%reldir%:
+	test '%reldir%'       = foo  &&  test '%reldir%' = foo
+	test '%D%'            = foo  &&  test '%D%'      = foo
+	test '%canon_reldir%' = foo  &&  test '%C%'      = foo
+END
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+./configure
+
+check ()
+{
+  test $# -eq 2 || fatal_ "made_into(): bad usage"
+  target=$1 contents=$2
+  rm -f "$target" \
+   && $MAKE "$target" \
+   && test x"$(cat "$target")" = x"$contents"
+}
+
+check whoami "I am local.mk"
+check foo_whoami "I am foo/local.mk"
+check foo_bar_whoami "I am foo/bar/local.mk"
+check foo_foobar_whoami "I am foo/foobar/local.mk"
+$MAKE test-foo
+
+cd zot
+check whoami "I am local.mk"
+check ___top_whoami "I am ../top.mk"
+check ___reltop_whoami "I am ../reltop.mk"
+check zot_whoami "I am Makefile.am"
+
+:
diff --git a/t/preproc-c-compile.sh b/t/preproc-c-compile.sh
new file mode 100755
index 0000000..79e9325
--- /dev/null
+++ b/t/preproc-c-compile.sh
@@ -0,0 +1,118 @@
+#! /bin/sh
+# Copyright (C) 2013 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/>.
+
+# Test pre-processing substitutions '%reldir%' and '%canon_reldir%'
+# with C compilation and subdir objects.
+
+require=cc
+. test-init.sh
+
+cat >> configure.ac << 'END'
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_CONFIG_FILES([zot/Makefile])
+AC_OUTPUT
+END
+
+mkdir foo
+mkdir foo/bar
+mkdir foo/foobar
+mkdir zot
+
+cat > Makefile.am << 'END'
+AUTOMAKE_OPTIONS = subdir-objects
+SUBDIRS = zot
+bin_PROGRAMS =
+
+include $(top_srcdir)/foo/local.mk
+include $(srcdir)/foo/foobar/local.mk
+include local.mk
+
+check-local:
+	is $(bin_PROGRAMS) == \
+	  foo/mumble2$(EXEEXT) \
+	  foo/bar/mumble$(EXEEXT) \
+	  foo/foobar/mumble$(EXEEXT) \
+	  mumble$(EXEEXT)
+	test '$(mumble_SOURCES)' = one.c
+	test '$(foo_mumble2_SOURCES)' = foo/one.c
+	test '$(foo_bar_mumble_SOURCES)' = foo/bar/one.c
+	test '$(foo_foobar_mumble_SOURCES)' = foo/foobar/one.c
+	test -f mumble$(EXEEXT)
+	test -f foo/mumble2$(EXEEXT)
+	test -f foo/bar/mumble$(EXEEXT)
+	test -f foo/foobar/mumble$(EXEEXT)
+	test -f zot/mumble$(EXEEXT)
+	: Test some of the object files too.
+	test -f one.$(OBJEXT)
+	test -f foo/foobar/one.$(OBJEXT)
+	test -f zot/one.$(OBJEXT)
+END
+
+cat > zot/Makefile.am << 'END'
+AUTOMAKE_OPTIONS = subdir-objects
+bin_PROGRAMS =
+include $(top_srcdir)/zot/local.mk
+
+test:
+	test '$(bin_PROGRAMS)' == mumble$(EXEEXT)
+	test '$(mumble_SOURCES)' = one.c
+check-local: test
+END
+
+cat > local.mk << 'END'
+bin_PROGRAMS += %reldir%/mumble
+%canon_reldir%_mumble_SOURCES = %reldir%/one.c
+END
+
+echo 'int main (void) { return 0; }' > one.c
+
+sed 's/mumble/mumble2/' local.mk > foo/local.mk
+cp local.mk foo/bar
+cp local.mk foo/foobar
+cp local.mk zot
+echo "include %reldir%/bar/local.mk" >> foo/local.mk
+
+cp one.c foo
+cp one.c foo/bar
+cp one.c foo/foobar
+cp one.c zot
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+./configure
+
+$MAKE
+$MAKE check-local
+if ! cross_compiling; then
+  ./mumble
+  ./foo/mumble2
+  ./foo/bar/mumble
+  ./foo/foobar/mumble
+  ./zot/mumble
+fi
+
+(cd zot && $MAKE test)
+
+# GNU install refuses to override a just-installed file; since we
+# have plenty of 'mumble' dummy programs to install in the same
+# location, such "overridden installations" are not a problem for
+# us, so just force the use the 'install-sh' script
+ac_cv_path_install=$(pwd)/install-sh; export ac_cv_path_install
+$MAKE distcheck
+
+:
diff --git a/t/preproc-demo.sh b/t/preproc-demo.sh
new file mode 100755
index 0000000..f8d1e25
--- /dev/null
+++ b/t/preproc-demo.sh
@@ -0,0 +1,222 @@
+#! /bin/sh
+# Copyright (C) 2013 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/>.
+
+# Demo of a package using pre-processing substitutions '%reldir%' and
+# '%canon_reldir%', and their respective shorthands '%D%' and '%C%'.
+
+am_create_testdir=empty
+required=cc
+. test-init.sh
+
+if cross_compiling; then
+  WE_ARE_CROSS_COMPILING=yes
+else
+  WE_ARE_CROSS_COMPILING=no
+fi
+export WE_ARE_CROSS_COMPILING
+
+cat > configure.ac << 'END'
+AC_INIT([GNU Demo], [0.7], [[email-masked]])
+AC_CONFIG_AUX_DIR([build-aux])
+AM_INIT_AUTOMAKE([1.12.6 foreign subdir-objects -Wall])
+AM_CONDITIONAL([NATIVE_BUILD], [test $WE_ARE_CROSS_COMPILING != yes])
+AC_CONFIG_FILES([Makefile])
+AC_PROG_CC
+AM_PROG_CC_C_O
+AM_PROG_AR
+AC_PROG_RANLIB
+AC_OUTPUT
+END
+
+mkdir build-aux lib lib/tests src tests
+
+## Top level.
+
+cat > Makefile.am << 'END'
+bin_PROGRAMS =
+check_PROGRAMS =
+noinst_LIBRARIES =
+AM_CPPFLAGS =
+AM_TESTS_ENVIRONMENT =
+CLEANFILES =
+EXTRA_DIST =
+LDADD =
+TESTS =
+XFAIL_TESTS =
+
+include $(srcdir)/src/progs.am
+include $(srcdir)/lib/gnulib.am
+include $(srcdir)/tests/check.am
+END
+
+## Src subdir.
+
+cat > src/progs.am <<'END'
+bin_PROGRAMS += %reldir%/hello
+
+bin_PROGRAMS += %D%/goodbye
+%canon_reldir%_goodbye_SOURCES = %D%/hello.c
+%C%_goodbye_CPPFLAGS = $(AM_CPPFLAGS) -DGREETINGS='"Goodbye"'
+
+# The testsuite should have access to our built programs.
+AM_TESTS_ENVIRONMENT += \
+  PATH='$(abs_builddir)/%reldir%':$$PATH; \
+  export PATH;
+END
+
+cat > src/hello.c <<'END'
+#include "safe-print.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef GREETINGS
+#  define GREETINGS "Hello"
+#endif
+
+int
+main (void)
+{
+  safe_print (stdout, GREETINGS ", World!\n");
+  exit (EXIT_SUCCESS);
+}
+END
+
+## Lib subdir.
+
+cat > lib/gnulib.am << 'END'
+noinst_LIBRARIES += %D%/libgnu.a
+
+AM_CPPFLAGS += -I%D% -I$(top_srcdir)/%D%
+LDADD += $(noinst_LIBRARIES)
+
+%C%_libgnu_a_SOURCES = \
+  %D%/safe-print.c \
+  %D%/safe-print.h
+
+if NATIVE_BUILD
+include %D%/tests/gnulib-check.am
+endif
+END
+
+cat > lib/safe-print.c <<'END'
+#include "safe-print.h"
+#include <string.h>
+#include <stdlib.h>
+
+void
+safe_print (FILE *fp, const char * str)
+{
+  if (fprintf (fp, "%s", str) != strlen (str)
+       || fflush (fp) != 0 || ferror (fp))
+    {
+      fprintf (stderr, "I/O error\n");
+      exit (EXIT_FAILURE);
+    }
+}
+
+END
+
+cat > lib/safe-print.h <<'END'
+#include <stdio.h>
+void safe_print (FILE *, const char *);
+END
+
+## Lib/Tests (sub)subdir.
+
+cat > lib/tests/gnulib-check.am <<'END'
+check_PROGRAMS += %D%/safe-print-test
+TESTS += $(check_PROGRAMS)
+XFAIL_TESTS += %D%/safe-print-test
+END
+
+cat > lib/tests/safe-print-test.c <<'END'
+#include "safe-print.h"
+int
+main (void)
+{
+  FILE *fp;
+  if ((fp = fopen ("/dev/full", "w")) == NULL)
+    return 77;
+  safe_print (fp, "dummy\n");
+  return 0;
+}
+END
+
+## Tests subdir.
+
+cat > tests/check.am <<'END'
+TEST_EXTENSIONS = .sh
+SH_LOG_COMPILER = $(SHELL)
+
+TESTS += %D%/hello.sh
+EXTRA_DIST += %D%/hello.sh
+
+TESTS += %D%/goodbye.sh
+CLEANFILES += %D%/goodbye.sh
+%D%/goodbye.sh: %D%/hello.sh
+	$(MKDIR_P) %D%
+	rm -f $@ $@-t
+	sed -e 's/hello/goodbye/' \
+	    -e 's/Hello/Goodbye/' \
+          < $(srcdir)/%D%/hello.sh >$@-t
+	chmod a-w,a+x $@-t && mv -f $@-t $@
+END
+
+cat > tests/hello.sh <<'END'
+#!/bin/sh
+set -x -e
+if test "$WE_ARE_CROSS_COMPILING" = yes; then
+  echo Skipping: cannot run in cross-compilation mode
+  exit 77
+else
+  hello || exit 1
+  test "`hello`" = 'Hello, World!' || exit 1
+fi
+END
+
+## Go.
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE --add-missing --copy
+test ! -e compile
+test -f build-aux/compile
+
+./configure
+
+$MAKE
+
+$MAKE check >stdout || { cat stdout; exit 1; }
+cat stdout
+cat tests/hello.log
+cat tests/goodbye.log
+if cross_compiling; then
+  test ! -e lib/tests/safe-print-test.log
+  count_test_results total=2 pass=0 fail=0 xpass=0 xfail=0 skip=2 error=0
+else
+  if test -c /dev/full && test -w /dev/full; then
+    s=0 x=1
+    grep "I/O error" lib/tests/safe-print-test.log
+  else
+    cat lib/tests/safe-print-test.log
+    s=1 x=0
+  fi
+  count_test_results total=3 pass=2 fail=0 xpass=0 xfail=$x skip=$s error=0
+fi
+
+$MAKE distcheck
+
+:
diff --git a/t/preproc-errmsg.sh b/t/preproc-errmsg.sh
new file mode 100755
index 0000000..d7cf488
--- /dev/null
+++ b/t/preproc-errmsg.sh
@@ -0,0 +1,75 @@
+#! /bin/sh
+# Copyright (C) 2013 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/>.
+
+# Tests error messages when '%reldir%' and '%canon_reldir%' substitutions
+# (and their shorthands '%D%' and '%C%') are involved.
+
+. test-init.sh
+
+cat >> configure.ac <<'END'
+AC_PROG_CC
+AC_PROG_RANLIB
+AM_PROG_AR
+END
+
+: > ar-lib
+
+mkdir sub sub/sub2
+
+cat > Makefile.am <<'END'
+%canon_reldir%_x1_SOURCES = bar.c
+include sub/local.mk
+END
+
+cat > sub/local.mk <<'END'
+AUTOMAKE_OPTIONS = -Wno-extra-portability
+include %D%/sub2/more.mk
+noinst_LIBRARIES = %reldir%-one.a %D%-two.a
+%C%_x2_SOURCES = foo.c
+END
+
+cat > sub/sub2/more.mk <<'END'
+%C%_UNDEFINED +=
+END
+
+$ACLOCAL
+AUTOMAKE_fails
+
+cat > expected << 'END'
+sub/sub2/more.mk:1: sub_sub2_UNDEFINED must be set with '=' before using '+='
+Makefile.am:2: 'sub/local.mk' included from here
+sub/local.mk:2: 'sub/sub2/more.mk' included from here
+sub/local.mk:3: 'sub-one.a' is not a standard library name
+sub/local.mk:3: did you mean 'libsub-one.a'?
+Makefile.am:2: 'sub/local.mk' included from here
+sub/local.mk:3: 'sub-two.a' is not a standard library name
+sub/local.mk:3: did you mean 'libsub-two.a'?
+Makefile.am:2: 'sub/local.mk' included from here
+Makefile.am:1: variable 'x1_SOURCES' is defined but no program or
+Makefile.am:1: library has 'x1' as canonical name (possible typo)
+sub/local.mk:4: variable 'sub_x2_SOURCES' is defined but no program or
+sub/local.mk:4: library has 'sub_x2' as canonical name (possible typo)
+Makefile.am:2: 'sub/local.mk' included from here
+END
+
+sed -e '/warnings are treated as errors/d' \
+    -e 's/: warning:/:/' -e 's/: error:/:/' \
+    -e 's/  */ /g' \
+  <stderr >obtained
+
+diff expected obtained
+
+:
diff --git a/t/preproc-reldir.sh b/t/preproc-reldir.sh
deleted file mode 100755
index ab443df..0000000
--- a/t/preproc-reldir.sh
+++ /dev/null
@@ -1,129 +0,0 @@
-#! /bin/sh
-# Copyright (C) 2013 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/>.
-
-# Test %reldir% and %canon_reldir%.
-
-. test-init.sh
-
-cat >> configure.ac << 'END'
-AC_PROG_CC
-AM_PROG_CC_C_O
-AC_CONFIG_FILES([zot/Makefile])
-AC_OUTPUT
-END
-
-mkdir foo
-mkdir foo/bar
-mkdir foo/foobar
-mkdir zot
-
-cat > Makefile.am << 'END'
-AUTOMAKE_OPTIONS = subdir-objects
-bin_PROGRAMS =
-include $(top_srcdir)/foo/local.mk
-include $(srcdir)/foo/foobar/local.mk
-include local.mk
-END
-
-cat > zot/Makefile.am << 'END'
-AUTOMAKE_OPTIONS = subdir-objects
-bin_PROGRAMS =
-include $(top_srcdir)/zot/local.mk
-include $(top_srcdir)/top.mk
-include ../reltop.mk
-END
-
-cat > local.mk << 'END'
-%canon_reldir%_whoami:
-	@echo "I am %reldir%/local.mk"
-
-bin_PROGRAMS += %reldir%/mumble
-%canon_reldir%_mumble_SOURCES = %reldir%/one.c
-END
-
-cat > top.mk << 'END'
-%canon_reldir%_top_whoami:
-	@echo "I am %reldir%/top.mk"
-
-bin_PROGRAMS += %D%/scream
-%C%_scream_SOURCES = %D%/two.c
-END
-
-cat > reltop.mk << 'END'
-%C%_reltop_whoami:
-	@echo "I am %D%/reltop.mk"
-
-bin_PROGRAMS += %reldir%/sigh
-%canon_reldir%_sigh_SOURCES = %reldir%/three.c
-END
-
-cat > one.c << 'END'
-int main(void) { return 0; }
-END
-
-cp local.mk foo
-cp local.mk foo/bar
-cp local.mk foo/foobar
-cp local.mk zot
-echo "include %reldir%/bar/local.mk" >> foo/local.mk
-
-cp one.c foo
-cp one.c foo/bar
-cp one.c foo/foobar
-cp one.c zot
-cp one.c two.c
-cp one.c three.c
-
-$ACLOCAL
-$AUTOCONF
-$AUTOMAKE -a
-./configure
-
-$MAKE whoami >output 2>&1 || { cat output; exit 1; }
-cat output
-grep "I am local.mk" output
-$MAKE foo_whoami >output 2>&1 || { cat output; exit 1; }
-cat output
-grep "I am foo/local.mk" output
-$MAKE foo_bar_whoami >output 2>&1 || { cat output; exit 1; }
-cat output
-grep "I am foo/bar/local.mk" output
-$MAKE foo_foobar_whoami >output 2>&1 || { cat output; exit 1; }
-cat output
-grep "I am foo/foobar/local.mk" output
-
-$MAKE
-./mumble
-foo/mumble
-foo/bar/mumble
-foo/foobar/mumble
-
-cd zot
-
-$MAKE ___top_whoami >output 2>&1 || { cat output; exit 1; }
-cat output
-grep "I am ../top.mk" output
-$MAKE ___reltop_whoami >output 2>&1 || { cat output; exit 1; }
-cat output
-grep "I am ../reltop.mk" output
-$MAKE whoami >output 2>&1 || { cat output; exit 1; }
-cat output
-grep "I am local.mk" output
-
-$MAKE
-./mumble
-../scream
-../sigh
-- 
1.7.9