1*f2a19305Safresh1#!perl 2*f2a19305Safresh1# this should be perl 5.8 compatible, since it will be used 3*f2a19305Safresh1# with old perls while testing dist modules on those perls 4*f2a19305Safresh1use strict; 5*f2a19305Safresh1use warnings; 6*f2a19305Safresh1use File::Temp "tempdir"; 7*f2a19305Safresh1use ExtUtils::Manifest "maniread"; 8*f2a19305Safresh1use Cwd "getcwd"; 9*f2a19305Safresh1use Getopt::Long; 10*f2a19305Safresh1use Config; 11*f2a19305Safresh1 12*f2a19305Safresh1my $continue; 13*f2a19305Safresh1my $separate; 14*f2a19305Safresh1GetOptions("c|continue" => \$continue, 15*f2a19305Safresh1 "s|separate" => \$separate, 16*f2a19305Safresh1 "h|help" => \&usage) 17*f2a19305Safresh1 or die "Unknown options\n"; 18*f2a19305Safresh1 19*f2a19305Safresh1$|++; 20*f2a19305Safresh1 21*f2a19305Safresh1-f "Configure" 22*f2a19305Safresh1 or die "Expected to be run from a perl checkout"; 23*f2a19305Safresh1 24*f2a19305Safresh1my $github_ci = $ENV{'GITHUB_SHA'} ? 1 : 0; 25*f2a19305Safresh1 26*f2a19305Safresh1my $manifest = maniread(); 27*f2a19305Safresh1my @failures = (); 28*f2a19305Safresh1 29*f2a19305Safresh1my @config; 30*f2a19305Safresh1my $install_path; 31*f2a19305Safresh1if ($separate) { 32*f2a19305Safresh1 # require EU::MM 6.31 or later 33*f2a19305Safresh1 my $install_base = tempdir( CLEANUP => 1 ); 34*f2a19305Safresh1 push @config, "INSTALL_BASE=$install_base"; 35*f2a19305Safresh1 $ENV{PERL5LIB} .= $Config{path_sep} if $ENV{PERL5LIB}; 36*f2a19305Safresh1 $ENV{PERL5LIB} .= join $Config{path_sep}, 37*f2a19305Safresh1 "$install_base/lib/perl5/$Config{archname}", 38*f2a19305Safresh1 "$install_base/lib/perl5"; 39*f2a19305Safresh1} 40*f2a19305Safresh1 41*f2a19305Safresh1my %dist_config = ( 42*f2a19305Safresh1 # these are defined by the modules as distributed on CPAN 43*f2a19305Safresh1 # I don't know why their Makefile.PLs aren't in core 44*f2a19305Safresh1 "threads" => [ "DEFINE=-DHAS_PPPORT_H" ], 45*f2a19305Safresh1 "threads-shared" => [ "DEFINE=-DHAS_PPPORT_H" ], 46*f2a19305Safresh1 ); 47*f2a19305Safresh1 48*f2a19305Safresh1my $start = getcwd() 49*f2a19305Safresh1 or die "Cannot fetch current directory: $!\n"; 50*f2a19305Safresh1 51*f2a19305Safresh1# get ppport.h 52*f2a19305Safresh1my $pppdir = test_dist("Devel-PPPort"); 53*f2a19305Safresh1 54*f2a19305Safresh1if (@failures) { 55*f2a19305Safresh1 if ($github_ci) { 56*f2a19305Safresh1 # GitHub may show STDERR before STDOUT.. despite autoflush 57*f2a19305Safresh1 # being enabled.. Make sure it detects the 'endgroup' before 58*f2a19305Safresh1 # the `die` statement. 59*f2a19305Safresh1 print STDERR "::endgroup::\n"; 60*f2a19305Safresh1 } 61*f2a19305Safresh1 die "Devel-PPPort failed, aborting other tests.\n"; 62*f2a19305Safresh1} 63*f2a19305Safresh1 64*f2a19305Safresh1my $pppfile = "$pppdir/ppport.h"; 65*f2a19305Safresh1 66*f2a19305Safresh1-f $pppfile 67*f2a19305Safresh1 or die "No ppport.h found in $pppdir\n"; 68*f2a19305Safresh1 69*f2a19305Safresh1# Devel-PPPort is manually processed before anything else to ensure we 70*f2a19305Safresh1# have an up to date ppport.h 71*f2a19305Safresh1my @dists = @ARGV; 72*f2a19305Safresh1if (@dists) { 73*f2a19305Safresh1 for my $dist (@dists) { 74*f2a19305Safresh1 -d "dist/$dist" or die "dist/$dist not a directory\n"; 75*f2a19305Safresh1 } 76*f2a19305Safresh1} 77*f2a19305Safresh1else { 78*f2a19305Safresh1 opendir my $distdir, "dist" 79*f2a19305Safresh1 or die "Cannot opendir 'dist': $!\n"; 80*f2a19305Safresh1 @dists = sort { lc $a cmp lc $b } grep { /^\w/ && $_ ne "Devel-PPPort" } readdir $distdir; 81*f2a19305Safresh1 closedir $distdir; 82*f2a19305Safresh1} 83*f2a19305Safresh1 84*f2a19305Safresh1# These may end up being included if their problems are resolved 85*f2a19305Safresh1{ 86*f2a19305Safresh1 # https://github.com/Perl/version.pm claims CPAN is upstream 87*f2a19305Safresh1 @dists = grep { $_ ne "version" } @dists; 88*f2a19305Safresh1 89*f2a19305Safresh1 # Safe is tied pretty heavily to core 90*f2a19305Safresh1 # in any case it didn't seem simple to fix 91*f2a19305Safresh1 @dists = grep { $_ ne "Safe" } @dists; 92*f2a19305Safresh1} 93*f2a19305Safresh1 94*f2a19305Safresh1for my $dist (@dists) { 95*f2a19305Safresh1 test_dist($dist); 96*f2a19305Safresh1} 97*f2a19305Safresh1 98*f2a19305Safresh1if (@failures) { 99*f2a19305Safresh1 if ($github_ci) { 100*f2a19305Safresh1 # GitHub may show STDERR before STDOUT.. despite autoflush 101*f2a19305Safresh1 # being enabled.. Make sure it detects the 'endgroup' before 102*f2a19305Safresh1 # the `die` statement. 103*f2a19305Safresh1 print STDERR "::endgroup::\n"; 104*f2a19305Safresh1 } 105*f2a19305Safresh1 my $msg = join("\n", map { "\t'$_->[0]' failed at $_->[1]" } @failures); 106*f2a19305Safresh1 die "Following dists had failures:\n$msg\n"; 107*f2a19305Safresh1} 108*f2a19305Safresh1 109*f2a19305Safresh1sub test_dist { 110*f2a19305Safresh1 my ($name) = @_; 111*f2a19305Safresh1 112*f2a19305Safresh1 print "::group::Testing $name\n" if $github_ci; 113*f2a19305Safresh1 print "*** Testing $name ***\n"; 114*f2a19305Safresh1 my $dir = tempdir( CLEANUP => 1); 115*f2a19305Safresh1 run("cp", "-a", "dist/$name/.", "$dir/.") 116*f2a19305Safresh1 or die "Cannot copy dist files to working directory\n"; 117*f2a19305Safresh1 chdir $dir 118*f2a19305Safresh1 or die "Cannot chdir to dist working directory '$dir': $!\n"; 119*f2a19305Safresh1 if ($pppfile) { 120*f2a19305Safresh1 run("cp", $pppfile, ".") 121*f2a19305Safresh1 or die "Cannot copy $pppfile to .\n"; 122*f2a19305Safresh1 } 123*f2a19305Safresh1 if ($name eq "IO" || $name eq "threads" || $name eq "threads-shared") { 124*f2a19305Safresh1 write_testpl(); 125*f2a19305Safresh1 } 126*f2a19305Safresh1 if ($name eq "threads" || $name eq "threads-shared") { 127*f2a19305Safresh1 write_threads_h(); 128*f2a19305Safresh1 } 129*f2a19305Safresh1 if ($name eq "threads-shared") { 130*f2a19305Safresh1 write_shared_h(); 131*f2a19305Safresh1 } 132*f2a19305Safresh1 unless (-f "Makefile.PL") { 133*f2a19305Safresh1 print " Creating Makefile.PL for $name\n"; 134*f2a19305Safresh1 my $key = "ABSTRACT_FROM"; 135*f2a19305Safresh1 my @parts = split /-/, $name; 136*f2a19305Safresh1 my $last = $parts[-1]; 137*f2a19305Safresh1 my $module = join "::", @parts; 138*f2a19305Safresh1 my $fromname; 139*f2a19305Safresh1 for my $check ("$last.pm", join("/", "lib", @parts) . ".pm") { 140*f2a19305Safresh1 if (-f $check) { 141*f2a19305Safresh1 $fromname = $check; 142*f2a19305Safresh1 last; 143*f2a19305Safresh1 } 144*f2a19305Safresh1 } 145*f2a19305Safresh1 $fromname 146*f2a19305Safresh1 or die "Cannot find ABSTRACT_FROM for $name\n"; 147*f2a19305Safresh1 my $value = $fromname; 148*f2a19305Safresh1 open my $fh, ">", "Makefile.PL" 149*f2a19305Safresh1 or die "Cannot create Makefile.PL: $!\n"; 150*f2a19305Safresh1 # adapted from make_ext.pl 151*f2a19305Safresh1 printf $fh <<'EOM', $module, $fromname, $key, $value; 152*f2a19305Safresh1use strict; 153*f2a19305Safresh1use ExtUtils::MakeMaker; 154*f2a19305Safresh1 155*f2a19305Safresh1# This is what the .PL extracts to. Not the ultimate file that is installed. 156*f2a19305Safresh1# (ie Win32 runs pl2bat after this) 157*f2a19305Safresh1 158*f2a19305Safresh1# Doing this here avoids all sort of quoting issues that would come from 159*f2a19305Safresh1# attempting to write out perl source with literals to generate the arrays and 160*f2a19305Safresh1# hash. 161*f2a19305Safresh1my @temps = 'Makefile.PL'; 162*f2a19305Safresh1foreach (glob('scripts/pod*.PL')) { 163*f2a19305Safresh1 # The various pod*.PL extractors change directory. Doing that with relative 164*f2a19305Safresh1 # paths in @INC breaks. It seems the lesser of two evils to copy (to avoid) 165*f2a19305Safresh1 # the chdir doing anything, than to attempt to convert lib paths to 166*f2a19305Safresh1 # absolute, and potentially run into problems with quoting special 167*f2a19305Safresh1 # characters in the path to our build dir (such as spaces) 168*f2a19305Safresh1 require File::Copy; 169*f2a19305Safresh1 170*f2a19305Safresh1 my $temp = $_; 171*f2a19305Safresh1 $temp =~ s!scripts/!!; 172*f2a19305Safresh1 File::Copy::copy($_, $temp) or die "Can't copy $temp to $_: $!"; 173*f2a19305Safresh1 push @temps, $temp; 174*f2a19305Safresh1} 175*f2a19305Safresh1 176*f2a19305Safresh1my $script_ext = $^O eq 'VMS' ? '.com' : ''; 177*f2a19305Safresh1my %%pod_scripts; 178*f2a19305Safresh1foreach (glob('pod*.PL')) { 179*f2a19305Safresh1 my $script = $_; 180*f2a19305Safresh1 s/.PL$/$script_ext/i; 181*f2a19305Safresh1 $pod_scripts{$script} = $_; 182*f2a19305Safresh1} 183*f2a19305Safresh1my @exe_files = values %%pod_scripts; 184*f2a19305Safresh1 185*f2a19305Safresh1WriteMakefile( 186*f2a19305Safresh1 NAME => '%s', 187*f2a19305Safresh1 VERSION_FROM => '%s', 188*f2a19305Safresh1 %-13s => '%s', 189*f2a19305Safresh1 realclean => { FILES => "@temps" }, 190*f2a19305Safresh1 (%%pod_scripts ? ( 191*f2a19305Safresh1 PL_FILES => \%%pod_scripts, 192*f2a19305Safresh1 EXE_FILES => \@exe_files, 193*f2a19305Safresh1 clean => { FILES => "@exe_files" }, 194*f2a19305Safresh1 ) : ()), 195*f2a19305Safresh1); 196*f2a19305Safresh1 197*f2a19305Safresh1EOM 198*f2a19305Safresh1 close $fh; 199*f2a19305Safresh1 } 200*f2a19305Safresh1 201*f2a19305Safresh1 my $verbose = $github_ci && $ENV{'RUNNER_DEBUG'} ? 1 : 0; 202*f2a19305Safresh1 my $failed = ""; 203*f2a19305Safresh1 my @my_config = @config; 204*f2a19305Safresh1 if (my $cfg = $dist_config{$name}) { 205*f2a19305Safresh1 push @my_config, @$cfg; 206*f2a19305Safresh1 } 207*f2a19305Safresh1 if (!run($^X, "Makefile.PL", @my_config)) { 208*f2a19305Safresh1 $failed = "Makefile.PL"; 209*f2a19305Safresh1 die "$name: Makefile.PL failed\n" unless $continue; 210*f2a19305Safresh1 } 211*f2a19305Safresh1 elsif (!run("make", "test", "TEST_VERBOSE=$verbose")) { 212*f2a19305Safresh1 $failed = "make test"; 213*f2a19305Safresh1 die "$name: make test failed\n" unless $continue; 214*f2a19305Safresh1 } 215*f2a19305Safresh1 elsif (!run("make", "install")) { 216*f2a19305Safresh1 $failed = "make install"; 217*f2a19305Safresh1 die "$name: make install failed\n" unless $continue; 218*f2a19305Safresh1 } 219*f2a19305Safresh1 220*f2a19305Safresh1 chdir $start 221*f2a19305Safresh1 or die "Cannot return to $start: $!\n"; 222*f2a19305Safresh1 223*f2a19305Safresh1 if ($github_ci) { 224*f2a19305Safresh1 print "::endgroup::\n"; 225*f2a19305Safresh1 } 226*f2a19305Safresh1 if ($continue && $failed) { 227*f2a19305Safresh1 print "::error ::$name failed at $failed\n" if $github_ci; 228*f2a19305Safresh1 push @failures, [ $name, $failed ]; 229*f2a19305Safresh1 } 230*f2a19305Safresh1 231*f2a19305Safresh1 $dir; 232*f2a19305Safresh1} 233*f2a19305Safresh1 234*f2a19305Safresh1# IO, threads and threads-shared use the blead t/test.pl when tested in core 235*f2a19305Safresh1# and bundle their own test.pl when distributed on CPAN. 236*f2a19305Safresh1# The test.pl source below is from the IO distribution but so far seems sufficient 237*f2a19305Safresh1# for threads and threads-shared. 238*f2a19305Safresh1sub write_testpl { 239*f2a19305Safresh1 _write_from_data("t/test.pl"); 240*f2a19305Safresh1} 241*f2a19305Safresh1 242*f2a19305Safresh1# threads and threads-shared bundle this file, which isn't needed in core 243*f2a19305Safresh1sub write_threads_h { 244*f2a19305Safresh1 _write_from_data("threads.h"); 245*f2a19305Safresh1} 246*f2a19305Safresh1 247*f2a19305Safresh1# threads-shared bundles this file, which isn't needed in core 248*f2a19305Safresh1sub write_shared_h { 249*f2a19305Safresh1 _write_from_data("shared.h"); 250*f2a19305Safresh1} 251*f2a19305Safresh1 252*f2a19305Safresh1# file data read from <DATA> 253*f2a19305Safresh1my %file_data; 254*f2a19305Safresh1 255*f2a19305Safresh1sub _write_from_data { 256*f2a19305Safresh1 my ($want_name) = @_; 257*f2a19305Safresh1 258*f2a19305Safresh1 unless (keys %file_data) { 259*f2a19305Safresh1 my $name; 260*f2a19305Safresh1 while (<DATA>) { 261*f2a19305Safresh1 if (/^-- (\S+) --/) { 262*f2a19305Safresh1 $name = $1; 263*f2a19305Safresh1 } 264*f2a19305Safresh1 else { 265*f2a19305Safresh1 $file_data{$name} .= $_; 266*f2a19305Safresh1 } 267*f2a19305Safresh1 } 268*f2a19305Safresh1 close DATA; 269*f2a19305Safresh1 } 270*f2a19305Safresh1 271*f2a19305Safresh1 my $data = $file_data{$want_name} or die "No data found for $want_name"; 272*f2a19305Safresh1 open my $fh, ">", $want_name 273*f2a19305Safresh1 or die "Cannot create $want_name: $!\n"; 274*f2a19305Safresh1 print $fh $data; 275*f2a19305Safresh1 close $fh 276*f2a19305Safresh1 or die "Cannot close $want_name: $!\n"; 277*f2a19305Safresh1} 278*f2a19305Safresh1 279*f2a19305Safresh1sub run { 280*f2a19305Safresh1 my (@cmd) = @_; 281*f2a19305Safresh1 282*f2a19305Safresh1 print "\$ @cmd\n"; 283*f2a19305Safresh1 my $result = system(@cmd); 284*f2a19305Safresh1 if ($result < 0) { 285*f2a19305Safresh1 print "Failed: $!\n"; 286*f2a19305Safresh1 } 287*f2a19305Safresh1 elsif ($result) { 288*f2a19305Safresh1 printf "Failed: %d (%#x)\n", $result, $?; 289*f2a19305Safresh1 } 290*f2a19305Safresh1 return $result == 0; 291*f2a19305Safresh1} 292*f2a19305Safresh1 293*f2a19305Safresh1sub usage { 294*f2a19305Safresh1 print <<EOS; 295*f2a19305Safresh1Usage: $^X $0 [options] [distnames] 296*f2a19305Safresh1 -c | -continue 297*f2a19305Safresh1 Continue processing after failures 298*f2a19305Safresh1 Devel::PPPort must successfully build to continue. 299*f2a19305Safresh1 -s | -separate 300*f2a19305Safresh1 Install to a work path, not to perl's site_perl. 301*f2a19305Safresh1 -h | -help 302*f2a19305Safresh1 Display this message. 303*f2a19305Safresh1 304*f2a19305Safresh1Optional distnames should be names of the distributions under dist/ to 305*f2a19305Safresh1test. If omitted all of the distributions under dist/ are tested. 306*f2a19305Safresh1Devel-PPPort is always tested. 307*f2a19305Safresh1 308*f2a19305Safresh1Test all of the distributions, stop on the first failure: 309*f2a19305Safresh1 310*f2a19305Safresh1 $^X $0 -s 311*f2a19305Safresh1 312*f2a19305Safresh1Test the various threads distributions, continue on failure: 313*f2a19305Safresh1 314*f2a19305Safresh1 $^X $0 -s -c threads threads-shared Thread-Queue Thread-Semaphore 315*f2a19305Safresh1EOS 316*f2a19305Safresh1} 317*f2a19305Safresh1 318*f2a19305Safresh1__DATA__ 319*f2a19305Safresh1-- t/test.pl -- 320*f2a19305Safresh1# 321*f2a19305Safresh1# t/test.pl - most of Test::More functionality without the fuss 322*f2a19305Safresh1 323*f2a19305Safresh1 324*f2a19305Safresh1# NOTE: 325*f2a19305Safresh1# 326*f2a19305Safresh1# Increment ($x++) has a certain amount of cleverness for things like 327*f2a19305Safresh1# 328*f2a19305Safresh1# $x = 'zz'; 329*f2a19305Safresh1# $x++; # $x eq 'aaa'; 330*f2a19305Safresh1# 331*f2a19305Safresh1# stands more chance of breaking than just a simple 332*f2a19305Safresh1# 333*f2a19305Safresh1# $x = $x + 1 334*f2a19305Safresh1# 335*f2a19305Safresh1# In this file, we use the latter "Baby Perl" approach, and increment 336*f2a19305Safresh1# will be worked over by t/op/inc.t 337*f2a19305Safresh1 338*f2a19305Safresh1$Level = 1; 339*f2a19305Safresh1my $test = 1; 340*f2a19305Safresh1my $planned; 341*f2a19305Safresh1my $noplan; 342*f2a19305Safresh1my $Perl; # Safer version of $^X set by which_perl() 343*f2a19305Safresh1 344*f2a19305Safresh1$TODO = 0; 345*f2a19305Safresh1$NO_ENDING = 0; 346*f2a19305Safresh1 347*f2a19305Safresh1# Use this instead of print to avoid interference while testing globals. 348*f2a19305Safresh1sub _print { 349*f2a19305Safresh1 local($\, $", $,) = (undef, ' ', ''); 350*f2a19305Safresh1 print STDOUT @_; 351*f2a19305Safresh1} 352*f2a19305Safresh1 353*f2a19305Safresh1sub _print_stderr { 354*f2a19305Safresh1 local($\, $", $,) = (undef, ' ', ''); 355*f2a19305Safresh1 print STDERR @_; 356*f2a19305Safresh1} 357*f2a19305Safresh1 358*f2a19305Safresh1sub plan { 359*f2a19305Safresh1 my $n; 360*f2a19305Safresh1 if (@_ == 1) { 361*f2a19305Safresh1 $n = shift; 362*f2a19305Safresh1 if ($n eq 'no_plan') { 363*f2a19305Safresh1 undef $n; 364*f2a19305Safresh1 $noplan = 1; 365*f2a19305Safresh1 } 366*f2a19305Safresh1 } else { 367*f2a19305Safresh1 my %plan = @_; 368*f2a19305Safresh1 $n = $plan{tests}; 369*f2a19305Safresh1 } 370*f2a19305Safresh1 _print "1..$n\n" unless $noplan; 371*f2a19305Safresh1 $planned = $n; 372*f2a19305Safresh1} 373*f2a19305Safresh1 374*f2a19305Safresh1END { 375*f2a19305Safresh1 my $ran = $test - 1; 376*f2a19305Safresh1 if (!$NO_ENDING) { 377*f2a19305Safresh1 if (defined $planned && $planned != $ran) { 378*f2a19305Safresh1 _print_stderr 379*f2a19305Safresh1 "# Looks like you planned $planned tests but ran $ran.\n"; 380*f2a19305Safresh1 } elsif ($noplan) { 381*f2a19305Safresh1 _print "1..$ran\n"; 382*f2a19305Safresh1 } 383*f2a19305Safresh1 } 384*f2a19305Safresh1} 385*f2a19305Safresh1 386*f2a19305Safresh1# Use this instead of "print STDERR" when outputing failure diagnostic 387*f2a19305Safresh1# messages 388*f2a19305Safresh1sub _diag { 389*f2a19305Safresh1 return unless @_; 390*f2a19305Safresh1 my @mess = map { /^#/ ? "$_\n" : "# $_\n" } 391*f2a19305Safresh1 map { split /\n/ } @_; 392*f2a19305Safresh1 $TODO ? _print(@mess) : _print_stderr(@mess); 393*f2a19305Safresh1} 394*f2a19305Safresh1 395*f2a19305Safresh1sub diag { 396*f2a19305Safresh1 _diag(@_); 397*f2a19305Safresh1} 398*f2a19305Safresh1 399*f2a19305Safresh1sub skip_all { 400*f2a19305Safresh1 if (@_) { 401*f2a19305Safresh1 _print "1..0 # Skip @_\n"; 402*f2a19305Safresh1 } else { 403*f2a19305Safresh1 _print "1..0\n"; 404*f2a19305Safresh1 } 405*f2a19305Safresh1 exit(0); 406*f2a19305Safresh1} 407*f2a19305Safresh1 408*f2a19305Safresh1sub _ok { 409*f2a19305Safresh1 my ($pass, $where, $name, @mess) = @_; 410*f2a19305Safresh1 # Do not try to microoptimize by factoring out the "not ". 411*f2a19305Safresh1 # VMS will avenge. 412*f2a19305Safresh1 my $out; 413*f2a19305Safresh1 if ($name) { 414*f2a19305Safresh1 # escape out '#' or it will interfere with '# skip' and such 415*f2a19305Safresh1 $name =~ s/#/\\#/g; 416*f2a19305Safresh1 $out = $pass ? "ok $test - $name" : "not ok $test - $name"; 417*f2a19305Safresh1 } else { 418*f2a19305Safresh1 $out = $pass ? "ok $test" : "not ok $test"; 419*f2a19305Safresh1 } 420*f2a19305Safresh1 421*f2a19305Safresh1 $out .= " # TODO $TODO" if $TODO; 422*f2a19305Safresh1 _print "$out\n"; 423*f2a19305Safresh1 424*f2a19305Safresh1 unless ($pass) { 425*f2a19305Safresh1 _diag "# Failed $where\n"; 426*f2a19305Safresh1 } 427*f2a19305Safresh1 428*f2a19305Safresh1 # Ensure that the message is properly escaped. 429*f2a19305Safresh1 _diag @mess; 430*f2a19305Safresh1 431*f2a19305Safresh1 $test = $test + 1; # don't use ++ 432*f2a19305Safresh1 433*f2a19305Safresh1 return $pass; 434*f2a19305Safresh1} 435*f2a19305Safresh1 436*f2a19305Safresh1sub _where { 437*f2a19305Safresh1 my @caller = caller($Level); 438*f2a19305Safresh1 return "at $caller[1] line $caller[2]"; 439*f2a19305Safresh1} 440*f2a19305Safresh1 441*f2a19305Safresh1# DON'T use this for matches. Use like() instead. 442*f2a19305Safresh1sub ok ($@) { 443*f2a19305Safresh1 my ($pass, $name, @mess) = @_; 444*f2a19305Safresh1 _ok($pass, _where(), $name, @mess); 445*f2a19305Safresh1} 446*f2a19305Safresh1 447*f2a19305Safresh1sub _q { 448*f2a19305Safresh1 my $x = shift; 449*f2a19305Safresh1 return 'undef' unless defined $x; 450*f2a19305Safresh1 my $q = $x; 451*f2a19305Safresh1 $q =~ s/\\/\\\\/g; 452*f2a19305Safresh1 $q =~ s/'/\\'/g; 453*f2a19305Safresh1 return "'$q'"; 454*f2a19305Safresh1} 455*f2a19305Safresh1 456*f2a19305Safresh1sub _qq { 457*f2a19305Safresh1 my $x = shift; 458*f2a19305Safresh1 return defined $x ? '"' . display ($x) . '"' : 'undef'; 459*f2a19305Safresh1}; 460*f2a19305Safresh1 461*f2a19305Safresh1# keys are the codes \n etc map to, values are 2 char strings such as \n 462*f2a19305Safresh1my %backslash_escape; 463*f2a19305Safresh1foreach my $x (split //, 'nrtfa\\\'"') { 464*f2a19305Safresh1 $backslash_escape{ord eval "\"\\$x\""} = "\\$x"; 465*f2a19305Safresh1} 466*f2a19305Safresh1# A way to display scalars containing control characters and Unicode. 467*f2a19305Safresh1# Trying to avoid setting $_, or relying on local $_ to work. 468*f2a19305Safresh1sub display { 469*f2a19305Safresh1 my @result; 470*f2a19305Safresh1 foreach my $x (@_) { 471*f2a19305Safresh1 if (defined $x and not ref $x) { 472*f2a19305Safresh1 my $y = ''; 473*f2a19305Safresh1 foreach my $c (unpack("U*", $x)) { 474*f2a19305Safresh1 if ($c > 255) { 475*f2a19305Safresh1 $y .= sprintf "\\x{%x}", $c; 476*f2a19305Safresh1 } elsif ($backslash_escape{$c}) { 477*f2a19305Safresh1 $y .= $backslash_escape{$c}; 478*f2a19305Safresh1 } else { 479*f2a19305Safresh1 my $z = chr $c; # Maybe we can get away with a literal... 480*f2a19305Safresh1 $z = sprintf "\\%03o", $c if $z =~ /[[:^print:]]/; 481*f2a19305Safresh1 $y .= $z; 482*f2a19305Safresh1 } 483*f2a19305Safresh1 } 484*f2a19305Safresh1 $x = $y; 485*f2a19305Safresh1 } 486*f2a19305Safresh1 return $x unless wantarray; 487*f2a19305Safresh1 push @result, $x; 488*f2a19305Safresh1 } 489*f2a19305Safresh1 return @result; 490*f2a19305Safresh1} 491*f2a19305Safresh1 492*f2a19305Safresh1sub is ($$@) { 493*f2a19305Safresh1 my ($got, $expected, $name, @mess) = @_; 494*f2a19305Safresh1 495*f2a19305Safresh1 my $pass; 496*f2a19305Safresh1 if( !defined $got || !defined $expected ) { 497*f2a19305Safresh1 # undef only matches undef 498*f2a19305Safresh1 $pass = !defined $got && !defined $expected; 499*f2a19305Safresh1 } 500*f2a19305Safresh1 else { 501*f2a19305Safresh1 $pass = $got eq $expected; 502*f2a19305Safresh1 } 503*f2a19305Safresh1 504*f2a19305Safresh1 unless ($pass) { 505*f2a19305Safresh1 unshift(@mess, "# got "._q($got)."\n", 506*f2a19305Safresh1 "# expected "._q($expected)."\n"); 507*f2a19305Safresh1 } 508*f2a19305Safresh1 _ok($pass, _where(), $name, @mess); 509*f2a19305Safresh1} 510*f2a19305Safresh1 511*f2a19305Safresh1sub isnt ($$@) { 512*f2a19305Safresh1 my ($got, $isnt, $name, @mess) = @_; 513*f2a19305Safresh1 514*f2a19305Safresh1 my $pass; 515*f2a19305Safresh1 if( !defined $got || !defined $isnt ) { 516*f2a19305Safresh1 # undef only matches undef 517*f2a19305Safresh1 $pass = defined $got || defined $isnt; 518*f2a19305Safresh1 } 519*f2a19305Safresh1 else { 520*f2a19305Safresh1 $pass = $got ne $isnt; 521*f2a19305Safresh1 } 522*f2a19305Safresh1 523*f2a19305Safresh1 unless( $pass ) { 524*f2a19305Safresh1 unshift(@mess, "# it should not be "._q($got)."\n", 525*f2a19305Safresh1 "# but it is.\n"); 526*f2a19305Safresh1 } 527*f2a19305Safresh1 _ok($pass, _where(), $name, @mess); 528*f2a19305Safresh1} 529*f2a19305Safresh1 530*f2a19305Safresh1sub cmp_ok ($$$@) { 531*f2a19305Safresh1 my($got, $type, $expected, $name, @mess) = @_; 532*f2a19305Safresh1 533*f2a19305Safresh1 my $pass; 534*f2a19305Safresh1 { 535*f2a19305Safresh1 local $^W = 0; 536*f2a19305Safresh1 local($@,$!); # don't interfere with $@ 537*f2a19305Safresh1 # eval() sometimes resets $! 538*f2a19305Safresh1 $pass = eval "\$got $type \$expected"; 539*f2a19305Safresh1 } 540*f2a19305Safresh1 unless ($pass) { 541*f2a19305Safresh1 # It seems Irix long doubles can have 2147483648 and 2147483648 542*f2a19305Safresh1 # that stringify to the same thing but are acutally numerically 543*f2a19305Safresh1 # different. Display the numbers if $type isn't a string operator, 544*f2a19305Safresh1 # and the numbers are stringwise the same. 545*f2a19305Safresh1 # (all string operators have alphabetic names, so tr/a-z// is true) 546*f2a19305Safresh1 # This will also show numbers for some uneeded cases, but will 547*f2a19305Safresh1 # definately be helpful for things such as == and <= that fail 548*f2a19305Safresh1 if ($got eq $expected and $type !~ tr/a-z//) { 549*f2a19305Safresh1 unshift @mess, "# $got - $expected = " . ($got - $expected) . "\n"; 550*f2a19305Safresh1 } 551*f2a19305Safresh1 unshift(@mess, "# got "._q($got)."\n", 552*f2a19305Safresh1 "# expected $type "._q($expected)."\n"); 553*f2a19305Safresh1 } 554*f2a19305Safresh1 _ok($pass, _where(), $name, @mess); 555*f2a19305Safresh1} 556*f2a19305Safresh1 557*f2a19305Safresh1# Check that $got is within $range of $expected 558*f2a19305Safresh1# if $range is 0, then check it's exact 559*f2a19305Safresh1# else if $expected is 0, then $range is an absolute value 560*f2a19305Safresh1# otherwise $range is a fractional error. 561*f2a19305Safresh1# Here $range must be numeric, >= 0 562*f2a19305Safresh1# Non numeric ranges might be a useful future extension. (eg %) 563*f2a19305Safresh1sub within ($$$@) { 564*f2a19305Safresh1 my ($got, $expected, $range, $name, @mess) = @_; 565*f2a19305Safresh1 my $pass; 566*f2a19305Safresh1 if (!defined $got or !defined $expected or !defined $range) { 567*f2a19305Safresh1 # This is a fail, but doesn't need extra diagnostics 568*f2a19305Safresh1 } elsif ($got !~ tr/0-9// or $expected !~ tr/0-9// or $range !~ tr/0-9//) { 569*f2a19305Safresh1 # This is a fail 570*f2a19305Safresh1 unshift @mess, "# got, expected and range must be numeric\n"; 571*f2a19305Safresh1 } elsif ($range < 0) { 572*f2a19305Safresh1 # This is also a fail 573*f2a19305Safresh1 unshift @mess, "# range must not be negative\n"; 574*f2a19305Safresh1 } elsif ($range == 0) { 575*f2a19305Safresh1 # Within 0 is == 576*f2a19305Safresh1 $pass = $got == $expected; 577*f2a19305Safresh1 } elsif ($expected == 0) { 578*f2a19305Safresh1 # If expected is 0, treat range as absolute 579*f2a19305Safresh1 $pass = ($got <= $range) && ($got >= - $range); 580*f2a19305Safresh1 } else { 581*f2a19305Safresh1 my $diff = $got - $expected; 582*f2a19305Safresh1 $pass = abs ($diff / $expected) < $range; 583*f2a19305Safresh1 } 584*f2a19305Safresh1 unless ($pass) { 585*f2a19305Safresh1 if ($got eq $expected) { 586*f2a19305Safresh1 unshift @mess, "# $got - $expected = " . ($got - $expected) . "\n"; 587*f2a19305Safresh1 } 588*f2a19305Safresh1 unshift@mess, "# got "._q($got)."\n", 589*f2a19305Safresh1 "# expected "._q($expected)." (within "._q($range).")\n"; 590*f2a19305Safresh1 } 591*f2a19305Safresh1 _ok($pass, _where(), $name, @mess); 592*f2a19305Safresh1} 593*f2a19305Safresh1 594*f2a19305Safresh1# Note: this isn't quite as fancy as Test::More::like(). 595*f2a19305Safresh1 596*f2a19305Safresh1sub like ($$@) { like_yn (0,@_) }; # 0 for - 597*f2a19305Safresh1sub unlike ($$@) { like_yn (1,@_) }; # 1 for un- 598*f2a19305Safresh1 599*f2a19305Safresh1sub like_yn ($$$@) { 600*f2a19305Safresh1 my ($flip, $got, $expected, $name, @mess) = @_; 601*f2a19305Safresh1 my $pass; 602*f2a19305Safresh1 $pass = $got =~ /$expected/ if !$flip; 603*f2a19305Safresh1 $pass = $got !~ /$expected/ if $flip; 604*f2a19305Safresh1 unless ($pass) { 605*f2a19305Safresh1 unshift(@mess, "# got '$got'\n", 606*f2a19305Safresh1 $flip 607*f2a19305Safresh1 ? "# expected !~ /$expected/\n" : "# expected /$expected/\n"); 608*f2a19305Safresh1 } 609*f2a19305Safresh1 local $Level = $Level + 1; 610*f2a19305Safresh1 _ok($pass, _where(), $name, @mess); 611*f2a19305Safresh1} 612*f2a19305Safresh1 613*f2a19305Safresh1sub pass { 614*f2a19305Safresh1 _ok(1, '', @_); 615*f2a19305Safresh1} 616*f2a19305Safresh1 617*f2a19305Safresh1sub fail { 618*f2a19305Safresh1 _ok(0, _where(), @_); 619*f2a19305Safresh1} 620*f2a19305Safresh1 621*f2a19305Safresh1sub curr_test { 622*f2a19305Safresh1 $test = shift if @_; 623*f2a19305Safresh1 return $test; 624*f2a19305Safresh1} 625*f2a19305Safresh1 626*f2a19305Safresh1sub next_test { 627*f2a19305Safresh1 my $retval = $test; 628*f2a19305Safresh1 $test = $test + 1; # don't use ++ 629*f2a19305Safresh1 $retval; 630*f2a19305Safresh1} 631*f2a19305Safresh1 632*f2a19305Safresh1# Note: can't pass multipart messages since we try to 633*f2a19305Safresh1# be compatible with Test::More::skip(). 634*f2a19305Safresh1sub skip { 635*f2a19305Safresh1 my $why = shift; 636*f2a19305Safresh1 my $n = @_ ? shift : 1; 637*f2a19305Safresh1 for (1..$n) { 638*f2a19305Safresh1 _print "ok $test # skip $why\n"; 639*f2a19305Safresh1 $test = $test + 1; 640*f2a19305Safresh1 } 641*f2a19305Safresh1 local $^W = 0; 642*f2a19305Safresh1 last SKIP; 643*f2a19305Safresh1} 644*f2a19305Safresh1 645*f2a19305Safresh1sub todo_skip { 646*f2a19305Safresh1 my $why = shift; 647*f2a19305Safresh1 my $n = @_ ? shift : 1; 648*f2a19305Safresh1 649*f2a19305Safresh1 for (1..$n) { 650*f2a19305Safresh1 _print "not ok $test # TODO & SKIP $why\n"; 651*f2a19305Safresh1 $test = $test + 1; 652*f2a19305Safresh1 } 653*f2a19305Safresh1 local $^W = 0; 654*f2a19305Safresh1 last TODO; 655*f2a19305Safresh1} 656*f2a19305Safresh1 657*f2a19305Safresh1sub eq_array { 658*f2a19305Safresh1 my ($ra, $rb) = @_; 659*f2a19305Safresh1 return 0 unless $#$ra == $#$rb; 660*f2a19305Safresh1 for my $i (0..$#$ra) { 661*f2a19305Safresh1 next if !defined $ra->[$i] && !defined $rb->[$i]; 662*f2a19305Safresh1 return 0 if !defined $ra->[$i]; 663*f2a19305Safresh1 return 0 if !defined $rb->[$i]; 664*f2a19305Safresh1 return 0 unless $ra->[$i] eq $rb->[$i]; 665*f2a19305Safresh1 } 666*f2a19305Safresh1 return 1; 667*f2a19305Safresh1} 668*f2a19305Safresh1 669*f2a19305Safresh1sub eq_hash { 670*f2a19305Safresh1 my ($orig, $suspect) = @_; 671*f2a19305Safresh1 my $fail; 672*f2a19305Safresh1 while (my ($key, $value) = each %$suspect) { 673*f2a19305Safresh1 # Force a hash recompute if this perl's internals can cache the hash key. 674*f2a19305Safresh1 $key = "" . $key; 675*f2a19305Safresh1 if (exists $orig->{$key}) { 676*f2a19305Safresh1 if ($orig->{$key} ne $value) { 677*f2a19305Safresh1 _print "# key ", _qq($key), " was ", _qq($orig->{$key}), 678*f2a19305Safresh1 " now ", _qq($value), "\n"; 679*f2a19305Safresh1 $fail = 1; 680*f2a19305Safresh1 } 681*f2a19305Safresh1 } else { 682*f2a19305Safresh1 _print "# key ", _qq($key), " is ", _qq($value), 683*f2a19305Safresh1 ", not in original.\n"; 684*f2a19305Safresh1 $fail = 1; 685*f2a19305Safresh1 } 686*f2a19305Safresh1 } 687*f2a19305Safresh1 foreach (keys %$orig) { 688*f2a19305Safresh1 # Force a hash recompute if this perl's internals can cache the hash key. 689*f2a19305Safresh1 $_ = "" . $_; 690*f2a19305Safresh1 next if (exists $suspect->{$_}); 691*f2a19305Safresh1 _print "# key ", _qq($_), " was ", _qq($orig->{$_}), " now missing.\n"; 692*f2a19305Safresh1 $fail = 1; 693*f2a19305Safresh1 } 694*f2a19305Safresh1 !$fail; 695*f2a19305Safresh1} 696*f2a19305Safresh1 697*f2a19305Safresh1sub require_ok ($) { 698*f2a19305Safresh1 my ($require) = @_; 699*f2a19305Safresh1 eval <<REQUIRE_OK; 700*f2a19305Safresh1require $require; 701*f2a19305Safresh1REQUIRE_OK 702*f2a19305Safresh1 _ok(!$@, _where(), "require $require"); 703*f2a19305Safresh1} 704*f2a19305Safresh1 705*f2a19305Safresh1sub use_ok ($) { 706*f2a19305Safresh1 my ($use) = @_; 707*f2a19305Safresh1 eval <<USE_OK; 708*f2a19305Safresh1use $use; 709*f2a19305Safresh1USE_OK 710*f2a19305Safresh1 _ok(!$@, _where(), "use $use"); 711*f2a19305Safresh1} 712*f2a19305Safresh1 713*f2a19305Safresh1# runperl - Runs a separate perl interpreter. 714*f2a19305Safresh1# Arguments : 715*f2a19305Safresh1# switches => [ command-line switches ] 716*f2a19305Safresh1# nolib => 1 # don't use -I../lib (included by default) 717*f2a19305Safresh1# prog => one-liner (avoid quotes) 718*f2a19305Safresh1# progs => [ multi-liner (avoid quotes) ] 719*f2a19305Safresh1# progfile => perl script 720*f2a19305Safresh1# stdin => string to feed the stdin 721*f2a19305Safresh1# stderr => redirect stderr to stdout 722*f2a19305Safresh1# args => [ command-line arguments to the perl program ] 723*f2a19305Safresh1# verbose => print the command line 724*f2a19305Safresh1 725*f2a19305Safresh1my $is_mswin = $^O eq 'MSWin32'; 726*f2a19305Safresh1my $is_netware = $^O eq 'NetWare'; 727*f2a19305Safresh1my $is_macos = $^O eq 'MacOS'; 728*f2a19305Safresh1my $is_vms = $^O eq 'VMS'; 729*f2a19305Safresh1my $is_cygwin = $^O eq 'cygwin'; 730*f2a19305Safresh1 731*f2a19305Safresh1sub _quote_args { 732*f2a19305Safresh1 my ($runperl, $args) = @_; 733*f2a19305Safresh1 734*f2a19305Safresh1 foreach (@$args) { 735*f2a19305Safresh1 # In VMS protect with doublequotes because otherwise 736*f2a19305Safresh1 # DCL will lowercase -- unless already doublequoted. 737*f2a19305Safresh1 $_ = q(").$_.q(") if $is_vms && !/^\"/ && length($_) > 0; 738*f2a19305Safresh1 $$runperl .= ' ' . $_; 739*f2a19305Safresh1 } 740*f2a19305Safresh1} 741*f2a19305Safresh1 742*f2a19305Safresh1sub _create_runperl { # Create the string to qx in runperl(). 743*f2a19305Safresh1 my %args = @_; 744*f2a19305Safresh1 my $runperl = which_perl(); 745*f2a19305Safresh1 if ($runperl =~ m/\s/) { 746*f2a19305Safresh1 $runperl = qq{"$runperl"}; 747*f2a19305Safresh1 } 748*f2a19305Safresh1 #- this allows, for example, to set PERL_RUNPERL_DEBUG=/usr/bin/valgrind 749*f2a19305Safresh1 if ($ENV{PERL_RUNPERL_DEBUG}) { 750*f2a19305Safresh1 $runperl = "$ENV{PERL_RUNPERL_DEBUG} $runperl"; 751*f2a19305Safresh1 } 752*f2a19305Safresh1 unless ($args{nolib}) { 753*f2a19305Safresh1 if ($is_macos) { 754*f2a19305Safresh1 $runperl .= ' -I::lib'; 755*f2a19305Safresh1 # Use UNIX style error messages instead of MPW style. 756*f2a19305Safresh1 $runperl .= ' -MMac::err=unix' if $args{stderr}; 757*f2a19305Safresh1 } 758*f2a19305Safresh1 else { 759*f2a19305Safresh1 $runperl .= ' "-I../lib"'; # doublequotes because of VMS 760*f2a19305Safresh1 } 761*f2a19305Safresh1 } 762*f2a19305Safresh1 if ($args{switches}) { 763*f2a19305Safresh1 local $Level = 2; 764*f2a19305Safresh1 die "test.pl:runperl(): 'switches' must be an ARRAYREF " . _where() 765*f2a19305Safresh1 unless ref $args{switches} eq "ARRAY"; 766*f2a19305Safresh1 _quote_args(\$runperl, $args{switches}); 767*f2a19305Safresh1 } 768*f2a19305Safresh1 if (defined $args{prog}) { 769*f2a19305Safresh1 die "test.pl:runperl(): both 'prog' and 'progs' cannot be used " . _where() 770*f2a19305Safresh1 if defined $args{progs}; 771*f2a19305Safresh1 $args{progs} = [$args{prog}] 772*f2a19305Safresh1 } 773*f2a19305Safresh1 if (defined $args{progs}) { 774*f2a19305Safresh1 die "test.pl:runperl(): 'progs' must be an ARRAYREF " . _where() 775*f2a19305Safresh1 unless ref $args{progs} eq "ARRAY"; 776*f2a19305Safresh1 foreach my $prog (@{$args{progs}}) { 777*f2a19305Safresh1 if ($is_mswin || $is_netware || $is_vms) { 778*f2a19305Safresh1 $runperl .= qq ( -e "$prog" ); 779*f2a19305Safresh1 } 780*f2a19305Safresh1 else { 781*f2a19305Safresh1 $runperl .= qq ( -e '$prog' ); 782*f2a19305Safresh1 } 783*f2a19305Safresh1 } 784*f2a19305Safresh1 } elsif (defined $args{progfile}) { 785*f2a19305Safresh1 $runperl .= qq( "$args{progfile}"); 786*f2a19305Safresh1 } else { 787*f2a19305Safresh1 # You probaby didn't want to be sucking in from the upstream stdin 788*f2a19305Safresh1 die "test.pl:runperl(): none of prog, progs, progfile, args, " 789*f2a19305Safresh1 . " switches or stdin specified" 790*f2a19305Safresh1 unless defined $args{args} or defined $args{switches} 791*f2a19305Safresh1 or defined $args{stdin}; 792*f2a19305Safresh1 } 793*f2a19305Safresh1 if (defined $args{stdin}) { 794*f2a19305Safresh1 # so we don't try to put literal newlines and crs onto the 795*f2a19305Safresh1 # command line. 796*f2a19305Safresh1 $args{stdin} =~ s/\n/\\n/g; 797*f2a19305Safresh1 $args{stdin} =~ s/\r/\\r/g; 798*f2a19305Safresh1 799*f2a19305Safresh1 if ($is_mswin || $is_netware || $is_vms) { 800*f2a19305Safresh1 $runperl = qq{$Perl -e "print qq(} . 801*f2a19305Safresh1 $args{stdin} . q{)" | } . $runperl; 802*f2a19305Safresh1 } 803*f2a19305Safresh1 elsif ($is_macos) { 804*f2a19305Safresh1 # MacOS can only do two processes under MPW at once; 805*f2a19305Safresh1 # the test itself is one; we can't do two more, so 806*f2a19305Safresh1 # write to temp file 807*f2a19305Safresh1 my $stdin = qq{$Perl -e 'print qq(} . $args{stdin} . qq{)' > teststdin; }; 808*f2a19305Safresh1 if ($args{verbose}) { 809*f2a19305Safresh1 my $stdindisplay = $stdin; 810*f2a19305Safresh1 $stdindisplay =~ s/\n/\n\#/g; 811*f2a19305Safresh1 _print_stderr "# $stdindisplay\n"; 812*f2a19305Safresh1 } 813*f2a19305Safresh1 `$stdin`; 814*f2a19305Safresh1 $runperl .= q{ < teststdin }; 815*f2a19305Safresh1 } 816*f2a19305Safresh1 else { 817*f2a19305Safresh1 $runperl = qq{$Perl -e 'print qq(} . 818*f2a19305Safresh1 $args{stdin} . q{)' | } . $runperl; 819*f2a19305Safresh1 } 820*f2a19305Safresh1 } 821*f2a19305Safresh1 if (defined $args{args}) { 822*f2a19305Safresh1 _quote_args(\$runperl, $args{args}); 823*f2a19305Safresh1 } 824*f2a19305Safresh1 $runperl .= ' 2>&1' if $args{stderr} && !$is_macos; 825*f2a19305Safresh1 $runperl .= " \xB3 Dev:Null" if !$args{stderr} && $is_macos; 826*f2a19305Safresh1 if ($args{verbose}) { 827*f2a19305Safresh1 my $runperldisplay = $runperl; 828*f2a19305Safresh1 $runperldisplay =~ s/\n/\n\#/g; 829*f2a19305Safresh1 _print_stderr "# $runperldisplay\n"; 830*f2a19305Safresh1 } 831*f2a19305Safresh1 return $runperl; 832*f2a19305Safresh1} 833*f2a19305Safresh1 834*f2a19305Safresh1sub runperl { 835*f2a19305Safresh1 die "test.pl:runperl() does not take a hashref" 836*f2a19305Safresh1 if ref $_[0] and ref $_[0] eq 'HASH'; 837*f2a19305Safresh1 my $runperl = &_create_runperl; 838*f2a19305Safresh1 my $result; 839*f2a19305Safresh1 840*f2a19305Safresh1 my $tainted = ${^TAINT}; 841*f2a19305Safresh1 my %args = @_; 842*f2a19305Safresh1 exists $args{switches} && grep m/^-T$/, @{$args{switches}} and $tainted = $tainted + 1; 843*f2a19305Safresh1 844*f2a19305Safresh1 if ($tainted) { 845*f2a19305Safresh1 # We will assume that if you're running under -T, you really mean to 846*f2a19305Safresh1 # run a fresh perl, so we'll brute force launder everything for you 847*f2a19305Safresh1 my $sep; 848*f2a19305Safresh1 849*f2a19305Safresh1 if (! eval 'require Config; 1') { 850*f2a19305Safresh1 warn "test.pl had problems loading Config: $@"; 851*f2a19305Safresh1 $sep = ':'; 852*f2a19305Safresh1 } else { 853*f2a19305Safresh1 $sep = $Config::Config{path_sep}; 854*f2a19305Safresh1 } 855*f2a19305Safresh1 856*f2a19305Safresh1 my @keys = grep {exists $ENV{$_}} qw(CDPATH IFS ENV BASH_ENV); 857*f2a19305Safresh1 local @ENV{@keys} = (); 858*f2a19305Safresh1 # Untaint, plus take out . and empty string: 859*f2a19305Safresh1 local $ENV{'DCL$PATH'} = $1 if $is_vms && ($ENV{'DCL$PATH'} =~ /(.*)/s); 860*f2a19305Safresh1 $ENV{PATH} =~ /(.*)/s; 861*f2a19305Safresh1 local $ENV{PATH} = 862*f2a19305Safresh1 join $sep, grep { $_ ne "" and $_ ne "." and -d $_ and 863*f2a19305Safresh1 ($is_mswin or $is_vms or !(stat && (stat _)[2]&0022)) } 864*f2a19305Safresh1 split quotemeta ($sep), $1; 865*f2a19305Safresh1 $ENV{PATH} .= "$sep/bin" if $is_cygwin; # Must have /bin under Cygwin 866*f2a19305Safresh1 867*f2a19305Safresh1 $runperl =~ /(.*)/s; 868*f2a19305Safresh1 $runperl = $1; 869*f2a19305Safresh1 870*f2a19305Safresh1 $result = `$runperl`; 871*f2a19305Safresh1 } else { 872*f2a19305Safresh1 $result = `$runperl`; 873*f2a19305Safresh1 } 874*f2a19305Safresh1 $result =~ s/\n\n/\n/ if $is_vms; # XXX pipes sometimes double these 875*f2a19305Safresh1 return $result; 876*f2a19305Safresh1} 877*f2a19305Safresh1 878*f2a19305Safresh1*run_perl = \&runperl; # Nice alias. 879*f2a19305Safresh1 880*f2a19305Safresh1sub DIE { 881*f2a19305Safresh1 _print_stderr "# @_\n"; 882*f2a19305Safresh1 exit 1; 883*f2a19305Safresh1} 884*f2a19305Safresh1 885*f2a19305Safresh1# A somewhat safer version of the sometimes wrong $^X. 886*f2a19305Safresh1sub which_perl { 887*f2a19305Safresh1 unless (defined $Perl) { 888*f2a19305Safresh1 $Perl = $^X; 889*f2a19305Safresh1 890*f2a19305Safresh1 # VMS should have 'perl' aliased properly 891*f2a19305Safresh1 return $Perl if $^O eq 'VMS'; 892*f2a19305Safresh1 893*f2a19305Safresh1 my $exe; 894*f2a19305Safresh1 if (! eval 'require Config; 1') { 895*f2a19305Safresh1 warn "test.pl had problems loading Config: $@"; 896*f2a19305Safresh1 $exe = ''; 897*f2a19305Safresh1 } else { 898*f2a19305Safresh1 $exe = $Config::Config{_exe}; 899*f2a19305Safresh1 } 900*f2a19305Safresh1 $exe = '' unless defined $exe; 901*f2a19305Safresh1 902*f2a19305Safresh1 # This doesn't absolutize the path: beware of future chdirs(). 903*f2a19305Safresh1 # We could do File::Spec->abs2rel() but that does getcwd()s, 904*f2a19305Safresh1 # which is a bit heavyweight to do here. 905*f2a19305Safresh1 906*f2a19305Safresh1 if ($Perl =~ /^perl\Q$exe\E$/i) { 907*f2a19305Safresh1 my $perl = "perl$exe"; 908*f2a19305Safresh1 if (! eval 'require File::Spec; 1') { 909*f2a19305Safresh1 warn "test.pl had problems loading File::Spec: $@"; 910*f2a19305Safresh1 $Perl = "./$perl"; 911*f2a19305Safresh1 } else { 912*f2a19305Safresh1 $Perl = File::Spec->catfile(File::Spec->curdir(), $perl); 913*f2a19305Safresh1 } 914*f2a19305Safresh1 } 915*f2a19305Safresh1 916*f2a19305Safresh1 # Build up the name of the executable file from the name of 917*f2a19305Safresh1 # the command. 918*f2a19305Safresh1 919*f2a19305Safresh1 if ($Perl !~ /\Q$exe\E$/i) { 920*f2a19305Safresh1 $Perl .= $exe; 921*f2a19305Safresh1 } 922*f2a19305Safresh1 923*f2a19305Safresh1 warn "which_perl: cannot find $Perl from $^X" unless -f $Perl; 924*f2a19305Safresh1 925*f2a19305Safresh1 # For subcommands to use. 926*f2a19305Safresh1 $ENV{PERLEXE} = $Perl; 927*f2a19305Safresh1 } 928*f2a19305Safresh1 return $Perl; 929*f2a19305Safresh1} 930*f2a19305Safresh1 931*f2a19305Safresh1sub unlink_all { 932*f2a19305Safresh1 foreach my $file (@_) { 933*f2a19305Safresh1 1 while unlink $file; 934*f2a19305Safresh1 _print_stderr "# Couldn't unlink '$file': $!\n" if -f $file; 935*f2a19305Safresh1 } 936*f2a19305Safresh1} 937*f2a19305Safresh1 938*f2a19305Safresh1my %tmpfiles; 939*f2a19305Safresh1END { unlink_all keys %tmpfiles } 940*f2a19305Safresh1 941*f2a19305Safresh1# A regexp that matches the tempfile names 942*f2a19305Safresh1$::tempfile_regexp = 'tmp\d+[A-Z][A-Z]?'; 943*f2a19305Safresh1 944*f2a19305Safresh1# Avoid ++, avoid ranges, avoid split // 945*f2a19305Safresh1my @letters = qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z); 946*f2a19305Safresh1sub tempfile { 947*f2a19305Safresh1 my $count = 0; 948*f2a19305Safresh1 do { 949*f2a19305Safresh1 my $temp = $count; 950*f2a19305Safresh1 my $try = "tmp$$"; 951*f2a19305Safresh1 do { 952*f2a19305Safresh1 $try .= $letters[$temp % 26]; 953*f2a19305Safresh1 $temp = int ($temp / 26); 954*f2a19305Safresh1 } while $temp; 955*f2a19305Safresh1 # Need to note all the file names we allocated, as a second request may 956*f2a19305Safresh1 # come before the first is created. 957*f2a19305Safresh1 if (!-e $try && !$tmpfiles{$try}) { 958*f2a19305Safresh1 # We have a winner 959*f2a19305Safresh1 $tmpfiles{$try}++; 960*f2a19305Safresh1 return $try; 961*f2a19305Safresh1 } 962*f2a19305Safresh1 $count = $count + 1; 963*f2a19305Safresh1 } while $count < 26 * 26; 964*f2a19305Safresh1 die "Can't find temporary file name starting 'tmp$$'"; 965*f2a19305Safresh1} 966*f2a19305Safresh1 967*f2a19305Safresh1# This is the temporary file for _fresh_perl 968*f2a19305Safresh1my $tmpfile = tempfile(); 969*f2a19305Safresh1 970*f2a19305Safresh1# 971*f2a19305Safresh1# _fresh_perl 972*f2a19305Safresh1# 973*f2a19305Safresh1# The $resolve must be a subref that tests the first argument 974*f2a19305Safresh1# for success, or returns the definition of success (e.g. the 975*f2a19305Safresh1# expected scalar) if given no arguments. 976*f2a19305Safresh1# 977*f2a19305Safresh1 978*f2a19305Safresh1sub _fresh_perl { 979*f2a19305Safresh1 my($prog, $resolve, $runperl_args, $name) = @_; 980*f2a19305Safresh1 981*f2a19305Safresh1 $runperl_args ||= {}; 982*f2a19305Safresh1 $runperl_args->{progfile} = $tmpfile; 983*f2a19305Safresh1 $runperl_args->{stderr} = 1; 984*f2a19305Safresh1 985*f2a19305Safresh1 open TEST, ">$tmpfile" or die "Cannot open $tmpfile: $!"; 986*f2a19305Safresh1 987*f2a19305Safresh1 # VMS adjustments 988*f2a19305Safresh1 if( $^O eq 'VMS' ) { 989*f2a19305Safresh1 $prog =~ s#/dev/null#NL:#; 990*f2a19305Safresh1 991*f2a19305Safresh1 # VMS file locking 992*f2a19305Safresh1 $prog =~ s{if \(-e _ and -f _ and -r _\)} 993*f2a19305Safresh1 {if (-e _ and -f _)} 994*f2a19305Safresh1 } 995*f2a19305Safresh1 996*f2a19305Safresh1 print TEST $prog; 997*f2a19305Safresh1 close TEST or die "Cannot close $tmpfile: $!"; 998*f2a19305Safresh1 999*f2a19305Safresh1 my $results = runperl(%$runperl_args); 1000*f2a19305Safresh1 my $status = $?; 1001*f2a19305Safresh1 1002*f2a19305Safresh1 # Clean up the results into something a bit more predictable. 1003*f2a19305Safresh1 $results =~ s/\n+$//; 1004*f2a19305Safresh1 $results =~ s/at\s+$::tempfile_regexp\s+line/at - line/g; 1005*f2a19305Safresh1 $results =~ s/of\s+$::tempfile_regexp\s+aborted/of - aborted/g; 1006*f2a19305Safresh1 1007*f2a19305Safresh1 # bison says 'parse error' instead of 'syntax error', 1008*f2a19305Safresh1 # various yaccs may or may not capitalize 'syntax'. 1009*f2a19305Safresh1 $results =~ s/^(syntax|parse) error/syntax error/mig; 1010*f2a19305Safresh1 1011*f2a19305Safresh1 if ($^O eq 'VMS') { 1012*f2a19305Safresh1 # some tests will trigger VMS messages that won't be expected 1013*f2a19305Safresh1 $results =~ s/\n?%[A-Z]+-[SIWEF]-[A-Z]+,.*//; 1014*f2a19305Safresh1 1015*f2a19305Safresh1 # pipes double these sometimes 1016*f2a19305Safresh1 $results =~ s/\n\n/\n/g; 1017*f2a19305Safresh1 } 1018*f2a19305Safresh1 1019*f2a19305Safresh1 my $pass = $resolve->($results); 1020*f2a19305Safresh1 unless ($pass) { 1021*f2a19305Safresh1 _diag "# PROG: \n$prog\n"; 1022*f2a19305Safresh1 _diag "# EXPECTED:\n", $resolve->(), "\n"; 1023*f2a19305Safresh1 _diag "# GOT:\n$results\n"; 1024*f2a19305Safresh1 _diag "# STATUS: $status\n"; 1025*f2a19305Safresh1 } 1026*f2a19305Safresh1 1027*f2a19305Safresh1 # Use the first line of the program as a name if none was given 1028*f2a19305Safresh1 unless( $name ) { 1029*f2a19305Safresh1 ($first_line, $name) = $prog =~ /^((.{1,50}).*)/; 1030*f2a19305Safresh1 $name .= '...' if length $first_line > length $name; 1031*f2a19305Safresh1 } 1032*f2a19305Safresh1 1033*f2a19305Safresh1 _ok($pass, _where(), "fresh_perl - $name"); 1034*f2a19305Safresh1} 1035*f2a19305Safresh1 1036*f2a19305Safresh1# 1037*f2a19305Safresh1# fresh_perl_is 1038*f2a19305Safresh1# 1039*f2a19305Safresh1# Combination of run_perl() and is(). 1040*f2a19305Safresh1# 1041*f2a19305Safresh1 1042*f2a19305Safresh1sub fresh_perl_is { 1043*f2a19305Safresh1 my($prog, $expected, $runperl_args, $name) = @_; 1044*f2a19305Safresh1 local $Level = 2; 1045*f2a19305Safresh1 _fresh_perl($prog, 1046*f2a19305Safresh1 sub { @_ ? $_[0] eq $expected : $expected }, 1047*f2a19305Safresh1 $runperl_args, $name); 1048*f2a19305Safresh1} 1049*f2a19305Safresh1 1050*f2a19305Safresh1# 1051*f2a19305Safresh1# fresh_perl_like 1052*f2a19305Safresh1# 1053*f2a19305Safresh1# Combination of run_perl() and like(). 1054*f2a19305Safresh1# 1055*f2a19305Safresh1 1056*f2a19305Safresh1sub fresh_perl_like { 1057*f2a19305Safresh1 my($prog, $expected, $runperl_args, $name) = @_; 1058*f2a19305Safresh1 local $Level = 2; 1059*f2a19305Safresh1 _fresh_perl($prog, 1060*f2a19305Safresh1 sub { @_ ? 1061*f2a19305Safresh1 $_[0] =~ (ref $expected ? $expected : /$expected/) : 1062*f2a19305Safresh1 $expected }, 1063*f2a19305Safresh1 $runperl_args, $name); 1064*f2a19305Safresh1} 1065*f2a19305Safresh1 1066*f2a19305Safresh1sub can_ok ($@) { 1067*f2a19305Safresh1 my($proto, @methods) = @_; 1068*f2a19305Safresh1 my $class = ref $proto || $proto; 1069*f2a19305Safresh1 1070*f2a19305Safresh1 unless( @methods ) { 1071*f2a19305Safresh1 return _ok( 0, _where(), "$class->can(...)" ); 1072*f2a19305Safresh1 } 1073*f2a19305Safresh1 1074*f2a19305Safresh1 my @nok = (); 1075*f2a19305Safresh1 foreach my $method (@methods) { 1076*f2a19305Safresh1 local($!, $@); # don't interfere with caller's $@ 1077*f2a19305Safresh1 # eval sometimes resets $! 1078*f2a19305Safresh1 eval { $proto->can($method) } || push @nok, $method; 1079*f2a19305Safresh1 } 1080*f2a19305Safresh1 1081*f2a19305Safresh1 my $name; 1082*f2a19305Safresh1 $name = @methods == 1 ? "$class->can('$methods[0]')" 1083*f2a19305Safresh1 : "$class->can(...)"; 1084*f2a19305Safresh1 1085*f2a19305Safresh1 _ok( !@nok, _where(), $name ); 1086*f2a19305Safresh1} 1087*f2a19305Safresh1 1088*f2a19305Safresh1sub isa_ok ($$;$) { 1089*f2a19305Safresh1 my($object, $class, $obj_name) = @_; 1090*f2a19305Safresh1 1091*f2a19305Safresh1 my $diag; 1092*f2a19305Safresh1 $obj_name = 'The object' unless defined $obj_name; 1093*f2a19305Safresh1 my $name = "$obj_name isa $class"; 1094*f2a19305Safresh1 if( !defined $object ) { 1095*f2a19305Safresh1 $diag = "$obj_name isn't defined"; 1096*f2a19305Safresh1 } 1097*f2a19305Safresh1 elsif( !ref $object ) { 1098*f2a19305Safresh1 $diag = "$obj_name isn't a reference"; 1099*f2a19305Safresh1 } 1100*f2a19305Safresh1 else { 1101*f2a19305Safresh1 # We can't use UNIVERSAL::isa because we want to honor isa() overrides 1102*f2a19305Safresh1 local($@, $!); # eval sometimes resets $! 1103*f2a19305Safresh1 my $rslt = eval { $object->isa($class) }; 1104*f2a19305Safresh1 if( $@ ) { 1105*f2a19305Safresh1 if( $@ =~ /^Can't call method "isa" on unblessed reference/ ) { 1106*f2a19305Safresh1 if( !UNIVERSAL::isa($object, $class) ) { 1107*f2a19305Safresh1 my $ref = ref $object; 1108*f2a19305Safresh1 $diag = "$obj_name isn't a '$class' it's a '$ref'"; 1109*f2a19305Safresh1 } 1110*f2a19305Safresh1 } else { 1111*f2a19305Safresh1 die <<WHOA; 1112*f2a19305Safresh1WHOA! I tried to call ->isa on your object and got some weird error. 1113*f2a19305Safresh1This should never happen. Please contact the author immediately. 1114*f2a19305Safresh1Here's the error. 1115*f2a19305Safresh1$@ 1116*f2a19305Safresh1WHOA 1117*f2a19305Safresh1 } 1118*f2a19305Safresh1 } 1119*f2a19305Safresh1 elsif( !$rslt ) { 1120*f2a19305Safresh1 my $ref = ref $object; 1121*f2a19305Safresh1 $diag = "$obj_name isn't a '$class' it's a '$ref'"; 1122*f2a19305Safresh1 } 1123*f2a19305Safresh1 } 1124*f2a19305Safresh1 1125*f2a19305Safresh1 _ok( !$diag, _where(), $name ); 1126*f2a19305Safresh1} 1127*f2a19305Safresh1 1128*f2a19305Safresh1# Set a watchdog to timeout the entire test file 1129*f2a19305Safresh1# NOTE: If the test file uses 'threads', then call the watchdog() function 1130*f2a19305Safresh1# _AFTER_ the 'threads' module is loaded. 1131*f2a19305Safresh1sub watchdog ($) 1132*f2a19305Safresh1{ 1133*f2a19305Safresh1 my $timeout = shift; 1134*f2a19305Safresh1 my $timeout_msg = 'Test process timed out - terminating'; 1135*f2a19305Safresh1 1136*f2a19305Safresh1 my $pid_to_kill = $$; # PID for this process 1137*f2a19305Safresh1 1138*f2a19305Safresh1 # Don't use a watchdog process if 'threads' is loaded - 1139*f2a19305Safresh1 # use a watchdog thread instead 1140*f2a19305Safresh1 if (! $threads::threads) { 1141*f2a19305Safresh1 1142*f2a19305Safresh1 # On Windows and VMS, try launching a watchdog process 1143*f2a19305Safresh1 # using system(1, ...) (see perlport.pod) 1144*f2a19305Safresh1 if (($^O eq 'MSWin32') || ($^O eq 'VMS')) { 1145*f2a19305Safresh1 # On Windows, try to get the 'real' PID 1146*f2a19305Safresh1 if ($^O eq 'MSWin32') { 1147*f2a19305Safresh1 eval { require Win32; }; 1148*f2a19305Safresh1 if (defined(&Win32::GetCurrentProcessId)) { 1149*f2a19305Safresh1 $pid_to_kill = Win32::GetCurrentProcessId(); 1150*f2a19305Safresh1 } 1151*f2a19305Safresh1 } 1152*f2a19305Safresh1 1153*f2a19305Safresh1 # If we still have a fake PID, we can't use this method at all 1154*f2a19305Safresh1 return if ($pid_to_kill <= 0); 1155*f2a19305Safresh1 1156*f2a19305Safresh1 # Launch watchdog process 1157*f2a19305Safresh1 my $watchdog; 1158*f2a19305Safresh1 eval { 1159*f2a19305Safresh1 local $SIG{'__WARN__'} = sub { 1160*f2a19305Safresh1 _diag("Watchdog warning: $_[0]"); 1161*f2a19305Safresh1 }; 1162*f2a19305Safresh1 my $sig = $^O eq 'VMS' ? 'TERM' : 'KILL'; 1163*f2a19305Safresh1 $watchdog = system(1, which_perl(), '-e', 1164*f2a19305Safresh1 "sleep($timeout);" . 1165*f2a19305Safresh1 "warn('# $timeout_msg\n');" . 1166*f2a19305Safresh1 "kill($sig, $pid_to_kill);"); 1167*f2a19305Safresh1 }; 1168*f2a19305Safresh1 if ($@ || ($watchdog <= 0)) { 1169*f2a19305Safresh1 _diag('Failed to start watchdog'); 1170*f2a19305Safresh1 _diag($@) if $@; 1171*f2a19305Safresh1 undef($watchdog); 1172*f2a19305Safresh1 return; 1173*f2a19305Safresh1 } 1174*f2a19305Safresh1 1175*f2a19305Safresh1 # Add END block to parent to terminate and 1176*f2a19305Safresh1 # clean up watchdog process 1177*f2a19305Safresh1 eval "END { local \$! = 0; local \$? = 0; 1178*f2a19305Safresh1 wait() if kill('KILL', $watchdog); };"; 1179*f2a19305Safresh1 return; 1180*f2a19305Safresh1 } 1181*f2a19305Safresh1 1182*f2a19305Safresh1 # Try using fork() to generate a watchdog process 1183*f2a19305Safresh1 my $watchdog; 1184*f2a19305Safresh1 eval { $watchdog = fork() }; 1185*f2a19305Safresh1 if (defined($watchdog)) { 1186*f2a19305Safresh1 if ($watchdog) { # Parent process 1187*f2a19305Safresh1 # Add END block to parent to terminate and 1188*f2a19305Safresh1 # clean up watchdog process 1189*f2a19305Safresh1 eval "END { local \$! = 0; local \$? = 0; 1190*f2a19305Safresh1 wait() if kill('KILL', $watchdog); };"; 1191*f2a19305Safresh1 return; 1192*f2a19305Safresh1 } 1193*f2a19305Safresh1 1194*f2a19305Safresh1 ### Watchdog process code 1195*f2a19305Safresh1 1196*f2a19305Safresh1 # Load POSIX if available 1197*f2a19305Safresh1 eval { require POSIX; }; 1198*f2a19305Safresh1 1199*f2a19305Safresh1 # Execute the timeout 1200*f2a19305Safresh1 sleep($timeout - 2) if ($timeout > 2); # Workaround for perlbug #49073 1201*f2a19305Safresh1 sleep(2); 1202*f2a19305Safresh1 1203*f2a19305Safresh1 # Kill test process if still running 1204*f2a19305Safresh1 if (kill(0, $pid_to_kill)) { 1205*f2a19305Safresh1 _diag($timeout_msg); 1206*f2a19305Safresh1 kill('KILL', $pid_to_kill); 1207*f2a19305Safresh1 } 1208*f2a19305Safresh1 1209*f2a19305Safresh1 # Don't execute END block (added at beginning of this file) 1210*f2a19305Safresh1 $NO_ENDING = 1; 1211*f2a19305Safresh1 1212*f2a19305Safresh1 # Terminate ourself (i.e., the watchdog) 1213*f2a19305Safresh1 POSIX::_exit(1) if (defined(&POSIX::_exit)); 1214*f2a19305Safresh1 exit(1); 1215*f2a19305Safresh1 } 1216*f2a19305Safresh1 1217*f2a19305Safresh1 # fork() failed - fall through and try using a thread 1218*f2a19305Safresh1 } 1219*f2a19305Safresh1 1220*f2a19305Safresh1 # Use a watchdog thread because either 'threads' is loaded, 1221*f2a19305Safresh1 # or fork() failed 1222*f2a19305Safresh1 if (eval 'require threads; 1') { 1223*f2a19305Safresh1 threads->create(sub { 1224*f2a19305Safresh1 # Load POSIX if available 1225*f2a19305Safresh1 eval { require POSIX; }; 1226*f2a19305Safresh1 1227*f2a19305Safresh1 # Execute the timeout 1228*f2a19305Safresh1 my $time_left = $timeout; 1229*f2a19305Safresh1 do { 1230*f2a19305Safresh1 $time_left -= sleep($time_left); 1231*f2a19305Safresh1 } while ($time_left > 0); 1232*f2a19305Safresh1 1233*f2a19305Safresh1 # Kill the parent (and ourself) 1234*f2a19305Safresh1 select(STDERR); $| = 1; 1235*f2a19305Safresh1 _diag($timeout_msg); 1236*f2a19305Safresh1 POSIX::_exit(1) if (defined(&POSIX::_exit)); 1237*f2a19305Safresh1 my $sig = $^O eq 'VMS' ? 'TERM' : 'KILL'; 1238*f2a19305Safresh1 kill($sig, $pid_to_kill); 1239*f2a19305Safresh1 })->detach(); 1240*f2a19305Safresh1 return; 1241*f2a19305Safresh1 } 1242*f2a19305Safresh1 1243*f2a19305Safresh1 # If everything above fails, then just use an alarm timeout 1244*f2a19305Safresh1 if (eval { alarm($timeout); 1; }) { 1245*f2a19305Safresh1 # Load POSIX if available 1246*f2a19305Safresh1 eval { require POSIX; }; 1247*f2a19305Safresh1 1248*f2a19305Safresh1 # Alarm handler will do the actual 'killing' 1249*f2a19305Safresh1 $SIG{'ALRM'} = sub { 1250*f2a19305Safresh1 select(STDERR); $| = 1; 1251*f2a19305Safresh1 _diag($timeout_msg); 1252*f2a19305Safresh1 POSIX::_exit(1) if (defined(&POSIX::_exit)); 1253*f2a19305Safresh1 my $sig = $^O eq 'VMS' ? 'TERM' : 'KILL'; 1254*f2a19305Safresh1 kill($sig, $pid_to_kill); 1255*f2a19305Safresh1 }; 1256*f2a19305Safresh1 } 1257*f2a19305Safresh1} 1258*f2a19305Safresh1 1259*f2a19305Safresh11; 1260*f2a19305Safresh1-- threads.h -- 1261*f2a19305Safresh1#ifndef _THREADS_H_ 1262*f2a19305Safresh1#define _THREADS_H_ 1263*f2a19305Safresh1 1264*f2a19305Safresh1/* Needed for 5.8.0 */ 1265*f2a19305Safresh1#ifndef CLONEf_JOIN_IN 1266*f2a19305Safresh1# define CLONEf_JOIN_IN 8 1267*f2a19305Safresh1#endif 1268*f2a19305Safresh1#ifndef SAVEBOOL 1269*f2a19305Safresh1# define SAVEBOOL(a) 1270*f2a19305Safresh1#endif 1271*f2a19305Safresh1 1272*f2a19305Safresh1/* Added in 5.11.x */ 1273*f2a19305Safresh1#ifndef G_WANT 1274*f2a19305Safresh1# define G_WANT (128|1) 1275*f2a19305Safresh1#endif 1276*f2a19305Safresh1 1277*f2a19305Safresh1/* Added in 5.24.x */ 1278*f2a19305Safresh1#ifndef PERL_TSA_RELEASE 1279*f2a19305Safresh1# define PERL_TSA_RELEASE(x) 1280*f2a19305Safresh1#endif 1281*f2a19305Safresh1#ifndef PERL_TSA_EXCLUDES 1282*f2a19305Safresh1# define PERL_TSA_EXCLUDES(x) 1283*f2a19305Safresh1#endif 1284*f2a19305Safresh1#ifndef CLANG_DIAG_IGNORE 1285*f2a19305Safresh1# define CLANG_DIAG_IGNORE(x) 1286*f2a19305Safresh1#endif 1287*f2a19305Safresh1#ifndef CLANG_DIAG_RESTORE 1288*f2a19305Safresh1# define CLANG_DIAG_RESTORE 1289*f2a19305Safresh1#endif 1290*f2a19305Safresh1 1291*f2a19305Safresh1/* Added in 5.38 */ 1292*f2a19305Safresh1#ifndef PERL_SRAND_OVERRIDE_NEXT_PARENT 1293*f2a19305Safresh1# define PERL_SRAND_OVERRIDE_NEXT_PARENT() 1294*f2a19305Safresh1#endif 1295*f2a19305Safresh1 1296*f2a19305Safresh1#endif 1297*f2a19305Safresh1-- shared.h -- 1298*f2a19305Safresh1#ifndef _SHARED_H_ 1299*f2a19305Safresh1#define _SHARED_H_ 1300*f2a19305Safresh1 1301*f2a19305Safresh1#include "ppport.h" 1302*f2a19305Safresh1 1303*f2a19305Safresh1#ifndef HvNAME_get 1304*f2a19305Safresh1# define HvNAME_get(hv) (0 + ((XPVHV*)SvANY(hv))->xhv_name) 1305*f2a19305Safresh1#endif 1306*f2a19305Safresh1 1307*f2a19305Safresh1#endif 1308