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