2 # Automatically compute some dependencies for the hand-written tests
3 # of the Automake testsuite. Also, automatically generate some more
4 # tests from them (for particular cases/setups only).
6 # Copyright (C) 2011-2012 Free Software Foundation, Inc.
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2, or (at your option)
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #--------------------------------------------------------------------------
23 use warnings FATAL => "all";
25 use File::Basename ();
26 use constant TRUE => 1;
27 use constant FALSE => 0;
29 my $me = File::Basename::basename $0;
31 # For use in VPATH builds.
34 #--------------------------------------------------------------------------
41 $text =~ s/^$indentation//gm;
45 sub atomic_write ($$;$)
47 my ($outfile, $func) = (shift, shift);
48 my $perms = @_ > 0 ? shift : 0777;
49 my $tmpfile = "$outfile-t";
50 foreach my $f ($outfile, $tmpfile)
52 unlink $f or die "$me: cannot unlink '$f': $!\n"
55 open (my $fh, ">$tmpfile")
56 or die "$me: can't write to '$tmpfile': $!\n";
59 or die "$me: closing '$tmpfile': $!\n";
60 chmod ($perms & ~umask, $tmpfile)
61 or die "$me: cannot change perms for '$tmpfile': $!\n";
62 rename ($tmpfile, $outfile)
63 or die "$me: renaming '$tmpfile' -> '$outfile: $!\n'";
68 my ($re, $file) = (shift, shift);
69 # Try both builddir and srcdir, with builddir first, to play nice
71 open (FH, "<$file") or open (FH, "<$srcdir/$file")
72 or die "$me: cannot open file '$file': $!\n";
74 while (defined (my $line = <FH>))
82 close FH or die "$me: cannot close file '$file': $!\n";
86 sub write_wrapper_script ($$$)
88 my ($file_handle, $wrapped_test, $shell_setup_code, $creator_name) = @_;
89 # FIXME: we use some creative quoting in the generated scripts,
90 # FIXME: to please maintainer-check.
91 print $file_handle unindent <<EOF;
93 # This file has been automatically generated. DO NOT EDIT BY HAND!
94 . ./defs-static || exit '99';
96 # In the spirit of VPATH, we prefer a test in the build tree
97 # over one in the source tree.
98 for dir in . "\$am_top_srcdir"; do
99 if test -f "\$dir/$wrapped_test"; then
100 echo "\$0: will source \$dir/$wrapped_test"
101 . "\$dir/$wrapped_test"; exit "\$?"
104 echo "\$0: cannot find wrapped test '$wrapped_test'" >&2
109 sub get_list_of_tests ()
111 my $make = defined $ENV{MAKE} ? $ENV{MAKE} : "make";
112 # Unset MAKEFLAGS, for when we are called from make itself.
113 my $cmd = "MAKEFLAGS= && unset MAKEFLAGS && cd '$srcdir' && "
114 . "$make -s -f t/list-of-tests.mk print-list-of-tests";
115 my @tests_list = split /\s+/, `$cmd`;
116 die "$me: cannot get list of tests\n" unless $? == 0 && @tests_list;
118 foreach my $test (@tests_list)
120 # Respect VPATH builds.
121 next if -f $test || -f "$srcdir/$test";
122 warn "$me: test '$test' not found\n";
125 die "$me: some test scripts not found\n" if !$ok;
129 sub parse_options (@)
131 use Getopt::Long qw/GetOptions/;
133 GetOptions ('srcdir=s' => \$srcdir) or die "$me: usage error\n";
134 die "$me: too many arguments\n" if @ARGV > 0;
135 die "$me: srcdir '$srcdir': not a directory\n" unless -d $srcdir;
138 #--------------------------------------------------------------------------
140 # Where testsuite-related helper scripts, data files and shell libraries
141 # are placed. Relative to the 't/' subdirectory.
148 line_matcher => qr/^\s*required=.*\blibtool/,
149 nodist_prereqs => "t/libtool-macros.log",
153 line_matcher => qr/^\s*required=.*\bgettext/,
154 nodist_prereqs => "t/gettext-macros.log",
156 use_trivial_test_driver =>
158 line_matcher => qr/\btrivial-test-driver\b/,
159 dist_prereqs => "t/$auxdir/trivial-test-driver",
161 check_testsuite_summary =>
163 line_matcher => qr/\btestsuite-summary-checks\.sh\b/,
164 dist_prereqs => "t/$auxdir/testsuite-summary-checks.sh",
166 extract_testsuite_summary =>
168 line_matcher => qr/\bextract-testsuite-summary\.pl\b/,
169 dist_prereqs => "t/$auxdir/extract-testsuite-summary.pl",
171 check_tap_testsuite_summary =>
173 line_matcher => qr/\btap-summary-aux\.sh\b/,
174 dist_prereqs => "t/$auxdir/tap-summary-aux.sh",
176 on_tap_with_common_setup =>
178 line_matcher => qr/\btap-setup\.sh\b/,
179 dist_prereqs => "t/$auxdir/tap-setup.sh",
180 nodist_prereqs => "t/tap-common-setup.log",
184 line_matcher => qr/\bdepcomp\.sh\b/,
185 dist_prereqs => "t/$auxdir/depcomp.sh",
189 #--------------------------------------------------------------------------
191 my %test_generators =
194 # Any test script in the Automake testsuite that checks features of
195 # the Automake-provided parallel testsuite harness might want to
196 # define a sibling test that does similar checks, but for the old
197 # serial testsuite harness instead.
199 # Individual tests can request the creation of such a sibling by
200 # making the string "try-with-serial-tests" appear any line of the
203 serial_testsuite_harness =>
205 line_matcher => qr/\btry-with-serial-tests\b/,
206 shell_setup_code => 'am_serial_tests=yes',
209 # For each test script in the Automake testsuite that tests features
210 # of one or more automake-provided shell script from the 'lib/'
211 # subdirectory by running those scripts directly (i.e., not thought
212 # make calls and automake-generated makefiles), define a sibling test
213 # that does likewise, but running the said script with the configure
214 # time $SHELL instead of the default system shell /bin/sh.
216 # A test is considered a candidate for sibling-generation if it calls
217 # the 'get_shell_script' function anywhere.
219 # Individual tests can prevent the creation of such a sibling by
220 # explicitly setting the '$am_test_prefer_config_shell' variable
221 # to either "yes" or "no".
222 # The rationale for this is that if the variable is set to "yes",
223 # the test already uses $SHELL, so that a sibling would be just a
224 # duplicate; while if the variable is set to "no", the test doesn't
225 # support, or is not meant to use, $SHELL to run the script under
226 # testing, and forcing it to do so in the sibling would likely
227 # cause a spurious failure.
229 prefer_config_shell =>
232 qr/(^|\s)get_shell_script\s/,
234 qr/\bam_test_prefer_config_shell=/,
236 'am_test_prefer_config_shell=yes',
239 # Tests on tap support should be run with both the perl and awk
240 # implementations of the TAP driver (they run with the awk one
246 qr<(?:\bfetch_tap_driver\b|[\s/]tap-setup\.sh\b)>,
248 qr/\bam_tap_implementation=/,
250 'am_tap_implementation=perl',
254 #--------------------------------------------------------------------------
258 my @all_tests = get_list_of_tests;
259 my @generated_tests = (); # Will be updated later.
261 print "## -*- Makefile -*-\n";
262 print "## Generated by $me. DO NOT EDIT BY HAND!\n\n";
266 ## --------------------------------------------- ##
267 ## Autogenerated tests and their dependencies. ##
268 ## --------------------------------------------- ##
272 # FIXME: the following is not really right, since cannot compose wrapping
273 # of tests matching more than one condition. Still, there should be no
274 # such test at the moment, so the limitation is (temporarily) acceptable.
275 while (my ($k, $g) = each %test_generators)
277 my @wrapped_tests = grep {
278 line_match ($g->{line_matcher}, $_)
279 && (!$g->{line_rejecter} || !line_match ($g->{line_rejecter}, $_))
281 foreach my $wrapped_test (@wrapped_tests)
283 (my $base = $wrapped_test) =~ s/\.([^.]*)$//;
284 my $suf = $1 or die "$me: test '$wrapped_test' lacks a suffix\n";
285 my $wrapper_test = "$base-w.$suf";
286 # Register wrapper test as "autogenerated".
287 push @generated_tests, $wrapper_test;
288 # Create wrapper test.
289 atomic_write $wrapper_test,
290 sub { write_wrapper_script $_[0], $wrapped_test,
291 $g->{shell_setup_code} },
293 # The generated test works by sourcing the original test, so that
294 # it has to be re-run every time that changes ...
295 print "$base-w.log: $wrapped_test\n";
296 # ... but also every time the prerequisites of the wrapped test
297 # changes. The simpler (although suboptimal) way to do so is to
298 # ensure that the wrapped tests runs before the wrappee one (in
299 # case it needs to be re-run *at all*.
300 # FIXME: we could maybe refactor the script to find a more
301 # granular way to express such implicit dependencies.
302 print "$base-w.log: $base.log\n";
308 ## ---------------------------------------------------- ##
309 ## Ad-hoc autogenerated tests and their dependencies. ##
310 ## ---------------------------------------------------- ##
314 print "## Tests on automatic dependency tracking (see 'depcomp.sh').\n";
316 # Key: depmode, value: list of required programs.
321 makedepend => ["cc", "makedepend"],
322 dashmstdout => ["gcc"],
324 # This is for older (pre-3.x) GCC versions. Newer versions
325 # have depmode "gcc3".
327 # This is for older (pre-7) msvc versions. Newer versions
328 # have depmodes "msvc7" and "msvc7msys".
329 msvisualcpp => ["cl", "cygpath"],
330 msvcmsys => ["cl", "mingw"],
333 foreach my $lt (TRUE, FALSE)
335 foreach my $m (keys %depmodes)
337 my $planned = ($lt && $m eq "auto") ? 84 : 28;
341 $lt ? ("libtoolize",) : (),
345 "am_create_testdir=empty",
347 "depcomp_with_libtool=" . ($lt ? "yes" : "no"),
349 my $test = "t/depcomp" . ($lt ? "-lt-" : "-") . $m . ".tap";
350 # Register wrapper test as "autogenerated" ...
351 push @generated_tests, $test;
353 atomic_write ($test, sub
355 my $file_handle = shift;
356 print $file_handle unindent <<EOF;
358 # Automatically generated test. DO NOT EDIT BY HAND!
363 . "\$am_testauxdir/depcomp.sh"; exit "\$?"
370 # Update generated makefile fragment to account for all the generated tests.
371 print "generated_TESTS =\n";
372 map { print "generated_TESTS += $_\n" } @generated_tests;
374 # The test scripts are scanned for automatic dependency generation *after*
375 # the generated tests have been created, so they too can be scanned. To
376 # do so correctly, we need to update the list in '@all_tests' to make it
377 # comprise also the freshly-generated tests.
379 push @all_tests, @generated_tests;
383 ## ----------------------------- ##
384 ## Autogenerated dependencies. ##
385 ## ----------------------------- ##
389 while (my ($k, $x) = each %deps_extractor)
391 my $dist_prereqs = $x->{dist_prereqs} || "";
392 my $nodist_prereqs = $x->{nodist_prereqs} || "";
393 my @tests = grep { line_match $x->{line_matcher}, $_ } @all_tests;
394 map { s/\.[^.]*$//; s/$/\.log/; } (my @logs = @tests);
395 print "## Added by deps-extracting key '$k'.\n";
396 ## The list of all tests which have a dependency detected by the
398 print join(" \\\n ", "${k}_TESTS =", @tests) . "\n";
399 print "EXTRA_DIST += $dist_prereqs\n";
400 map { print "$_: $dist_prereqs $nodist_prereqs\n" } @logs;