This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix building with -Accflags=-DDL_UNLOAD_ALL_AT_EXIT
[perl5.git] / t / TEST
CommitLineData
63217fa2 1#!./perl
8d063cd8 2
8d063cd8 3# This is written in a peculiar style, since we're trying to avoid
1de9afcd 4# most of the constructs we'll be testing for. (This comment is
8bdd21ca 5# probably obsolete on the avoidance side, though still current
1de9afcd 6# on the peculiarity side.)
8d063cd8 7
c537bcda
NC
8# t/TEST and t/harness need to share code. The logical way to do this would be
9# to have the common code in a file both require or use. However, t/TEST needs
10# to still work, to generate test results, even if require isn't working, so
11# we cannot do that. t/harness has no such restriction, so it is quite
12# acceptable to have it require t/TEST.
13
14# In which case, we need to stop t/TEST actually running tests, as all
15# t/harness needs are its subroutines.
16
94708f6d
JH
17# Measure the elapsed wallclock time.
18my $t0 = time();
19
2722144b
MH
20# If we're doing deparse tests, ignore failures for these
21my $deparse_failures;
22
23# And skip even running these
24my $deparse_skips;
2adbc9b6 25
10d90405
DM
26my $deparse_skip_file = '../Porting/deparse-skips.txt';
27
2adbc9b6
NC
28# directories with special sets of test switches
29my %dir_to_switch =
30 (base => '',
31 comp => '',
32 run => '',
30b6e591 33 '../ext/File-Glob/t' => '-I.. -MTestInit', # FIXME - tests assume t/
2adbc9b6
NC
34 );
35
cb596ae4 36# "not absolute" is the default, as it saves some fakery within TestInit
8bdd21ca 37# which can perturb tests, and takes CPU. Working with the upstream author of
41239ce7
NC
38# any of these, to figure out how to remove them from this list, considered
39# "a good thing".
40my %abs = (
41239ce7
NC
41 '../cpan/Archive-Tar' => 1,
42 '../cpan/AutoLoader' => 1,
43 '../cpan/CPAN' => 1,
41239ce7 44 '../cpan/Encode' => 1,
41239ce7 45 '../cpan/ExtUtils-Constant' => 1,
d393d7e5 46 '../cpan/ExtUtils-Install' => 1,
41239ce7 47 '../cpan/ExtUtils-MakeMaker' => 1,
854a00d8 48 '../cpan/ExtUtils-Manifest' => 1,
41239ce7
NC
49 '../cpan/File-Fetch' => 1,
50 '../cpan/IPC-Cmd' => 1,
51 '../cpan/IPC-SysV' => 1,
52 '../cpan/Locale-Codes' => 1,
41239ce7
NC
53 '../cpan/Module-Load' => 1,
54 '../cpan/Module-Load-Conditional' => 1,
41239ce7 55 '../cpan/Pod-Simple' => 1,
41239ce7 56 '../cpan/Test-Simple' => 1,
41239ce7 57 '../cpan/podlators' => 1,
2a6dc374 58 '../dist/Cwd' => 1,
7baf245a 59 '../dist/Devel-PPPort' => 1,
cc79184a 60 '../dist/ExtUtils-ParseXS' => 1,
c0504019 61 '../dist/Tie-File' => 1,
41239ce7 62 );
2a6dc374 63
9e01a143
DIM
64my %temp_no_core =
65 ('../cpan/B-Debug' => 1,
d371e02a 66 '../cpan/Compress-Raw-Bzip2' => 1,
c6f84bbd 67 '../cpan/Compress-Raw-Zlib' => 1,
b2861970 68 '../cpan/Devel-PPPort' => 1,
e41cfb92 69 '../cpan/Getopt-Long' => 1,
3fd969f4 70 '../cpan/IO-Compress' => 1,
b7c8007e 71 '../cpan/MIME-Base64' => 1,
a636c943 72 '../cpan/parent' => 1,
490d1888 73 '../cpan/Pod-Simple' => 1,
f4e6b692 74 '../cpan/podlators' => 1,
e0ee75a6 75 '../cpan/Test-Simple' => 1,
325914f9 76 '../cpan/Tie-RefHash' => 1,
a3e5f045 77 '../cpan/Unicode-Collate' => 1,
3baae3fa 78 '../dist/Unicode-Normalize' => 1,
2adbc9b6
NC
79 );
80
19641fd7
DM
81# temporary workaround Apr 2017. These need '.' in @INC.
82# Ideally this # list will eventually be empty
83
84my %temp_needs_dot = map { $_ => 1 } qw(
85 ../cpan/ExtUtils-Install
86 ../cpan/Filter-Util-Call
87 ../cpan/libnet
88 ../cpan/Locale-Codes
89 ../cpan/Math-BigInt
90 ../cpan/Math-BigRat
91 ../cpan/Test-Harness
92 ../cpan/Test-Simple
93 ../cpan/version
94);
95
96
2574563e
TB
97# delete env vars that may influence the results
98# but allow override via *_TEST env var if wanted
99# (e.g. PERL5OPT_TEST=-d:NYTProf)
b6646683
DG
100my @bad_env_vars = qw(
101 PERL5LIB PERLLIB PERL5OPT
102 PERL_YAML_BACKEND PERL_JSON_BACKEND
103);
104
105for my $envname (@bad_env_vars) {
2574563e
TB
106 my $override = $ENV{"${envname}_TEST"};
107 if (defined $override) {
108 warn "$0: $envname=$override\n";
109 $ENV{$envname} = $override;
110 }
111 else {
112 delete $ENV{$envname};
113 }
114}
60e23f2f 115
be075caf
MH
116# Location to put the Valgrind log.
117our $Valgrind_Log;
118
119my %skip = (
120 '.' => 1,
121 '..' => 1,
122 'CVS' => 1,
123 'RCS' => 1,
124 'SCCS' => 1,
125 '.svn' => 1,
126 );
127
75e21add 128
63217fa2 129if ($::do_nothing) {
75e21add
JH
130 return 1;
131}
132
a2d3de13
NC
133$| = 1;
134
135# for testing TEST only
136#BEGIN { require '../lib/strict.pm'; "strict"->import() };
137#BEGIN { require '../lib/warnings.pm'; "warnings"->import() };
138
cc6ae9e5
CB
139# remove empty elements due to insertion of empty symbols via "''p1'" syntax
140@ARGV = grep($_,@ARGV) if $^O eq 'VMS';
70a78ba7 141
7fa64c24
FC
142# String eval to avoid loading File::Glob on non-miniperl.
143# (Windows only uses this script for miniperl.)
804352e2 144@ARGV = eval 'map glob, @ARGV' if $^O eq 'MSWin32';
70a78ba7 145
551405c4 146our $show_elapsed_time = $ENV{HARNESS_TIMER} || 0;
cc6ae9e5 147
18869dc6
NC
148# Cheesy version of Getopt::Std. We can't replace it with that, because we
149# can't rely on require working.
80ed0dea
DM
150{
151 my @argv = ();
5d9a6404 152 foreach my $idx (0..$#ARGV) {
b03030b8 153 push( @argv, $ARGV[$idx] ), next unless $ARGV[$idx] =~ /^-(\S+)$/;
7019aa11 154 $::benchmark = 1 if $1 eq 'benchmark';
80ed0dea
DM
155 $::core = 1 if $1 eq 'core';
156 $::verbose = 1 if $1 eq 'v';
157 $::torture = 1 if $1 eq 'torture';
158 $::with_utf8 = 1 if $1 eq 'utf8';
159 $::with_utf16 = 1 if $1 eq 'utf16';
80ed0dea 160 $::taintwarn = 1 if $1 eq 'taintwarn';
485988ae 161 if ($1 =~ /^deparse(,.+)?$/) {
80ed0dea
DM
162 $::deparse = 1;
163 $::deparse_opts = $1;
2722144b 164 _process_deparse_config();
485988ae 165 }
5d9a6404 166 }
80ed0dea 167 @ARGV = @argv;
8d063cd8
LW
168}
169
378cc40b 170chdir 't' if -f 't/TEST';
ab662740
NC
171if (-f 'TEST' && -f 'harness' && -d '../lib') {
172 @INC = '../lib';
173}
378cc40b 174
3816c65f 175die "You need to run \"make test_prep\" first to set things up.\n"
196918b0 176 unless -e 'perl' or -e 'perl.exe' or -e 'perl.pm';
4633a7c4 177
3fb91a5e
GS
178# check leakage for embedders
179$ENV{PERL_DESTRUCT_LEVEL} = 2 unless exists $ENV{PERL_DESTRUCT_LEVEL};
da6a8325
GG
180# check existence of all symbols
181$ENV{PERL_DL_NONLAZY} = 1 unless exists $ENV{PERL_DL_NONLAZY};
3fb91a5e 182
4633a7c4 183$ENV{EMXSHELL} = 'sh'; # For OS/2
748a9306 184
28ffa55a 185if ($show_elapsed_time) { require Time::HiRes }
b49055e9 186my %timings = (); # testname => [@et] pairs if $show_elapsed_time.
7ebf5c89 187
18869dc6 188# Roll your own File::Find!
ac681bb3 189sub _find_tests { our @found=(); push @ARGV, _find_files('\.t$', $_[0]) }
c96083ea
JC
190sub _find_files {
191 my($patt, @dirs) = @_;
192 for my $dir (@dirs) {
193 opendir DIR, $dir or die "Trouble opening $dir: $!";
194 foreach my $f (sort { $a cmp $b } readdir DIR) {
195 next if $skip{$f};
196
197 my $fullpath = "$dir/$f";
198
199 if (-d $fullpath) {
200 _find_files($patt, $fullpath);
201 } elsif ($f =~ /$patt/) {
202 push @found, $fullpath;
203 }
7ebf5c89 204 }
24c841ba 205 }
c96083ea 206 @found;
24c841ba
MS
207}
208
3fd4b359
MS
209
210# Scan the text of the test program to find switches and special options
211# we might need to apply.
212sub _scan_test {
213 my($test, $type) = @_;
214
215 open(my $script, "<", $test) or die "Can't read $test.\n";
216 my $first_line = <$script>;
217
218 $first_line =~ tr/\0//d if $::with_utf16;
219
220 my $switch = "";
221 if ($first_line =~ /#!.*\bperl.*\s-\w*([tT])/) {
79b01a68 222 $switch = "-$1";
3fd4b359
MS
223 } else {
224 if ($::taintwarn) {
225 # not all tests are expected to pass with this option
79b01a68 226 $switch = '-t';
3fd4b359
MS
227 } else {
228 $switch = '';
229 }
230 }
231
232 my $file_opts = "";
233 if ($type eq 'deparse') {
234 # Look for #line directives which change the filename
235 while (<$script>) {
11ea18f2 236 $file_opts = $file_opts . ",-f$3$4"
3fd4b359
MS
237 if /^#\s*line\s+(\d+)\s+((\w+)|"([^"]+)")/;
238 }
239 }
240
491c9572 241 close $script;
84650816 242
70a78ba7 243 my $perl = $^O eq 'MSWin32' ? '.\perl' : './perl';
923e061d 244 my $lib = '../lib';
491c9572
VP
245 my $run_dir;
246 my $return_dir;
247
2adbc9b6
NC
248 $test =~ /^(.+)\/[^\/]+/;
249 my $dir = $1;
2adbc9b6 250 my $testswitch = $dir_to_switch{$dir};
5ed59b83 251 if (!defined $testswitch) {
55d965ca 252 if ($test =~ s!^(\.\./(cpan|dist|ext)/[^/]+)/t!t!) {
491c9572 253 $run_dir = $1;
2adbc9b6
NC
254 $return_dir = '../../t';
255 $lib = '../../lib';
1ff5bc37 256 $perl = '../../t/perl';
6d1e6673 257 $testswitch = "-I../.. -MTestInit=U2T";
4b05cdbd 258 if ($2 eq 'cpan' || $2 eq 'dist') {
41239ce7 259 if($abs{$run_dir}) {
55d965ca
NC
260 $testswitch = $testswitch . ',A';
261 }
262 if ($temp_no_core{$run_dir}) {
263 $testswitch = $testswitch . ',NC';
264 }
19641fd7
DM
265 if($temp_needs_dot{$run_dir}) {
266 $testswitch = $testswitch . ',DOT';
267 }
2adbc9b6 268 }
76cc22ec
NC
269 } elsif ($test =~ m!^\.\./lib!) {
270 $testswitch = '-I.. -MTestInit=U1'; # -T will remove . from @INC
2adbc9b6 271 } else {
30b6e591 272 $testswitch = '-I.. -MTestInit'; # -T will remove . from @INC
2adbc9b6 273 }
5ed59b83 274 }
923e061d 275
9fb03e61 276 my $utf8 = ($::with_utf8 || $::with_utf16) ? "-I$lib -Mutf8" : '';
84650816 277
9b37184d 278 my %options = (
491c9572
VP
279 perl => $perl,
280 lib => $lib,
281 test => $test,
282 run_dir => $run_dir,
283 return_dir => $return_dir,
284 testswitch => $testswitch,
285 utf8 => $utf8,
286 file => $file_opts,
287 switch => $switch,
9b37184d
VP
288 );
289
290 return \%options;
491c9572
VP
291}
292
d1fe220a
VP
293sub _cmd {
294 my($options, $type) = @_;
491c9572 295
d1fe220a 296 my $test = $options->{test};
491c9572 297
d1fe220a 298 my $cmd;
84650816 299 if ($type eq 'deparse') {
491c9572
VP
300 my $perl = "$options->{perl} $options->{testswitch}";
301 my $lib = $options->{lib};
d1fe220a
VP
302
303 $cmd = (
491c9572 304 "$perl $options->{switch} -I$lib -MO=-qq,Deparse,-sv1.,".
84650816
MS
305 "-l$::deparse_opts$options->{file} ".
306 "$test > $test.dp ".
d1fe220a
VP
307 "&& $perl $options->{switch} -I$lib $test.dp"
308 );
84650816
MS
309 }
310 elsif ($type eq 'perl') {
491c9572 311 my $perl = $options->{perl};
84650816
MS
312 my $redir = $^O eq 'VMS' ? '2>&1' : '';
313
314 if ($ENV{PERL_VALGRIND}) {
e07ce2e4 315 my $perl_supp = $options->{return_dir} ? "$options->{return_dir}/perl.supp" : "perl.supp";
c7b956bb 316 my $valgrind_exe = $ENV{VALGRIND} // 'valgrind';
be075caf 317 if ($options->{run_dir}) {
7ab0d5f3
MH
318 require Cwd;
319 $Valgrind_Log = Cwd::abs_path("$options->{run_dir}/$Valgrind_Log");
be075caf 320 }
84650816 321 my $vg_opts = $ENV{VG_OPTS}
be075caf 322 // "--log-file=$Valgrind_Log "
c7b956bb
JC
323 . "--suppressions=$perl_supp --leak-check=yes "
324 . "--leak-resolution=high --show-reachable=yes "
be075caf
MH
325 . "--num-callers=50 --track-origins=yes";
326 # Force logging if not asked for (so cachegrind reporting works below)
327 if ($vg_opts !~ /--log-file/) {
328 $vg_opts = "--log-file=$Valgrind_Log $vg_opts";
329 }
c7b956bb 330 $perl = "$valgrind_exe $vg_opts $perl";
84650816
MS
331 }
332
491c9572 333 my $args = "$options->{testswitch} $options->{switch} $options->{utf8}";
d1fe220a 334 $cmd = $perl . _quote_args($args) . " $test $redir";
84650816 335 }
d1fe220a
VP
336 return $cmd;
337}
338
9324df28
VP
339sub _before_fork {
340 my ($options) = @_;
341
342 if ($options->{run_dir}) {
343 my $run_dir = $options->{run_dir};
344 chdir $run_dir or die "Can't chdir to '$run_dir': $!";
345 }
346
be075caf
MH
347 # Remove previous valgrind output otherwise it will interfere
348 my $test = $options->{test};
349
350 (local $Valgrind_Log = "$test.valgrind-current") =~ s/^.*\///;
351
352 if ($ENV{PERL_VALGRIND} && -e $Valgrind_Log) {
353 unlink $Valgrind_Log
354 or warn "$0: Failed to unlink '$Valgrind_Log': $!\n";
355 }
356
9324df28
VP
357 return;
358}
359
360sub _after_fork {
361 my ($options) = @_;
362
363 if ($options->{return_dir}) {
364 my $return_dir = $options->{return_dir};
365 chdir $return_dir
366 or die "Can't chdir from '$options->{run_dir}' to '$return_dir': $!";
367 }
368
369 return;
370}
371
d1fe220a 372sub _run_test {
999051eb 373 my ($test, $type) = @_;
d1fe220a
VP
374
375 my $options = _scan_test($test, $type);
999051eb
VP
376 # $test might have changed if we're in ext/Foo, so don't use it anymore
377 # from now on. Use $options->{test} instead.
d1fe220a 378
9324df28 379 _before_fork($options);
d1fe220a
VP
380
381 my $cmd = _cmd($options, $type);
382
383 open(my $results, "$cmd |") or print "can't run '$cmd': $!.\n";
384
9324df28 385 _after_fork($options);
2adbc9b6 386
84650816
MS
387 # Our environment may force us to use UTF-8, but we can't be sure that
388 # anything we're reading from will be generating (well formed) UTF-8
389 # This may not be the best way - possibly we should unset ${^OPEN} up
390 # top?
391 binmode $results;
392
393 return $results;
394}
395
cc6ae9e5
CB
396sub _quote_args {
397 my ($args) = @_;
398 my $argstring = '';
399
400 foreach (split(/\s+/,$args)) {
401 # In VMS protect with doublequotes because otherwise
402 # DCL will lowercase -- unless already doublequoted.
403 $_ = q(").$_.q(") if ($^O eq 'VMS') && !/^\"/ && length($_) > 0;
11ea18f2 404 $argstring = $argstring . ' ' . $_;
cc6ae9e5
CB
405 }
406 return $argstring;
407}
408
6234cb77 409sub _populate_hash {
a3323f52 410 return unless defined $_[0];
6234cb77
NC
411 return map {$_, 1} split /\s+/, $_[0];
412}
413
a3323f52
NC
414sub _tests_from_manifest {
415 my ($extensions, $known_extensions) = @_;
6234cb77 416 my %skip;
a3323f52
NC
417 my %extensions = _populate_hash($extensions);
418 my %known_extensions = _populate_hash($known_extensions);
419
420 foreach (keys %known_extensions) {
11ea18f2 421 $skip{$_} = 1 unless $extensions{$_};
6234cb77 422 }
a3323f52
NC
423
424 my @results;
7ebf5c89 425 my $mani = '../MANIFEST';
7a315204 426 if (open(MANI, $mani)) {
18869dc6 427 while (<MANI>) {
a193a2db 428 if (m!^((?:cpan|dist|ext)/(\S+)/+(?:[^/\s]+\.t|test\.pl)|lib/\S+?(?:\.t|test\.pl))\s!) {
80ed0dea
DM
429 my $t = $1;
430 my $extension = $2;
2e0cc28b
KW
431
432 # XXX Generates way too many error lines currently. Skip for
433 # v5.22
434 next if $t =~ /^cpan/ && ord("A") != 65;
435
a3323f52 436 if (!$::core || $t =~ m!^lib/[a-z]!) {
6234cb77 437 if (defined $extension) {
b12cb1ba 438 $extension =~ s!/t(:?/\S+)*$!!;
6234cb77
NC
439 # XXX Do I want to warn that I'm skipping these?
440 next if $skip{$extension};
142f6a0d 441 my $flat_extension = $extension;
6ebb0601
CB
442 $flat_extension =~ s!-!/!g;
443 next if $skip{$flat_extension}; # Foo/Bar may live in Foo-Bar
6234cb77 444 }
7ebf5c89 445 my $path = "../$t";
a3323f52 446 push @results, $path;
80ed0dea 447 $::path_to_name{$path} = $t;
5a6e071d 448 }
7a315204
JH
449 }
450 }
35d88760 451 close MANI;
7a315204 452 } else {
f458b6e8 453 warn "$0: cannot open $mani: $!\n";
7a315204 454 }
a3323f52
NC
455 return @results;
456}
457
458unless (@ARGV) {
459 # base first, as TEST bails out if that can't run
460 # then comp, to validate that require works
461 # then run, to validate that -M works
462 # then we know we can -MTestInit for everything else, making life simpler
560a5958 463 foreach my $dir (qw(base comp run cmd io re opbasic op uni mro perf)) {
a3323f52
NC
464 _find_tests($dir);
465 }
cc306f49
NC
466 unless ($::core) {
467 _find_tests('porting');
468 _find_tests("lib");
469 }
a3323f52
NC
470 # Config.pm may be broken for make minitest. And this is only a refinement
471 # for skipping tests on non-default builds, so it is allowed to fail.
472 # What we want to to is make a list of extensions which we did not build.
473 my $configsh = '../config.sh';
474 my ($extensions, $known_extensions);
475 if (-f $configsh) {
476 open FH, $configsh or die "Can't open $configsh: $!";
477 while (<FH>) {
478 if (/^extensions=['"](.*)['"]$/) {
479 $extensions = $1;
480 }
481 elsif (/^known_extensions=['"](.*)['"]$/) {
482 $known_extensions = $1;
483 }
484 }
485 if (!defined $known_extensions) {
486 warn "No known_extensions line found in $configsh";
487 }
488 if (!defined $extensions) {
489 warn "No extensions line found in $configsh";
490 }
491 }
492 # The "complex" constructions of list return from a subroutine, and push of
493 # a list, might fail if perl is really hosed, but they aren't needed for
494 # make minitest, and the building of extensions will likely also fail if
495 # something is that badly wrong.
496 push @ARGV, _tests_from_manifest($extensions, $known_extensions);
80ed0dea 497 unless ($::core) {
80ed0dea 498 _find_tests('japh') if $::torture;
7e71d4a4 499 _find_tests('benchmark') if $::benchmark or $ENV{PERL_BENCHMARK};
ff5db609 500 _find_tests('bigmem') if $ENV{PERL_TEST_MEMORY};
e018f8be 501 }
8d063cd8 502}
60fae40d
YO
503@ARGV= do {
504 my @order= (
505 "base",
506 "comp",
507 "run",
508 "cmd",
509 "io",
510 "re",
511 "opbasic",
512 "op",
513 "uni",
514 "mro",
515 "lib",
516 "ext",
517 "dist",
518 "cpan",
519 "perf",
520 "porting",
521 );
522 my %order= map { $order[$_] => 1+$_ } 0..$#order;
523 my $idx= 0;
524 map {
525 $_->[0]
526 } sort {
527 $a->[3] <=> $b->[3] ||
528 $a->[1] <=> $b->[1]
529 } map {
530 my $root= /(\w+)/ ? $1 : "";
531 [ $_, $idx++, $root, $order{$root}||=0 ]
532 } @ARGV;
533};
8d063cd8 534
80ed0dea 535if ($::deparse) {
f193aa2f
MS
536 _testprogs('deparse', '', @ARGV);
537}
80ed0dea 538elsif ($::with_utf16) {
1de9afcd
RGS
539 for my $e (0, 1) {
540 for my $b (0, 1) {
541 print STDERR "# ENDIAN $e BOM $b\n";
542 my @UARGV;
543 for my $a (@ARGV) {
544 my $u = $a . "." . ($e ? "l" : "b") . "e" . ($b ? "b" : "");
545 my $f = $e ? "v" : "n";
546 push @UARGV, $u;
547 unlink($u);
548 if (open(A, $a)) {
549 if (open(U, ">$u")) {
90f6ca78 550 print U pack("$f", 0xFEFF) if $b;
1de9afcd
RGS
551 while (<A>) {
552 print U pack("$f*", unpack("C*", $_));
553 }
80ed0dea 554 close(U);
1de9afcd 555 }
80ed0dea 556 close(A);
1de9afcd
RGS
557 }
558 }
559 _testprogs('perl', '', @UARGV);
560 unlink(@UARGV);
561 }
562 }
563}
f193aa2f 564else {
f193aa2f 565 _testprogs('perl', '', @ARGV);
485988ae 566}
6ee623d5 567
bb365837 568sub _testprogs {
80ed0dea 569 my ($type, $args, @tests) = @_;
6ee623d5 570
485988ae 571 print <<'EOT' if ($type eq 'deparse');
7a315204 572------------------------------------------------------------------------------
485988ae 573TESTING DEPARSER
7a315204 574------------------------------------------------------------------------------
485988ae
RH
575EOT
576
80ed0dea 577 $::bad_files = 0;
73ddec28 578
cc6ae9e5 579 foreach my $t (@tests) {
80ed0dea 580 unless (exists $::path_to_name{$t}) {
7ebf5c89 581 my $tname = "t/$t";
f458b6e8 582 $::path_to_name{$t} = $tname;
cc6ae9e5 583 }
73ddec28 584 }
908801fe 585 my $maxlen = 0;
80ed0dea 586 foreach (@::path_to_name{@tests}) {
f7b9b043 587 s/\.\w+\z/ /; # space gives easy doubleclick to select fname
73ddec28
RB
588 my $len = length ;
589 $maxlen = $len if $len > $maxlen;
088b5126 590 }
908801fe 591 # + 3 : we want three dots between the test name and the "ok"
80ed0dea 592 my $dotdotdot = $maxlen + 3 ;
c7b956bb 593 my $grind_ct = 0; # count of non-empty valgrind reports
80ed0dea
DM
594 my $total_files = @tests;
595 my $good_files = 0;
33c0d182 596 my $tested_files = 0;
fb7ba3c8 597 my $totmax = 0;
ade55ef4 598 my %failed_tests;
10d90405 599 my @unexpected_pass; # files where deparse-skips.txt says fail but passed
c96083ea 600 my $toolnm; # valgrind, cachegrind, perf
80ed0dea 601
551405c4 602 while (my $test = shift @tests) {
25a2b27f
JC
603 my ($test_start_time, @starttimes) = 0;
604 if ($show_elapsed_time) {
605 $test_start_time = Time::HiRes::time();
606 # times() reports usage by TEST, but we want usage of each
607 # testprog it calls, so record accumulated times now,
608 # subtract them out afterwards. Ideally, we'd take times
609 # in BEGIN/END blocks (giving better visibility of self vs
610 # children of each testprog), but that would require some
611 # IPC to send results back here, or a completely different
8bdd21ca 612 # collection scheme (Storable isn't tuned for incremental use)
25a2b27f
JC
613 @starttimes = times;
614 }
bb365837
GS
615 if ($test =~ /^$/) {
616 next;
6ee623d5 617 }
2722144b
MH
618 if ($type eq 'deparse' && $test =~ $deparse_skips) {
619 next;
485988ae 620 }
80ed0dea 621 my $te = $::path_to_name{$test} . '.'
f7b9b043 622 x ($dotdotdot - length($::path_to_name{$test})) .' ';
cc6ae9e5
CB
623
624 if ($^O ne 'VMS') { # defer printing on VMS due to piping bug
625 print $te;
626 $te = '';
627 }
bb365837 628
be075caf
MH
629 (local $Valgrind_Log = "$test.valgrind-current") =~ s/^.*\///;
630
999051eb 631 my $results = _run_test($test, $type);
d638aca2 632
33c0d182 633 my $failure;
e1a5ed7a
JH
634 my $next = 0;
635 my $seen_leader = 0;
636 my $seen_ok = 0;
637 my $trailing_leader = 0;
638 my $max;
43fe0836 639 my %todo;
84650816 640 while (<$results>) {
cc6ae9e5 641 next if /^\s*$/; # skip blank lines
615b7a35
JM
642 if (/^1..$/ && ($^O eq 'VMS')) {
643 # VMS pipe bug inserts blank lines.
5403a9a2 644 my $l2 = <$results>;
615b7a35 645 if ($l2 =~ /^\s*$/) {
5403a9a2 646 $l2 = <$results>;
615b7a35
JM
647 }
648 $_ = '1..' . $l2;
649 }
80ed0dea 650 if ($::verbose) {
bb365837
GS
651 print $_;
652 }
21c74f43 653 unless (/^\#/) {
fb7ba3c8
JH
654 if ($trailing_leader) {
655 # shouldn't be anything following a postfix 1..n
656 $failure = 'FAILED--extra output after trailing 1..n';
657 last;
658 }
809908f7 659 if (/^1\.\.([0-9]+)( todo ([\d ]+))?/) {
fb7ba3c8
JH
660 if ($seen_leader) {
661 $failure = 'FAILED--seen duplicate leader';
662 last;
663 }
664 $max = $1;
665 %todo = map { $_ => 1 } split / /, $3 if $3;
666 $totmax = $totmax + $max;
667 $tested_files = $tested_files + 1;
668 if ($seen_ok) {
669 # 1..n appears at end of file
670 $trailing_leader = 1;
671 if ($next != $max) {
672 $failure = "FAILED--expected $max tests, saw $next";
20f82676
DM
673 last;
674 }
675 }
fb7ba3c8
JH
676 else {
677 $next = 0;
20f82676 678 }
fb7ba3c8 679 $seen_leader = 1;
bb365837
GS
680 }
681 else {
fb7ba3c8
JH
682 if (/^(not )?ok(?: (\d+))?[^\#]*(\s*\#.*)?/) {
683 unless ($seen_leader) {
684 unless ($seen_ok) {
685 $next = 0;
686 }
687 }
688 $seen_ok = 1;
11ea18f2 689 $next = $next + 1;
fb7ba3c8
JH
690 my($not, $num, $extra, $istodo) = ($1, $2, $3, 0);
691 $num = $next unless $num;
692
693 if ($num == $next) {
f458b6e8 694
eac7c728
MB
695 # SKIP is essentially the same as TODO for t/TEST
696 # this still conforms to TAP:
464a08e7 697 # http://testanything.org/wiki/index.php/TAP_specification
eac7c728 698 $extra and $istodo = $extra =~ /#\s*(?:TODO|SKIP)\b/;
21c74f43
A
699 $istodo = 1 if $todo{$num};
700
701 if( $not && !$istodo ) {
20f82676 702 $failure = "FAILED at test $num";
21c74f43
A
703 last;
704 }
20f82676 705 }
fb7ba3c8
JH
706 else {
707 $failure ="FAILED--expected test $next, saw test $num";
708 last;
709 }
f458b6e8
MS
710 }
711 elsif (/^Bail out!\s*(.*)/i) { # magic words
712 die "FAILED--Further testing stopped" . ($1 ? ": $1\n" : ".\n");
bb365837
GS
713 }
714 else {
dbf51d07
YST
715 # module tests are allowed extra output,
716 # because Test::Harness allows it
4d834435 717 next if $test =~ /^\W*(cpan|dist|ext|lib)\b/;
a5890677 718 $failure = "FAILED--unexpected output at test $next";
20f82676 719 last;
bb365837 720 }
8d063cd8
LW
721 }
722 }
723 }
983c6181
KW
724 my @junk = <$results>; # dump remaining output to prevent SIGPIPE
725 # (so far happens only on os390)
84650816 726 close $results;
983c6181 727 undef @junk;
20f82676 728
33c0d182 729 if (not defined $failure) {
fb7ba3c8 730 $failure = 'FAILED--no leader found' unless $seen_leader;
20f82676
DM
731 }
732
be075caf
MH
733 _check_valgrind(\$toolnm, \$grind_ct, \$test);
734
2722144b 735 if ($type eq 'deparse' && !$ENV{KEEP_DEPARSE_FILES}) {
485988ae
RH
736 unlink "./$test.dp";
737 }
33c0d182 738 if (not defined $failure and $next != $max) {
fb7ba3c8 739 $failure="FAILED--expected $max tests, saw $next";
20f82676
DM
740 }
741
33c0d182
JH
742 if( !defined $failure # don't mask a test failure
743 and $? )
744 {
343bc60d
MS
745 $failure = "FAILED--non-zero wait status: $?";
746 }
747
2722144b
MH
748 # Deparse? Should it have passed or failed?
749 if ($type eq 'deparse' && $test =~ $deparse_failures) {
750 if (!$failure) {
dcf4c706 751 # Wait, it didn't fail? Great news!
10d90405 752 push @unexpected_pass, $test;
2722144b
MH
753 } else {
754 # Bah, still failing. Mask it.
755 print "${te}skipped\n";
756 $tested_files = $tested_files - 1;
757 next;
758 }
759 }
760
33c0d182 761 if (defined $failure) {
20f82676 762 print "${te}$failure\n";
11ea18f2 763 $::bad_files = $::bad_files + 1;
25a4a90c
KW
764 if ($test =~ /^base/ && ! defined &DynaLoader::boot_DynaLoader) {
765 # Die if running under minitest (no DynaLoader). Otherwise
766 # keep going, as we know that Perl basically works, or we
767 # would not have been able to actually compile it all the way.
768 die "Failed a basic test ($test) under minitest -- cannot continue.\n";
20f82676 769 }
11ea18f2 770 $failed_tests{$test} = 1;
20f82676
DM
771 }
772 else {
fb7ba3c8 773 if ($max) {
b49055e9 774 my ($elapsed, $etms) = ("", 0);
551405c4 775 if ( $show_elapsed_time ) {
b49055e9 776 $etms = (Time::HiRes::time() - $test_start_time) * 1000;
25a2b27f
JC
777 $elapsed = sprintf(" %8.0f ms", $etms);
778
779 my (@endtimes) = times;
780 $endtimes[$_] -= $starttimes[$_] for 0..$#endtimes;
781 splice @endtimes, 0, 2; # drop self/harness times
782 $_ *= 1000 for @endtimes; # and scale to ms
783 $timings{$test} = [$etms,@endtimes];
784 $elapsed .= sprintf(" %5.0f ms", $_) for @endtimes;
551405c4
AL
785 }
786 print "${te}ok$elapsed\n";
11ea18f2 787 $good_files = $good_files + 1;
bb365837
GS
788 }
789 else {
6b202754 790 print "${te}skipped\n";
11ea18f2 791 $tested_files = $tested_files - 1;
bb365837 792 }
bcce72a7 793 }
551405c4 794 } # while tests
8d063cd8 795
80ed0dea 796 if ($::bad_files == 0) {
20f82676 797 if ($good_files) {
bb365837
GS
798 print "All tests successful.\n";
799 # XXX add mention of 'perlbug -ok' ?
800 }
801 else {
802 die "FAILED--no tests were run for some reason.\n";
803 }
8d063cd8 804 }
bb365837 805 else {
80ed0dea 806 my $pct = $tested_files ? sprintf("%.2f", ($tested_files - $::bad_files) / $tested_files * 100) : "0.00";
ade55ef4
AL
807 my $s = $::bad_files == 1 ? "" : "s";
808 warn "Failed $::bad_files test$s out of $tested_files, $pct% okay.\n";
809 for my $test ( sort keys %failed_tests ) {
810 print "\t$test\n";
bb365837 811 }
10d90405
DM
812
813 if (@unexpected_pass) {
814 print <<EOF;
815
816The following scripts were expected to fail under -deparse (at least
817according to $deparse_skip_file), but unexpectedly succeeded:
818EOF
819 print "\t$_\n" for sort @unexpected_pass;
820 print "\n";
821 }
822
4e4732c1 823 warn <<'SHRDLU_1';
f7d228c6
JH
824### Since not all tests were successful, you may want to run some of
825### them individually and examine any diagnostic messages they produce.
826### See the INSTALL document's section on "make test".
4e4732c1 827SHRDLU_1
80ed0dea 828 warn <<'SHRDLU_2' if $good_files / $total_files > 0.8;
f7d228c6
JH
829### You have a good chance to get more information by running
830### ./perl harness
831### in the 't' directory since most (>=80%) of the tests succeeded.
4e4732c1 832SHRDLU_2
f458b6e8 833 if (eval {require Config; import Config; 1}) {
80ed0dea 834 if ($::Config{usedl} && (my $p = $::Config{ldlibpthname})) {
4e4732c1 835 warn <<SHRDLU_3;
f7d228c6
JH
836### You may have to set your dynamic library search path,
837### $p, to point to the build directory:
4e4732c1 838SHRDLU_3
f458b6e8 839 if (exists $ENV{$p} && $ENV{$p} ne '') {
4e4732c1 840 warn <<SHRDLU_4a;
f7d228c6
JH
841### setenv $p `pwd`:\$$p; cd t; ./perl harness
842### $p=`pwd`:\$$p; export $p; cd t; ./perl harness
843### export $p=`pwd`:\$$p; cd t; ./perl harness
4e4732c1 844SHRDLU_4a
f458b6e8 845 } else {
4e4732c1 846 warn <<SHRDLU_4b;
f7d228c6
JH
847### setenv $p `pwd`; cd t; ./perl harness
848### $p=`pwd`; export $p; cd t; ./perl harness
849### export $p=`pwd`; cd t; ./perl harness
4e4732c1 850SHRDLU_4b
f458b6e8 851 }
4e4732c1 852 warn <<SHRDLU_5;
f7d228c6
JH
853### for csh-style shells, like tcsh; or for traditional/modern
854### Bourne-style shells, like bash, ksh, and zsh, respectively.
4e4732c1 855SHRDLU_5
f458b6e8 856 }
afd33fa9 857 }
bb365837 858 }
94708f6d 859 printf "Elapsed: %d sec\n", time() - $t0;
80ed0dea 860 my ($user,$sys,$cuser,$csys) = times;
8e03ad8f
JC
861 my $tot = sprintf("u=%.2f s=%.2f cu=%.2f cs=%.2f scripts=%d tests=%d",
862 $user,$sys,$cuser,$csys,$tested_files,$totmax);
863 print "$tot\n";
864 if ($good_files) {
865 if (-d $show_elapsed_time) {
56e28cb0
JH
866 # HARNESS_TIMER = <a-directory>. Save timings etc to
867 # storable file there. NB: the test cds to ./t/, so
868 # relative path must account for that, ie ../../perf
869 # points to dir next to source tree.
8e03ad8f 870 require Storable;
133d407a
JH
871 my @dt = localtime;
872 $dt[5] += 1900; $dt[4] += 1; # fix year, month
873 my $fn = "$show_elapsed_time/".join('-', @dt[5,4,3,2,1]).".ttimes";
56e28cb0 874 Storable::store({ perf => \%timings,
8e03ad8f
JC
875 gather_conf_platform_info(),
876 total => $tot,
877 }, $fn);
878 print "wrote storable file: $fn\n";
879 }
880 }
be075caf
MH
881
882 _cleanup_valgrind(\$toolnm, \$grind_ct);
6ee623d5 883}
80ed0dea 884exit ($::bad_files != 0);
ade55ef4 885
8e03ad8f
JC
886# Collect platform, config data that should allow comparing
887# performance data between different machines. With enough data,
888# and/or clever statistical analysis, it should be possible to
889# determine the effect of config choices, more memory, etc
890
891sub gather_conf_platform_info {
892 # currently rather quick & dirty, and subject to change
893 # for both content and format.
894 require Config;
895 my (%conf, @platform) = ();
896 $conf{$_} = $Config::Config{$_} for
897 grep /cc|git|config_arg\d+/, keys %Config::Config;
898 if (-f '/proc/cpuinfo') {
899 open my $fh, '/proc/cpuinfo' or warn "$!: /proc/cpuinfo\n";
900 @platform = grep /name|cpu/, <$fh>;
901 chomp $_ for @platform;
902 }
903 unshift @platform, $^O;
904
905 return (
906 conf => \%conf,
907 platform => {cpu => \@platform,
908 mem => [ grep s/\s+/ /,
909 grep chomp, `free` ],
910 load => [ grep chomp, `uptime` ],
911 },
912 host => (grep chomp, `hostname -f`),
56e28cb0 913 version => '0.03', # bump for conf, platform, or data collection changes
8e03ad8f
JC
914 );
915}
916
be075caf
MH
917sub _check_valgrind {
918 return unless $ENV{PERL_VALGRIND};
919
920 my ($toolnm, $grind_ct, $test) = @_;
921
922 $$toolnm = $ENV{VALGRIND};
923 $$toolnm =~ s|.*/||; # keep basename
924 my @valgrind; # gets content of file
925 if (-e $Valgrind_Log) {
926 if (open(V, $Valgrind_Log)) {
927 @valgrind = <V>;
928 close V;
929 } else {
930 warn "$0: Failed to open '$Valgrind_Log': $!\n";
931 }
932 }
933 if ($ENV{VG_OPTS} =~ /(cachegrind)/ or $$toolnm =~ /(perf)/) {
934 $$toolnm = $1;
935 if ($$toolnm eq 'perf') {
e73fd51e 936 # append perfs subcommand, not just stat
be075caf
MH
937 my ($sub) = split /\s/, $ENV{VG_OPTS};
938 $$toolnm .= "-$sub";
939 }
940 if (rename $Valgrind_Log, "$$test.$$toolnm") {
941 $$grind_ct++;
942 } else {
943 warn "$0: Failed to create '$$test.$$toolnm': $!\n";
944 }
945 }
946 elsif (@valgrind) {
947 my $leaks = 0;
948 my $errors = 0;
949 for my $i (0..$#valgrind) {
950 local $_ = $valgrind[$i];
951 if (/^==\d+== ERROR SUMMARY: (\d+) errors? /) {
952 $errors = $errors + $1; # there may be multiple error summaries
953 } elsif (/^==\d+== LEAK SUMMARY:/) {
954 for my $off (1 .. 4) {
955 if ($valgrind[$i+$off] =~
956 /(?:lost|reachable):\s+\d+ bytes in (\d+) blocks/) {
957 $leaks = $leaks + $1;
958 }
959 }
960 }
961 }
962 if ($errors or $leaks) {
963 if (rename $Valgrind_Log, "$$test.valgrind") {
964 $$grind_ct = $$grind_ct + 1;
965 } else {
966 warn "$0: Failed to create '$$test.valgrind': $!\n";
967 }
968 }
969 } else {
970 # Quiet wasn't asked for? Something may be amiss
971 if ($ENV{VG_OPTS} && $ENV{VG_OPTS} !~ /(^|\s)(-q|--quiet)(\s|$)/) {
972 warn "No valgrind output?\n";
973 }
974 }
975 if (-e $Valgrind_Log) {
976 unlink $Valgrind_Log
977 or warn "$0: Failed to unlink '$Valgrind_Log': $!\n";
978 }
979}
980
981sub _cleanup_valgrind {
982 return unless $ENV{PERL_VALGRIND};
983
984 my ($toolnm, $grind_ct) = @_;
985 my $s = $$grind_ct == 1 ? '' : 's';
986 print "$$grind_ct valgrind report$s created.\n", ;
987 if ($$toolnm eq 'cachegrind') {
988 # cachegrind leaves a lot of cachegrind.out.$pid litter
989 # around the tree, find and delete them
990 unlink _find_files('cachegrind.out.\d+$',
991 qw ( ../t ../cpan ../ext ../dist/ ));
992 }
993}
994
2722144b 995# Generate regexps of known bad filenames / skips from Porting/deparse-skips.txt
2722144b
MH
996
997sub _process_deparse_config {
998 my @deparse_failures;
999 my @deparse_skips;
1000
10d90405 1001 my $f = $deparse_skip_file;
2722144b
MH
1002
1003 my $skips;
1004 if (!open($skips, '<', $f)) {
1005 warn "Failed to find $f: $!\n";
1006 return;
1007 }
1008
94021b25 1009 my $in;
2722144b
MH
1010 while(<$skips>) {
1011 if (/__DEPARSE_FAILURES__/) {
1012 $in = \@deparse_failures; next;
1013 } elsif (/__DEPARSE_SKIPS__/) {
1014 $in = \@deparse_skips; next;
1015 } elsif (!$in) {
1016 next;
1017 }
1018
1019 s/#.*$//; # Kill comments
1020 s/\s+$//; # And trailing whitespace
1021
1022 next unless $_;
1023
1024 push @$in, $_;
94021b25 1025 warn "WARNING: $f:$.: excluded file doesn't exist: $_\n" unless -f $_;
2722144b
MH
1026 }
1027
1028 for my $f (@deparse_failures, @deparse_skips) {
1029 if ($f =~ m|/$|) { # Dir? Skip everything below it
1030 $f = qr/\Q$f\E.*/;
1031 } else {
1032 $f = qr/\Q$f\E/;
1033 }
1034 }
1035
1036 $deparse_failures = join('|', @deparse_failures);
1037 $deparse_failures = qr/^(?:$deparse_failures)$/;
1038
1039 $deparse_skips = join('|', @deparse_skips);
1040 $deparse_skips = qr/^(?:$deparse_skips)$/;
1041}
1042
ade55ef4 1043# ex: set ts=8 sts=4 sw=4 noet: