summaryrefslogtreecommitdiff
path: root/gen-testsuite-part
diff options
context:
space:
mode:
authorStefano Lattarini <stefano.lattarini@gmail.com>2012-04-06 15:20:54 +0200
committerStefano Lattarini <stefano.lattarini@gmail.com>2012-04-06 21:29:31 +0200
commit8e02441b00db75f21455edc92191e64cab19b031 (patch)
tree66d045b7a857d169f5d83be0a5ac526fad5102a8 /gen-testsuite-part
parent8a5096d150cf9803b8963768b7366cd68edcce03 (diff)
downloadautomake-8e02441b00db75f21455edc92191e64cab19b031.tar.gz
maint: no more make recursion in Automake's build system
We finally merge testsuite-related part of the Automake build system with the top-level one. See also yesterday's commit 'v1.11-2124-ga4b0f4b', "maint: remove most recursion in automake's own build system". * t/gen-testsuite-part: Move ... * gen-testsuite-part: ... here, with required adjustments. * t/defs-static.in: Move ... * defs-static.in: ... here, with required adjustments. In particular ... ($testsrcdir, $testbuilddir): Removed. ($top_testsrcdir): Renamed ... ($am_top_srcdir): ... to this. ($top_testbuilddir): Renamed ... ($am_top_builddir): ... to this. * t/defs: Move ... * defs: ... here, and adjust as required. * t/Makefile.am: Merge ... * Makefile.am: ... in here, with related adjustments and simplifications. * bootstrap: Adjust as required. * syntax-checks.mk: Likewise. * .gitignore: Likewise. * t/ax/tap-setup.sh: Likewise. * t/get-sysconf.sh: Likewise. * t/help-multilib.sh: Likewise. * t/multlib.sh: Likewise. * t/parallel-tests2.sh: Likewise. * t/self-check-cleanup.tap: Likewise. * t/self-check-exit.tap: Likewise. * t/self-check-dir.tap: Likewise. * t/self-check-explicit-skips.sh: Likewise. * t/self-check-reexec.tap: Likewise. * t/self-check-sanity.sh: Likewise. * t/yacc-d-cxx.sh: Likewise. Signed-off-by: Stefano Lattarini <stefano.lattarini@gmail.com>
Diffstat (limited to 'gen-testsuite-part')
-rwxr-xr-xgen-testsuite-part415
1 files changed, 415 insertions, 0 deletions
diff --git a/gen-testsuite-part b/gen-testsuite-part
new file mode 100755
index 000000000..a2db2d30b
--- /dev/null
+++ b/gen-testsuite-part
@@ -0,0 +1,415 @@
+#! /usr/bin/env perl
+# Automatically compute some dependencies for the hand-written tests
+# of the Automake testsuite. Also, automatically generate some more
+# tests from them (for particular cases/setups only).
+
+# Copyright (C) 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
+# 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/>.
+
+#--------------------------------------------------------------------------
+
+use warnings FATAL => "all";
+use strict;
+use File::Basename ();
+use constant TRUE => 1;
+use constant FALSE => 0;
+
+my $me = File::Basename::basename $0;
+
+# For use in VPATH builds.
+my $srcdir = ".";
+
+#--------------------------------------------------------------------------
+
+sub unindent ($)
+{
+ my $text = shift;
+ $text =~ /^(\s*)/;
+ my $indentation = $1;
+ $text =~ s/^$indentation//gm;
+ return $text;
+}
+
+sub atomic_write ($$;$)
+{
+ my ($outfile, $func) = (shift, shift);
+ my $perms = @_ > 0 ? shift : 0777;
+ my $tmpfile = "$outfile-t";
+ foreach my $f ($outfile, $tmpfile)
+ {
+ unlink $f or die "$me: cannot unlink '$f': $!\n"
+ if -e $f;
+ }
+ open (my $fh, ">$tmpfile")
+ or die "$me: can't write to '$tmpfile': $!\n";
+ $func->($fh);
+ close $fh
+ or die "$me: closing '$tmpfile': $!\n";
+ chmod ($perms & ~umask, $tmpfile)
+ or die "$me: cannot change perms for '$tmpfile': $!\n";
+ rename ($tmpfile, $outfile)
+ or die "$me: renaming '$tmpfile' -> '$outfile: $!\n'";
+}
+
+sub line_match ($$)
+{
+ my ($re, $file) = (shift, shift);
+ # Try both builddir and srcdir, with builddir first, to play nice
+ # with VPATH builds.
+ open (FH, "<$file") or open (FH, "<$srcdir/$file")
+ or die "$me: cannot open file '$file': $!\n";
+ my $ret = 0;
+ while (defined (my $line = <FH>))
+ {
+ if ($line =~ $re)
+ {
+ $ret = 1;
+ last;
+ }
+ }
+ close FH or die "$me: cannot close file '$file': $!\n";
+ return $ret;
+}
+
+sub write_wrapper_script ($$$)
+{
+ my ($file_handle, $wrapped_test, $shell_setup_code, $creator_name) = @_;
+ # FIXME: we use some creative quoting in the generated scripts,
+ # FIXME: to please maintainer-check.
+ print $file_handle unindent <<EOF;
+ #! /bin/sh
+ # This file has been automatically generated. DO NOT EDIT BY HAND!
+ . ./defs-static || exit '99';
+ $shell_setup_code
+ # In the spirit of VPATH, we prefer a test in the build tree
+ # over one in the source tree.
+ for dir in . "\$am_top_srcdir"; do
+ if test -f "\$dir/$wrapped_test"; then
+ echo "\$0: will source \$dir/$wrapped_test"
+ . "\$dir/$wrapped_test"; exit "\$?"
+ fi
+ done
+ echo "\$0: cannot find wrapped test '$wrapped_test'" >&2
+ exit '99'
+EOF
+}
+
+sub get_list_of_tests ()
+{
+ my $make = defined $ENV{MAKE} ? $ENV{MAKE} : "make";
+ # Unset MAKEFLAGS, for when we are called from make itself.
+ my $cmd = "MAKEFLAGS= && unset MAKEFLAGS && cd '$srcdir' && "
+ . "$make -s -f t/list-of-tests.mk print-list-of-tests";
+ my @tests_list = split /\s+/, `$cmd`;
+ die "$me: cannot get list of tests\n" unless $? == 0 && @tests_list;
+ my $ok = 1;
+ foreach my $test (@tests_list)
+ {
+ # Respect VPATH builds.
+ next if -f $test || -f "$srcdir/$test";
+ warn "$me: test '$test' not found\n";
+ $ok = 0;
+ }
+ die "$me: some test scripts not found\n" if !$ok;
+ return @tests_list;
+}
+
+sub parse_options (@)
+{
+ use Getopt::Long qw/GetOptions/;
+ local @ARGV = @_;
+ GetOptions ('srcdir=s' => \$srcdir) or die "$me: usage error\n";
+ die "$me: too many arguments\n" if @ARGV > 0;
+ die "$me: srcdir '$srcdir': not a directory\n" unless -d $srcdir;
+}
+
+#--------------------------------------------------------------------------
+
+# Where testsuite-related helper scripts, data files and shell libraries
+# are placed. Relative to the 't/' subdirectory.
+my $auxdir = "ax";
+
+my %deps_extractor =
+ (
+ libtool_macros =>
+ {
+ line_matcher => qr/^\s*required=.*\blibtool/,
+ nodist_prereqs => "t/libtool-macros.log",
+ },
+ gettext_macros =>
+ {
+ line_matcher => qr/^\s*required=.*\bgettext/,
+ nodist_prereqs => "t/gettext-macros.log",
+ },
+ use_trivial_test_driver =>
+ {
+ line_matcher => qr/\btrivial-test-driver\b/,
+ dist_prereqs => "t/$auxdir/trivial-test-driver",
+ },
+ check_testsuite_summary =>
+ {
+ line_matcher => qr/\btestsuite-summary-checks\.sh\b/,
+ dist_prereqs => "t/$auxdir/testsuite-summary-checks.sh",
+ },
+ extract_testsuite_summary =>
+ {
+ line_matcher => qr/\bextract-testsuite-summary\.pl\b/,
+ dist_prereqs => "t/$auxdir/extract-testsuite-summary.pl",
+ },
+ check_tap_testsuite_summary =>
+ {
+ line_matcher => qr/\btap-summary-aux\.sh\b/,
+ dist_prereqs => "t/$auxdir/tap-summary-aux.sh",
+ },
+ on_tap_with_common_setup =>
+ {
+ line_matcher => qr/\btap-setup\.sh\b/,
+ dist_prereqs => "t/$auxdir/tap-setup.sh",
+ nodist_prereqs => "t/tap-common-setup.log",
+ },
+ depcomp =>
+ {
+ line_matcher => qr/\bdepcomp\.sh\b/,
+ dist_prereqs => "t/$auxdir/depcomp.sh",
+ },
+ );
+
+#--------------------------------------------------------------------------
+
+my %test_generators =
+ (
+ #
+ # For each test script in the Automake testsuite that itself tests
+ # features of the TESTS automake interface, define a sibling test
+ # that does likewise, but with the option 'parallel-tests' enabled.
+ #
+ # A test is considered a candidate for sibling-generation if any
+ # Makefile.am generated by it define the TESTS variable.
+ #
+ # Individual tests can prevent the creation of such a sibling by
+ # explicitly setting the '$am_parallel_tests' variable to either "yes"
+ # or "no". The rationale for this is that if the variable is set to
+ # "yes", the test already uses the 'parallel-tests' option, so that
+ # a sibling would be just a duplicate; while if the variable is set
+ # to "no", the test doesn't support, or is not meant to run with, the
+ # 'parallel-tests' option, and forcing it to do so in the sibling
+ # would likely cause a spurious failure.
+ #
+ parallel_testsuite_harness =>
+ {
+ line_matcher =>
+ qr/(?:^|\s)TESTS\s*=/,
+ line_rejecter =>
+ qr/(?:^[^#]*\bparallel-tests\b)|\bam_parallel_tests=/,
+ shell_setup_code =>
+ 'am_parallel_tests=yes'
+ },
+ #
+ # For each test script in the Automake testsuite that tests features
+ # of one or more automake-provided shell script from the 'lib/'
+ # subdirectory by running those scripts directly (i.e., not thought
+ # make calls and automake-generated makefiles), define a sibling test
+ # that does likewise, but running the said script with the configure
+ # time $SHELL instead of the default system shell /bin/sh.
+ #
+ # A test is considered a candidate for sibling-generation if it calls
+ # the 'get_shell_script' function anywhere.
+ #
+ # Individual tests can prevent the creation of such a sibling by
+ # explicitly setting the '$am_test_prefer_config_shell' variable
+ # to either "yes" or "no".
+ # The rationale for this is that if the variable is set to "yes",
+ # the test already uses $SHELL, so that a sibling would be just a
+ # duplicate; while if the variable is set to "no", the test doesn't
+ # support, or is not meant to use, $SHELL to run the script under
+ # testing, and forcing it to do so in the sibling would likely
+ # cause a spurious failure.
+ #
+ prefer_config_shell =>
+ {
+ line_matcher =>
+ qr/(^|\s)get_shell_script\s/,
+ line_rejecter =>
+ qr/\bam_test_prefer_config_shell=/,
+ shell_setup_code =>
+ 'am_test_prefer_config_shell=yes',
+ },
+ #
+ # Tests on tap support should be run with both the perl and awk
+ # implementations of the TAP driver (they run with the awk one
+ # by default).
+ #
+ perl_tap_driver =>
+ {
+ line_matcher =>
+ qr<(?:\bfetch_tap_driver\b|[\s/]tap-setup\.sh\b)>,
+ line_rejecter =>
+ qr/\bam_tap_implementation=/,
+ shell_setup_code =>
+ 'am_tap_implementation=perl',
+ },
+ );
+
+#--------------------------------------------------------------------------
+
+parse_options @ARGV;
+
+my @all_tests = get_list_of_tests;
+my @generated_tests = (); # Will be updated later.
+
+print "## -*- Makefile -*-\n";
+print "## Generated by $me. DO NOT EDIT BY HAND!\n\n";
+
+print <<EOF;
+
+## --------------------------------------------- ##
+## Autogenerated tests and their dependencies. ##
+## --------------------------------------------- ##
+
+EOF
+
+# FIXME: the following is not really right, since cannot compose wrapping
+# of tests matching more than one condition. Still, there should be no
+# such test at the moment, so the limitation is (temporarily) acceptable.
+while (my ($k, $g) = each %test_generators)
+ {
+ my @wrapped_tests = grep {
+ line_match ($g->{line_matcher}, $_)
+ && !line_match ($g->{line_rejecter}, $_)
+ } @all_tests;
+ foreach my $wrapped_test (@wrapped_tests)
+ {
+ (my $base = $wrapped_test) =~ s/\.([^.]*)$//;
+ my $suf = $1 or die "$me: test '$wrapped_test' lacks a suffix\n";
+ my $wrapper_test = "$base-w.$suf";
+ # Register wrapper test as "autogenerated".
+ push @generated_tests, $wrapper_test;
+ # Create wrapper test.
+ atomic_write $wrapper_test,
+ sub { write_wrapper_script $_[0], $wrapped_test,
+ $g->{shell_setup_code} },
+ 0555;
+ # The generated test works by sourcing the original test, so that
+ # it has to be re-run every time that changes ...
+ print "$base-w.log: $wrapped_test\n";
+ # ... but also every time the prerequisites of the wrapped test
+ # changes. The simpler (although suboptimal) way to do so is to
+ # ensure that the wrapped tests runs before the wrappee one (in
+ # case it needs to be re-run *at all*.
+ # FIXME: we could maybe refactor the script to find a more
+ # granular way to express such implicit dependencies.
+ print "$base-w.log: $base.log\n";
+ }
+ }
+
+print <<EOF;
+
+## ---------------------------------------------------- ##
+## Ad-hoc autogenerated tests and their dependencies. ##
+## ---------------------------------------------------- ##
+
+EOF
+
+print "## Tests on automatic dependency tracking (see 'depcomp.sh').\n";
+
+# Key: depmode, value: list of required programs.
+my %depmodes =
+ (
+ auto => ["cc"],
+ disabled => ["cc"],
+ makedepend => ["cc", "makedepend"],
+ dashmstdout => ["gcc"],
+ cpp => ["gcc"],
+# This is for older (pre-3.x) GCC versions. Newer versions
+# have depmode "gcc3".
+ gcc => ["gcc"],
+# This is for older (pre-7) msvc versions. Newer versions
+# have depmodes "msvc7" and "msvc7msys".
+ msvisualcpp => ["cl", "cygpath"],
+ msvcmsys => ["cl", "mingw"],
+ );
+
+foreach my $lt (TRUE, FALSE)
+ {
+ foreach my $m (keys %depmodes)
+ {
+ my $planned = ($lt && $m eq "auto") ? 84 : 28;
+ my @required =
+ (
+ @{$depmodes{$m}},
+ $lt ? ("libtoolize",) : (),
+ );
+ my @vars_init =
+ (
+ "am_create_testdir=empty",
+ "depmode=$m",
+ "depcomp_with_libtool=" . ($lt ? "yes" : "no"),
+ );
+ my $test = "t/depcomp" . ($lt ? "-lt-" : "-") . $m . ".tap";
+ # Register wrapper test as "autogenerated" ...
+ push @generated_tests, $test;
+ # ... and create it.
+ atomic_write ($test, sub
+ {
+ my $file_handle = shift;
+ print $file_handle unindent <<EOF;
+ #! /bin/sh
+ # Automatically generated test. DO NOT EDIT BY HAND!
+ @vars_init
+ required="@required"
+ . ./defs || Exit 1
+ plan_ $planned
+ . "\$am_testauxdir/depcomp.sh"; exit "\$?"
+EOF
+ },
+ 0555);
+ }
+ }
+
+# Update generated makefile fragment to account for all the generated tests.
+print "generated_TESTS =\n";
+map { print "generated_TESTS += $_\n" } @generated_tests;
+
+# The test scripts are scanned for automatic dependency generation *after*
+# the generated tests have been created, so they too can be scanned. To
+# do so correctly, we need to update the list in '@all_tests' to make it
+# comprise also the freshly-generated tests.
+
+push @all_tests, @generated_tests;
+
+print <<EOF;
+
+## ----------------------------- ##
+## Autogenerated dependencies. ##
+## ----------------------------- ##
+
+EOF
+
+while (my ($k, $x) = each %deps_extractor)
+ {
+ my $dist_prereqs = $x->{dist_prereqs} || "";
+ my $nodist_prereqs = $x->{nodist_prereqs} || "";
+ my @tests = grep { line_match $x->{line_matcher}, $_ } @all_tests;
+ map { s/\.[^.]*$//; s/$/\.log/; } (my @logs = @tests);
+ print "## Added by deps-extracting key '$k'.\n";
+ ## The list of all tests which have a dependency detected by the
+ ## current key.
+ print join(" \\\n ", "${k}_TESTS =", @tests) . "\n";
+ print "EXTRA_DIST += $dist_prereqs\n";
+ map { print "$_: $dist_prereqs $nodist_prereqs\n" } @logs;
+ print "\n";
+ }
+
+__END__