X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2Ftest.pl;h=0c315561405a56c95032e436c5dc84c56f2ccc65;hb=b60cf05ab72950309ce22f1294b53484e06a00ac;hp=351963af635847afb2fe39dab77cc226c7566834;hpb=ea9ac5adc156dc923a1815b0059ca759e5ced3f0;p=p5sagit%2Fp5-mst-13.2.git diff --git a/t/test.pl b/t/test.pl index 351963a..0c31556 100644 --- a/t/test.pl +++ b/t/test.pl @@ -2,6 +2,7 @@ # t/test.pl - most of Test::More functionality without the fuss # +$Level = 1; my $test = 1; my $planned; @@ -30,13 +31,17 @@ END { # Use this instead of "print STDERR" when outputing failure diagnostic # messages sub _diag { + return unless @_; + my @mess = map { /^#/ ? "$_\n" : "# $_\n" } + map { split /\n/ } @_; my $fh = $TODO ? *STDOUT : *STDERR; - print $fh @_; + print $fh @mess; + } sub skip_all { if (@_) { - print STDOUT "1..0 - @_\n"; + print STDOUT "1..0 # Skipped: @_\n"; } else { print STDOUT "1..0\n"; } @@ -64,8 +69,7 @@ sub _ok { } # Ensure that the message is properly escaped. - _diag map { /^#/ ? "$_\n" : "# $_\n" } - map { split /\n/ } @mess if @mess; + _diag @mess; $test++; @@ -73,12 +77,12 @@ sub _ok { } sub _where { - my @caller = caller(1); + my @caller = caller($Level); return "at $caller[1] line $caller[2]"; } # DON'T use this for matches. Use like() instead. -sub ok { +sub ok ($@) { my ($pass, $name, @mess) = @_; _ok($pass, _where(), $name, @mess); } @@ -128,9 +132,18 @@ sub display { return @result; } -sub is { +sub is ($$@) { my ($got, $expected, $name, @mess) = @_; - my $pass = $got eq $expected; + + my $pass; + if( !defined $got || !defined $expected ) { + # undef only matches undef + $pass = !defined $got && !defined $expected; + } + else { + $pass = $got eq $expected; + } + unless ($pass) { unshift(@mess, "# got "._q($got)."\n", "# expected "._q($expected)."\n"); @@ -138,9 +151,18 @@ sub is { _ok($pass, _where(), $name, @mess); } -sub isnt { +sub isnt ($$@) { my ($got, $isnt, $name, @mess) = @_; - my $pass = $got ne $isnt; + + my $pass; + if( !defined $got || !defined $isnt ) { + # undef only matches undef + $pass = defined $got || defined $isnt; + } + else { + $pass = $got ne $isnt; + } + unless( $pass ) { unshift(@mess, "# it should not be "._q($got)."\n", "# but it is.\n"); @@ -148,8 +170,72 @@ sub isnt { _ok($pass, _where(), $name, @mess); } +sub cmp_ok ($$$@) { + my($got, $type, $expected, $name, @mess) = @_; + + my $pass; + { + local $^W = 0; + local($@,$!); # don't interfere with $@ + # eval() sometimes resets $! + $pass = eval "\$got $type \$expected"; + } + unless ($pass) { + # It seems Irix long doubles can have 2147483648 and 2147483648 + # that stringify to the same thing but are acutally numerically + # different. Display the numbers if $type isn't a string operator, + # and the numbers are stringwise the same. + # (all string operators have alphabetic names, so tr/a-z// is true) + # This will also show numbers for some uneeded cases, but will + # definately be helpful for things such as == and <= that fail + if ($got eq $expected and $type !~ tr/a-z//) { + unshift @mess, "# $got - $expected = " . ($got - $expected) . "\n"; + } + unshift(@mess, "# got "._q($got)."\n", + "# expected $type "._q($expected)."\n"); + } + _ok($pass, _where(), $name, @mess); +} + +# Check that $got is within $range of $expected +# if $range is 0, then check it's exact +# else if $expected is 0, then $range is an absolute value +# otherwise $range is a fractional error. +# Here $range must be numeric, >= 0 +# Non numeric ranges might be a useful future extension. (eg %) +sub within ($$$@) { + my ($got, $expected, $range, $name, @mess) = @_; + my $pass; + if (!defined $got or !defined $expected or !defined $range) { + # This is a fail, but doesn't need extra diagnostics + } elsif ($got !~ tr/0-9// or $expected !~ tr/0-9// or $range !~ tr/0-9//) { + # This is a fail + unshift @mess, "# got, expected and range must be numeric\n"; + } elsif ($range < 0) { + # This is also a fail + unshift @mess, "# range must not be negative\n"; + } elsif ($range == 0) { + # Within 0 is == + $pass = $got == $expected; + } elsif ($expected == 0) { + # If expected is 0, treat range as absolute + $pass = ($got <= $range) && ($got >= - $range); + } else { + my $diff = $got - $expected; + $pass = abs ($diff / $expected) < $range; + } + unless ($pass) { + if ($got eq $expected) { + unshift @mess, "# $got - $expected = " . ($got - $expected) . "\n"; + } + unshift@mess, "# got "._q($got)."\n", + "# expected "._q($expected)." (within "._q($range).")\n"; + } + _ok($pass, _where(), $name, @mess); +} + # Note: this isn't quite as fancy as Test::More::like(). -sub like { +sub like ($$@) { my ($got, $expected, $name, @mess) = @_; my $pass; if (ref $expected eq 'Regexp') { @@ -177,11 +263,12 @@ sub fail { } sub curr_test { + $test = shift if @_; return $test; } sub next_test { - $test++ + $test++; } # Note: can't pass multipart messages since we try to @@ -234,7 +321,7 @@ sub eq_hash { !$fail; } -sub require_ok { +sub require_ok ($) { my ($require) = @_; eval < [ command-line switches ] # nolib => 1 # don't use -I../lib (included by default) # prog => one-liner (avoid quotes) +# progs => [ multi-liner (avoid quotes) ] # progfile => perl script # stdin => string to feed the stdin # stderr => redirect stderr to stdout @@ -277,12 +365,9 @@ sub _quote_args { } } -sub runperl { +sub _create_runperl { # Create the string to qx in runperl(). my %args = @_; - my $runperl = $^X; - if ($args{switches}) { - _quote_args(\$runperl, $args{switches}); - } + my $runperl = $^X =~ m/\s/ ? qq{"$^X"} : $^X; unless ($args{nolib}) { if ($is_macos) { $runperl .= ' -I::lib'; @@ -293,26 +378,54 @@ sub runperl { $runperl .= ' "-I../lib"'; # doublequotes because of VMS } } + if ($args{switches}) { + local $Level = 2; + die "test.pl:runperl(): 'switches' must be an ARRAYREF " . _where() + unless ref $args{switches} eq "ARRAY"; + _quote_args(\$runperl, $args{switches}); + } if (defined $args{prog}) { - if ($is_mswin || $is_netware || $is_vms) { - $runperl .= qq( -e ") . $args{prog} . qq("); - } - else { - $runperl .= qq( -e ') . $args{prog} . qq('); - } + die "test.pl:runperl(): both 'prog' and 'progs' cannot be used " . _where() + if defined $args{progs}; + $args{progs} = [$args{prog}] + } + if (defined $args{progs}) { + die "test.pl:runperl(): 'progs' must be an ARRAYREF " . _where() + unless ref $args{progs} eq "ARRAY"; + foreach my $prog (@{$args{progs}}) { + if ($is_mswin || $is_netware || $is_vms) { + $runperl .= qq ( -e "$prog" ); + } + else { + $runperl .= qq ( -e '$prog' ); + } + } } elsif (defined $args{progfile}) { $runperl .= qq( "$args{progfile}"); } if (defined $args{stdin}) { - # so we don't try to put literal newlines and crs onto the - # command line. - $args{stdin} =~ s/\n/\\n/g; - $args{stdin} =~ s/\r/\\r/g; + # so we don't try to put literal newlines and crs onto the + # command line. + $args{stdin} =~ s/\n/\\n/g; + $args{stdin} =~ s/\r/\\r/g; if ($is_mswin || $is_netware || $is_vms) { $runperl = qq{$^X -e "print qq(} . $args{stdin} . q{)" | } . $runperl; } + elsif ($is_macos) { + # MacOS can only do two processes under MPW at once; + # the test itself is one; we can't do two more, so + # write to temp file + my $stdin = qq{$^X -e 'print qq(} . $args{stdin} . qq{)' > teststdin; }; + if ($args{verbose}) { + my $stdindisplay = $stdin; + $stdindisplay =~ s/\n/\n\#/g; + print STDERR "# $stdindisplay\n"; + } + `$stdin`; + $runperl .= q{ < teststdin }; + } else { $runperl = qq{$^X -e 'print qq(} . $args{stdin} . q{)' | } . $runperl; @@ -328,11 +441,17 @@ sub runperl { $runperldisplay =~ s/\n/\n\#/g; print STDERR "# $runperldisplay\n"; } + return $runperl; +} + +sub runperl { + my $runperl = &_create_runperl; my $result = `$runperl`; $result =~ s/\n\n/\n/ if $is_vms; # XXX pipes sometimes double these return $result; } +*run_perl = \&runperl; # Nice alias. sub DIE { print STDERR "# @_\n"; @@ -345,6 +464,9 @@ sub which_perl { unless (defined $Perl) { $Perl = $^X; + # VMS should have 'perl' aliased properly + return $Perl if $^O eq 'VMS'; + my $exe; eval "require Config; Config->import"; if ($@) { @@ -448,10 +570,10 @@ sub _fresh_perl { my $pass = $resolve->($results); unless ($pass) { - print STDERR "# PROG: $switch\n$prog\n"; - print STDERR "# EXPECTED:\n", $resolve->(), "\n"; - print STDERR "# GOT:\n$results\n"; - print STDERR "# STATUS: $status\n"; + _diag "# PROG: \n$prog\n"; + _diag "# EXPECTED:\n", $resolve->(), "\n"; + _diag "# GOT:\n$results\n"; + _diag "# STATUS: $status\n"; } # Use the first line of the program as a name if none was given @@ -471,6 +593,7 @@ sub _fresh_perl { sub fresh_perl_is { my($prog, $expected, $runperl_args, $name) = @_; + local $Level = 2; _fresh_perl($prog, sub { @_ ? $_[0] eq $expected : $expected }, $runperl_args, $name); @@ -484,6 +607,7 @@ sub fresh_perl_is { sub fresh_perl_like { my($prog, $expected, $runperl_args, $name) = @_; + local $Level = 2; _fresh_perl($prog, sub { @_ ? $_[0] =~ (ref $expected ? $expected : /$expected/) :