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