xref: /openbsd-src/gnu/usr.bin/perl/Porting/test-dist-modules.pl (revision f2a19305cfc49ea4d1a5feb55cd6c283c6f1e031)
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