gen-testsuite-part 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. #! /usr/bin/env perl
  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).
  5. # Copyright (C) 2011-2017 Free Software Foundation, Inc.
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2, or (at your option)
  9. # any later version.
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. #--------------------------------------------------------------------------
  17. use warnings FATAL => "all";
  18. use strict;
  19. use File::Basename ();
  20. use constant TRUE => 1;
  21. use constant FALSE => 0;
  22. my $me = File::Basename::basename $0;
  23. # For use in VPATH builds.
  24. my $srcdir = ".";
  25. # The testsuite subdirectory, relative to the top-lever source directory.
  26. my $testdir = "t";
  27. # Where testsuite-related helper scripts, data files and shell libraries
  28. # are placed. Relative to the top-lever source directory.
  29. my $testauxdir = "$testdir/ax";
  30. #--------------------------------------------------------------------------
  31. sub unindent ($)
  32. {
  33. my $text = shift;
  34. $text =~ /^(\s*)/;
  35. my $indentation = $1;
  36. $text =~ s/^$indentation//gm;
  37. return $text;
  38. }
  39. sub atomic_write ($$;$)
  40. {
  41. my ($outfile, $func) = (shift, shift);
  42. my $perms = @_ > 0 ? shift : 0777;
  43. my $tmpfile = "$outfile-t";
  44. foreach my $f ($outfile, $tmpfile)
  45. {
  46. unlink $f or die "$me: cannot unlink '$f': $!\n"
  47. if -e $f;
  48. }
  49. open (my $fh, ">$tmpfile")
  50. or die "$me: can't write to '$tmpfile': $!\n";
  51. $func->($fh);
  52. close $fh
  53. or die "$me: closing '$tmpfile': $!\n";
  54. chmod ($perms & ~umask, $tmpfile)
  55. or die "$me: cannot change perms for '$tmpfile': $!\n";
  56. rename ($tmpfile, $outfile)
  57. or die "$me: renaming '$tmpfile' -> '$outfile: $!\n'";
  58. }
  59. sub line_match ($$)
  60. {
  61. my ($re, $file) = (shift, shift);
  62. # Try both builddir and srcdir, with builddir first, to play nice
  63. # with VPATH builds.
  64. open (FH, "<$file") or open (FH, "<$srcdir/$file")
  65. or die "$me: cannot open file '$file': $!\n";
  66. my $ret = 0;
  67. while (defined (my $line = <FH>))
  68. {
  69. if ($line =~ $re)
  70. {
  71. $ret = 1;
  72. last;
  73. }
  74. }
  75. close FH or die "$me: cannot close file '$file': $!\n";
  76. return $ret;
  77. }
  78. sub write_wrapper_script ($$$)
  79. {
  80. my ($file_handle, $wrapped_test, $shell_setup_code, $creator_name) = @_;
  81. print $file_handle unindent <<EOF;
  82. #! /bin/sh
  83. # This file has been automatically generated. DO NOT EDIT BY HAND!
  84. . test-lib.sh
  85. $shell_setup_code
  86. # In the spirit of VPATH, we prefer a test in the build tree
  87. # over one in the source tree.
  88. for dir in . "\$am_top_srcdir"; do
  89. if test -f "\$dir/$wrapped_test"; then
  90. echo "\$0: will source \$dir/$wrapped_test"
  91. . "\$dir/$wrapped_test"; exit \$?
  92. fi
  93. done
  94. echo "\$0: cannot find wrapped test '$wrapped_test'" >&2
  95. exit 99
  96. EOF
  97. }
  98. sub get_list_of_tests ()
  99. {
  100. my $make = defined $ENV{MAKE} ? $ENV{MAKE} : "make";
  101. # Unset MAKEFLAGS, for when we are called from make itself.
  102. my $cmd = "MAKEFLAGS= && unset MAKEFLAGS && cd '$srcdir' && "
  103. . "$make -s -f $testdir/list-of-tests.mk print-list-of-tests";
  104. my @tests_list = split /\s+/, `$cmd`;
  105. die "$me: cannot get list of tests\n" unless $? == 0 && @tests_list;
  106. my $ok = 1;
  107. foreach my $test (@tests_list)
  108. {
  109. # Respect VPATH builds.
  110. next if -f $test || -f "$srcdir/$test";
  111. warn "$me: test '$test' not found\n";
  112. $ok = 0;
  113. }
  114. die "$me: some test scripts not found\n" if !$ok;
  115. return @tests_list;
  116. }
  117. sub parse_options (@)
  118. {
  119. use Getopt::Long qw/GetOptions/;
  120. local @ARGV = @_;
  121. GetOptions ('srcdir=s' => \$srcdir) or die "$me: usage error\n";
  122. die "$me: too many arguments\n" if @ARGV > 0;
  123. die "$me: srcdir '$srcdir': not a directory\n" unless -d $srcdir;
  124. }
  125. #--------------------------------------------------------------------------
  126. my %deps_extractor =
  127. (
  128. libtool_macros =>
  129. {
  130. line_matcher => qr/^\s*required=.*\blibtool/,
  131. nodist_prereqs => "$testdir/libtool-macros.log",
  132. },
  133. gettext_macros =>
  134. {
  135. line_matcher => qr/^\s*required=.*\bgettext/,
  136. nodist_prereqs => "$testdir/gettext-macros.log",
  137. },
  138. pkgconfig_macros =>
  139. {
  140. line_matcher => qr/^\s*required=.*\bpkg-config/,
  141. nodist_prereqs => "$testdir/pkg-config-macros.log",
  142. },
  143. use_trivial_test_driver =>
  144. {
  145. line_matcher => qr/\btrivial-test-driver\b/,
  146. dist_prereqs => "$testauxdir/trivial-test-driver",
  147. },
  148. check_testsuite_summary =>
  149. {
  150. line_matcher => qr/\btestsuite-summary-checks\.sh\b/,
  151. dist_prereqs => "$testauxdir/testsuite-summary-checks.sh",
  152. },
  153. extract_testsuite_summary =>
  154. {
  155. line_matcher => qr/\bextract-testsuite-summary\.pl\b/,
  156. dist_prereqs => "$testauxdir/extract-testsuite-summary.pl",
  157. },
  158. check_tap_testsuite_summary =>
  159. {
  160. line_matcher => qr/\btap-summary-aux\.sh\b/,
  161. dist_prereqs => "$testauxdir/tap-summary-aux.sh",
  162. },
  163. on_tap_with_common_setup =>
  164. {
  165. line_matcher => qr/\btap-setup\.sh\b/,
  166. dist_prereqs => "$testauxdir/tap-setup.sh",
  167. nodist_prereqs => "$testdir/tap-common-setup.log",
  168. },
  169. depcomp =>
  170. {
  171. line_matcher => qr/\bdepcomp\.sh\b/,
  172. dist_prereqs => "$testauxdir/depcomp.sh",
  173. },
  174. );
  175. #--------------------------------------------------------------------------
  176. my %test_generators =
  177. (
  178. #
  179. # Any test script in the Automake testsuite that checks features of
  180. # the Automake-provided parallel testsuite harness might want to
  181. # define a sibling test that does similar checks, but for the old
  182. # serial testsuite harness instead.
  183. #
  184. # Individual tests can request the creation of such a sibling by
  185. # making the string "try-with-serial-tests" appear any line of the
  186. # test itself.
  187. #
  188. serial_testsuite_harness =>
  189. {
  190. line_matcher => qr/\btry-with-serial-tests\b/,
  191. shell_setup_code => 'am_serial_tests=yes',
  192. },
  193. #
  194. # For each test script in the Automake testsuite that tests features
  195. # of one or more automake-provided shell script from the 'lib/'
  196. # subdirectory by running those scripts directly (i.e., not thought
  197. # make calls and automake-generated makefiles), define a sibling test
  198. # that does likewise, but running the said script with the configure
  199. # time $SHELL instead of the default system shell /bin/sh.
  200. #
  201. # A test is considered a candidate for sibling-generation if it calls
  202. # the 'get_shell_script' function anywhere.
  203. #
  204. # Individual tests can prevent the creation of such a sibling by
  205. # explicitly setting the '$am_test_prefer_config_shell' variable
  206. # to either "yes" or "no".
  207. # The rationale for this is that if the variable is set to "yes",
  208. # the test already uses $SHELL, so that a sibling would be just a
  209. # duplicate; while if the variable is set to "no", the test doesn't
  210. # support, or is not meant to use, $SHELL to run the script under
  211. # testing, and forcing it to do so in the sibling would likely
  212. # cause a spurious failure.
  213. #
  214. prefer_config_shell =>
  215. {
  216. line_matcher =>
  217. qr/(^|\s)get_shell_script\s/,
  218. line_rejecter =>
  219. qr/\bam_test_prefer_config_shell=/,
  220. shell_setup_code =>
  221. 'am_test_prefer_config_shell=yes',
  222. },
  223. );
  224. #--------------------------------------------------------------------------
  225. parse_options @ARGV;
  226. my @all_tests = get_list_of_tests;
  227. my @generated_tests = (); # Will be updated later.
  228. print "## -*- Makefile -*-\n";
  229. print "## Generated by $me. DO NOT EDIT BY HAND!\n\n";
  230. print <<EOF;
  231. ## --------------------------------------------- ##
  232. ## Autogenerated tests and their dependencies. ##
  233. ## --------------------------------------------- ##
  234. EOF
  235. # A test script '$test' can possibly match more than one condition, so
  236. # for each tests we need to keep a list of generated wrapper tests.
  237. # Since what defines these wrapper scripts is the set of initializations
  238. # that are issued before sourcing the original, wrapped tests, these
  239. # initializations is what we put in our list entries.
  240. # The list will be saved in the hash entry '$wrapper_setups{$test}'.
  241. my %wrapper_setups = ();
  242. foreach my $test (@all_tests)
  243. {
  244. my @setups = ('');
  245. foreach my $x (values %test_generators)
  246. {
  247. next
  248. if not line_match $x->{line_matcher}, $test;
  249. next
  250. if $x->{line_rejecter} and line_match $x->{line_rejecter}, $test;
  251. @setups = map { ($_, "$_\n$x->{shell_setup_code}") } @setups;
  252. }
  253. @setups = grep { $_ ne '' } @setups;
  254. $wrapper_setups{$test} = \@setups if @setups;
  255. }
  256. # And now create all the wrapper tests.
  257. for my $wrapped_test (sort keys %wrapper_setups)
  258. {
  259. my $setup_list = $wrapper_setups{$wrapped_test};
  260. (my $base = $wrapped_test) =~ s/\.([^.]*)$//;
  261. my $suf = $1 or die "$me: test '$wrapped_test' lacks a suffix\n";
  262. my $count = 0;
  263. foreach my $setup (@$setup_list)
  264. {
  265. $count++;
  266. my $wbase = "$base-w" . ($count > 1 ? $count : '');
  267. my $wrapper_test = "$wbase.$suf";
  268. # Register wrapper test as "autogenerated".
  269. push @generated_tests, $wrapper_test;
  270. # Create wrapper test.
  271. atomic_write $wrapper_test,
  272. sub { write_wrapper_script $_[0], $wrapped_test,
  273. $setup },
  274. 0444;
  275. # The generated test works by sourcing the original test, so that
  276. # it has to be re-run every time that changes ...
  277. print "$wbase.log: $wrapped_test\n";
  278. # ... but also every time the prerequisites of the wrapped test
  279. # changes. The simpler (although suboptimal) way to do so is to
  280. # ensure that the wrapped tests runs before the wrapper one (in
  281. # case it needs to be re-run *at all*).
  282. # FIXME: we could maybe refactor the script to find a more
  283. # granular way to express such implicit dependencies.
  284. print "$wbase.log: $base.log\n";
  285. }
  286. }
  287. print <<EOF;
  288. ## ---------------------------------------------------- ##
  289. ## Ad-hoc autogenerated tests and their dependencies. ##
  290. ## ---------------------------------------------------- ##
  291. EOF
  292. print "## Tests on automatic dependency tracking (see 'depcomp.sh').\n";
  293. # Key: depmode, value: list of required programs.
  294. my %depmodes =
  295. (
  296. auto => ["cc"],
  297. disabled => ["cc"],
  298. makedepend => ["cc", "makedepend", "-c-o"],
  299. dashmstdout => ["gcc"],
  300. cpp => ["gcc"],
  301. # This was for older (pre-3.x) GCC versions (newer versions
  302. # have depmode "gcc3"). But other compilers use this depmode
  303. # as well (for example, the IMB xlc/xlC compilers, and the HP
  304. # C compiler, see 'lib/depcomp' for more info), so it's not
  305. # obsolete, and it's worth giving it some coverage.
  306. gcc => ["gcc"],
  307. # This is for older (pre-7) msvc versions. Newer versions
  308. # have depmodes "msvc7" and "msvc7msys".
  309. msvisualcpp => ["cl", "cygpath"],
  310. msvcmsys => ["cl", "mingw"],
  311. );
  312. foreach my $lt (TRUE, FALSE)
  313. {
  314. foreach my $m (sort keys %depmodes)
  315. {
  316. my $planned = ($lt && $m eq "auto") ? 84 : 28;
  317. my @required =
  318. (
  319. @{$depmodes{$m}},
  320. $lt ? ("libtoolize",) : (),
  321. );
  322. my @vars_init =
  323. (
  324. "am_create_testdir=empty",
  325. "depmode=$m",
  326. "depcomp_with_libtool=" . ($lt ? "yes" : "no"),
  327. );
  328. my $test = "$testdir/depcomp" . ($lt ? "-lt-" : "-") . "$m.tap";
  329. # Register wrapper test as "autogenerated" ...
  330. push @generated_tests, $test;
  331. # ... and create it.
  332. atomic_write ($test, sub
  333. {
  334. my $file_handle = shift;
  335. print $file_handle unindent <<EOF;
  336. #! /bin/sh
  337. # Automatically generated test. DO NOT EDIT BY HAND!
  338. @vars_init
  339. required="@required"
  340. . test-init.sh
  341. plan_ $planned
  342. . depcomp.sh
  343. exit \$?
  344. EOF
  345. },
  346. 0444);
  347. }
  348. }
  349. # Update generated makefile fragment to account for all the generated tests.
  350. print "generated_TESTS =\n";
  351. map { print "generated_TESTS += $_\n" } @generated_tests;
  352. # The test scripts are scanned for automatic dependency generation *after*
  353. # the generated tests have been created, so they too can be scanned. To
  354. # do so correctly, we need to update the list in '@all_tests' to make it
  355. # comprise also the freshly-generated tests.
  356. push @all_tests, @generated_tests;
  357. print <<EOF;
  358. ## ----------------------------- ##
  359. ## Autogenerated dependencies. ##
  360. ## ----------------------------- ##
  361. EOF
  362. for my $k (sort keys %deps_extractor)
  363. {
  364. my $x = $deps_extractor{$k};
  365. my $dist_prereqs = $x->{dist_prereqs} || "";
  366. my $nodist_prereqs = $x->{nodist_prereqs} || "";
  367. my @tests = grep { line_match $x->{line_matcher}, $_ } @all_tests;
  368. map { s/\.[^.]*$//; s/$/\.log/; } (my @logs = @tests);
  369. print "## Added by deps-extracting key '$k'.\n";
  370. ## The list of all tests which have a dependency detected by the
  371. ## current key.
  372. print join(" \\\n ", "${k}_TESTS =", @tests) . "\n";
  373. print "EXTRA_DIST += $dist_prereqs\n";
  374. map { print "$_: $dist_prereqs $nodist_prereqs\n" } @logs;
  375. print "\n";
  376. }
  377. __END__