op/exec Win32 patch from Schwern via Abe Timmerman.
[p5sagit/p5-mst-13.2.git] / t / test.pl
index 223a197..4fdbd6f 100644 (file)
--- a/t/test.pl
+++ b/t/test.pl
@@ -6,6 +6,7 @@ my $test = 1;
 my $planned;
 
 $TODO = 0;
+$NO_ENDING = 0;
 
 sub plan {
     my $n;
@@ -21,11 +22,18 @@ sub plan {
 
 END {
     my $ran = $test - 1;
-    if (defined $planned && $planned != $ran) {
-       print STDOUT "# Looks like you planned $planned tests but ran $ran.\n";
+    if (!$NO_ENDING && defined $planned && $planned != $ran) {
+        print STDERR "# Looks like you planned $planned tests but ran $ran.\n";
     }
 }
 
+# Use this instead of "print STDERR" when outputing failure diagnostic 
+# messages
+sub _diag {
+    my $fh = $TODO ? *STDOUT : *STDERR;
+    print $fh @_;
+}
+
 sub skip_all {
     if (@_) {
        print STDOUT "1..0 - @_\n";
@@ -41,6 +49,8 @@ sub _ok {
     # VMS will avenge.
     my $out;
     if ($name) {
+        # escape out '#' or it will interfere with '# skip' and such
+        $name =~ s/#/\\#/g;
        $out = $pass ? "ok $test - $name" : "not ok $test - $name";
     } else {
        $out = $pass ? "ok $test" : "not ok $test";
@@ -50,12 +60,12 @@ sub _ok {
     print STDOUT "$out\n";
 
     unless ($pass) {
-       print STDOUT "# Failed $where\n";
+       _diag "# Failed $where\n";
     }
 
     # Ensure that the message is properly escaped.
-    print STDOUT map { /^#/ ? "$_\n" : "# $_\n" } 
-                 map { split /\n/ } @mess if @mess;
+    _diag map { /^#/ ? "$_\n" : "# $_\n" } 
+          map { split /\n/ } @mess if @mess;
 
     $test++;
 
@@ -76,10 +86,47 @@ sub _q {
     my $x = shift;
     return 'undef' unless defined $x;
     my $q = $x;
+    $q =~ s/\\/\\\\/;
     $q =~ s/'/\\'/;
     return "'$q'";
 }
 
+sub _qq {
+    my $x = shift;
+    return defined $x ? '"' . display ($x) . '"' : 'undef';
+};
+
+# keys are the codes \n etc map to, values are 2 char strings such as \n
+my %backslash_escape;
+foreach my $x (split //, 'nrtfa\\\'"') {
+    $backslash_escape{ord eval "\"\\$x\""} = "\\$x";
+}
+# A way to display scalars containing control characters and Unicode.
+# Trying to avoid setting $_, or relying on local $_ to work.
+sub display {
+    my @result;
+    foreach my $x (@_) {
+        if (defined $x and not ref $x) {
+            my $y = '';
+            foreach my $c (unpack("U*", $x)) {
+                if ($c > 255) {
+                    $y .= sprintf "\\x{%x}", $c;
+                } elsif ($backslash_escape{$c}) {
+                    $y .= $backslash_escape{$c};
+                } else {
+                    my $z = chr $c; # Maybe we can get away with a literal...
+                    $z = sprintf "\\%03o", $c if $z =~ /[[:^print:]]/;
+                    $y .= $z;
+                }
+            }
+            $x = $y;
+        }
+        return $x unless wantarray;
+        push @result, $x;
+    }
+    return @result;
+}
+
 sub is {
     my ($got, $expected, $name, @mess) = @_;
     my $pass = $got eq $expected;
@@ -107,7 +154,8 @@ sub like {
     if (ref $expected eq 'Regexp') {
        $pass = $got =~ $expected;
        unless ($pass) {
-           unshift(@mess, "#      got '$got'\n");
+           unshift(@mess, "#      got '$got'\n",
+                          "# expected /$expected/\n");
        }
     } else {
        $pass = $got =~ /$expected/;
@@ -157,6 +205,34 @@ sub eq_array {
     return 1;
 }
 
+sub eq_hash {
+  my ($orig, $suspect) = @_;
+  my $fail;
+  while (my ($key, $value) = each %$suspect) {
+    # Force a hash recompute if this perl's internals can cache the hash key.
+    $key = "" . $key;
+    if (exists $orig->{$key}) {
+      if ($orig->{$key} ne $value) {
+        print STDOUT "# key ", _qq($key), " was ", _qq($orig->{$key}),
+                     " now ", _qq($value), "\n";
+        $fail = 1;
+      }
+    } else {
+      print STDOUT "# key ", _qq($key), " is ", _qq($value), 
+                   ", not in original.\n";
+      $fail = 1;
+    }
+  }
+  foreach (keys %$orig) {
+    # Force a hash recompute if this perl's internals can cache the hash key.
+    $_ = "" . $_;
+    next if (exists $suspect->{$_});
+    print STDOUT "# key ", _qq($_), " was ", _qq($orig->{$_}), " now missing.\n";
+    $fail = 1;
+  }
+  !$fail;
+}
+
 sub require_ok {
     my ($require) = @_;
     eval <<REQUIRE_OK;
@@ -249,7 +325,7 @@ sub runperl {
     if ($args{verbose}) {
        my $runperldisplay = $runperl;
        $runperldisplay =~ s/\n/\n\#/g;
-       print STDOUT "# $runperldisplay\n";
+       print STDERR "# $runperldisplay\n";
     }
     my $result = `$runperl`;
     $result =~ s/\n\n/\n/ if $is_vms; # XXX pipes sometimes double these
@@ -257,57 +333,59 @@ sub runperl {
 }
 
 
-sub BAILOUT {
-    print STDOUT "Bail out! @_\n";
-    exit;
+sub DIE {
+    print STDERR "# @_\n";
+    exit 1;
 }
 
-
-# A way to display scalars containing control characters and Unicode.
-sub display {
-    map { join("", map { $_ > 255 ? sprintf("\\x{%x}", $_) : chr($_) =~ /[[:cntrl:]]/ ? sprintf("\\%03o", $_) : chr($_) } unpack("U*", $_)) } @_;
-}
-
-
 # A somewhat safer version of the sometimes wrong $^X.
-BEGIN: {
-    my $exe;
-    eval {
-        require Config;
-        Config->import;
-    };
-    if ($@) {
-       warn "test.pl had problems loading Config: $@";
-       $exe = '';
-    } else {
-       $exe = $Config{_exe};
-    }
-
-    my $Perl = $^X;
-
-    # 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) {
-        eval {
-           require File::Spec;
-       };
+my $Perl;
+sub which_perl {
+    unless (defined $Perl) {
+       $Perl = $^X;
+       
+       my $exe;
+       eval "require Config; Config->import";
        if ($@) {
-           warn "test.pl had problems loading File::Spec: $@";
+           warn "test.pl had problems loading Config: $@";
+           $exe = '';
        } else {
-           $Perl = File::Spec->catfile(File::Spec->curdir(), "perl$exe");
+           $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";
+           if ($@) {
+               warn "test.pl had problems loading File::Spec: $@";
+               $Perl = "./$perl";
+           } else {
+               $Perl = File::Spec->catfile(File::Spec->curdir(), $perl);
+           }
        }
+       
+        # Its like this.  stat on Cygwin treats 'perl' to mean 'perl.exe'
+        # but open does not.  This can get confusing, so to be safe we
+        # always put the .exe on the end on Cygwin.
+        $Perl .= $exe if $^O eq 'cygwin' && $Perl !~ /\Q$exe\E$/;
+
+       warn "which_perl: cannot find $Perl from $^X" unless -f $Perl;
+       
+       # For subcommands to use.
+       $ENV{PERLEXE} = $Perl;
     }
+    return $Perl;
+}
 
-    warn "Can't generate which_perl from $^X" unless -f $Perl;
-
-    # For subcommands to use.
-    $ENV{PERLEXE} = $Perl;
-
-    sub which_perl {
-       return $Perl;
+sub unlink_all {
+    foreach my $file (@_) {
+        1 while unlink $file;
+        print STDERR "# Couldn't unlink '$file': $!\n" if -f $file;
     }
 }
-
 1;