ExtUtils::Manifest fix-ups for VMS:
[p5sagit/p5-mst-13.2.git] / lib / Test / Harness.pm
1 # -*- Mode: cperl; cperl-indent-level: 4 -*-
2
3 package Test::Harness;
4
5 require 5.00405;
6 use Test::Harness::Straps;
7 use Test::Harness::Assert;
8 use Exporter;
9 use Benchmark;
10 use Config;
11 use strict;
12
13
14 use vars qw(
15     $VERSION 
16     @ISA @EXPORT @EXPORT_OK 
17     $Verbose $Switches $Debug
18     $verbose $switches $debug
19     $Columns
20     $Timer
21     $ML $Last_ML_Print
22     $Strap
23     $has_time_hires
24 );
25
26 BEGIN {
27     eval q{use Time::HiRes 'time'};
28     $has_time_hires = !$@;
29 }
30
31 =head1 NAME
32
33 Test::Harness - Run Perl standard test scripts with statistics
34
35 =head1 VERSION
36
37 Version 2.64
38
39 =cut
40
41 $VERSION = '2.64';
42
43 # Backwards compatibility for exportable variable names.
44 *verbose  = *Verbose;
45 *switches = *Switches;
46 *debug    = *Debug;
47
48 $ENV{HARNESS_ACTIVE} = 1;
49 $ENV{HARNESS_VERSION} = $VERSION;
50
51 END {
52     # For VMS.
53     delete $ENV{HARNESS_ACTIVE};
54     delete $ENV{HARNESS_VERSION};
55 }
56
57 my $Files_In_Dir = $ENV{HARNESS_FILELEAK_IN_DIR};
58
59 # Stolen from Params::Util
60 sub _CLASS {
61     (defined $_[0] and ! ref $_[0] and $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*$/s) ? $_[0] : undef;
62 }
63
64 # Strap Overloading
65 if ( $ENV{HARNESS_STRAPS_CLASS} ) {
66     die 'Set HARNESS_STRAP_CLASS, singular, not HARNESS_STRAPS_CLASS';
67 }
68 my $HARNESS_STRAP_CLASS  = $ENV{HARNESS_STRAP_CLASS} || 'Test::Harness::Straps';
69 if ( $HARNESS_STRAP_CLASS =~ /\.pm$/ ) {
70     # "Class" is actually a filename, that should return the
71     # class name as its true return value.
72     $HARNESS_STRAP_CLASS = require $HARNESS_STRAP_CLASS;
73     if ( !_CLASS($HARNESS_STRAP_CLASS) ) {
74         die "HARNESS_STRAP_CLASS '$HARNESS_STRAP_CLASS' is not a valid class name";
75     }
76 }
77 else {
78     # It is a class name within the current @INC
79     if ( !_CLASS($HARNESS_STRAP_CLASS) ) {
80         die "HARNESS_STRAP_CLASS '$HARNESS_STRAP_CLASS' is not a valid class name";
81     }
82     eval "require $HARNESS_STRAP_CLASS";
83     die $@ if $@;
84 }
85 if ( !$HARNESS_STRAP_CLASS->isa('Test::Harness::Straps') ) {
86     die "HARNESS_STRAP_CLASS '$HARNESS_STRAP_CLASS' must be a Test::Harness::Straps subclass";
87 }
88
89 $Strap = $HARNESS_STRAP_CLASS->new;
90
91 sub strap { return $Strap };
92
93 @ISA = ('Exporter');
94 @EXPORT    = qw(&runtests);
95 @EXPORT_OK = qw(&execute_tests $verbose $switches);
96
97 $Verbose  = $ENV{HARNESS_VERBOSE} || 0;
98 $Debug    = $ENV{HARNESS_DEBUG} || 0;
99 $Switches = '-w';
100 $Columns  = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
101 $Columns--;             # Some shells have trouble with a full line of text.
102 $Timer    = $ENV{HARNESS_TIMER} || 0;
103
104 =head1 SYNOPSIS
105
106   use Test::Harness;
107
108   runtests(@test_files);
109
110 =head1 DESCRIPTION
111
112 B<STOP!> If all you want to do is write a test script, consider
113 using Test::Simple.  Test::Harness is the module that reads the
114 output from Test::Simple, Test::More and other modules based on
115 Test::Builder.  You don't need to know about Test::Harness to use
116 those modules.
117
118 Test::Harness runs tests and expects output from the test in a
119 certain format.  That format is called TAP, the Test Anything
120 Protocol.  It is defined in L<Test::Harness::TAP>.
121
122 C<Test::Harness::runtests(@tests)> runs all the testscripts named
123 as arguments and checks standard output for the expected strings
124 in TAP format.
125
126 The F<prove> utility is a thin wrapper around Test::Harness.
127
128 =head2 Taint mode
129
130 Test::Harness will honor the C<-T> or C<-t> in the #! line on your
131 test files.  So if you begin a test with:
132
133     #!perl -T
134
135 the test will be run with taint mode on.
136
137 =head2 Configuration variables.
138
139 These variables can be used to configure the behavior of
140 Test::Harness.  They are exported on request.
141
142 =over 4
143
144 =item C<$Test::Harness::Verbose>
145
146 The package variable C<$Test::Harness::Verbose> is exportable and can be
147 used to let C<runtests()> display the standard output of the script
148 without altering the behavior otherwise.  The F<prove> utility's C<-v>
149 flag will set this.
150
151 =item C<$Test::Harness::switches>
152
153 The package variable C<$Test::Harness::switches> is exportable and can be
154 used to set perl command line options used for running the test
155 script(s). The default value is C<-w>. It overrides C<HARNESS_PERL_SWITCHES>.
156
157 =item C<$Test::Harness::Timer>
158
159 If set to true, and C<Time::HiRes> is available, print elapsed seconds
160 after each test file.
161
162 =back
163
164
165 =head2 Failure
166
167 When tests fail, analyze the summary report:
168
169   t/base..............ok
170   t/nonumbers.........ok
171   t/ok................ok
172   t/test-harness......ok
173   t/waterloo..........dubious
174           Test returned status 3 (wstat 768, 0x300)
175   DIED. FAILED tests 1, 3, 5, 7, 9, 11, 13, 15, 17, 19
176           Failed 10/20 tests, 50.00% okay
177   Failed Test  Stat Wstat Total Fail  List of Failed
178   ---------------------------------------------------------------
179   t/waterloo.t    3   768    20   10  1 3 5 7 9 11 13 15 17 19
180   Failed 1/5 test scripts, 80.00% okay. 10/44 subtests failed, 77.27% okay.
181
182 Everything passed but F<t/waterloo.t>.  It failed 10 of 20 tests and
183 exited with non-zero status indicating something dubious happened.
184
185 The columns in the summary report mean:
186
187 =over 4
188
189 =item B<Failed Test>
190
191 The test file which failed.
192
193 =item B<Stat>
194
195 If the test exited with non-zero, this is its exit status.
196
197 =item B<Wstat>
198
199 The wait status of the test.
200
201 =item B<Total>
202
203 Total number of tests expected to run.
204
205 =item B<Fail>
206
207 Number which failed, either from "not ok" or because they never ran.
208
209 =item B<List of Failed>
210
211 A list of the tests which failed.  Successive failures may be
212 abbreviated (ie. 15-20 to indicate that tests 15, 16, 17, 18, 19 and
213 20 failed).
214
215 =back
216
217
218 =head1 FUNCTIONS
219
220 The following functions are available.
221
222 =head2 runtests( @test_files )
223
224 This runs all the given I<@test_files> and divines whether they passed
225 or failed based on their output to STDOUT (details above).  It prints
226 out each individual test which failed along with a summary report and
227 a how long it all took.
228
229 It returns true if everything was ok.  Otherwise it will C<die()> with
230 one of the messages in the DIAGNOSTICS section.
231
232 =cut
233
234 sub runtests {
235     my(@tests) = @_;
236
237     local ($\, $,);
238
239     my ($tot, $failedtests,$todo_passed) = execute_tests(tests => \@tests);
240     print get_results($tot, $failedtests,$todo_passed);
241
242     my $ok = _all_ok($tot);
243
244     assert(($ok xor keys %$failedtests), 
245            q{ok status jives with $failedtests});
246
247     if (! $ok) {
248         die("Failed $tot->{bad}/$tot->{tests} test programs. " .
249             "@{[$tot->{max} - $tot->{ok}]}/$tot->{max} subtests failed.\n");
250     }
251
252     return $ok;
253 }
254
255 # my $ok = _all_ok(\%tot);
256 # Tells you if this test run is overall successful or not.
257
258 sub _all_ok {
259     my($tot) = shift;
260
261     return $tot->{bad} == 0 && ($tot->{max} || $tot->{skipped}) ? 1 : 0;
262 }
263
264 # Returns all the files in a directory.  This is shorthand for backwards
265 # compatibility on systems where C<glob()> doesn't work right.
266
267 sub _globdir {
268     local *DIRH;
269
270     opendir DIRH, shift;
271     my @f = readdir DIRH;
272     closedir DIRH;
273
274     return @f;
275 }
276
277 =head2 execute_tests( tests => \@test_files, out => \*FH )
278
279 Runs all the given C<@test_files> (just like C<runtests()>) but
280 doesn't generate the final report.  During testing, progress
281 information will be written to the currently selected output
282 filehandle (usually C<STDOUT>), or to the filehandle given by the
283 C<out> parameter.  The I<out> is optional.
284
285 Returns a list of two values, C<$total> and C<$failed>, describing the
286 results.  C<$total> is a hash ref summary of all the tests run.  Its
287 keys and values are this:
288
289     bonus           Number of individual todo tests unexpectedly passed
290     max             Number of individual tests ran
291     ok              Number of individual tests passed
292     sub_skipped     Number of individual tests skipped
293     todo            Number of individual todo tests
294
295     files           Number of test files ran
296     good            Number of test files passed
297     bad             Number of test files failed
298     tests           Number of test files originally given
299     skipped         Number of test files skipped
300
301 If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've
302 got a successful test.
303
304 C<$failed> is a hash ref of all the test scripts that failed.  Each key
305 is the name of a test script, each value is another hash representing
306 how that script failed.  Its keys are these:
307
308     name        Name of the test which failed
309     estat       Script's exit value
310     wstat       Script's wait status
311     max         Number of individual tests
312     failed      Number which failed
313     canon       List of tests which failed (as string).
314
315 C<$failed> should be empty if everything passed.
316
317 =cut
318
319 sub execute_tests {
320     my %args = @_;
321     my @tests = @{$args{tests}};
322     my $out = $args{out} || select();
323
324     # We allow filehandles that are symbolic refs
325     no strict 'refs';
326     _autoflush($out);
327     _autoflush(\*STDERR);
328
329     my %failedtests;
330     my %todo_passed;
331
332     # Test-wide totals.
333     my(%tot) = (
334                 bonus    => 0,
335                 max      => 0,
336                 ok       => 0,
337                 files    => 0,
338                 bad      => 0,
339                 good     => 0,
340                 tests    => scalar @tests,
341                 sub_skipped  => 0,
342                 todo     => 0,
343                 skipped  => 0,
344                 bench    => 0,
345                );
346
347     my @dir_files;
348     @dir_files = _globdir $Files_In_Dir if defined $Files_In_Dir;
349     my $run_start_time = new Benchmark;
350
351     my $width = _leader_width(@tests);
352     foreach my $tfile (@tests) {
353         $Last_ML_Print = 0;  # so each test prints at least once
354         my($leader, $ml) = _mk_leader($tfile, $width);
355         local $ML = $ml;
356
357         print $out $leader;
358
359         $tot{files}++;
360
361         $Strap->{_seen_header} = 0;
362         if ( $Test::Harness::Debug ) {
363             print $out "# Running: ", $Strap->_command_line($tfile), "\n";
364         }
365         my $test_start_time = $Timer ? time : 0;
366         my $results = $Strap->analyze_file($tfile) or
367           do { warn $Strap->{error}, "\n";  next };
368         my $elapsed;
369         if ( $Timer ) {
370             $elapsed = time - $test_start_time;
371             if ( $has_time_hires ) {
372                 $elapsed = sprintf( " %8d ms", $elapsed*1000 );
373             }
374             else {
375                 $elapsed = sprintf( " %8s s", $elapsed ? $elapsed : "<1" );
376             }
377         }
378         else {
379             $elapsed = "";
380         }
381
382         # state of the current test.
383         my @failed = grep { !$results->details->[$_-1]{ok} }
384                      1..@{$results->details};
385         my @todo_pass = grep { $results->details->[$_-1]{actual_ok} &&
386                                $results->details->[$_-1]{type} eq 'todo' }
387                         1..@{$results->details};
388
389         my %test = (
390             ok          => $results->ok,
391             'next'      => $Strap->{'next'},
392             max         => $results->max,
393             failed      => \@failed,
394             todo_pass   => \@todo_pass,
395             todo        => $results->todo,
396             bonus       => $results->bonus,
397             skipped     => $results->skip,
398             skip_reason => $results->skip_reason,
399             skip_all    => $Strap->{skip_all},
400             ml          => $ml,
401         );
402
403         $tot{bonus}       += $results->bonus;
404         $tot{max}         += $results->max;
405         $tot{ok}          += $results->ok;
406         $tot{todo}        += $results->todo;
407         $tot{sub_skipped} += $results->skip;
408
409         my $estatus = $results->exit;
410         my $wstatus = $results->wait;
411
412         if ( $results->passing ) {
413             # XXX Combine these first two
414             if ($test{max} and $test{skipped} + $test{bonus}) {
415                 my @msg;
416                 push(@msg, "$test{skipped}/$test{max} skipped: $test{skip_reason}")
417                     if $test{skipped};
418                 if ($test{bonus}) {
419                     my ($txt, $canon) = _canondetail($test{todo},0,'TODO passed',
420                                                     @{$test{todo_pass}});
421                     $todo_passed{$tfile} = {
422                         canon   => $canon,
423                         max     => $test{todo},
424                         failed  => $test{bonus},
425                         name    => $tfile,
426                         estat   => '',
427                         wstat   => '',
428                     };
429
430                     push(@msg, "$test{bonus}/$test{max} unexpectedly succeeded\n$txt");
431                 }
432                 print $out "$test{ml}ok$elapsed\n        ".join(', ', @msg)."\n";
433             }
434             elsif ( $test{max} ) {
435                 print $out "$test{ml}ok$elapsed\n";
436             }
437             elsif ( defined $test{skip_all} and length $test{skip_all} ) {
438                 print $out "skipped\n        all skipped: $test{skip_all}\n";
439                 $tot{skipped}++;
440             }
441             else {
442                 print $out "skipped\n        all skipped: no reason given\n";
443                 $tot{skipped}++;
444             }
445             $tot{good}++;
446         }
447         else {
448             # List unrun tests as failures.
449             if ($test{'next'} <= $test{max}) {
450                 push @{$test{failed}}, $test{'next'}..$test{max};
451             }
452             # List overruns as failures.
453             else {
454                 my $details = $results->details;
455                 foreach my $overrun ($test{max}+1..@$details) {
456                     next unless ref $details->[$overrun-1];
457                     push @{$test{failed}}, $overrun
458                 }
459             }
460
461             if ($wstatus) {
462                 $failedtests{$tfile} = _dubious_return(\%test, \%tot, 
463                                                        $estatus, $wstatus);
464                 $failedtests{$tfile}{name} = $tfile;
465             }
466             elsif ( $results->seen ) {
467                 if (@{$test{failed}} and $test{max}) {
468                     my ($txt, $canon) = _canondetail($test{max},$test{skipped},'Failed',
469                                                     @{$test{failed}});
470                     print $out "$test{ml}$txt";
471                     $failedtests{$tfile} = { canon   => $canon,
472                                              max     => $test{max},
473                                              failed  => scalar @{$test{failed}},
474                                              name    => $tfile, 
475                                              estat   => '',
476                                              wstat   => '',
477                                            };
478                 }
479                 else {
480                     print $out "Don't know which tests failed: got $test{ok} ok, ".
481                           "expected $test{max}\n";
482                     $failedtests{$tfile} = { canon   => '??',
483                                              max     => $test{max},
484                                              failed  => '??',
485                                              name    => $tfile, 
486                                              estat   => '', 
487                                              wstat   => '',
488                                            };
489                 }
490                 $tot{bad}++;
491             }
492             else {
493                 print $out "FAILED before any test output arrived\n";
494                 $tot{bad}++;
495                 $failedtests{$tfile} = { canon       => '??',
496                                          max         => '??',
497                                          failed      => '??',
498                                          name        => $tfile,
499                                          estat       => '', 
500                                          wstat       => '',
501                                        };
502             }
503         }
504
505         if (defined $Files_In_Dir) {
506             my @new_dir_files = _globdir $Files_In_Dir;
507             if (@new_dir_files != @dir_files) {
508                 my %f;
509                 @f{@new_dir_files} = (1) x @new_dir_files;
510                 delete @f{@dir_files};
511                 my @f = sort keys %f;
512                 print $out "LEAKED FILES: @f\n";
513                 @dir_files = @new_dir_files;
514             }
515         }
516     } # foreach test
517     $tot{bench} = timediff(new Benchmark, $run_start_time);
518
519     $Strap->_restore_PERL5LIB;
520
521     return(\%tot, \%failedtests, \%todo_passed);
522 }
523
524 # Turns on autoflush for the handle passed
525 sub _autoflush {
526     my $flushy_fh = shift;
527     my $old_fh = select $flushy_fh;
528     $| = 1;
529     select $old_fh;
530 }
531
532 =for private _mk_leader
533
534     my($leader, $ml) = _mk_leader($test_file, $width);
535
536 Generates the 't/foo........' leader for the given C<$test_file> as well
537 as a similar version which will overwrite the current line (by use of
538 \r and such).  C<$ml> may be empty if Test::Harness doesn't think you're
539 on TTY.
540
541 The C<$width> is the width of the "yada/blah.." string.
542
543 =cut
544
545 sub _mk_leader {
546     my($te, $width) = @_;
547     chomp($te);
548     $te =~ s/\.\w+$/./;
549
550     if ($^O eq 'VMS') {
551         $te =~ s/^.*\.t\./\[.t./s;
552     }
553     my $leader = "$te" . '.' x ($width - length($te));
554     my $ml = "";
555
556     if ( -t STDOUT and not $ENV{HARNESS_NOTTY} and not $Verbose ) {
557         $ml = "\r" . (' ' x 77) . "\r$leader"
558     }
559
560     return($leader, $ml);
561 }
562
563 =for private _leader_width
564
565   my($width) = _leader_width(@test_files);
566
567 Calculates how wide the leader should be based on the length of the
568 longest test name.
569
570 =cut
571
572 sub _leader_width {
573     my $maxlen = 0;
574     my $maxsuflen = 0;
575     foreach (@_) {
576         my $suf    = /\.(\w+)$/ ? $1 : '';
577         my $len    = length;
578         my $suflen = length $suf;
579         $maxlen    = $len    if $len    > $maxlen;
580         $maxsuflen = $suflen if $suflen > $maxsuflen;
581     }
582     # + 3 : we want three dots between the test name and the "ok"
583     return $maxlen + 3 - $maxsuflen;
584 }
585
586 sub get_results {
587     my $tot = shift;
588     my $failedtests = shift;
589     my $todo_passed = shift;
590
591     my $out = '';
592
593     my $bonusmsg = _bonusmsg($tot);
594
595     if (_all_ok($tot)) {
596         $out .= "All tests successful$bonusmsg.\n";
597         if ($tot->{bonus}) {
598             my($fmt_top, $fmt) = _create_fmts("Passed TODO",$todo_passed);
599             # Now write to formats
600             $out .= swrite( $fmt_top );
601             for my $script (sort keys %{$todo_passed||{}}) {
602                 my $Curtest = $todo_passed->{$script};
603                 $out .= swrite( $fmt, @{ $Curtest }{qw(name estat wstat max failed canon)} );
604             }
605         }
606     }
607     elsif (!$tot->{tests}){
608         die "FAILED--no tests were run for some reason.\n";
609     }
610     elsif (!$tot->{max}) {
611         my $blurb = $tot->{tests}==1 ? "script" : "scripts";
612         die "FAILED--$tot->{tests} test $blurb could be run, ".
613             "alas--no output ever seen\n";
614     }
615     else {
616         my $subresults = sprintf( " %d/%d subtests failed.",
617                               $tot->{max} - $tot->{ok}, $tot->{max} );
618
619         my($fmt_top, $fmt1, $fmt2) = _create_fmts("Failed Test",$failedtests);
620
621         # Now write to formats
622         $out .= swrite( $fmt_top );
623         for my $script (sort keys %$failedtests) {
624             my $Curtest = $failedtests->{$script};
625             $out .= swrite( $fmt1, @{ $Curtest }{qw(name estat wstat max failed canon)} );
626             $out .= swrite( $fmt2, $Curtest->{canon} );
627         }
628         if ($tot->{bad}) {
629             $bonusmsg =~ s/^,\s*//;
630             $out .= "$bonusmsg.\n" if $bonusmsg;
631             $out .= "Failed $tot->{bad}/$tot->{tests} test scripts.$subresults\n";
632         }
633     }
634
635     $out .= sprintf("Files=%d, Tests=%d, %s\n",
636            $tot->{files}, $tot->{max}, timestr($tot->{bench}, 'nop'));
637     return $out;
638 }
639
640 sub swrite {
641     my $format = shift;
642     $^A = '';
643     formline($format,@_);
644     my $out = $^A;
645     $^A = '';
646     return $out;
647 }
648
649
650 my %Handlers = (
651     header  => \&header_handler,
652     test    => \&test_handler,
653     bailout => \&bailout_handler,
654 );
655
656 $Strap->set_callback(\&strap_callback);
657 sub strap_callback {
658     my($self, $line, $type, $totals) = @_;
659     print $line if $Verbose;
660
661     my $meth = $Handlers{$type};
662     $meth->($self, $line, $type, $totals) if $meth;
663 };
664
665
666 sub header_handler {
667     my($self, $line, $type, $totals) = @_;
668
669     warn "Test header seen more than once!\n" if $self->{_seen_header};
670
671     $self->{_seen_header}++;
672
673     warn "1..M can only appear at the beginning or end of tests\n"
674       if $totals->seen && ($totals->max < $totals->seen);
675 };
676
677 sub test_handler {
678     my($self, $line, $type, $totals) = @_;
679
680     my $curr = $totals->seen;
681     my $next = $self->{'next'};
682     my $max  = $totals->max;
683     my $detail = $totals->details->[-1];
684
685     if( $detail->{ok} ) {
686         _print_ml_less("ok $curr/$max");
687
688         if( $detail->{type} eq 'skip' ) {
689             $totals->set_skip_reason( $detail->{reason} )
690               unless defined $totals->skip_reason;
691             $totals->set_skip_reason( 'various reasons' )
692               if $totals->skip_reason ne $detail->{reason};
693         }
694     }
695     else {
696         _print_ml("NOK $curr/$max");
697     }
698
699     if( $curr > $next ) {
700         print "Test output counter mismatch [test $curr]\n";
701     }
702     elsif( $curr < $next ) {
703         print "Confused test output: test $curr answered after ".
704               "test ", $next - 1, "\n";
705     }
706
707 };
708
709 sub bailout_handler {
710     my($self, $line, $type, $totals) = @_;
711
712     die "FAILED--Further testing stopped" .
713       ($self->{bailout_reason} ? ": $self->{bailout_reason}\n" : ".\n");
714 };
715
716
717 sub _print_ml {
718     print join '', $ML, @_ if $ML;
719 }
720
721
722 # Print updates only once per second.
723 sub _print_ml_less {
724     my $now = CORE::time;
725     if ( $Last_ML_Print != $now ) {
726         _print_ml(@_);
727         $Last_ML_Print = $now;
728     }
729 }
730
731 sub _bonusmsg {
732     my($tot) = @_;
733
734     my $bonusmsg = '';
735     $bonusmsg = (" ($tot->{bonus} subtest".($tot->{bonus} > 1 ? 's' : '').
736                " UNEXPECTEDLY SUCCEEDED)")
737         if $tot->{bonus};
738
739     if ($tot->{skipped}) {
740         $bonusmsg .= ", $tot->{skipped} test"
741                      . ($tot->{skipped} != 1 ? 's' : '');
742         if ($tot->{sub_skipped}) {
743             $bonusmsg .= " and $tot->{sub_skipped} subtest"
744                          . ($tot->{sub_skipped} != 1 ? 's' : '');
745         }
746         $bonusmsg .= ' skipped';
747     }
748     elsif ($tot->{sub_skipped}) {
749         $bonusmsg .= ", $tot->{sub_skipped} subtest"
750                      . ($tot->{sub_skipped} != 1 ? 's' : '')
751                      . " skipped";
752     }
753     return $bonusmsg;
754 }
755
756 # Test program go boom.
757 sub _dubious_return {
758     my($test, $tot, $estatus, $wstatus) = @_;
759
760     my $failed = '??';
761     my $canon  = '??';
762
763     printf "$test->{ml}dubious\n\tTest returned status $estatus ".
764            "(wstat %d, 0x%x)\n",
765            $wstatus,$wstatus;
766     print "\t\t(VMS status is $estatus)\n" if $^O eq 'VMS';
767
768     $tot->{bad}++;
769
770     if ($test->{max}) {
771         if ($test->{'next'} == $test->{max} + 1 and not @{$test->{failed}}) {
772             print "\tafter all the subtests completed successfully\n";
773             $failed = 0;        # But we do not set $canon!
774         }
775         else {
776             push @{$test->{failed}}, $test->{'next'}..$test->{max};
777             $failed = @{$test->{failed}};
778             (my $txt, $canon) = _canondetail($test->{max},$test->{skipped},'Failed',@{$test->{failed}});
779             print "DIED. ",$txt;
780         }
781     }
782
783     return { canon => $canon,  max => $test->{max} || '??',
784              failed => $failed, 
785              estat => $estatus, wstat => $wstatus,
786            };
787 }
788
789
790 sub _create_fmts {
791     my $failed_str = shift;
792     my $failedtests = shift;
793
794     my ($type) = split /\s/,$failed_str;
795     my $short = substr($type,0,4);
796     my $total = $short eq 'Pass' ? 'TODOs' : 'Total';
797     my $middle_str = " Stat Wstat $total $short  ";
798     my $list_str = "List of $type";
799
800     # Figure out our longest name string for formatting purposes.
801     my $max_namelen = length($failed_str);
802     foreach my $script (keys %$failedtests) {
803         my $namelen = length $failedtests->{$script}->{name};
804         $max_namelen = $namelen if $namelen > $max_namelen;
805     }
806
807     my $list_len = $Columns - length($middle_str) - $max_namelen;
808     if ($list_len < length($list_str)) {
809         $list_len = length($list_str);
810         $max_namelen = $Columns - length($middle_str) - $list_len;
811         if ($max_namelen < length($failed_str)) {
812             $max_namelen = length($failed_str);
813             $Columns = $max_namelen + length($middle_str) + $list_len;
814         }
815     }
816
817     my $fmt_top =   sprintf("%-${max_namelen}s", $failed_str)
818                   . $middle_str
819                   . $list_str . "\n"
820                   . "-" x $Columns
821                   . "\n";
822
823     my $fmt1 =  "@" . "<" x ($max_namelen - 1)
824               . "  @>> @>>>> @>>>> @>>>  "
825               . "^" . "<" x ($list_len - 1) . "\n";
826     my $fmt2 =  "~~" . " " x ($Columns - $list_len - 2) . "^"
827               . "<" x ($list_len - 1) . "\n";
828
829     return($fmt_top, $fmt1, $fmt2);
830 }
831
832 sub _canondetail {
833     my $max = shift;
834     my $skipped = shift;
835     my $type = shift;
836     my @detail = @_;
837     my %seen;
838     @detail = sort {$a <=> $b} grep !$seen{$_}++, @detail;
839     my $detail = @detail;
840     my @result = ();
841     my @canon = ();
842     my $min;
843     my $last = $min = shift @detail;
844     my $canon;
845     my $uc_type = uc($type);
846     if (@detail) {
847         for (@detail, $detail[-1]) { # don't forget the last one
848             if ($_ > $last+1 || $_ == $last) {
849                 push @canon, ($min == $last) ? $last : "$min-$last";
850                 $min = $_;
851             }
852             $last = $_;
853         }
854         local $" = ", ";
855         push @result, "$uc_type tests @canon\n";
856         $canon = join ' ', @canon;
857     }
858     else {
859         push @result, "$uc_type test $last\n";
860         $canon = $last;
861     }
862
863     return (join("", @result), $canon)
864         if $type=~/todo/i;
865     push @result, "\t$type $detail/$max tests, ";
866     if ($max) {
867         push @result, sprintf("%.2f",100*(1-$detail/$max)), "% okay";
868     }
869     else {
870         push @result, "?% okay";
871     }
872     my $ender = 's' x ($skipped > 1);
873     if ($skipped) {
874         my $good = $max - $detail - $skipped;
875         my $skipmsg = " (less $skipped skipped test$ender: $good okay, ";
876         if ($max) {
877             my $goodper = sprintf("%.2f",100*($good/$max));
878             $skipmsg .= "$goodper%)";
879         }
880         else {
881             $skipmsg .= "?%)";
882         }
883         push @result, $skipmsg;
884     }
885     push @result, "\n";
886     my $txt = join "", @result;
887     return ($txt, $canon);
888 }
889
890 1;
891 __END__
892
893
894 =head1 EXPORT
895
896 C<&runtests> is exported by Test::Harness by default.
897
898 C<&execute_tests>, C<$verbose>, C<$switches> and C<$debug> are
899 exported upon request.
900
901 =head1 DIAGNOSTICS
902
903 =over 4
904
905 =item C<All tests successful.\nFiles=%d,  Tests=%d, %s>
906
907 If all tests are successful some statistics about the performance are
908 printed.
909
910 =item C<FAILED tests %s\n\tFailed %d/%d tests, %.2f%% okay.>
911
912 For any single script that has failing subtests statistics like the
913 above are printed.
914
915 =item C<Test returned status %d (wstat %d)>
916
917 Scripts that return a non-zero exit status, both C<$? E<gt>E<gt> 8>
918 and C<$?> are printed in a message similar to the above.
919
920 =item C<Failed 1 test, %.2f%% okay. %s>
921
922 =item C<Failed %d/%d tests, %.2f%% okay. %s>
923
924 If not all tests were successful, the script dies with one of the
925 above messages.
926
927 =item C<FAILED--Further testing stopped: %s>
928
929 If a single subtest decides that further testing will not make sense,
930 the script dies with this message.
931
932 =back
933
934 =head1 ENVIRONMENT VARIABLES THAT TEST::HARNESS SETS
935
936 Test::Harness sets these before executing the individual tests.
937
938 =over 4
939
940 =item C<HARNESS_ACTIVE>
941
942 This is set to a true value.  It allows the tests to determine if they
943 are being executed through the harness or by any other means.
944
945 =item C<HARNESS_VERSION>
946
947 This is the version of Test::Harness.
948
949 =back
950
951 =head1 ENVIRONMENT VARIABLES THAT AFFECT TEST::HARNESS
952
953 =over 4
954
955 =item C<HARNESS_COLUMNS>
956
957 This value will be used for the width of the terminal. If it is not
958 set then it will default to C<COLUMNS>. If this is not set, it will
959 default to 80. Note that users of Bourne-sh based shells will need to
960 C<export COLUMNS> for this module to use that variable.
961
962 =item C<HARNESS_COMPILE_TEST>
963
964 When true it will make harness attempt to compile the test using
965 C<perlcc> before running it.
966
967 B<NOTE> This currently only works when sitting in the perl source
968 directory!
969
970 =item C<HARNESS_DEBUG>
971
972 If true, Test::Harness will print debugging information about itself as
973 it runs the tests.  This is different from C<HARNESS_VERBOSE>, which prints
974 the output from the test being run.  Setting C<$Test::Harness::Debug> will
975 override this, or you can use the C<-d> switch in the F<prove> utility.
976
977 =item C<HARNESS_FILELEAK_IN_DIR>
978
979 When set to the name of a directory, harness will check after each
980 test whether new files appeared in that directory, and report them as
981
982   LEAKED FILES: scr.tmp 0 my.db
983
984 If relative, directory name is with respect to the current directory at
985 the moment runtests() was called.  Putting absolute path into 
986 C<HARNESS_FILELEAK_IN_DIR> may give more predictable results.
987
988 =item C<HARNESS_NOTTY>
989
990 When set to a true value, forces it to behave as though STDOUT were
991 not a console.  You may need to set this if you don't want harness to
992 output more frequent progress messages using carriage returns.  Some
993 consoles may not handle carriage returns properly (which results in a
994 somewhat messy output).
995
996 =item C<HARNESS_PERL>
997
998 Usually your tests will be run by C<$^X>, the currently-executing Perl.
999 However, you may want to have it run by a different executable, such as
1000 a threading perl, or a different version.
1001
1002 If you're using the F<prove> utility, you can use the C<--perl> switch.
1003
1004 =item C<HARNESS_PERL_SWITCHES>
1005
1006 Its value will be prepended to the switches used to invoke perl on
1007 each test.  For example, setting C<HARNESS_PERL_SWITCHES> to C<-W> will
1008 run all tests with all warnings enabled.
1009
1010 =item C<HARNESS_TIMER>
1011
1012 Setting this to true will make the harness display the number of
1013 milliseconds each test took.  You can also use F<prove>'s C<--timer>
1014 switch.
1015
1016 =item C<HARNESS_VERBOSE>
1017
1018 If true, Test::Harness will output the verbose results of running
1019 its tests.  Setting C<$Test::Harness::verbose> will override this,
1020 or you can use the C<-v> switch in the F<prove> utility.
1021
1022 If true, Test::Harness will output the verbose results of running
1023 its tests.  Setting C<$Test::Harness::verbose> will override this,
1024 or you can use the C<-v> switch in the F<prove> utility.
1025
1026 =item C<HARNESS_STRAP_CLASS>
1027
1028 Defines the Test::Harness::Straps subclass to use.  The value may either
1029 be a filename or a class name.
1030
1031 If HARNESS_STRAP_CLASS is a class name, the class must be in C<@INC>
1032 like any other class.
1033
1034 If HARNESS_STRAP_CLASS is a filename, the .pm file must return the name
1035 of the class, instead of the canonical "1".
1036
1037 =back
1038
1039 =head1 EXAMPLE
1040
1041 Here's how Test::Harness tests itself
1042
1043   $ cd ~/src/devel/Test-Harness
1044   $ perl -Mblib -e 'use Test::Harness qw(&runtests $verbose);
1045     $verbose=0; runtests @ARGV;' t/*.t
1046   Using /home/schwern/src/devel/Test-Harness/blib
1047   t/base..............ok
1048   t/nonumbers.........ok
1049   t/ok................ok
1050   t/test-harness......ok
1051   All tests successful.
1052   Files=4, Tests=24, 2 wallclock secs ( 0.61 cusr + 0.41 csys = 1.02 CPU)
1053
1054 =head1 SEE ALSO
1055
1056 The included F<prove> utility for running test scripts from the command line,
1057 L<Test> and L<Test::Simple> for writing test scripts, L<Benchmark> for
1058 the underlying timing routines, and L<Devel::Cover> for test coverage
1059 analysis.
1060
1061 =head1 TODO
1062
1063 Provide a way of running tests quietly (ie. no printing) for automated
1064 validation of tests.  This will probably take the form of a version
1065 of runtests() which rather than printing its output returns raw data
1066 on the state of the tests.  (Partially done in Test::Harness::Straps)
1067
1068 Document the format.
1069
1070 Fix HARNESS_COMPILE_TEST without breaking its core usage.
1071
1072 Figure a way to report test names in the failure summary.
1073
1074 Rework the test summary so long test names are not truncated as badly.
1075 (Partially done with new skip test styles)
1076
1077 Add option for coverage analysis.
1078
1079 Trap STDERR.
1080
1081 Implement Straps total_results()
1082
1083 Remember exit code
1084
1085 Completely redo the print summary code.
1086
1087 Straps->analyze_file() not taint clean, don't know if it can be
1088
1089 Fix that damned VMS nit.
1090
1091 Add a test for verbose.
1092
1093 Change internal list of test results to a hash.
1094
1095 Fix stats display when there's an overrun.
1096
1097 Fix so perls with spaces in the filename work.
1098
1099 Keeping whittling away at _run_all_tests()
1100
1101 Clean up how the summary is printed.  Get rid of those damned formats.
1102
1103 =head1 BUGS
1104
1105 Please report any bugs or feature requests to
1106 C<bug-test-harness at rt.cpan.org>, or through the web interface at
1107 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Harness>.
1108 I will be notified, and then you'll automatically be notified of progress on
1109 your bug as I make changes.
1110
1111 =head1 SUPPORT
1112
1113 You can find documentation for this module with the F<perldoc> command.
1114
1115     perldoc Test::Harness
1116
1117 You can get docs for F<prove> with
1118
1119     prove --man
1120
1121 You can also look for information at:
1122
1123 =over 4
1124
1125 =item * AnnoCPAN: Annotated CPAN documentation
1126
1127 L<http://annocpan.org/dist/Test-Harness>
1128
1129 =item * CPAN Ratings
1130
1131 L<http://cpanratings.perl.org/d/Test-Harness>
1132
1133 =item * RT: CPAN's request tracker
1134
1135 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-Harness>
1136
1137 =item * Search CPAN
1138
1139 L<http://search.cpan.org/dist/Test-Harness>
1140
1141 =back
1142
1143 =head1 SOURCE CODE
1144
1145 The source code repository for Test::Harness is at
1146 L<http://svn.perl.org/modules/Test-Harness>.
1147
1148 =head1 AUTHORS
1149
1150 Either Tim Bunce or Andreas Koenig, we don't know. What we know for
1151 sure is, that it was inspired by Larry Wall's F<TEST> script that came
1152 with perl distributions for ages. Numerous anonymous contributors
1153 exist.  Andreas Koenig held the torch for many years, and then
1154 Michael G Schwern.
1155
1156 Current maintainer is Andy Lester C<< <andy at petdance.com> >>.
1157
1158 =head1 COPYRIGHT
1159
1160 Copyright 2002-2006
1161 by Michael G Schwern C<< <schwern at pobox.com> >>,
1162 Andy Lester C<< <andy at petdance.com> >>.
1163
1164 This program is free software; you can redistribute it and/or 
1165 modify it under the same terms as Perl itself.
1166
1167 See L<http://www.perl.com/perl/misc/Artistic.html>.
1168
1169 =cut