threads::shared 1.24 (phase 2)
[p5sagit/p5-mst-13.2.git] / lib / TAP / Parser.pm
CommitLineData
b965d173 1package TAP::Parser;
2
3use strict;
4use vars qw($VERSION @ISA);
5
6use TAP::Base ();
7use TAP::Parser::Grammar ();
8use TAP::Parser::Result ();
9use TAP::Parser::Source ();
10use TAP::Parser::Source::Perl ();
11use TAP::Parser::Iterator ();
2a7f4b9b 12
13use Carp qw( confess );
b965d173 14
15@ISA = qw(TAP::Base);
16
17=head1 NAME
18
19TAP::Parser - Parse L<TAP|Test::Harness::TAP> output
20
21=head1 VERSION
22
2a7f4b9b 23Version 3.10
b965d173 24
25=cut
26
2a7f4b9b 27$VERSION = '3.10';
b965d173 28
29my $DEFAULT_TAP_VERSION = 12;
30my $MAX_TAP_VERSION = 13;
31
32$ENV{TAP_VERSION} = $MAX_TAP_VERSION;
33
34END {
35
36 # For VMS.
37 delete $ENV{TAP_VERSION};
38}
39
40BEGIN { # making accessors
41 foreach my $method (
42 qw(
43 _stream
44 _spool
45 _grammar
46 exec
47 exit
48 is_good_plan
49 plan
50 tests_planned
51 tests_run
52 wait
53 version
54 in_todo
55 start_time
56 end_time
57 skip_all
58 )
59 )
60 {
61 no strict 'refs';
62
63 # another tiny performance hack
64 if ( $method =~ /^_/ ) {
65 *$method = sub {
66 my $self = shift;
67 return $self->{$method} unless @_;
68
69 # Trusted methods
70 unless ( ( ref $self ) =~ /^TAP::Parser/ ) {
71 Carp::croak("$method() may not be set externally");
72 }
73
74 $self->{$method} = shift;
75 };
76 }
77 else {
78 *$method = sub {
79 my $self = shift;
80 return $self->{$method} unless @_;
81 $self->{$method} = shift;
82 };
83 }
84 }
85} # done making accessors
86
87=head1 SYNOPSIS
88
89 use TAP::Parser;
90
91 my $parser = TAP::Parser->new( { source => $source } );
92
93 while ( my $result = $parser->next ) {
94 print $result->as_string;
95 }
96
97=head1 DESCRIPTION
98
99C<TAP::Parser> is designed to produce a proper parse of TAP output. For
100an example of how to run tests through this module, see the simple
101harnesses C<examples/>.
102
103There's a wiki dedicated to the Test Anything Protocol:
104
105L<http://testanything.org>
106
107It includes the TAP::Parser Cookbook:
108
109L<http://testanything.org/wiki/index.php/TAP::Parser_Cookbook>
110
111=head1 METHODS
112
113=head2 Class Methods
114
115=head3 C<new>
116
117 my $parser = TAP::Parser->new(\%args);
118
119Returns a new C<TAP::Parser> object.
120
121The arguments should be a hashref with I<one> of the following keys:
122
123=over 4
124
125=item * C<source>
126
127This is the preferred method of passing arguments to the constructor. To
128determine how to handle the source, the following steps are taken.
129
130If the source contains a newline, it's assumed to be a string of raw TAP
131output.
132
133If the source is a reference, it's assumed to be something to pass to
134the L<TAP::Parser::Iterator::Stream> constructor. This is used
135internally and you should not use it.
136
137Otherwise, the parser does a C<-e> check to see if the source exists. If so,
138it attempts to execute the source and read the output as a stream. This is by
139far the preferred method of using the parser.
140
141 foreach my $file ( @test_files ) {
142 my $parser = TAP::Parser->new( { source => $file } );
143 # do stuff with the parser
144 }
145
146=item * C<tap>
147
148The value should be the complete TAP output.
149
150=item * C<exec>
151
152If passed an array reference, will attempt to create the iterator by
153passing a L<TAP::Parser::Source> object to
154L<TAP::Parser::Iterator::Source>, using the array reference strings as
155the command arguments to L<IPC::Open3::open3|IPC::Open3>:
156
157 exec => [ '/usr/bin/ruby', 't/my_test.rb' ]
158
159Note that C<source> and C<exec> are mutually exclusive.
160
161=back
162
163The following keys are optional.
164
165=over 4
166
167=item * C<callback>
168
169If present, each callback corresponding to a given result type will be called
170with the result as the argument if the C<run> method is used:
171
172 my %callbacks = (
173 test => \&test_callback,
174 plan => \&plan_callback,
175 comment => \&comment_callback,
176 bailout => \&bailout_callback,
177 unknown => \&unknown_callback,
178 );
179
180 my $aggregator = TAP::Parser::Aggregator->new;
181 foreach my $file ( @test_files ) {
182 my $parser = TAP::Parser->new(
183 {
184 source => $file,
185 callbacks => \%callbacks,
186 }
187 );
188 $parser->run;
189 $aggregator->add( $file, $parser );
190 }
191
192=item * C<switches>
193
194If using a Perl file as a source, optional switches may be passed which will
195be used when invoking the perl executable.
196
197 my $parser = TAP::Parser->new( {
198 source => $test_file,
199 switches => '-Ilib',
200 } );
201
202=item * C<test_args>
203
204Used in conjunction with the C<source> option to supply a reference to
205an C<@ARGV> style array of arguments to pass to the test program.
206
207=item * C<spool>
208
209If passed a filehandle will write a copy of all parsed TAP to that handle.
210
211=item * C<merge>
212
213If false, STDERR is not captured (though it is 'relayed' to keep it
214somewhat synchronized with STDOUT.)
215
216If true, STDERR and STDOUT are the same filehandle. This may cause
217breakage if STDERR contains anything resembling TAP format, but does
218allow exact synchronization.
219
220Subtleties of this behavior may be platform-dependent and may change in
221the future.
222
223=back
224
225=cut
226
227# new implementation supplied by TAP::Base
228
229##############################################################################
230
231=head2 Instance Methods
232
233=head3 C<next>
234
235 my $parser = TAP::Parser->new( { source => $file } );
236 while ( my $result = $parser->next ) {
237 print $result->as_string, "\n";
238 }
239
240This method returns the results of the parsing, one result at a time. Note
241that it is destructive. You can't rewind and examine previous results.
242
243If callbacks are used, they will be issued before this call returns.
244
245Each result returned is a subclass of L<TAP::Parser::Result>. See that
246module and related classes for more information on how to use them.
247
248=cut
249
250sub next {
251 my $self = shift;
252 return ( $self->{_iter} ||= $self->_iter )->();
253}
254
255##############################################################################
256
257=head3 C<run>
258
259 $parser->run;
260
261This method merely runs the parser and parses all of the TAP.
262
263=cut
264
265sub run {
266 my $self = shift;
267 while ( defined( my $result = $self->next ) ) {
268
269 # do nothing
270 }
271}
272
273{
274
275 # of the following, anything beginning with an underscore is strictly
276 # internal and should not be exposed.
277 my %initialize = (
278 version => $DEFAULT_TAP_VERSION,
279 plan => '', # the test plan (e.g., 1..3)
280 tap => '', # the TAP
281 tests_run => 0, # actual current test numbers
282 results => [], # TAP parser results
283 skipped => [], #
284 todo => [], #
285 passed => [], #
286 failed => [], #
287 actual_failed => [], # how many tests really failed
288 actual_passed => [], # how many tests really passed
289 todo_passed => [], # tests which unexpectedly succeed
290 parse_errors => [], # perfect TAP should have none
291 );
292
293 # We seem to have this list hanging around all over the place. We could
294 # probably get it from somewhere else to avoid the repetition.
295 my @legal_callback = qw(
296 test
297 version
298 plan
299 comment
300 bailout
301 unknown
302 yaml
303 ALL
304 ELSE
305 EOF
306 );
307
308 sub _initialize {
309 my ( $self, $arg_for ) = @_;
310
311 # everything here is basically designed to convert any TAP source to a
312 # stream.
313
314 # Shallow copy
315 my %args = %{ $arg_for || {} };
316
317 $self->SUPER::_initialize( \%args, \@legal_callback );
318
319 my $stream = delete $args{stream};
320 my $tap = delete $args{tap};
321 my $source = delete $args{source};
322 my $exec = delete $args{exec};
323 my $merge = delete $args{merge};
324 my $spool = delete $args{spool};
325 my $switches = delete $args{switches};
326 my @test_args = @{ delete $args{test_args} || [] };
327
328 if ( 1 < grep {defined} $stream, $tap, $source, $exec ) {
329 $self->_croak(
330 "You may only choose one of 'exec', 'stream', 'tap' or 'source'"
331 );
332 }
333
334 if ( my @excess = sort keys %args ) {
335 $self->_croak("Unknown options: @excess");
336 }
337
338 if ($tap) {
339 $stream = TAP::Parser::Iterator->new( [ split "\n" => $tap ] );
340 }
341 elsif ($exec) {
342 my $source = TAP::Parser::Source->new;
343 $source->source( [ @$exec, @test_args ] );
344 $source->merge($merge); # XXX should just be arguments?
345 $stream = $source->get_stream;
346 }
347 elsif ($source) {
348 if ( my $ref = ref $source ) {
349 $stream = TAP::Parser::Iterator->new($source);
350 }
351 elsif ( -e $source ) {
352
353 my $perl = TAP::Parser::Source::Perl->new;
354
355 $perl->switches($switches)
356 if $switches;
357
358 $perl->merge($merge); # XXX args to new()?
359
360 $perl->source( [ $source, @test_args ] );
361
362 $stream = $perl->get_stream;
363 }
364 else {
365 $self->_croak("Cannot determine source for $source");
366 }
367 }
368
369 unless ($stream) {
370 $self->_croak('PANIC: could not determine stream');
371 }
372
373 while ( my ( $k, $v ) = each %initialize ) {
374 $self->{$k} = 'ARRAY' eq ref $v ? [] : $v;
375 }
376
377 $self->_stream($stream);
378 my $grammar = TAP::Parser::Grammar->new($stream);
379 $grammar->set_version( $self->version );
380 $self->_grammar($grammar);
381 $self->_spool($spool);
382
383 $self->start_time( $self->get_time );
384
385 return $self;
386 }
387}
388
389=head1 INDIVIDUAL RESULTS
390
391If you've read this far in the docs, you've seen this:
392
393 while ( my $result = $parser->next ) {
394 print $result->as_string;
395 }
396
397Each result returned is a L<TAP::Parser::Result> subclass, referred to as
398I<result types>.
399
400=head2 Result types
401
402Basically, you fetch individual results from the TAP. The six types, with
403examples of each, are as follows:
404
405=over 4
406
407=item * Version
408
409 TAP version 12
410
411=item * Plan
412
413 1..42
414
2a7f4b9b 415=item * Pragma
416
417 pragma +strict
418
b965d173 419=item * Test
420
421 ok 3 - We should start with some foobar!
422
423=item * Comment
424
425 # Hope we don't use up the foobar.
426
427=item * Bailout
428
429 Bail out! We ran out of foobar!
430
431=item * Unknown
432
433 ... yo, this ain't TAP! ...
434
435=back
436
437Each result fetched is a result object of a different type. There are common
438methods to each result object and different types may have methods unique to
439their type. Sometimes a type method may be overridden in a subclass, but its
440use is guaranteed to be identical.
441
442=head2 Common type methods
443
444=head3 C<type>
445
446Returns the type of result, such as C<comment> or C<test>.
447
448=head3 C<as_string>
449
450Prints a string representation of the token. This might not be the exact
451output, however. Tests will have test numbers added if not present, TODO and
452SKIP directives will be capitalized and, in general, things will be cleaned
453up. If you need the original text for the token, see the C<raw> method.
454
455=head3 C<raw>
456
457Returns the original line of text which was parsed.
458
459=head3 C<is_plan>
460
461Indicates whether or not this is the test plan line.
462
463=head3 C<is_test>
464
465Indicates whether or not this is a test line.
466
467=head3 C<is_comment>
468
469Indicates whether or not this is a comment. Comments will generally only
470appear in the TAP stream if STDERR is merged to STDOUT. See the
471C<merge> option.
472
473=head3 C<is_bailout>
474
475Indicates whether or not this is bailout line.
476
477=head3 C<is_yaml>
478
479Indicates whether or not the current item is a YAML block.
480
481=head3 C<is_unknown>
482
483Indicates whether or not the current line could be parsed.
484
485=head3 C<is_ok>
486
487 if ( $result->is_ok ) { ... }
488
489Reports whether or not a given result has passed. Anything which is B<not> a
490test result returns true. This is merely provided as a convenient shortcut
491which allows you to do this:
492
493 my $parser = TAP::Parser->new( { source => $source } );
494 while ( my $result = $parser->next ) {
495 # only print failing results
496 print $result->as_string unless $result->is_ok;
497 }
498
499=head2 C<plan> methods
500
501 if ( $result->is_plan ) { ... }
502
503If the above evaluates as true, the following methods will be available on the
504C<$result> object.
505
506=head3 C<plan>
507
508 if ( $result->is_plan ) {
509 print $result->plan;
510 }
511
512This is merely a synonym for C<as_string>.
513
b965d173 514=head3 C<directive>
515
516 my $directive = $result->directive;
517
518If a SKIP directive is included with the plan, this method will return it.
519
520 1..0 # SKIP: why bother?
521
522=head3 C<explanation>
523
524 my $explanation = $result->explanation;
525
526If a SKIP directive was included with the plan, this method will return the
527explanation, if any.
528
2a7f4b9b 529=head2 C<pragma> methods
530
531 if ( $result->is_pragma ) { ... }
532
533If the above evaluates as true, the following methods will be available on the
534C<$result> object.
535
536=head3 C<pragmas>
537
538Returns a list of pragmas each of which is a + or - followed by the
539pragma name.
540
b965d173 541=head2 C<commment> methods
542
543 if ( $result->is_comment ) { ... }
544
545If the above evaluates as true, the following methods will be available on the
546C<$result> object.
547
548=head3 C<comment>
549
550 if ( $result->is_comment ) {
551 my $comment = $result->comment;
552 print "I have something to say: $comment";
553 }
554
555=head2 C<bailout> methods
556
557 if ( $result->is_bailout ) { ... }
558
559If the above evaluates as true, the following methods will be available on the
560C<$result> object.
561
562=head3 C<explanation>
563
564 if ( $result->is_bailout ) {
565 my $explanation = $result->explanation;
566 print "We bailed out because ($explanation)";
567 }
568
569If, and only if, a token is a bailout token, you can get an "explanation" via
570this method. The explanation is the text after the mystical "Bail out!" words
571which appear in the tap output.
572
573=head2 C<unknown> methods
574
575 if ( $result->is_unknown ) { ... }
576
577There are no unique methods for unknown results.
578
579=head2 C<test> methods
580
581 if ( $result->is_test ) { ... }
582
583If the above evaluates as true, the following methods will be available on the
584C<$result> object.
585
586=head3 C<ok>
587
588 my $ok = $result->ok;
589
590Returns the literal text of the C<ok> or C<not ok> status.
591
592=head3 C<number>
593
594 my $test_number = $result->number;
595
596Returns the number of the test, even if the original TAP output did not supply
597that number.
598
599=head3 C<description>
600
601 my $description = $result->description;
602
603Returns the description of the test, if any. This is the portion after the
604test number but before the directive.
605
606=head3 C<directive>
607
608 my $directive = $result->directive;
609
610Returns either C<TODO> or C<SKIP> if either directive was present for a test
611line.
612
613=head3 C<explanation>
614
615 my $explanation = $result->explanation;
616
617If a test had either a C<TODO> or C<SKIP> directive, this method will return
618the accompanying explantion, if present.
619
620 not ok 17 - 'Pigs can fly' # TODO not enough acid
621
622For the above line, the explanation is I<not enough acid>.
623
624=head3 C<is_ok>
625
626 if ( $result->is_ok ) { ... }
627
628Returns a boolean value indicating whether or not the test passed. Remember
629that for TODO tests, the test always passes.
630
631B<Note:> this was formerly C<passed>. The latter method is deprecated and
632will issue a warning.
633
634=head3 C<is_actual_ok>
635
636 if ( $result->is_actual_ok ) { ... }
637
638Returns a boolean value indicating whether or not the test passed, regardless
639of its TODO status.
640
641B<Note:> this was formerly C<actual_passed>. The latter method is deprecated
642and will issue a warning.
643
644=head3 C<is_unplanned>
645
646 if ( $test->is_unplanned ) { ... }
647
648If a test number is greater than the number of planned tests, this method will
649return true. Unplanned tests will I<always> return false for C<is_ok>,
650regardless of whether or not the test C<has_todo> (see
651L<TAP::Parser::Result::Test> for more information about this).
652
653=head3 C<has_skip>
654
655 if ( $result->has_skip ) { ... }
656
657Returns a boolean value indicating whether or not this test had a SKIP
658directive.
659
660=head3 C<has_todo>
661
662 if ( $result->has_todo ) { ... }
663
664Returns a boolean value indicating whether or not this test had a TODO
665directive.
666
667Note that TODO tests I<always> pass. If you need to know whether or not
668they really passed, check the C<is_actual_ok> method.
669
670=head3 C<in_todo>
671
672 if ( $parser->in_todo ) { ... }
673
674True while the most recent result was a TODO. Becomes true before the
675TODO result is returned and stays true until just before the next non-
676TODO test is returned.
677
678=head1 TOTAL RESULTS
679
680After parsing the TAP, there are many methods available to let you dig through
681the results and determine what is meaningful to you.
682
683=head2 Individual Results
684
685These results refer to individual tests which are run.
686
687=head3 C<passed>
688
689 my @passed = $parser->passed; # the test numbers which passed
690 my $passed = $parser->passed; # the number of tests which passed
691
692This method lets you know which (or how many) tests passed. If a test failed
693but had a TODO directive, it will be counted as a passed test.
694
695=cut
696
697sub passed { @{ shift->{passed} } }
698
699=head3 C<failed>
700
701 my @failed = $parser->failed; # the test numbers which failed
702 my $failed = $parser->failed; # the number of tests which failed
703
704This method lets you know which (or how many) tests failed. If a test passed
705but had a TODO directive, it will B<NOT> be counted as a failed test.
706
707=cut
708
709sub failed { @{ shift->{failed} } }
710
711=head3 C<actual_passed>
712
713 # the test numbers which actually passed
714 my @actual_passed = $parser->actual_passed;
715
716 # the number of tests which actually passed
717 my $actual_passed = $parser->actual_passed;
718
719This method lets you know which (or how many) tests actually passed,
720regardless of whether or not a TODO directive was found.
721
722=cut
723
724sub actual_passed { @{ shift->{actual_passed} } }
725*actual_ok = \&actual_passed;
726
727=head3 C<actual_ok>
728
729This method is a synonym for C<actual_passed>.
730
731=head3 C<actual_failed>
732
733 # the test numbers which actually failed
734 my @actual_failed = $parser->actual_failed;
735
736 # the number of tests which actually failed
737 my $actual_failed = $parser->actual_failed;
738
739This method lets you know which (or how many) tests actually failed,
740regardless of whether or not a TODO directive was found.
741
742=cut
743
744sub actual_failed { @{ shift->{actual_failed} } }
745
746##############################################################################
747
748=head3 C<todo>
749
750 my @todo = $parser->todo; # the test numbers with todo directives
751 my $todo = $parser->todo; # the number of tests with todo directives
752
753This method lets you know which (or how many) tests had TODO directives.
754
755=cut
756
757sub todo { @{ shift->{todo} } }
758
759=head3 C<todo_passed>
760
761 # the test numbers which unexpectedly succeeded
762 my @todo_passed = $parser->todo_passed;
763
764 # the number of tests which unexpectedly succeeded
765 my $todo_passed = $parser->todo_passed;
766
767This method lets you know which (or how many) tests actually passed but were
768declared as "TODO" tests.
769
770=cut
771
772sub todo_passed { @{ shift->{todo_passed} } }
773
774##############################################################################
775
776=head3 C<todo_failed>
777
778 # deprecated in favor of 'todo_passed'. This method was horribly misnamed.
779
780This was a badly misnamed method. It indicates which TODO tests unexpectedly
781succeeded. Will now issue a warning and call C<todo_passed>.
782
783=cut
784
785sub todo_failed {
786 warn
787 '"todo_failed" is deprecated. Please use "todo_passed". See the docs.';
788 goto &todo_passed;
789}
790
791=head3 C<skipped>
792
793 my @skipped = $parser->skipped; # the test numbers with SKIP directives
794 my $skipped = $parser->skipped; # the number of tests with SKIP directives
795
796This method lets you know which (or how many) tests had SKIP directives.
797
798=cut
799
800sub skipped { @{ shift->{skipped} } }
801
2a7f4b9b 802=head2 Pragmas
803
804=head3 C<pragma>
805
806Get or set a pragma. To get the state of a pragma:
807
808 if ( $p->pragma('strict') ) {
809 # be strict
810 }
811
812To set the state of a pragma:
813
814 $p->pragma('strict', 1); # enable strict mode
815
816=cut
817
818sub pragma {
819 my ( $self, $pragma ) = splice @_, 0, 2;
820
821 return $self->{pragma}->{$pragma} unless @_;
822
823 if ( my $state = shift ) {
824 $self->{pragma}->{$pragma} = 1;
825 }
826 else {
827 delete $self->{pragma}->{$pragma};
828 }
829
830 return;
831}
832
833=head3 C<pragmas>
834
835Get a list of all the currently enabled pragmas:
836
837 my @pragmas_enabled = $p->pragmas;
838
839=cut
840
841sub pragmas { sort keys %{ shift->{pragma} || {} } }
842
b965d173 843=head2 Summary Results
844
845These results are "meta" information about the total results of an individual
846test program.
847
848=head3 C<plan>
849
850 my $plan = $parser->plan;
851
852Returns the test plan, if found.
853
854=head3 C<good_plan>
855
856Deprecated. Use C<is_good_plan> instead.
857
858=cut
859
860sub good_plan {
861 warn 'good_plan() is deprecated. Please use "is_good_plan()"';
862 goto &is_good_plan;
863}
864
865##############################################################################
866
867=head3 C<is_good_plan>
868
869 if ( $parser->is_good_plan ) { ... }
870
871Returns a boolean value indicating whether or not the number of tests planned
872matches the number of tests run.
873
874B<Note:> this was formerly C<good_plan>. The latter method is deprecated and
875will issue a warning.
876
877And since we're on that subject ...
878
879=head3 C<tests_planned>
880
881 print $parser->tests_planned;
882
883Returns the number of tests planned, according to the plan. For example, a
884plan of '1..17' will mean that 17 tests were planned.
885
886=head3 C<tests_run>
887
888 print $parser->tests_run;
889
890Returns the number of tests which actually were run. Hopefully this will
891match the number of C<< $parser->tests_planned >>.
892
893=head3 C<skip_all>
894
895Returns a true value (actually the reason for skipping) if all tests
896were skipped.
897
898=head3 C<start_time>
899
900Returns the time when the Parser was created.
901
902=head3 C<end_time>
903
904Returns the time when the end of TAP input was seen.
905
906=head3 C<has_problems>
907
908 if ( $parser->has_problems ) {
909 ...
910 }
911
912This is a 'catch-all' method which returns true if any tests have currently
913failed, any TODO tests unexpectedly succeeded, or any parse errors occurred.
914
915=cut
916
917sub has_problems {
918 my $self = shift;
69f36734 919 return
920 $self->failed
b965d173 921 || $self->parse_errors
922 || $self->wait
923 || $self->exit;
924}
925
926=head3 C<version>
927
928 $parser->version;
929
930Once the parser is done, this will return the version number for the
931parsed TAP. Version numbers were introduced with TAP version 13 so if no
932version number is found version 12 is assumed.
933
934=head3 C<exit>
935
936 $parser->exit;
937
938Once the parser is done, this will return the exit status. If the parser ran
939an executable, it returns the exit status of the executable.
940
941=head3 C<wait>
942
943 $parser->wait;
944
945Once the parser is done, this will return the wait status. If the parser ran
946an executable, it returns the wait status of the executable. Otherwise, this
947mererely returns the C<exit> status.
948
949=head3 C<parse_errors>
950
951 my @errors = $parser->parse_errors; # the parser errors
952 my $errors = $parser->parse_errors; # the number of parser_errors
953
954Fortunately, all TAP output is perfect. In the event that it is not, this
955method will return parser errors. Note that a junk line which the parser does
956not recognize is C<not> an error. This allows this parser to handle future
957versions of TAP. The following are all TAP errors reported by the parser:
958
959=over 4
960
961=item * Misplaced plan
962
963The plan (for example, '1..5'), must only come at the beginning or end of the
964TAP output.
965
966=item * No plan
967
968Gotta have a plan!
969
970=item * More than one plan
971
972 1..3
973 ok 1 - input file opened
974 not ok 2 - first line of the input valid # todo some data
975 ok 3 read the rest of the file
976 1..3
977
978Right. Very funny. Don't do that.
979
980=item * Test numbers out of sequence
981
982 1..3
983 ok 1 - input file opened
984 not ok 2 - first line of the input valid # todo some data
985 ok 2 read the rest of the file
986
987That last test line above should have the number '3' instead of '2'.
988
989Note that it's perfectly acceptable for some lines to have test numbers and
990others to not have them. However, when a test number is found, it must be in
991sequence. The following is also an error:
992
993 1..3
994 ok 1 - input file opened
995 not ok - first line of the input valid # todo some data
996 ok 2 read the rest of the file
997
998But this is not:
999
1000 1..3
1001 ok - input file opened
1002 not ok - first line of the input valid # todo some data
1003 ok 3 read the rest of the file
1004
1005=back
1006
1007=cut
1008
1009sub parse_errors { @{ shift->{parse_errors} } }
1010
1011sub _add_error {
1012 my ( $self, $error ) = @_;
1013 push @{ $self->{parse_errors} } => $error;
1014 return $self;
1015}
1016
1017sub _make_state_table {
1018 my $self = shift;
1019 my %states;
1020 my %planned_todo = ();
1021
1022 # These transitions are defaults for all states
1023 my %state_globals = (
1024 comment => {},
1025 bailout => {},
2a7f4b9b 1026 yaml => {},
b965d173 1027 version => {
1028 act => sub {
b965d173 1029 $self->_add_error(
1030 'If TAP version is present it must be the first line of output'
1031 );
1032 },
1033 },
2a7f4b9b 1034 unknown => {
1035 act => sub {
1036 my $unk = shift;
1037 if ( $self->pragma('strict') ) {
1038 $self->_add_error(
1039 'Unknown TAP token: "' . $unk->raw . '"' );
1040 }
1041 },
1042 },
1043 pragma => {
1044 act => sub {
1045 my ($pragma) = @_;
1046 for my $pr ( $pragma->pragmas ) {
1047 if ( $pr =~ /^ ([-+])(\w+) $/x ) {
1048 $self->pragma( $2, $1 eq '+' );
1049 }
1050 }
1051 },
1052 },
b965d173 1053 );
1054
1055 # Provides default elements for transitions
1056 my %state_defaults = (
1057 plan => {
1058 act => sub {
1059 my ($plan) = @_;
1060 $self->tests_planned( $plan->tests_planned );
1061 $self->plan( $plan->plan );
1062 if ( $plan->has_skip ) {
1063 $self->skip_all( $plan->explanation
1064 || '(no reason given)' );
1065 }
1066
1067 $planned_todo{$_}++ for @{ $plan->todo_list };
1068 },
1069 },
1070 test => {
1071 act => sub {
1072 my ($test) = @_;
1073
1074 my ( $number, $tests_run )
1075 = ( $test->number, ++$self->{tests_run} );
1076
1077 # Fake TODO state
1078 if ( defined $number && delete $planned_todo{$number} ) {
1079 $test->set_directive('TODO');
1080 }
1081
1082 my $has_todo = $test->has_todo;
1083
1084 $self->in_todo($has_todo);
1085 if ( defined( my $tests_planned = $self->tests_planned ) ) {
1086 if ( $tests_run > $tests_planned ) {
1087 $test->is_unplanned(1);
1088 }
1089 }
1090
1091 if ($number) {
1092 if ( $number != $tests_run ) {
1093 my $count = $tests_run;
1094 $self->_add_error( "Tests out of sequence. Found "
1095 . "($number) but expected ($count)" );
1096 }
1097 }
1098 else {
1099 $test->_number( $number = $tests_run );
1100 }
1101
1102 push @{ $self->{todo} } => $number if $has_todo;
1103 push @{ $self->{todo_passed} } => $number
1104 if $test->todo_passed;
1105 push @{ $self->{skipped} } => $number
1106 if $test->has_skip;
1107
1108 push @{ $self->{ $test->is_ok ? 'passed' : 'failed' } } =>
1109 $number;
1110 push @{
1111 $self->{
1112 $test->is_actual_ok
1113 ? 'actual_passed'
1114 : 'actual_failed'
1115 }
1116 } => $number;
1117 },
1118 },
2a7f4b9b 1119 yaml => { act => sub { }, },
b965d173 1120 );
1121
1122 # Each state contains a hash the keys of which match a token type. For
1123 # each token
1124 # type there may be:
1125 # act A coderef to run
1126 # goto The new state to move to. Stay in this state if
1127 # missing
1128 # continue Goto the new state and run the new state for the
1129 # current token
1130 %states = (
1131 INIT => {
1132 version => {
1133 act => sub {
1134 my ($version) = @_;
1135 my $ver_num = $version->version;
1136 if ( $ver_num <= $DEFAULT_TAP_VERSION ) {
1137 my $ver_min = $DEFAULT_TAP_VERSION + 1;
1138 $self->_add_error(
1139 "Explicit TAP version must be at least "
1140 . "$ver_min. Got version $ver_num" );
1141 $ver_num = $DEFAULT_TAP_VERSION;
1142 }
1143 if ( $ver_num > $MAX_TAP_VERSION ) {
1144 $self->_add_error(
1145 "TAP specified version $ver_num but "
1146 . "we don't know about versions later "
1147 . "than $MAX_TAP_VERSION" );
1148 $ver_num = $MAX_TAP_VERSION;
1149 }
1150 $self->version($ver_num);
1151 $self->_grammar->set_version($ver_num);
1152 },
1153 goto => 'PLAN'
1154 },
1155 plan => { goto => 'PLANNED' },
1156 test => { goto => 'UNPLANNED' },
1157 },
1158 PLAN => {
1159 plan => { goto => 'PLANNED' },
1160 test => { goto => 'UNPLANNED' },
1161 },
1162 PLANNED => {
1163 test => { goto => 'PLANNED_AFTER_TEST' },
1164 plan => {
1165 act => sub {
1166 my ($version) = @_;
1167 $self->_add_error(
1168 'More than one plan found in TAP output');
1169 },
1170 },
1171 },
1172 PLANNED_AFTER_TEST => {
1173 test => { goto => 'PLANNED_AFTER_TEST' },
1174 plan => { act => sub { }, continue => 'PLANNED' },
1175 yaml => { goto => 'PLANNED' },
1176 },
1177 GOT_PLAN => {
1178 test => {
1179 act => sub {
1180 my ($plan) = @_;
1181 my $line = $self->plan;
1182 $self->_add_error(
1183 "Plan ($line) must be at the beginning "
1184 . "or end of the TAP output" );
1185 $self->is_good_plan(0);
1186 },
1187 continue => 'PLANNED'
1188 },
1189 plan => { continue => 'PLANNED' },
1190 },
1191 UNPLANNED => {
1192 test => { goto => 'UNPLANNED_AFTER_TEST' },
1193 plan => { goto => 'GOT_PLAN' },
1194 },
1195 UNPLANNED_AFTER_TEST => {
1196 test => { act => sub { }, continue => 'UNPLANNED' },
1197 plan => { act => sub { }, continue => 'UNPLANNED' },
1198 yaml => { goto => 'PLANNED' },
1199 },
1200 );
1201
1202 # Apply globals and defaults to state table
2a7f4b9b 1203 for my $name ( keys %states ) {
b965d173 1204
1205 # Merge with globals
1206 my $st = { %state_globals, %{ $states{$name} } };
1207
1208 # Add defaults
1209 for my $next ( sort keys %{$st} ) {
1210 if ( my $default = $state_defaults{$next} ) {
1211 for my $def ( sort keys %{$default} ) {
1212 $st->{$next}->{$def} ||= $default->{$def};
1213 }
1214 }
1215 }
1216
1217 # Stuff back in table
1218 $states{$name} = $st;
1219 }
1220
1221 return \%states;
1222}
1223
1224=head3 C<get_select_handles>
1225
1226Get an a list of file handles which can be passed to C<select> to
1227determine the readiness of this parser.
1228
1229=cut
1230
1231sub get_select_handles { shift->_stream->get_select_handles }
1232
1233sub _iter {
1234 my $self = shift;
1235 my $stream = $self->_stream;
1236 my $spool = $self->_spool;
1237 my $grammar = $self->_grammar;
1238 my $state = 'INIT';
1239 my $state_table = $self->_make_state_table;
1240
1241 # Make next_state closure
1242 my $next_state = sub {
1243 my $token = shift;
1244 my $type = $token->type;
b965d173 1245 TRANS: {
1246 my $state_spec = $state_table->{$state}
1247 or die "Illegal state: $state";
1248
1249 if ( my $next = $state_spec->{$type} ) {
1250 if ( my $act = $next->{act} ) {
1251 $act->($token);
1252 }
1253 if ( my $cont = $next->{continue} ) {
1254 $state = $cont;
1255 redo TRANS;
1256 }
1257 elsif ( my $goto = $next->{goto} ) {
1258 $state = $goto;
1259 }
1260 }
2a7f4b9b 1261 else {
1262 confess("Unhandled token type: $type\n");
1263 }
b965d173 1264 }
1265 return $token;
1266 };
1267
1268 # Handle end of stream - which means either pop a block or finish
1269 my $end_handler = sub {
1270 $self->exit( $stream->exit );
1271 $self->wait( $stream->wait );
1272 $self->_finish;
1273 return;
1274 };
1275
1276 # Finally make the closure that we return. For performance reasons
1277 # there are two versions of the returned function: one that handles
1278 # callbacks and one that does not.
1279 if ( $self->_has_callbacks ) {
1280 return sub {
1281 my $result = eval { $grammar->tokenize };
1282 $self->_add_error($@) if $@;
1283
1284 if ( defined $result ) {
1285 $result = $next_state->($result);
1286
1287 if ( my $code = $self->_callback_for( $result->type ) ) {
1288 $_->($result) for @{$code};
1289 }
1290 else {
1291 $self->_make_callback( 'ELSE', $result );
1292 }
1293
1294 $self->_make_callback( 'ALL', $result );
1295
1296 # Echo TAP to spool file
1297 print {$spool} $result->raw, "\n" if $spool;
1298 }
1299 else {
1300 $result = $end_handler->();
1301 $self->_make_callback( 'EOF', $result )
1302 unless defined $result;
1303 }
1304
1305 return $result;
1306 };
1307 } # _has_callbacks
1308 else {
1309 return sub {
1310 my $result = eval { $grammar->tokenize };
1311 $self->_add_error($@) if $@;
1312
1313 if ( defined $result ) {
1314 $result = $next_state->($result);
1315
1316 # Echo TAP to spool file
1317 print {$spool} $result->raw, "\n" if $spool;
1318 }
1319 else {
1320 $result = $end_handler->();
1321 }
1322
1323 return $result;
1324 };
1325 } # no callbacks
1326}
1327
1328sub _finish {
1329 my $self = shift;
1330
1331 $self->end_time( $self->get_time );
1332
1333 # sanity checks
1334 if ( !$self->plan ) {
1335 $self->_add_error('No plan found in TAP output');
1336 }
1337 else {
1338 $self->is_good_plan(1) unless defined $self->is_good_plan;
1339 }
1340 if ( $self->tests_run != ( $self->tests_planned || 0 ) ) {
1341 $self->is_good_plan(0);
1342 if ( defined( my $planned = $self->tests_planned ) ) {
1343 my $ran = $self->tests_run;
1344 $self->_add_error(
1345 "Bad plan. You planned $planned tests but ran $ran.");
1346 }
1347 }
1348 if ( $self->tests_run != ( $self->passed + $self->failed ) ) {
1349
1350 # this should never happen
1351 my $actual = $self->tests_run;
1352 my $passed = $self->passed;
1353 my $failed = $self->failed;
1354 $self->_croak( "Panic: planned test count ($actual) did not equal "
1355 . "sum of passed ($passed) and failed ($failed) tests!" );
1356 }
1357
1358 $self->is_good_plan(0) unless defined $self->is_good_plan;
1359 return $self;
1360}
1361
1362=head3 C<delete_spool>
1363
1364Delete and return the spool.
1365
1366 my $fh = $parser->delete_spool;
1367
1368=cut
1369
1370sub delete_spool {
1371 my $self = shift;
1372
1373 return delete $self->{_spool};
1374}
1375
1376##############################################################################
1377
1378=head1 CALLBACKS
1379
1380As mentioned earlier, a "callback" key may be added to the
1381C<TAP::Parser> constructor. If present, each callback corresponding to a
1382given result type will be called with the result as the argument if the
1383C<run> method is used. The callback is expected to be a subroutine
1384reference (or anonymous subroutine) which is invoked with the parser
1385result as its argument.
1386
1387 my %callbacks = (
1388 test => \&test_callback,
1389 plan => \&plan_callback,
1390 comment => \&comment_callback,
1391 bailout => \&bailout_callback,
1392 unknown => \&unknown_callback,
1393 );
1394
1395 my $aggregator = TAP::Parser::Aggregator->new;
1396 foreach my $file ( @test_files ) {
1397 my $parser = TAP::Parser->new(
1398 {
1399 source => $file,
1400 callbacks => \%callbacks,
1401 }
1402 );
1403 $parser->run;
1404 $aggregator->add( $file, $parser );
1405 }
1406
1407Callbacks may also be added like this:
1408
1409 $parser->callback( test => \&test_callback );
1410 $parser->callback( plan => \&plan_callback );
1411
1412The following keys allowed for callbacks. These keys are case-sensitive.
1413
1414=over 4
1415
1416=item * C<test>
1417
1418Invoked if C<< $result->is_test >> returns true.
1419
1420=item * C<version>
1421
1422Invoked if C<< $result->is_version >> returns true.
1423
1424=item * C<plan>
1425
1426Invoked if C<< $result->is_plan >> returns true.
1427
1428=item * C<comment>
1429
1430Invoked if C<< $result->is_comment >> returns true.
1431
1432=item * C<bailout>
1433
1434Invoked if C<< $result->is_unknown >> returns true.
1435
1436=item * C<yaml>
1437
1438Invoked if C<< $result->is_yaml >> returns true.
1439
1440=item * C<unknown>
1441
1442Invoked if C<< $result->is_unknown >> returns true.
1443
1444=item * C<ELSE>
1445
1446If a result does not have a callback defined for it, this callback will
1447be invoked. Thus, if all of the previous result types are specified as
1448callbacks, this callback will I<never> be invoked.
1449
1450=item * C<ALL>
1451
1452This callback will always be invoked and this will happen for each
1453result after one of the above callbacks is invoked. For example, if
1454L<Term::ANSIColor> is loaded, you could use the following to color your
1455test output:
1456
1457 my %callbacks = (
1458 test => sub {
1459 my $test = shift;
1460 if ( $test->is_ok && not $test->directive ) {
1461 # normal passing test
1462 print color 'green';
1463 }
1464 elsif ( !$test->is_ok ) { # even if it's TODO
1465 print color 'white on_red';
1466 }
1467 elsif ( $test->has_skip ) {
1468 print color 'white on_blue';
1469
1470 }
1471 elsif ( $test->has_todo ) {
1472 print color 'white';
1473 }
1474 },
1475 ELSE => sub {
1476 # plan, comment, and so on (anything which isn't a test line)
1477 print color 'black on_white';
1478 },
1479 ALL => sub {
1480 # now print them
1481 print shift->as_string;
1482 print color 'reset';
1483 print "\n";
1484 },
1485 );
1486
1487=item * C<EOF>
1488
1489Invoked when there are no more lines to be parsed. Since there is no
1490accompanying L<TAP::Parser::Result> object the C<TAP::Parser> object is
1491passed instead.
1492
1493=back
1494
1495=head1 TAP GRAMMAR
1496
1497If you're looking for an EBNF grammar, see L<TAP::Parser::Grammar>.
1498
1499=head1 BACKWARDS COMPATABILITY
1500
1501The Perl-QA list attempted to ensure backwards compatability with
1502L<Test::Harness>. However, there are some minor differences.
1503
1504=head2 Differences
1505
1506=over 4
1507
1508=item * TODO plans
1509
1510A little-known feature of L<Test::Harness> is that it supported TODO
1511lists in the plan:
1512
1513 1..2 todo 2
1514 ok 1 - We have liftoff
1515 not ok 2 - Anti-gravity device activated
1516
1517Under L<Test::Harness>, test number 2 would I<pass> because it was
1518listed as a TODO test on the plan line. However, we are not aware of
1519anyone actually using this feature and hard-coding test numbers is
1520discouraged because it's very easy to add a test and break the test
1521number sequence. This makes test suites very fragile. Instead, the
1522following should be used:
1523
1524 1..2
1525 ok 1 - We have liftoff
1526 not ok 2 - Anti-gravity device activated # TODO
1527
1528=item * 'Missing' tests
1529
1530It rarely happens, but sometimes a harness might encounter
1531'missing tests:
1532
1533 ok 1
1534 ok 2
1535 ok 15
1536 ok 16
1537 ok 17
1538
1539L<Test::Harness> would report tests 3-14 as having failed. For the
1540C<TAP::Parser>, these tests are not considered failed because they've
1541never run. They're reported as parse failures (tests out of sequence).
1542
1543=back
1544
1545=head1 ACKNOWLEDGEMENTS
1546
1547All of the following have helped. Bug reports, patches, (im)moral
1548support, or just words of encouragement have all been forthcoming.
1549
1550=over 4
1551
1552=item * Michael Schwern
1553
1554=item * Andy Lester
1555
1556=item * chromatic
1557
1558=item * GEOFFR
1559
1560=item * Shlomi Fish
1561
1562=item * Torsten Schoenfeld
1563
1564=item * Jerry Gay
1565
1566=item * Aristotle
1567
1568=item * Adam Kennedy
1569
1570=item * Yves Orton
1571
1572=item * Adrian Howard
1573
1574=item * Sean & Lil
1575
1576=item * Andreas J. Koenig
1577
1578=item * Florian Ragwitz
1579
1580=item * Corion
1581
1582=item * Mark Stosberg
1583
1584=item * Matt Kraai
1585
1586=back
1587
1588=head1 AUTHORS
1589
1590Curtis "Ovid" Poe <ovid@cpan.org>
1591
1592Andy Armstong <andy@hexten.net>
1593
1594Eric Wilhelm @ <ewilhelm at cpan dot org>
1595
1596Michael Peters <mpeters at plusthree dot com>
1597
1598Leif Eriksen <leif dot eriksen at bigpond dot com>
1599
1600=head1 BUGS
1601
1602Please report any bugs or feature requests to
1603C<bug-tapx-parser@rt.cpan.org>, or through the web interface at
1604L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=TAP-Parser>.
1605We will be notified, and then you'll automatically be notified of
1606progress on your bug as we make changes.
1607
1608Obviously, bugs which include patches are best. If you prefer, you can
1609patch against bleed by via anonymous checkout of the latest version:
1610
1611 svn checkout http://svn.hexten.net/tapx
1612
1613=head1 COPYRIGHT & LICENSE
1614
53bc175b 1615Copyright 2006-2008 Curtis "Ovid" Poe, all rights reserved.
b965d173 1616
1617This program is free software; you can redistribute it and/or modify it
1618under the same terms as Perl itself.
1619
1620=cut
1621
16221;