X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2Ftest.pl;h=cdfa018fccce80defe39d500af9ceb69684ab83e;hb=5b9c067131ee63b4afa00d1d71c771377deb6ff9;hp=152028537148e67d184f9000ebdfd28690a1eda7;hpb=141f445b878212088a7c51f894a67b497c69a785;p=p5sagit%2Fp5-mst-13.2.git diff --git a/t/test.pl b/t/test.pl index 1520285..cdfa018 100644 --- a/t/test.pl +++ b/t/test.pl @@ -5,6 +5,7 @@ $Level = 1; my $test = 1; my $planned; +my $noplan; $TODO = 0; $NO_ENDING = 0; @@ -13,26 +14,35 @@ sub plan { my $n; if (@_ == 1) { $n = shift; + if ($n eq 'no_plan') { + undef $n; + $noplan = 1; + } } else { my %plan = @_; - $n = $plan{tests}; + $n = $plan{tests}; } - print STDOUT "1..$n\n"; + print STDOUT "1..$n\n" unless $noplan; $planned = $n; } END { my $ran = $test - 1; - if (!$NO_ENDING && defined $planned && $planned != $ran) { - print STDERR "# Looks like you planned $planned tests but ran $ran.\n"; + if (!$NO_ENDING) { + if (defined $planned && $planned != $ran) { + print STDERR + "# Looks like you planned $planned tests but ran $ran.\n"; + } elsif ($noplan) { + print "1..$ran\n"; + } } } -# Use this instead of "print STDERR" when outputing failure diagnostic +# Use this instead of "print STDERR" when outputing failure diagnostic # messages sub _diag { return unless @_; - my @mess = map { /^#/ ? "$_\n" : "# $_\n" } + my @mess = map { /^#/ ? "$_\n" : "# $_\n" } map { split /\n/ } @_; my $fh = $TODO ? *STDOUT : *STDERR; print $fh @mess; @@ -91,8 +101,8 @@ sub _q { my $x = shift; return 'undef' unless defined $x; my $q = $x; - $q =~ s/\\/\\\\/; - $q =~ s/'/\\'/; + $q =~ s/\\/\\\\/g; + $q =~ s/'/\\'/g; return "'$q'"; } @@ -235,22 +245,20 @@ sub within ($$$@) { } # Note: this isn't quite as fancy as Test::More::like(). -sub like ($$@) { - my ($got, $expected, $name, @mess) = @_; + +sub like ($$@) { like_yn (0,@_) }; # 0 for - +sub unlike ($$@) { like_yn (1,@_) }; # 1 for un- + +sub like_yn ($$$@) { + my ($flip, $got, $expected, $name, @mess) = @_; my $pass; - if (ref $expected eq 'Regexp') { - $pass = $got =~ $expected; - unless ($pass) { - unshift(@mess, "# got '$got'\n", - "# expected /$expected/\n"); - } - } else { - $pass = $got =~ /$expected/; - unless ($pass) { - unshift(@mess, "# got '$got'\n", - "# expected /$expected/\n"); - } + $pass = $got =~ /$expected/ if !$flip; + $pass = $got !~ /$expected/ if $flip; + unless ($pass) { + unshift(@mess, "# got '$got'\n", + "# expected /$expected/\n"); } + local $Level = 2; _ok($pass, _where(), $name, @mess); } @@ -284,10 +292,25 @@ sub skip { last SKIP; } +sub todo_skip { + my $why = shift; + my $n = @_ ? shift : 1; + + for (1..$n) { + print STDOUT "not ok $test # TODO & SKIP: $why\n"; + $test++; + } + local $^W = 0; + last TODO; +} + sub eq_array { my ($ra, $rb) = @_; return 0 unless $#$ra == $#$rb; for my $i (0..$#$ra) { + next if !defined $ra->[$i] && !defined $rb->[$i]; + return 0 if !defined $ra->[$i]; + return 0 if !defined $rb->[$i]; return 0 unless $ra->[$i] eq $rb->[$i]; } return 1; @@ -306,7 +329,7 @@ sub eq_hash { $fail = 1; } } else { - print STDOUT "# key ", _qq($key), " is ", _qq($value), + print STDOUT "# key ", _qq($key), " is ", _qq($value), ", not in original.\n"; $fail = 1; } @@ -368,6 +391,10 @@ sub _quote_args { sub _create_runperl { # Create the string to qx in runperl(). my %args = @_; my $runperl = $^X =~ m/\s/ ? qq{"$^X"} : $^X; + #- this allows, for example, to set PERL_RUNPERL_DEBUG=/usr/bin/valgrind + if ($ENV{PERL_RUNPERL_DEBUG}) { + $runperl = "$ENV{PERL_RUNPERL_DEBUG} $runperl"; + } unless ($args{nolib}) { if ($is_macos) { $runperl .= ' -I::lib'; @@ -402,6 +429,12 @@ sub _create_runperl { # Create the string to qx in runperl(). } } elsif (defined $args{progfile}) { $runperl .= qq( "$args{progfile}"); + } else { + # You probaby didn't want to be sucking in from the upstream stdin + die "test.pl:runperl(): none of prog, progs, progfile, args, " + . " switches or stdin specified" + unless defined $args{args} or defined $args{switches} + or defined $args{stdin}; } if (defined $args{stdin}) { # so we don't try to put literal newlines and crs onto the @@ -445,8 +478,44 @@ sub _create_runperl { # Create the string to qx in runperl(). } sub runperl { + die "test.pl:runperl() does not take a hashref" + if ref $_[0] and ref $_[0] eq 'HASH'; my $runperl = &_create_runperl; - my $result = `$runperl`; + my $result; + + my $tainted = ${^TAINT}; + my %args = @_; + exists $args{switches} && grep m/^-T$/, @{$args{switches}} and $tainted++; + + if ($tainted) { + # We will assume that if you're running under -T, you really mean to + # run a fresh perl, so we'll brute force launder everything for you + my $sep; + + eval "require Config; Config->import"; + if ($@) { + warn "test.pl had problems loading Config: $@"; + $sep = ':'; + } else { + $sep = $Config{path_sep}; + } + + my @keys = grep {exists $ENV{$_}} qw(CDPATH IFS ENV BASH_ENV); + local @ENV{@keys} = (); + # Untaint, plus take out . and empty string: + $ENV{PATH} =~ /(.*)/s; + local $ENV{PATH} = + join $sep, grep { $_ ne "" and $_ ne "." and + ($is_mswin or !(stat && (stat _)[2]&0022)) } + split quotemeta ($sep), $1; + + $runperl =~ /(.*)/s; + $runperl = $1; + + $result = `$runperl`; + } else { + $result = `$runperl`; + } $result =~ s/\n\n/\n/ if $is_vms; # XXX pipes sometimes double these return $result; } @@ -463,7 +532,7 @@ my $Perl; sub which_perl { unless (defined $Perl) { $Perl = $^X; - + # VMS should have 'perl' aliased properly return $Perl if $^O eq 'VMS'; @@ -476,11 +545,11 @@ sub which_perl { $exe = $Config{_exe}; } $exe = '' unless defined $exe; - + # This doesn't absolutize the path: beware of future chdirs(). # We could do File::Spec->abs2rel() but that does getcwd()s, # which is a bit heavyweight to do here. - + if ($Perl =~ /^perl\Q$exe\E$/i) { my $perl = "perl$exe"; eval "require File::Spec"; @@ -500,7 +569,7 @@ sub which_perl { } warn "which_perl: cannot find $Perl from $^X" unless -f $Perl; - + # For subcommands to use. $ENV{PERLEXE} = $Perl; } @@ -540,12 +609,12 @@ sub _fresh_perl { if( $^O eq 'VMS' ) { $prog =~ s#/dev/null#NL:#; - # VMS file locking + # VMS file locking $prog =~ s{if \(-e _ and -f _ and -r _\)} {if (-e _ and -f _)} } - print TEST $prog, "\n"; + print TEST $prog; close TEST or die "Cannot close $tmpfile: $!"; my $results = runperl(%$runperl_args); @@ -615,4 +684,66 @@ sub fresh_perl_like { $runperl_args, $name); } +sub can_ok ($@) { + my($proto, @methods) = @_; + my $class = ref $proto || $proto; + + unless( @methods ) { + return _ok( 0, _where(), "$class->can(...)" ); + } + + my @nok = (); + foreach my $method (@methods) { + local($!, $@); # don't interfere with caller's $@ + # eval sometimes resets $! + eval { $proto->can($method) } || push @nok, $method; + } + + my $name; + $name = @methods == 1 ? "$class->can('$methods[0]')" + : "$class->can(...)"; + + _ok( !@nok, _where(), $name ); +} + +sub isa_ok ($$;$) { + my($object, $class, $obj_name) = @_; + + my $diag; + $obj_name = 'The object' unless defined $obj_name; + my $name = "$obj_name isa $class"; + if( !defined $object ) { + $diag = "$obj_name isn't defined"; + } + elsif( !ref $object ) { + $diag = "$obj_name isn't a reference"; + } + else { + # We can't use UNIVERSAL::isa because we want to honor isa() overrides + local($@, $!); # eval sometimes resets $! + my $rslt = eval { $object->isa($class) }; + if( $@ ) { + if( $@ =~ /^Can't call method "isa" on unblessed reference/ ) { + if( !UNIVERSAL::isa($object, $class) ) { + my $ref = ref $object; + $diag = "$obj_name isn't a '$class' it's a '$ref'"; + } + } else { + die <isa on your object and got some weird error. +This should never happen. Please contact the author immediately. +Here's the error. +$@ +WHOA + } + } + elsif( !$rslt ) { + my $ref = ref $object; + $diag = "$obj_name isn't a '$class' it's a '$ref'"; + } + } + + _ok( !$diag, _where(), $name ); +} + 1;