This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: Change 34184: Convert all unimaginative (ie race condition) temporary file names to
[perl5.git] / lib / Test / Harness.pm
CommitLineData
a0d0e21e
LW
1package Test::Harness;
2
3c87ea76 3require 5.00405;
b965d173 4
760ac839
LW
5use strict;
6
b965d173
NC
7use constant IS_WIN32 => ( $^O =~ /^(MS)?Win32$/ );
8use constant IS_VMS => ( $^O eq 'VMS' );
9
10use TAP::Harness ();
11use TAP::Parser::Aggregator ();
12use TAP::Parser::Source::Perl ();
ca09b021 13
bd3ac2f1
SP
14use TAP::Parser::Utils qw( split_shell );
15
b965d173
NC
16use Config;
17use Exporter;
18
19# TODO: Emulate at least some of these
e4fc8a1e 20use vars qw(
b965d173
NC
21 $VERSION
22 @ISA @EXPORT @EXPORT_OK
23 $Verbose $Switches $Debug
24 $verbose $switches $debug
25 $Columns
53bc175b 26 $Color
b965d173
NC
27 $Directives
28 $Timer
29 $Strap
30 $has_time_hires
f7c69158 31 $IgnoreExit
e4fc8a1e
RGS
32);
33
b965d173
NC
34# $ML $Last_ML_Print
35
43ef773b 36BEGIN {
5b1ebecd 37 eval q{use Time::HiRes 'time'};
43ef773b
RGS
38 $has_time_hires = !$@;
39}
40
e4fc8a1e
RGS
41=head1 NAME
42
43Test::Harness - Run Perl standard test scripts with statistics
44
45=head1 VERSION
46
f7c69158 47Version 3.13
e4fc8a1e
RGS
48
49=cut
50
f7c69158 51$VERSION = '3.13';
4633a7c4 52
9c5c68c8 53# Backwards compatibility for exportable variable names.
5c0604c3
MS
54*verbose = *Verbose;
55*switches = *Switches;
e4fc8a1e 56*debug = *Debug;
9c5c68c8 57
b965d173 58$ENV{HARNESS_ACTIVE} = 1;
c0c1f8c2 59$ENV{HARNESS_VERSION} = $VERSION;
f19ae7a7 60
13287dd5 61END {
b965d173 62
13287dd5
MS
63 # For VMS.
64 delete $ENV{HARNESS_ACTIVE};
c0c1f8c2 65 delete $ENV{HARNESS_VERSION};
13287dd5
MS
66}
67
b965d173 68@ISA = ('Exporter');
9c5c68c8 69@EXPORT = qw(&runtests);
20f9f807 70@EXPORT_OK = qw(&execute_tests $verbose $switches);
4633a7c4 71
b965d173
NC
72$Verbose = $ENV{HARNESS_VERBOSE} || 0;
73$Debug = $ENV{HARNESS_DEBUG} || 0;
5b1ebecd 74$Switches = '-w';
b965d173
NC
75$Columns = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
76$Columns--; # Some shells have trouble with a full line of text.
f7c69158
NC
77$Timer = $ENV{HARNESS_TIMER} || 0;
78$Color = $ENV{HARNESS_COLOR} || 0;
79$IgnoreExit = $ENV{HARNESS_IGNORE_EXIT} || 0;
b82fa0b7 80
b82fa0b7
MS
81=head1 SYNOPSIS
82
83 use Test::Harness;
84
85 runtests(@test_files);
86
87=head1 DESCRIPTION
a0d0e21e 88
b965d173
NC
89Although, for historical reasons, the L<Test::Harness> distribution
90takes its name from this module it now exists only to provide
91L<TAP::Harness> with an interface that is somewhat backwards compatible
92with L<Test::Harness> 2.xx. If you're writing new code consider using
93L<TAP::Harness> directly instead.
b82fa0b7 94
b965d173
NC
95Emulation is provided for C<runtests> and C<execute_tests> but the
96pluggable 'Straps' interface that previous versions of L<Test::Harness>
97supported is not reproduced here. Straps is now available as a stand
98alone module: L<Test::Harness::Straps>.
b82fa0b7 99
bd3ac2f1
SP
100See L<TAP::Parser>, L<TAP::Harness> for the main documentation for this
101distribution.
13287dd5 102
b965d173 103=head1 FUNCTIONS
13287dd5 104
b965d173 105The following functions are available.
13287dd5 106
b965d173 107=head2 runtests( @test_files )
13287dd5 108
b965d173
NC
109This runs all the given I<@test_files> and divines whether they passed
110or failed based on their output to STDOUT (details above). It prints
111out each individual test which failed along with a summary report and
112a how long it all took.
13287dd5 113
b965d173
NC
114It returns true if everything was ok. Otherwise it will C<die()> with
115one of the messages in the DIAGNOSTICS section.
13287dd5 116
b965d173 117=cut
13287dd5 118
b965d173
NC
119sub _has_taint {
120 my $test = shift;
121 return TAP::Parser::Source::Perl->get_taint(
122 TAP::Parser::Source::Perl->shebang($test) );
123}
13287dd5 124
b965d173
NC
125sub _aggregate {
126 my ( $harness, $aggregate, @tests ) = @_;
13287dd5 127
b965d173
NC
128 # Don't propagate to our children
129 local $ENV{HARNESS_OPTIONS};
13287dd5 130
b965d173 131 if (IS_VMS) {
43ef773b 132
b965d173
NC
133 # Jiggery pokery doesn't appear to work on VMS - so disable it
134 # pending investigation.
53bc175b 135 _aggregate_tests( $harness, $aggregate, @tests );
b965d173
NC
136 }
137 else {
138 my $path_sep = $Config{path_sep};
139 my $path_pat = qr{$path_sep};
140 my @extra_inc = _filtered_inc();
141
142 # Supply -I switches in taint mode
143 $harness->callback(
144 parser_args => sub {
145 my ( $args, $test ) = @_;
146 if ( _has_taint( $test->[0] ) ) {
147 push @{ $args->{switches} }, map {"-I$_"} _filtered_inc();
148 }
149 }
150 );
43ef773b 151
b965d173
NC
152 my $previous = $ENV{PERL5LIB};
153 local $ENV{PERL5LIB};
13287dd5 154
b965d173
NC
155 if ($previous) {
156 push @extra_inc, split( $path_pat, $previous );
157 }
13287dd5 158
b965d173
NC
159 if (@extra_inc) {
160 $ENV{PERL5LIB} = join( $path_sep, @extra_inc );
161 }
b82fa0b7 162
53bc175b 163 _aggregate_tests( $harness, $aggregate, @tests );
b965d173
NC
164 }
165}
b82fa0b7 166
53bc175b
RGS
167sub _aggregate_tests {
168 my ( $harness, $aggregate, @tests ) = @_;
169 $aggregate->start();
170 $harness->aggregate_tests( $aggregate, @tests );
171 $aggregate->stop();
172
173}
174
b965d173
NC
175sub runtests {
176 my @tests = @_;
b82fa0b7 177
b965d173
NC
178 # shield against -l
179 local ( $\, $, );
b82fa0b7 180
b965d173
NC
181 my $harness = _new_harness();
182 my $aggregate = TAP::Parser::Aggregator->new();
b82fa0b7 183
b965d173 184 _aggregate( $harness, $aggregate, @tests );
b82fa0b7 185
b965d173 186 $harness->formatter->summary($aggregate);
b82fa0b7 187
b965d173
NC
188 my $total = $aggregate->total;
189 my $passed = $aggregate->passed;
190 my $failed = $aggregate->failed;
b82fa0b7 191
b965d173 192 my @parsers = $aggregate->parsers;
b82fa0b7 193
b965d173
NC
194 my $num_bad = 0;
195 for my $parser (@parsers) {
196 $num_bad++ if $parser->has_problems;
197 }
b82fa0b7 198
b965d173
NC
199 die(sprintf(
200 "Failed %d/%d test programs. %d/%d subtests failed.\n",
201 $num_bad, scalar @parsers, $failed, $total
202 )
203 ) if $num_bad;
b82fa0b7 204
b965d173
NC
205 return $total && $total == $passed;
206}
b82fa0b7 207
b965d173
NC
208sub _canon {
209 my @list = sort { $a <=> $b } @_;
210 my @ranges = ();
211 my $count = scalar @list;
212 my $pos = 0;
213
214 while ( $pos < $count ) {
215 my $end = $pos + 1;
216 $end++ while $end < $count && $list[$end] <= $list[ $end - 1 ] + 1;
217 push @ranges, ( $end == $pos + 1 )
218 ? $list[$pos]
219 : join( '-', $list[$pos], $list[ $end - 1 ] );
220 $pos = $end;
221 }
b82fa0b7 222
b965d173
NC
223 return join( ' ', @ranges );
224}
b82fa0b7 225
b965d173 226sub _new_harness {
41d86c6b 227 my $sub_args = shift || {};
b82fa0b7 228
b965d173 229 my ( @lib, @switches );
f7c69158 230 for my $opt ( split_shell( $Switches, $ENV{HARNESS_PERL_SWITCHES} ) ) {
b965d173
NC
231 if ( $opt =~ /^ -I (.*) $ /x ) {
232 push @lib, $1;
233 }
234 else {
235 push @switches, $opt;
236 }
237 }
b82fa0b7 238
b965d173
NC
239 # Do things the old way on VMS...
240 push @lib, _filtered_inc() if IS_VMS;
241
53bc175b
RGS
242 # If $Verbose isn't numeric default to 1. This helps core.
243 my $verbosity = ( $Verbose ? ( $Verbose !~ /\d/ ) ? 1 : $Verbose : 0 );
244
b965d173 245 my $args = {
f7c69158
NC
246 timer => $Timer,
247 directives => $Directives,
248 lib => \@lib,
249 switches => \@switches,
250 color => $Color,
251 verbosity => $verbosity,
252 ignore_exit => $IgnoreExit,
b965d173
NC
253 };
254
41d86c6b
SP
255 $args->{stdout} = $sub_args->{out}
256 if exists $sub_args->{out};
257
b965d173
NC
258 if ( defined( my $env_opt = $ENV{HARNESS_OPTIONS} ) ) {
259 for my $opt ( split /:/, $env_opt ) {
260 if ( $opt =~ /^j(\d*)$/ ) {
261 $args->{jobs} = $1 || 9;
262 }
263 elsif ( $opt eq 'f' ) {
264 $args->{fork} = 1;
265 }
53bc175b
RGS
266 elsif ( $opt eq 'c' ) {
267 $args->{color} = 1;
268 }
b965d173
NC
269 else {
270 die "Unknown HARNESS_OPTIONS item: $opt\n";
271 }
272 }
273 }
b82fa0b7 274
b965d173
NC
275 return TAP::Harness->new($args);
276}
b82fa0b7 277
b965d173
NC
278# Get the parts of @INC which are changed from the stock list AND
279# preserve reordering of stock directories.
280sub _filtered_inc {
281 my @inc = grep { !ref } @INC; #28567
b82fa0b7 282
b965d173 283 if (IS_VMS) {
b82fa0b7 284
b965d173
NC
285 # VMS has a 255-byte limit on the length of %ENV entries, so
286 # toss the ones that involve perl_root, the install location
287 @inc = grep !/perl_root/i, @inc;
b82fa0b7 288
b965d173
NC
289 }
290 elsif (IS_WIN32) {
b82fa0b7 291
b965d173
NC
292 # Lose any trailing backslashes in the Win32 paths
293 s/[\\\/+]$// foreach @inc;
294 }
b82fa0b7 295
b965d173 296 my @default_inc = _default_inc();
b82fa0b7 297
b965d173
NC
298 my @new_inc;
299 my %seen;
300 for my $dir (@inc) {
301 next if $seen{$dir}++;
17a79f5b 302
b965d173
NC
303 if ( $dir eq ( $default_inc[0] || '' ) ) {
304 shift @default_inc;
305 }
306 else {
307 push @new_inc, $dir;
308 }
9c5c68c8 309
b965d173
NC
310 shift @default_inc while @default_inc and $seen{ $default_inc[0] };
311 }
b82fa0b7 312
b965d173
NC
313 return @new_inc;
314}
9c5c68c8 315
b965d173 316{
b82fa0b7 317
b965d173
NC
318 # Cache this to avoid repeatedly shelling out to Perl.
319 my @inc;
b82fa0b7 320
b965d173
NC
321 sub _default_inc {
322 return @inc if @inc;
323 my $perl = $ENV{HARNESS_PERL} || $^X;
324 chomp( @inc = `$perl -le "print join qq[\\n], \@INC"` );
325 return @inc;
d1ef75db 326 }
b82fa0b7
MS
327}
328
b965d173
NC
329sub _check_sequence {
330 my @list = @_;
331 my $prev;
332 while ( my $next = shift @list ) {
333 return if defined $prev && $next <= $prev;
334 $prev = $next;
335 }
2fe373ce 336
b965d173 337 return 1;
2fe373ce
MS
338}
339
b965d173
NC
340sub execute_tests {
341 my %args = @_;
b82fa0b7 342
41d86c6b 343 my $harness = _new_harness( \%args );
b965d173
NC
344 my $aggregate = TAP::Parser::Aggregator->new();
345
346 my %tot = (
347 bonus => 0,
348 max => 0,
349 ok => 0,
350 bad => 0,
351 good => 0,
352 files => 0,
353 tests => 0,
354 sub_skipped => 0,
355 todo => 0,
356 skipped => 0,
357 bench => undef,
358 );
359
360 # Install a callback so we get to see any plans the
361 # harness executes.
362 $harness->callback(
363 made_parser => sub {
364 my $parser = shift;
365 $parser->callback(
366 plan => sub {
367 my $plan = shift;
368 if ( $plan->directive eq 'SKIP' ) {
369 $tot{skipped}++;
370 }
371 }
372 );
373 }
374 );
375
376 _aggregate( $harness, $aggregate, @{ $args{tests} } );
377
378 $tot{bench} = $aggregate->elapsed;
379 my @tests = $aggregate->descriptions;
380
381 # TODO: Work out the circumstances under which the files
382 # and tests totals can differ.
383 $tot{files} = $tot{tests} = scalar @tests;
384
385 my %failedtests = ();
386 my %todo_passed = ();
387
388 for my $test (@tests) {
389 my ($parser) = $aggregate->parsers($test);
390
391 my @failed = $parser->failed;
392
393 my $wstat = $parser->wait;
394 my $estat = $parser->exit;
395 my $planned = $parser->tests_planned;
396 my @errors = $parser->parse_errors;
397 my $passed = $parser->passed;
398 my $actual_passed = $parser->actual_passed;
399
400 my $ok_seq = _check_sequence( $parser->actual_passed );
401
402 # Duplicate exit, wait status semantics of old version
403 $estat ||= '' unless $wstat;
404 $wstat ||= '';
405
406 $tot{max} += ( $planned || 0 );
407 $tot{bonus} += $parser->todo_passed;
408 $tot{ok} += $passed > $actual_passed ? $passed : $actual_passed;
409 $tot{sub_skipped} += $parser->skipped;
410 $tot{todo} += $parser->todo;
411
412 if ( @failed || $estat || @errors ) {
413 $tot{bad}++;
414
415 my $huh_planned = $planned ? undef : '??';
416 my $huh_errors = $ok_seq ? undef : '??';
417
418 $failedtests{$test} = {
419 'canon' => $huh_planned
420 || $huh_errors
421 || _canon(@failed)
422 || '??',
423 'estat' => $estat,
424 'failed' => $huh_planned
425 || $huh_errors
426 || scalar @failed,
427 'max' => $huh_planned || $planned,
428 'name' => $test,
429 'wstat' => $wstat
430 };
431 }
432 else {
433 $tot{good}++;
434 }
b82fa0b7 435
b965d173
NC
436 my @todo = $parser->todo_passed;
437 if (@todo) {
438 $todo_passed{$test} = {
439 'canon' => _canon(@todo),
440 'estat' => $estat,
441 'failed' => scalar @todo,
442 'max' => scalar $parser->todo,
443 'name' => $test,
444 'wstat' => $wstat
445 };
446 }
447 }
b82fa0b7 448
b965d173 449 return ( \%tot, \%failedtests, \%todo_passed );
9c5c68c8
MS
450}
451
20f9f807 452=head2 execute_tests( tests => \@test_files, out => \*FH )
b82fa0b7 453
20f9f807
RGS
454Runs all the given C<@test_files> (just like C<runtests()>) but
455doesn't generate the final report. During testing, progress
456information will be written to the currently selected output
457filehandle (usually C<STDOUT>), or to the filehandle given by the
458C<out> parameter. The I<out> is optional.
b82fa0b7 459
20f9f807
RGS
460Returns a list of two values, C<$total> and C<$failed>, describing the
461results. C<$total> is a hash ref summary of all the tests run. Its
462keys and values are this:
b82fa0b7
MS
463
464 bonus Number of individual todo tests unexpectedly passed
465 max Number of individual tests ran
466 ok Number of individual tests passed
467 sub_skipped Number of individual tests skipped
2fe373ce 468 todo Number of individual todo tests
b82fa0b7
MS
469
470 files Number of test files ran
471 good Number of test files passed
472 bad Number of test files failed
473 tests Number of test files originally given
474 skipped Number of test files skipped
475
e4fc8a1e
RGS
476If C<< $total->{bad} == 0 >> and C<< $total->{max} > 0 >>, you've
477got a successful test.
b82fa0b7 478
20f9f807 479C<$failed> is a hash ref of all the test scripts that failed. Each key
b82fa0b7
MS
480is the name of a test script, each value is another hash representing
481how that script failed. Its keys are these:
9c5c68c8 482
b82fa0b7
MS
483 name Name of the test which failed
484 estat Script's exit value
485 wstat Script's wait status
486 max Number of individual tests
487 failed Number which failed
b82fa0b7
MS
488 canon List of tests which failed (as string).
489
e4fc8a1e 490C<$failed> should be empty if everything passed.
b82fa0b7 491
b82fa0b7
MS
492=cut
493
b82fa0b7
MS
4941;
495__END__
9c5c68c8 496
cb1a09d0
AD
497=head1 EXPORT
498
b965d173 499C<&runtests> is exported by C<Test::Harness> by default.
cb1a09d0 500
20f9f807
RGS
501C<&execute_tests>, C<$verbose>, C<$switches> and C<$debug> are
502exported upon request.
9c5c68c8 503
b965d173 504=head1 ENVIRONMENT VARIABLES THAT TAP::HARNESS::COMPATIBLE SETS
c0c1f8c2 505
b965d173 506C<Test::Harness> sets these before executing the individual tests.
9b0ceca9 507
37ce32a7
MS
508=over 4
509
356733da 510=item C<HARNESS_ACTIVE>
37ce32a7 511
c0c1f8c2
RGS
512This is set to a true value. It allows the tests to determine if they
513are being executed through the harness or by any other means.
514
515=item C<HARNESS_VERSION>
516
b965d173 517This is the version of C<Test::Harness>.
c0c1f8c2
RGS
518
519=back
520
521=head1 ENVIRONMENT VARIABLES THAT AFFECT TEST::HARNESS
522
523=over 4
37ce32a7 524
ea5423ed
NC
525=item C<HARNESS_TIMER>
526
527Setting this to true will make the harness display the number of
528milliseconds each test took. You can also use F<prove>'s C<--timer>
529switch.
530
356733da 531=item C<HARNESS_VERBOSE>
37ce32a7 532
b965d173 533If true, C<Test::Harness> will output the verbose results of running
5b1ebecd
SP
534its tests. Setting C<$Test::Harness::verbose> will override this,
535or you can use the C<-v> switch in the F<prove> utility.
536
b965d173 537=item C<HARNESS_OPTIONS>
5b1ebecd 538
b965d173 539Provide additional options to the harness. Currently supported options are:
5b1ebecd 540
b965d173 541=over
5b1ebecd 542
b965d173 543=item C<< j<n> >>
5b1ebecd 544
b965d173 545Run <n> (default 9) parallel jobs.
b82fa0b7 546
b965d173 547=item C<< f >>
37ce32a7 548
b965d173 549Use forked parallelism.
b82fa0b7 550
b965d173 551=back
cf2ab31a 552
b965d173 553Multiple options may be separated by colons:
cf2ab31a 554
b965d173 555 HARNESS_OPTIONS=j9:f make test
cf2ab31a 556
b965d173 557=back
cf2ab31a 558
bd3ac2f1
SP
559=head1 Taint Mode
560
561Normally when a Perl program is run in taint mode the contents of the
562C<PERL5LIB> environment variable do not appear in C<@INC>.
563
564Because C<PERL5LIB> is often used during testing to add build
565directories to C<@INC> C<Test::Harness> (actually
566L<TAP::Parser::Source::Perl>) passes the names of any directories found
567in C<PERL5LIB> as -I switches. The net effect of this is that
568C<PERL5LIB> is honoured even in taint mode.
569
b965d173 570=head1 SEE ALSO
b82fa0b7 571
b965d173 572L<TAP::Harness>
cb1a09d0
AD
573
574=head1 BUGS
575
20f9f807
RGS
576Please report any bugs or feature requests to
577C<bug-test-harness at rt.cpan.org>, or through the web interface at
b965d173
NC
578L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Harness>. I will be
579notified, and then you'll automatically be notified of progress on your bug
580as I make changes.
e4fc8a1e
RGS
581
582=head1 AUTHORS
583
b965d173 584Andy Armstrong C<< <andy@hexten.net> >>
3c87ea76 585
bd3ac2f1
SP
586L<Test::Harness> 2.64 (maintained by Andy Lester and on which this
587module is based) has this attribution:
e4fc8a1e 588
b965d173
NC
589 Either Tim Bunce or Andreas Koenig, we don't know. What we know for
590 sure is, that it was inspired by Larry Wall's F<TEST> script that came
591 with perl distributions for ages. Numerous anonymous contributors
592 exist. Andreas Koenig held the torch for many years, and then
593 Michael G Schwern.
e4fc8a1e 594
b965d173 595=head1 LICENCE AND COPYRIGHT
e4fc8a1e 596
53bc175b 597Copyright (c) 2007-2008, Andy Armstrong C<< <andy@hexten.net> >>. All rights reserved.
e4fc8a1e 598
b965d173
NC
599This module is free software; you can redistribute it and/or
600modify it under the same terms as Perl itself. See L<perlartistic>.
e4fc8a1e 601