[patch @13687] Unicode::Collate 0.10
[p5sagit/p5-mst-13.2.git] / lib / Test / Harness.pm
index 29344cd..26bdf71 100644 (file)
@@ -1,5 +1,5 @@
 # -*- Mode: cperl; cperl-indent-level: 4 -*-
-# $Id: Harness.pm,v 1.11 2001/05/23 18:24:41 schwern Exp $
+# $Id: Harness.pm,v 1.17 2001/09/07 06:20:29 schwern Exp $
 
 package Test::Harness;
 
@@ -20,7 +20,7 @@ use vars qw($VERSION $Verbose $Switches $Have_Devel_Corestack $Curtest
 
 $Have_Devel_Corestack = 0;
 
-$VERSION = "1.21";
+$VERSION = 1.26;
 
 $ENV{HARNESS_ACTIVE} = 1;
 
@@ -206,11 +206,11 @@ test script, please use a comment.
 It will happen, your tests will fail.  After you mop up your ego, you
 can begin examining the summary report:
 
-  t/base..............ok                                                       
-  t/nonumbers.........ok                                                      
-  t/ok................ok                                                       
-  t/test-harness......ok                                                       
-  t/waterloo..........dubious                                                  
+  t/base..............ok
+  t/nonumbers.........ok
+  t/ok................ok
+  t/test-harness......ok
+  t/waterloo..........dubious
           Test returned status 3 (wstat 768, 0x300)
   DIED. FAILED tests 1, 3, 5, 7, 9, 11, 13, 15, 17, 19
           Failed 10/20 tests, 50.00% okay
@@ -289,7 +289,7 @@ sub runtests {
     my($tot, $failedtests) = _run_all_tests(@tests);
     _show_results($tot, $failedtests);
 
-    my $ok = ($tot->{bad} == 0 && $tot->{max});
+    my $ok = _all_ok($tot);
 
     die q{Assert '$ok xor keys %$failedtests' failed!}
       unless $ok xor keys %$failedtests;
@@ -299,6 +299,20 @@ sub runtests {
 
 =begin _private
 
+=item B<_all_ok>
+
+  my $ok = _all_ok(\%tot);
+
+Tells you if this test run is overall successful or not.
+
+=cut
+
+sub _all_ok {
+    my($tot) = shift;
+
+    return $tot->{bad} == 0 && ($tot->{max} || $tot->{skipped}) ? 1 : 0;
+}
+
 =item B<_globdir>
 
   my @files = _globdir $dir;
@@ -328,6 +342,7 @@ and values are this:
     max             Number of individual tests ran
     ok              Number of individual tests passed
     sub_skipped     Number of individual tests skipped
+    todo            Number of individual todo tests
 
     files           Number of test files ran
     good            Number of test files passed
@@ -371,8 +386,9 @@ sub _run_all_tests {
                 good     => 0,
                 tests    => scalar @tests,
                 sub_skipped  => 0,
+                todo     => 0,
                 skipped  => 0,
-                bench    => 0
+                bench    => 0,
                );
 
     # pass -I flags to children
@@ -383,8 +399,8 @@ sub _run_all_tests {
     # for VMS
     my $new5lib;
     if ($^O eq 'VMS') {
-       $new5lib = join($Config{path_sep}, grep {!/perl_root/i;} @INC);
-       $Switches =~ s/-(\S*[A-Z]\S*)/"-$1"/g;
+        $new5lib = join($Config{path_sep}, grep {!/perl_root/i;} @INC);
+        $Switches =~ s/-(\S*[A-Z]\S*)/"-$1"/g;
     }
     else {
         $new5lib = join($Config{path_sep}, @INC);
@@ -398,14 +414,15 @@ sub _run_all_tests {
     my $maxlen = 0;
     my $maxsuflen = 0;
     foreach (@tests) { # The same code in t/TEST
-       my $suf    = /\.(\w+)$/ ? $1 : '';
-       my $len    = length;
-       my $suflen = length $suf;
-       $maxlen    = $len    if $len    > $maxlen;
-       $maxsuflen = $suflen if $suflen > $maxsuflen;
+       my $suf    = /\.(\w+)$/ ? $1 : '';
+       my $len    = length;
+       my $suflen = length $suf;
+       $maxlen    = $len    if $len    > $maxlen;
+       $maxsuflen = $suflen if $suflen > $maxsuflen;
     }
     # + 3 : we want three dots between the test name and the "ok"
     my $width = $maxlen + 3 - $maxsuflen;
+
     foreach my $tfile (@tests) {
         my($leader, $ml) = _mk_leader($tfile, $width);
         print $leader;
@@ -426,7 +443,7 @@ sub _run_all_tests {
                    );
 
         my($seen_header, $tests_seen) = (0,0);
-       while (<$fh>) {
+        while (<$fh>) {
             if( _parse_header($_, \%test, \%tot) ) {
                 warn "Test header seen twice!\n" if $seen_header;
 
@@ -439,36 +456,36 @@ sub _run_all_tests {
                 $tests_seen++;
             }
             # else, ignore it.
-       }
+        }
 
         my($estatus, $wstatus) = _close_fh($fh);
 
         my $allok = $test{ok} == $test{max} && $test{'next'} == $test{max}+1;
 
-       if ($wstatus) {
+        if ($wstatus) {
             $failedtests{$tfile} = _dubious_return(\%test, \%tot, 
                                                   $estatus, $wstatus);
             $failedtests{$tfile}{name} = $tfile;
-       }
+        }
         elsif ($allok) {
-           if ($test{max} and $test{skipped} + $test{bonus}) {
-               my @msg;
-               push(@msg, "$test{skipped}/$test{max} skipped: $test{skip_reason}")
-                   if $test{skipped};
-               push(@msg, "$test{bonus}/$test{max} unexpectedly succeeded")
-                   if $test{bonus};
-               print "$test{ml}ok, ".join(', ', @msg)."\n";
-           } elsif ($test{max}) {
-               print "$test{ml}ok\n";
-           } elsif (defined $test{skip_reason}) {
-               print "skipped: $test{skip_reason}\n";
-               $tot{skipped}++;
-           } else {
-               print "skipped test on this platform\n";
-               $tot{skipped}++;
-           }
-           $tot{good}++;
-       }
+            if ($test{max} and $test{skipped} + $test{bonus}) {
+                my @msg;
+                push(@msg, "$test{skipped}/$test{max} skipped: $test{skip_reason}")
+                    if $test{skipped};
+                push(@msg, "$test{bonus}/$test{max} unexpectedly succeeded")
+                    if $test{bonus};
+                print "$test{ml}ok, ".join(', ', @msg)."\n";
+            } elsif ($test{max}) {
+                print "$test{ml}ok\n";
+            } elsif (defined $test{skip_reason}) {
+                print "skipped: $test{skip_reason}\n";
+                $tot{skipped}++;
+            } else {
+                print "skipped test on this platform\n";
+                $tot{skipped}++;
+            }
+            $tot{good}++;
+        }
         else {
             if ($test{max}) {
                 if ($test{'next'} <= $test{max}) {
@@ -513,28 +530,28 @@ sub _run_all_tests {
             }
         }
 
-       $tot{sub_skipped} += $test{skipped};
-
-       if (defined $Files_In_Dir) {
-           my @new_dir_files = _globdir $Files_In_Dir;
-           if (@new_dir_files != @dir_files) {
-               my %f;
-               @f{@new_dir_files} = (1) x @new_dir_files;
-               delete @f{@dir_files};
-               my @f = sort keys %f;
-               print "LEAKED FILES: @f\n";
-               @dir_files = @new_dir_files;
-           }
-       }
+        $tot{sub_skipped} += $test{skipped};
+
+        if (defined $Files_In_Dir) {
+            my @new_dir_files = _globdir $Files_In_Dir;
+            if (@new_dir_files != @dir_files) {
+                my %f;
+                @f{@new_dir_files} = (1) x @new_dir_files;
+                delete @f{@dir_files};
+                my @f = sort keys %f;
+                print "LEAKED FILES: @f\n";
+                @dir_files = @new_dir_files;
+            }
+        }
     }
     $tot{bench} = timediff(new Benchmark, $t_start);
 
     if ($^O eq 'VMS') {
-       if (defined $old5lib) {
-           $ENV{PERL5LIB} = $old5lib;
-       } else {
-           delete $ENV{PERL5LIB};
-       }
+        if (defined $old5lib) {
+            $ENV{PERL5LIB} = $old5lib;
+        } else {
+            delete $ENV{PERL5LIB};
+        }
     }
 
     return(\%tot, \%failedtests);
@@ -547,13 +564,15 @@ sub _run_all_tests {
 Generates the 't/foo........' $leader for the given $test_file as well
 as a similar version which will overwrite the current line (by use of
 \r and such).  $ml may be empty if Test::Harness doesn't think you're
-on TTY.  The width is the width of the "yada/blah..." string.
+on TTY.
+
+The $width is the width of the "yada/blah.." string.
 
 =cut
 
 sub _mk_leader {
-    my ($te, $width) = @_;
-
+    my($te, $width) = @_;
+    chomp($te);
     $te =~ s/\.\w+$/./;
 
     if ($^O eq 'VMS') { $te =~ s/^.*\.t\./\[.t./s; }
@@ -574,33 +593,34 @@ sub _show_results {
     my $pct;
     my $bonusmsg = _bonusmsg($tot);
 
-    if ($tot->{bad} == 0 && $tot->{max}) {
-       print "All tests successful$bonusmsg.\n";
-    } elsif ($tot->{tests}==0){
-       die "FAILED--no tests were run for some reason.\n";
-    } elsif ($tot->{max} == 0) {
-       my $blurb = $tot->{tests}==1 ? "script" : "scripts";
-       die "FAILED--$tot->{tests} test $blurb could be run, ".
+    if (_all_ok($tot)) {
+        print "All tests successful$bonusmsg.\n";
+    } elsif (!$tot->{tests}){
+        die "FAILED--no tests were run for some reason.\n";
+    } elsif (!$tot->{max}) {
+        my $blurb = $tot->{tests}==1 ? "script" : "scripts";
+        die "FAILED--$tot->{tests} test $blurb could be run, ".
             "alas--no output ever seen\n";
     } else {
-       $pct = sprintf("%.2f", $tot->{good} / $tot->{tests} * 100);
-       my $subpct = sprintf " %d/%d subtests failed, %.2f%% okay.",
-                             $tot->{max} - $tot->{ok}, $tot->{max}, 
-                              100*$tot->{ok}/$tot->{max};
+        $pct = sprintf("%.2f", $tot->{good} / $tot->{tests} * 100);
+        my $percent_ok = 100*$tot->{ok}/$tot->{max};
+        my $subpct = sprintf " %d/%d subtests failed, %.2f%% okay.",
+                              $tot->{max} - $tot->{ok}, $tot->{max}, 
+                              $percent_ok;
 
         my($fmt_top, $fmt) = _create_fmts($failedtests);
 
-       # Now write to formats
-       for my $script (sort keys %$failedtests) {
-         $Curtest = $failedtests->{$script};
-         write;
-       }
-       if ($tot->{bad}) {
-           $bonusmsg =~ s/^,\s*//;
-           print "$bonusmsg.\n" if $bonusmsg;
-           die "Failed $tot->{bad}/$tot->{tests} test scripts, $pct% okay.".
+        # Now write to formats
+        for my $script (sort keys %$failedtests) {
+          $Curtest = $failedtests->{$script};
+          write;
+        }
+        if ($tot->{bad}) {
+            $bonusmsg =~ s/^,\s*//;
+            print "$bonusmsg.\n" if $bonusmsg;
+            die "Failed $tot->{bad}/$tot->{tests} test scripts, $pct% okay.".
                 "$subpct\n";
-       }
+        }
     }
 
     printf("Files=%d, Tests=%d, %s\n",
@@ -656,8 +676,8 @@ sub _open_test {
     # XXX This is WAY too core specific!
     my $cmd = ($ENV{'HARNESS_COMPILE_TEST'})
                 ? "./perl -I../lib ../utils/perlcc $test "
-                 . "-r 2>> ./compilelog |" 
-               : "$^X $s $test|";
+                  . "-r 2>> ./compilelog |" 
+                : "$^X $s $test|";
     $cmd = "MCR $cmd" if $^O eq 'VMS';
 
     if( open(PERL, $cmd) ) {
@@ -680,51 +700,54 @@ sub _parse_test_line {
     my($line, $test, $tot) = @_;
 
     if ($line =~ /^(not\s+)?ok\b/i) {
-        my $this = $test->{'next'} || 1;
+        $test->{'next'} ||= 1;
+        my $this = $test->{'next'};
         # "not ok 23"
-        if ($line =~ /^(not )?ok\s*(\d*)(\s*#.*)?/) {
-           my($not, $tnum, $extra) = ($1, $2, $3);
-
-           $this = $tnum if $tnum;
-
-           my($type, $reason) = $extra =~ /^\s*#\s*([Ss]kip\S*|TODO)(\s+.+)?/
-             if defined $extra;
-
-           my($istodo, $isskip);
-           if( defined $type ) {
-               $istodo = $type =~ /TODO/;
-               $isskip = $type =~ /skip/i;
-           }
-
-           $test->{todo}{$tnum} = 1 if $istodo;
-
-           if( $not ) {
-               print "$test->{ml}NOK $this" if $test->{ml};
-               if (!$test->{todo}{$this}) {
-                   push @{$test->{failed}}, $this;
-               } else {
-                   $test->{ok}++;
-                   $tot->{ok}++;
-               }
-           }
-           else {
-               print "$test->{ml}ok $this/$test->{max}" if $test->{ml};
-               $test->{ok}++;
-               $tot->{ok}++;
-               $test->{skipped}++ if $isskip;
-
-               $reason = '[no reason given]'
-                   if $isskip and not defined $reason;
-               if (defined $reason and defined $test->{skip_reason}) {
-                   # print "was: '$skip_reason' new '$reason'\n";
-                   $test->{skip_reason} = 'various reasons'
-                     if $test->{skip_reason} ne $reason;
-               } elsif (defined $reason) {
-                   $test->{skip_reason} = $reason;
-               }
-
-               $test->{bonus}++, $tot->{bonus}++ if $test->{todo}{$this};
-           }
+        if ($line =~ /^(not )?ok\s*(\d*)[^#]*(\s*#.*)?/) {
+            my($not, $tnum, $extra) = ($1, $2, $3);
+
+            $this = $tnum if $tnum;
+
+            my($type, $reason) = $extra =~ /^\s*#\s*([Ss]kip\S*|TODO)(\s+.+)?/
+              if defined $extra;
+
+            my($istodo, $isskip);
+            if( defined $type ) {
+                $istodo = 1 if $type =~ /TODO/;
+                $isskip = 1 if $type =~ /skip/i;
+            }
+
+            $test->{todo}{$this} = 1 if $istodo;
+
+            $tot->{todo}++ if $test->{todo}{$this};
+
+            if( $not ) {
+                print "$test->{ml}NOK $this" if $test->{ml};
+                if (!$test->{todo}{$this}) {
+                    push @{$test->{failed}}, $this;
+                } else {
+                    $test->{ok}++;
+                    $tot->{ok}++;
+                }
+            }
+            else {
+                print "$test->{ml}ok $this/$test->{max}" if $test->{ml};
+                $test->{ok}++;
+                $tot->{ok}++;
+                $test->{skipped}++ if $isskip;
+
+                $reason = '[no reason given]'
+                    if $isskip and not defined $reason;
+                if (defined $reason and defined $test->{skip_reason}) {
+                    # print "was: '$skip_reason' new '$reason'\n";
+                    $test->{skip_reason} = 'various reasons'
+                      if $test->{skip_reason} ne $reason;
+                } elsif (defined $reason) {
+                    $test->{skip_reason} = $reason;
+                }
+
+                $test->{bonus}++, $tot->{bonus}++ if $test->{todo}{$this};
+            }
         }
         # XXX ummm... dunno
         elsif ($line =~ /^ok\s*(\d*)\s*\#([^\r]*)$/) { # XXX multiline ok?
@@ -740,8 +763,7 @@ sub _parse_test_line {
         }
 
         if ($this > $test->{'next'}) {
-            # print "Test output counter mismatch [test $this]\n";
-            # no need to warn probably
+            print "Test output counter mismatch [test $this]\n";
             push @{$test->{failed}}, $test->{'next'}..$this-1;
         }
         elsif ($this < $test->{'next'}) {
@@ -765,22 +787,22 @@ sub _bonusmsg {
 
     my $bonusmsg = '';
     $bonusmsg = (" ($tot->{bonus} subtest".($tot->{bonus} > 1 ? 's' : '').
-              " UNEXPECTEDLY SUCCEEDED)")
-       if $tot->{bonus};
+               " UNEXPECTEDLY SUCCEEDED)")
+        if $tot->{bonus};
 
     if ($tot->{skipped}) {
-       $bonusmsg .= ", $tot->{skipped} test"
+        $bonusmsg .= ", $tot->{skipped} test"
                      . ($tot->{skipped} != 1 ? 's' : '');
-       if ($tot->{sub_skipped}) {
-           $bonusmsg .= " and $tot->{sub_skipped} subtest"
-                        . ($tot->{sub_skipped} != 1 ? 's' : '');
-       }
-       $bonusmsg .= ' skipped';
+        if ($tot->{sub_skipped}) {
+            $bonusmsg .= " and $tot->{sub_skipped} subtest"
+                         . ($tot->{sub_skipped} != 1 ? 's' : '');
+        }
+        $bonusmsg .= ' skipped';
     }
     elsif ($tot->{sub_skipped}) {
-       $bonusmsg .= ", $tot->{sub_skipped} subtest"
-                    . ($tot->{sub_skipped} != 1 ? 's' : '')
-                    . " skipped";
+        $bonusmsg .= ", $tot->{sub_skipped} subtest"
+                     . ($tot->{sub_skipped} != 1 ? 's' : '')
+                     . " skipped";
     }
 
     return $bonusmsg;
@@ -792,7 +814,7 @@ sub _close_fh {
 
     close($fh); # must close to reap child resource values
 
-    my $wstatus = $Ignore_Exitcode ? 0 : $?;   # Can trust $? ?
+    my $wstatus = $Ignore_Exitcode ? 0 : $?;    # Can trust $? ?
     my $estatus;
     $estatus = ($^O eq 'VMS'
                   ? eval 'use vmsish "status"; $estatus = $?'
@@ -812,8 +834,8 @@ sub _set_switches {
     my $s = $Switches;
     $s .= " $ENV{'HARNESS_PERL_SWITCHES'}"
       if exists $ENV{'HARNESS_PERL_SWITCHES'};
-    $s .= join " ", q[ "-T"], map {qq["-I$_"]} @INC
-      if $first =~ /^#!.*\bperl.*-\w*T/;
+    $s .= join " ", qq[ "-$1"], map {qq["-I$_"]} @INC
+      if $first =~ /^#!.*\bperl.*-\w*([tT])/;
 
     close(TEST) or print "can't close $test. $!\n";
 
@@ -845,7 +867,7 @@ sub _dubious_return {
         if ($test->{'next'} == $test->{max} + 1 and not @{$test->{failed}}) {
             print "\tafter all the subtests completed successfully\n";
             $percent = 0;
-            $failed = 0;       # But we do not set $canon!
+            $failed = 0;        # But we do not set $canon!
         }
         else {
             push @{$test->{failed}}, $test->{'next'}..$test->{max};
@@ -897,23 +919,23 @@ sub _create_fmts {
     my $fmt_top = "format STDOUT_TOP =\n"
                   . sprintf("%-${max_namelen}s", $failed_str)
                   . $middle_str
-                 . $list_str . "\n"
-                 . "-" x $Columns
-                 . "\n.\n";
+                  . $list_str . "\n"
+                  . "-" x $Columns
+                  . "\n.\n";
 
     my $fmt = "format STDOUT =\n"
-             . "@" . "<" x ($max_namelen - 1)
+              . "@" . "<" x ($max_namelen - 1)
               . "  @>> @>>>> @>>>> @>>> ^##.##%  "
-             . "^" . "<" x ($list_len - 1) . "\n"
-             . '{ $Curtest->{name}, $Curtest->{estat},'
-             . '  $Curtest->{wstat}, $Curtest->{max},'
-             . '  $Curtest->{failed}, $Curtest->{percent},'
-             . '  $Curtest->{canon}'
-             . "\n}\n"
-             . "~~" . " " x ($Columns - $list_len - 2) . "^"
-             . "<" x ($list_len - 1) . "\n"
-             . '$Curtest->{canon}'
-             . "\n.\n";
+              . "^" . "<" x ($list_len - 1) . "\n"
+              . '{ $Curtest->{name}, $Curtest->{estat},'
+              . '  $Curtest->{wstat}, $Curtest->{max},'
+              . '  $Curtest->{failed}, $Curtest->{percent},'
+              . '  $Curtest->{canon}'
+              . "\n}\n"
+              . "~~" . " " x ($Columns - $list_len - 2) . "^"
+              . "<" x ($list_len - 1) . "\n"
+              . '$Curtest->{canon}'
+              . "\n.\n";
 
     eval $fmt_top;
     die $@ if $@;
@@ -950,23 +972,23 @@ sub canonfailed ($@) {
     my $last = $min = shift @failed;
     my $canon;
     if (@failed) {
-       for (@failed, $failed[-1]) { # don't forget the last one
-           if ($_ > $last+1 || $_ == $last) {
-               if ($min == $last) {
-                   push @canon, $last;
-               } else {
-                   push @canon, "$min-$last";
-               }
-               $min = $_;
-           }
-           $last = $_;
-       }
-       local $" = ", ";
-       push @result, "FAILED tests @canon\n";
-       $canon = join ' ', @canon;
+        for (@failed, $failed[-1]) { # don't forget the last one
+            if ($_ > $last+1 || $_ == $last) {
+                if ($min == $last) {
+                    push @canon, $last;
+                } else {
+                    push @canon, "$min-$last";
+                }
+                $min = $_;
+            }
+            $last = $_;
+        }
+        local $" = ", ";
+        push @result, "FAILED tests @canon\n";
+        $canon = join ' ', @canon;
     } else {
-       push @result, "FAILED test $last\n";
-       $canon = $last;
+        push @result, "FAILED test $last\n";
+        $canon = $last;
     }
 
     push @result, "\tFailed $failed/$max tests, ";