Probe for timegm
[p5sagit/p5-mst-13.2.git] / t / test.pl
CommitLineData
69026470 1#
2# t/test.pl - most of Test::More functionality without the fuss
485f531e 3
4
5# NOTE:
6#
7# Increment ($x++) has a certain amount of cleverness for things like
8#
9# $x = 'zz';
10# $x++; # $x eq 'aaa';
69026470 11#
485f531e 12# stands more chance of breaking than just a simple
13#
14# $x = $x + 1
15#
16# In this file, we use the latter "Baby Perl" approach, and increment
17# will be worked over by t/op/inc.t
69026470 18
dcc7f481 19$Level = 1;
69026470 20my $test = 1;
21my $planned;
6137113d 22my $noplan;
69026470 23
7d932aad 24$TODO = 0;
b6345914 25$NO_ENDING = 0;
7d932aad 26
3d66076a 27# Use this instead of print to avoid interference while testing globals.
28sub _print {
29 local($\, $", $,) = (undef, ' ', '');
30 print STDOUT @_;
31}
32
33sub _print_stderr {
34 local($\, $", $,) = (undef, ' ', '');
35 print STDERR @_;
36}
37
69026470 38sub plan {
39 my $n;
40 if (@_ == 1) {
41 $n = shift;
6137113d 42 if ($n eq 'no_plan') {
43 undef $n;
44 $noplan = 1;
45 }
69026470 46 } else {
47 my %plan = @_;
8210c8d3 48 $n = $plan{tests};
69026470 49 }
3d66076a 50 _print "1..$n\n" unless $noplan;
69026470 51 $planned = $n;
52}
53
54END {
55 my $ran = $test - 1;
6137113d 56 if (!$NO_ENDING) {
57 if (defined $planned && $planned != $ran) {
3d66076a 58 _print_stderr
6137113d 59 "# Looks like you planned $planned tests but ran $ran.\n";
60 } elsif ($noplan) {
3d66076a 61 _print "1..$ran\n";
6137113d 62 }
69026470 63 }
64}
65
8210c8d3 66# Use this instead of "print STDERR" when outputing failure diagnostic
de522f7a 67# messages
68sub _diag {
cf8feb78 69 return unless @_;
8210c8d3 70 my @mess = map { /^#/ ? "$_\n" : "# $_\n" }
cf8feb78 71 map { split /\n/ } @_;
44826442 72 $TODO ? _print(@mess) : _print_stderr(@mess);
de522f7a 73}
74
485f531e 75sub diag {
76 _diag(@_);
77}
78
69026470 79sub skip_all {
80 if (@_) {
3d66076a 81 _print "1..0 # Skipped: @_\n";
69026470 82 } else {
3d66076a 83 _print "1..0\n";
69026470 84 }
85 exit(0);
86}
87
88sub _ok {
7d932aad 89 my ($pass, $where, $name, @mess) = @_;
69026470 90 # Do not try to microoptimize by factoring out the "not ".
91 # VMS will avenge.
7d932aad 92 my $out;
93 if ($name) {
b734d6c9 94 # escape out '#' or it will interfere with '# skip' and such
95 $name =~ s/#/\\#/g;
7d932aad 96 $out = $pass ? "ok $test - $name" : "not ok $test - $name";
69026470 97 } else {
7d932aad 98 $out = $pass ? "ok $test" : "not ok $test";
69026470 99 }
7d932aad 100
101 $out .= " # TODO $TODO" if $TODO;
3d66076a 102 _print "$out\n";
7d932aad 103
69026470 104 unless ($pass) {
de522f7a 105 _diag "# Failed $where\n";
69026470 106 }
7d932aad 107
108 # Ensure that the message is properly escaped.
cf8feb78 109 _diag @mess;
7d932aad 110
485f531e 111 $test = $test + 1; # don't use ++
1577bb16 112
113 return $pass;
69026470 114}
115
116sub _where {
dcc7f481 117 my @caller = caller($Level);
69026470 118 return "at $caller[1] line $caller[2]";
119}
120
1d662fb6 121# DON'T use this for matches. Use like() instead.
c3029c66 122sub ok ($@) {
7d932aad 123 my ($pass, $name, @mess) = @_;
124 _ok($pass, _where(), $name, @mess);
69026470 125}
126
b3c72391 127sub _q {
128 my $x = shift;
129 return 'undef' unless defined $x;
130 my $q = $x;
d279d8f8 131 $q =~ s/\\/\\\\/g;
132 $q =~ s/'/\\'/g;
b3c72391 133 return "'$q'";
134}
135
677fb045 136sub _qq {
137 my $x = shift;
138 return defined $x ? '"' . display ($x) . '"' : 'undef';
139};
140
141# keys are the codes \n etc map to, values are 2 char strings such as \n
142my %backslash_escape;
143foreach my $x (split //, 'nrtfa\\\'"') {
144 $backslash_escape{ord eval "\"\\$x\""} = "\\$x";
145}
146# A way to display scalars containing control characters and Unicode.
147# Trying to avoid setting $_, or relying on local $_ to work.
148sub display {
149 my @result;
150 foreach my $x (@_) {
151 if (defined $x and not ref $x) {
152 my $y = '';
153 foreach my $c (unpack("U*", $x)) {
154 if ($c > 255) {
155 $y .= sprintf "\\x{%x}", $c;
156 } elsif ($backslash_escape{$c}) {
157 $y .= $backslash_escape{$c};
158 } else {
159 my $z = chr $c; # Maybe we can get away with a literal...
160 $z = sprintf "\\%03o", $c if $z =~ /[[:^print:]]/;
161 $y .= $z;
162 }
163 }
164 $x = $y;
165 }
166 return $x unless wantarray;
167 push @result, $x;
168 }
169 return @result;
170}
171
c3029c66 172sub is ($$@) {
7d932aad 173 my ($got, $expected, $name, @mess) = @_;
c831d34f 174
175 my $pass;
176 if( !defined $got || !defined $expected ) {
177 # undef only matches undef
178 $pass = !defined $got && !defined $expected;
179 }
180 else {
181 $pass = $got eq $expected;
182 }
183
69026470 184 unless ($pass) {
b3c72391 185 unshift(@mess, "# got "._q($got)."\n",
186 "# expected "._q($expected)."\n");
69026470 187 }
7d932aad 188 _ok($pass, _where(), $name, @mess);
69026470 189}
190
c3029c66 191sub isnt ($$@) {
3e90d5a3 192 my ($got, $isnt, $name, @mess) = @_;
c831d34f 193
194 my $pass;
195 if( !defined $got || !defined $isnt ) {
196 # undef only matches undef
197 $pass = defined $got || defined $isnt;
198 }
199 else {
200 $pass = $got ne $isnt;
201 }
202
3e90d5a3 203 unless( $pass ) {
b3c72391 204 unshift(@mess, "# it should not be "._q($got)."\n",
3e90d5a3 205 "# but it is.\n");
206 }
207 _ok($pass, _where(), $name, @mess);
208}
209
c3029c66 210sub cmp_ok ($$$@) {
58d76dfd 211 my($got, $type, $expected, $name, @mess) = @_;
212
213 my $pass;
214 {
215 local $^W = 0;
216 local($@,$!); # don't interfere with $@
217 # eval() sometimes resets $!
218 $pass = eval "\$got $type \$expected";
219 }
220 unless ($pass) {
221 # It seems Irix long doubles can have 2147483648 and 2147483648
222 # that stringify to the same thing but are acutally numerically
223 # different. Display the numbers if $type isn't a string operator,
224 # and the numbers are stringwise the same.
225 # (all string operators have alphabetic names, so tr/a-z// is true)
226 # This will also show numbers for some uneeded cases, but will
227 # definately be helpful for things such as == and <= that fail
228 if ($got eq $expected and $type !~ tr/a-z//) {
229 unshift @mess, "# $got - $expected = " . ($got - $expected) . "\n";
230 }
231 unshift(@mess, "# got "._q($got)."\n",
232 "# expected $type "._q($expected)."\n");
233 }
234 _ok($pass, _where(), $name, @mess);
235}
236
237# Check that $got is within $range of $expected
238# if $range is 0, then check it's exact
239# else if $expected is 0, then $range is an absolute value
240# otherwise $range is a fractional error.
241# Here $range must be numeric, >= 0
242# Non numeric ranges might be a useful future extension. (eg %)
c3029c66 243sub within ($$$@) {
58d76dfd 244 my ($got, $expected, $range, $name, @mess) = @_;
245 my $pass;
246 if (!defined $got or !defined $expected or !defined $range) {
247 # This is a fail, but doesn't need extra diagnostics
248 } elsif ($got !~ tr/0-9// or $expected !~ tr/0-9// or $range !~ tr/0-9//) {
249 # This is a fail
250 unshift @mess, "# got, expected and range must be numeric\n";
251 } elsif ($range < 0) {
252 # This is also a fail
253 unshift @mess, "# range must not be negative\n";
254 } elsif ($range == 0) {
255 # Within 0 is ==
256 $pass = $got == $expected;
257 } elsif ($expected == 0) {
258 # If expected is 0, treat range as absolute
259 $pass = ($got <= $range) && ($got >= - $range);
260 } else {
261 my $diff = $got - $expected;
262 $pass = abs ($diff / $expected) < $range;
263 }
264 unless ($pass) {
265 if ($got eq $expected) {
266 unshift @mess, "# $got - $expected = " . ($got - $expected) . "\n";
267 }
268 unshift@mess, "# got "._q($got)."\n",
269 "# expected "._q($expected)." (within "._q($range).")\n";
270 }
271 _ok($pass, _where(), $name, @mess);
272}
273
69026470 274# Note: this isn't quite as fancy as Test::More::like().
724aa791 275
276sub like ($$@) { like_yn (0,@_) }; # 0 for -
277sub unlike ($$@) { like_yn (1,@_) }; # 1 for un-
278
279sub like_yn ($$$@) {
280 my ($flip, $got, $expected, $name, @mess) = @_;
69026470 281 my $pass;
724aa791 282 $pass = $got =~ /$expected/ if !$flip;
283 $pass = $got !~ /$expected/ if $flip;
284 unless ($pass) {
285 unshift(@mess, "# got '$got'\n",
5a4a8c8b 286 $flip
287 ? "# expected !~ /$expected/\n" : "# expected /$expected/\n");
69026470 288 }
5693d826 289 local $Level = $Level + 1;
7d932aad 290 _ok($pass, _where(), $name, @mess);
69026470 291}
292
293sub pass {
294 _ok(1, '', @_);
295}
296
297sub fail {
298 _ok(0, _where(), @_);
299}
300
ad20d923 301sub curr_test {
cf8feb78 302 $test = shift if @_;
ad20d923 303 return $test;
304}
305
3e90d5a3 306sub next_test {
178eff92 307 my $retval = $test;
485f531e 308 $test = $test + 1; # don't use ++
178eff92 309 $retval;
3e90d5a3 310}
311
69026470 312# Note: can't pass multipart messages since we try to
313# be compatible with Test::More::skip().
314sub skip {
7d932aad 315 my $why = shift;
982b7cb7 316 my $n = @_ ? shift : 1;
69026470 317 for (1..$n) {
3d66076a 318 _print "ok $test # skip: $why\n";
485f531e 319 $test = $test + 1;
69026470 320 }
321 local $^W = 0;
322 last SKIP;
323}
324
09f04786 325sub todo_skip {
326 my $why = shift;
327 my $n = @_ ? shift : 1;
328
329 for (1..$n) {
3d66076a 330 _print "not ok $test # TODO & SKIP: $why\n";
485f531e 331 $test = $test + 1;
09f04786 332 }
333 local $^W = 0;
334 last TODO;
335}
336
69026470 337sub eq_array {
338 my ($ra, $rb) = @_;
339 return 0 unless $#$ra == $#$rb;
340 for my $i (0..$#$ra) {
8210c8d3 341 next if !defined $ra->[$i] && !defined $rb->[$i];
135d199b 342 return 0 if !defined $ra->[$i];
343 return 0 if !defined $rb->[$i];
69026470 344 return 0 unless $ra->[$i] eq $rb->[$i];
345 }
346 return 1;
347}
348
677fb045 349sub eq_hash {
350 my ($orig, $suspect) = @_;
351 my $fail;
352 while (my ($key, $value) = each %$suspect) {
353 # Force a hash recompute if this perl's internals can cache the hash key.
354 $key = "" . $key;
355 if (exists $orig->{$key}) {
356 if ($orig->{$key} ne $value) {
3d66076a 357 _print "# key ", _qq($key), " was ", _qq($orig->{$key}),
de522f7a 358 " now ", _qq($value), "\n";
677fb045 359 $fail = 1;
360 }
361 } else {
3d66076a 362 _print "# key ", _qq($key), " is ", _qq($value),
75385f53 363 ", not in original.\n";
677fb045 364 $fail = 1;
365 }
366 }
367 foreach (keys %$orig) {
368 # Force a hash recompute if this perl's internals can cache the hash key.
369 $_ = "" . $_;
370 next if (exists $suspect->{$_});
3d66076a 371 _print "# key ", _qq($_), " was ", _qq($orig->{$_}), " now missing.\n";
677fb045 372 $fail = 1;
373 }
374 !$fail;
375}
376
c3029c66 377sub require_ok ($) {
69026470 378 my ($require) = @_;
379 eval <<REQUIRE_OK;
380require $require;
381REQUIRE_OK
1577bb16 382 _ok(!$@, _where(), "require $require");
69026470 383}
384
c3029c66 385sub use_ok ($) {
69026470 386 my ($use) = @_;
387 eval <<USE_OK;
388use $use;
389USE_OK
1577bb16 390 _ok(!$@, _where(), "use $use");
69026470 391}
392
137352a2 393# runperl - Runs a separate perl interpreter.
394# Arguments :
395# switches => [ command-line switches ]
396# nolib => 1 # don't use -I../lib (included by default)
397# prog => one-liner (avoid quotes)
d83945bc 398# progs => [ multi-liner (avoid quotes) ]
137352a2 399# progfile => perl script
400# stdin => string to feed the stdin
401# stderr => redirect stderr to stdout
402# args => [ command-line arguments to the perl program ]
cb9c5e20 403# verbose => print the command line
137352a2 404
405my $is_mswin = $^O eq 'MSWin32';
406my $is_netware = $^O eq 'NetWare';
407my $is_macos = $^O eq 'MacOS';
408my $is_vms = $^O eq 'VMS';
e67ed694 409my $is_cygwin = $^O eq 'cygwin';
137352a2 410
cb9c5e20 411sub _quote_args {
412 my ($runperl, $args) = @_;
413
414 foreach (@$args) {
415 # In VMS protect with doublequotes because otherwise
416 # DCL will lowercase -- unless already doublequoted.
ea9ac5ad 417 $_ = q(").$_.q(") if $is_vms && !/^\"/ && length($_) > 0;
cb9c5e20 418 $$runperl .= ' ' . $_;
419 }
420}
421
4cd2bd1f 422sub _create_runperl { # Create the string to qx in runperl().
137352a2 423 my %args = @_;
44cb023c 424 my $runperl = $^X =~ m/\s/ ? qq{"$^X"} : $^X;
6cf707aa 425 #- this allows, for example, to set PERL_RUNPERL_DEBUG=/usr/bin/valgrind
426 if ($ENV{PERL_RUNPERL_DEBUG}) {
427 $runperl = "$ENV{PERL_RUNPERL_DEBUG} $runperl";
428 }
f93a5f07 429 unless ($args{nolib}) {
430 if ($is_macos) {
cb9c5e20 431 $runperl .= ' -I::lib';
f93a5f07 432 # Use UNIX style error messages instead of MPW style.
cb9c5e20 433 $runperl .= ' -MMac::err=unix' if $args{stderr};
137352a2 434 }
435 else {
cb9c5e20 436 $runperl .= ' "-I../lib"'; # doublequotes because of VMS
137352a2 437 }
438 }
d83945bc 439 if ($args{switches}) {
343d4a7b 440 local $Level = 2;
441 die "test.pl:runperl(): 'switches' must be an ARRAYREF " . _where()
442 unless ref $args{switches} eq "ARRAY";
d83945bc 443 _quote_args(\$runperl, $args{switches});
444 }
137352a2 445 if (defined $args{prog}) {
21820af6 446 die "test.pl:runperl(): both 'prog' and 'progs' cannot be used " . _where()
447 if defined $args{progs};
d83945bc 448 $args{progs} = [$args{prog}]
449 }
450 if (defined $args{progs}) {
21820af6 451 die "test.pl:runperl(): 'progs' must be an ARRAYREF " . _where()
452 unless ref $args{progs} eq "ARRAY";
d83945bc 453 foreach my $prog (@{$args{progs}}) {
454 if ($is_mswin || $is_netware || $is_vms) {
455 $runperl .= qq ( -e "$prog" );
456 }
457 else {
458 $runperl .= qq ( -e '$prog' );
459 }
460 }
137352a2 461 } elsif (defined $args{progfile}) {
462 $runperl .= qq( "$args{progfile}");
9a731dbd 463 } else {
464 # You probaby didn't want to be sucking in from the upstream stdin
465 die "test.pl:runperl(): none of prog, progs, progfile, args, "
466 . " switches or stdin specified"
467 unless defined $args{args} or defined $args{switches}
468 or defined $args{stdin};
137352a2 469 }
470 if (defined $args{stdin}) {
dc459aad 471 # so we don't try to put literal newlines and crs onto the
472 # command line.
473 $args{stdin} =~ s/\n/\\n/g;
474 $args{stdin} =~ s/\r/\\r/g;
5ae09a77 475
137352a2 476 if ($is_mswin || $is_netware || $is_vms) {
f93a5f07 477 $runperl = qq{$^X -e "print qq(} .
137352a2 478 $args{stdin} . q{)" | } . $runperl;
479 }
dc459aad 480 elsif ($is_macos) {
481 # MacOS can only do two processes under MPW at once;
482 # the test itself is one; we can't do two more, so
483 # write to temp file
484 my $stdin = qq{$^X -e 'print qq(} . $args{stdin} . qq{)' > teststdin; };
485 if ($args{verbose}) {
486 my $stdindisplay = $stdin;
487 $stdindisplay =~ s/\n/\n\#/g;
3d66076a 488 _print_stderr "# $stdindisplay\n";
dc459aad 489 }
490 `$stdin`;
491 $runperl .= q{ < teststdin };
492 }
137352a2 493 else {
f93a5f07 494 $runperl = qq{$^X -e 'print qq(} .
137352a2 495 $args{stdin} . q{)' | } . $runperl;
496 }
497 }
498 if (defined $args{args}) {
cb9c5e20 499 _quote_args(\$runperl, $args{args});
500 }
501 $runperl .= ' 2>&1' if $args{stderr} && !$is_macos;
502 $runperl .= " \xB3 Dev:Null" if !$args{stderr} && $is_macos;
503 if ($args{verbose}) {
504 my $runperldisplay = $runperl;
505 $runperldisplay =~ s/\n/\n\#/g;
3d66076a 506 _print_stderr "# $runperldisplay\n";
137352a2 507 }
4cd2bd1f 508 return $runperl;
509}
510
511sub runperl {
9a731dbd 512 die "test.pl:runperl() does not take a hashref"
513 if ref $_[0] and ref $_[0] eq 'HASH';
4cd2bd1f 514 my $runperl = &_create_runperl;
613de57f 515 my $result;
516
8210c8d3 517 my $tainted = ${^TAINT};
518 my %args = @_;
485f531e 519 exists $args{switches} && grep m/^-T$/, @{$args{switches}} and $tainted = $tainted + 1;
8210c8d3 520
521 if ($tainted) {
613de57f 522 # We will assume that if you're running under -T, you really mean to
523 # run a fresh perl, so we'll brute force launder everything for you
524 my $sep;
525
526 eval "require Config; Config->import";
527 if ($@) {
528 warn "test.pl had problems loading Config: $@";
529 $sep = ':';
530 } else {
531 $sep = $Config{path_sep};
a70a1627 532 }
613de57f 533
534 my @keys = grep {exists $ENV{$_}} qw(CDPATH IFS ENV BASH_ENV);
535 local @ENV{@keys} = ();
536 # Untaint, plus take out . and empty string:
326b5008 537 local $ENV{'DCL$PATH'} = $1 if $is_vms && ($ENV{'DCL$PATH'} =~ /(.*)/s);
613de57f 538 $ENV{PATH} =~ /(.*)/s;
8210c8d3 539 local $ENV{PATH} =
3b6d8381 540 join $sep, grep { $_ ne "" and $_ ne "." and -d $_ and
326b5008 541 ($is_mswin or $is_vms or !(stat && (stat _)[2]&0022)) }
8210c8d3 542 split quotemeta ($sep), $1;
e67ed694 543 $ENV{PATH} .= "$sep/bin" if $is_cygwin; # Must have /bin under Cygwin
613de57f 544
545 $runperl =~ /(.*)/s;
546 $runperl = $1;
547
548 $result = `$runperl`;
549 } else {
550 $result = `$runperl`;
a70a1627 551 }
137352a2 552 $result =~ s/\n\n/\n/ if $is_vms; # XXX pipes sometimes double these
553 return $result;
554}
555
d2c6a9c9 556*run_perl = \&runperl; # Nice alias.
8799135f 557
c4fbe247 558sub DIE {
3d66076a 559 _print_stderr "# @_\n";
c4fbe247 560 exit 1;
8799135f 561}
562
b5fe401b 563# A somewhat safer version of the sometimes wrong $^X.
17a740d5 564my $Perl;
565sub which_perl {
566 unless (defined $Perl) {
567 $Perl = $^X;
8210c8d3 568
73421c4a 569 # VMS should have 'perl' aliased properly
570 return $Perl if $^O eq 'VMS';
571
17a740d5 572 my $exe;
573 eval "require Config; Config->import";
85363d30 574 if ($@) {
17a740d5 575 warn "test.pl had problems loading Config: $@";
576 $exe = '';
85363d30 577 } else {
17a740d5 578 $exe = $Config{_exe};
85363d30 579 }
da405c16 580 $exe = '' unless defined $exe;
8210c8d3 581
17a740d5 582 # This doesn't absolutize the path: beware of future chdirs().
583 # We could do File::Spec->abs2rel() but that does getcwd()s,
584 # which is a bit heavyweight to do here.
8210c8d3 585
17a740d5 586 if ($Perl =~ /^perl\Q$exe\E$/i) {
8db06b02 587 my $perl = "perl$exe";
17a740d5 588 eval "require File::Spec";
589 if ($@) {
590 warn "test.pl had problems loading File::Spec: $@";
8db06b02 591 $Perl = "./$perl";
17a740d5 592 } else {
8db06b02 593 $Perl = File::Spec->catfile(File::Spec->curdir(), $perl);
17a740d5 594 }
595 }
196918b0 596
597 # Build up the name of the executable file from the name of
598 # the command.
599
600 if ($Perl !~ /\Q$exe\E$/i) {
601 $Perl .= $exe;
602 }
c880be78 603
8db06b02 604 warn "which_perl: cannot find $Perl from $^X" unless -f $Perl;
8210c8d3 605
17a740d5 606 # For subcommands to use.
607 $ENV{PERLEXE} = $Perl;
85363d30 608 }
17a740d5 609 return $Perl;
b5fe401b 610}
611
435e7af6 612sub unlink_all {
613 foreach my $file (@_) {
614 1 while unlink $file;
3d66076a 615 _print_stderr "# Couldn't unlink '$file': $!\n" if -f $file;
435e7af6 616 }
617}
eeabcb2d 618
619
620my $tmpfile = "misctmp000";
6211 while -f ++$tmpfile;
622END { unlink_all $tmpfile }
623
f5cda331 624#
625# _fresh_perl
626#
627# The $resolve must be a subref that tests the first argument
628# for success, or returns the definition of success (e.g. the
629# expected scalar) if given no arguments.
630#
631
632sub _fresh_perl {
633 my($prog, $resolve, $runperl_args, $name) = @_;
eeabcb2d 634
635 $runperl_args ||= {};
636 $runperl_args->{progfile} = $tmpfile;
637 $runperl_args->{stderr} = 1;
638
639 open TEST, ">$tmpfile" or die "Cannot open $tmpfile: $!";
640
641 # VMS adjustments
642 if( $^O eq 'VMS' ) {
643 $prog =~ s#/dev/null#NL:#;
644
8210c8d3 645 # VMS file locking
eeabcb2d 646 $prog =~ s{if \(-e _ and -f _ and -r _\)}
647 {if (-e _ and -f _)}
648 }
649
0d65d7d5 650 print TEST $prog;
eeabcb2d 651 close TEST or die "Cannot close $tmpfile: $!";
652
653 my $results = runperl(%$runperl_args);
654 my $status = $?;
655
656 # Clean up the results into something a bit more predictable.
657 $results =~ s/\n+$//;
658 $results =~ s/at\s+misctmp\d+\s+line/at - line/g;
659 $results =~ s/of\s+misctmp\d+\s+aborted/of - aborted/g;
660
661 # bison says 'parse error' instead of 'syntax error',
662 # various yaccs may or may not capitalize 'syntax'.
663 $results =~ s/^(syntax|parse) error/syntax error/mig;
664
665 if ($^O eq 'VMS') {
666 # some tests will trigger VMS messages that won't be expected
667 $results =~ s/\n?%[A-Z]+-[SIWEF]-[A-Z]+,.*//;
668
669 # pipes double these sometimes
670 $results =~ s/\n\n/\n/g;
671 }
672
f5cda331 673 my $pass = $resolve->($results);
eeabcb2d 674 unless ($pass) {
cf8feb78 675 _diag "# PROG: \n$prog\n";
676 _diag "# EXPECTED:\n", $resolve->(), "\n";
677 _diag "# GOT:\n$results\n";
678 _diag "# STATUS: $status\n";
eeabcb2d 679 }
680
e2c38acd 681 # Use the first line of the program as a name if none was given
682 unless( $name ) {
683 ($first_line, $name) = $prog =~ /^((.{1,50}).*)/;
684 $name .= '...' if length $first_line > length $name;
685 }
eeabcb2d 686
f5cda331 687 _ok($pass, _where(), "fresh_perl - $name");
688}
689
690#
141f445b 691# fresh_perl_is
f5cda331 692#
693# Combination of run_perl() and is().
694#
695
696sub fresh_perl_is {
697 my($prog, $expected, $runperl_args, $name) = @_;
dcc7f481 698 local $Level = 2;
f5cda331 699 _fresh_perl($prog,
700 sub { @_ ? $_[0] eq $expected : $expected },
701 $runperl_args, $name);
702}
703
704#
141f445b 705# fresh_perl_like
f5cda331 706#
707# Combination of run_perl() and like().
708#
709
710sub fresh_perl_like {
711 my($prog, $expected, $runperl_args, $name) = @_;
dcc7f481 712 local $Level = 2;
f5cda331 713 _fresh_perl($prog,
714 sub { @_ ?
715 $_[0] =~ (ref $expected ? $expected : /$expected/) :
716 $expected },
717 $runperl_args, $name);
eeabcb2d 718}
719
35a60386 720sub can_ok ($@) {
721 my($proto, @methods) = @_;
722 my $class = ref $proto || $proto;
723
724 unless( @methods ) {
725 return _ok( 0, _where(), "$class->can(...)" );
726 }
727
728 my @nok = ();
729 foreach my $method (@methods) {
730 local($!, $@); # don't interfere with caller's $@
731 # eval sometimes resets $!
732 eval { $proto->can($method) } || push @nok, $method;
733 }
734
735 my $name;
8210c8d3 736 $name = @methods == 1 ? "$class->can('$methods[0]')"
35a60386 737 : "$class->can(...)";
8210c8d3 738
35a60386 739 _ok( !@nok, _where(), $name );
740}
741
742sub isa_ok ($$;$) {
743 my($object, $class, $obj_name) = @_;
744
745 my $diag;
746 $obj_name = 'The object' unless defined $obj_name;
747 my $name = "$obj_name isa $class";
748 if( !defined $object ) {
749 $diag = "$obj_name isn't defined";
750 }
751 elsif( !ref $object ) {
752 $diag = "$obj_name isn't a reference";
753 }
754 else {
755 # We can't use UNIVERSAL::isa because we want to honor isa() overrides
756 local($@, $!); # eval sometimes resets $!
757 my $rslt = eval { $object->isa($class) };
758 if( $@ ) {
759 if( $@ =~ /^Can't call method "isa" on unblessed reference/ ) {
760 if( !UNIVERSAL::isa($object, $class) ) {
761 my $ref = ref $object;
762 $diag = "$obj_name isn't a '$class' it's a '$ref'";
763 }
764 } else {
765 die <<WHOA;
766WHOA! I tried to call ->isa on your object and got some weird error.
767This should never happen. Please contact the author immediately.
768Here's the error.
769$@
770WHOA
771 }
772 }
773 elsif( !$rslt ) {
774 my $ref = ref $object;
775 $diag = "$obj_name isn't a '$class' it's a '$ref'";
776 }
777 }
778
779 _ok( !$diag, _where(), $name );
780}
781
087986a7 782# Set a watchdog to timeout the entire test file
783sub watchdog ($)
784{
785 my $timeout = shift;
786 my $timeout_msg = 'Test process timed out - terminating';
787
788 my $pid_to_kill = $$; # PID for this process
789
790 # On Windows and VMS, try launching a watchdog process
791 # using system(1, ...) (see perlport.pod)
792 if (($^O eq 'MSWin32') || ($^O eq 'VMS')) {
793 # On Windows, try to get the 'real' PID
794 if ($^O eq 'MSWin32') {
795 eval { require Win32; };
796 if (defined(&Win32::GetCurrentProcessId)) {
797 $pid_to_kill = Win32::GetCurrentProcessId();
798 }
799 }
800
801 # If we still have a fake PID, we can't use this method at all
802 return if ($pid_to_kill <= 0);
803
804 # Launch watchdog process
805 my $watchdog;
806 eval {
807 local $SIG{'__WARN__'} = sub {};
808 $watchdog = system(1, $^X, '-e', "sleep($timeout);" .
809 "kill('KILL', $pid_to_kill);");
810 };
811
812 # If the above worked, add END block to parent
813 # to clean up watchdog process
814 if (! $@ && ($watchdog > 0)) {
815 eval "END { kill('KILL', $watchdog); }";
816 }
817 return;
818 }
819
820
821 # Try using fork() to generate a watchdog process
822 my $watchdog;
823 eval { $watchdog = fork() };
824 if (defined($watchdog)) {
825 if ($watchdog) { # Parent process
826 # Add END block to parent to clean up watchdog process
827 eval "END { kill('KILL', $watchdog); }";
828 return;
829 }
830
831 ### Watchdog process code
832
833 # Load POSIX if available
834 eval { require POSIX; };
835
836 # Execute the timeout
837 sleep($timeout - 2) if ($timeout > 2); # Workaround for perlbug #49073
838 sleep(2);
839
840 # Kill test process if still running
841 if (kill(0, $pid_to_kill)) {
842 _diag($timeout_msg);
843 kill('KILL', $pid_to_kill);
844 }
845
846 # Terminate ourself (i.e., the watchdog)
847 POSIX::_exit(1) if (defined(&POSIX::_exit));
848 exit(1);
849 }
850
851 # fork() failed - try a thread
852 if (eval { require threads; }) {
853 threads->create(sub {
854 # Load POSIX if available
855 eval { require POSIX; };
856
857 # Execute the timeout
858 sleep($timeout);
859
860 # Kill the parent (and ourself)
861 _diag($timeout_msg);
862 POSIX::_exit(1) if (defined(&POSIX::_exit));
863 kill('KILL', $pid_to_kill);
864 })->detach();
865 return;
866 }
867
868 # Threads failed, too - try use alarm()
869
870 # Try to set the timeout
871 if (eval { alarm($timeout); 1; }) {
872 # Load POSIX if available
873 eval { require POSIX; };
874
875 # Alarm handler will do the actual 'killing'
876 $SIG{'ALRM'} = sub {
877 _diag($timeout_msg);
878 POSIX::_exit(1) if (defined(&POSIX::_exit));
879 kill('KILL', $pid_to_kill);
880 };
881 }
882}
883
69026470 8841;