1 package TAP::Parser::SourceHandler::Executable;
4 use vars qw($VERSION @ISA);
6 use TAP::Parser::SourceHandler ();
7 use TAP::Parser::IteratorFactory ();
8 use TAP::Parser::Iterator::Process ();
10 @ISA = qw(TAP::Parser::SourceHandler);
12 TAP::Parser::IteratorFactory->register_handler(__PACKAGE__);
16 TAP::Parser::SourceHandler::Executable - Stream output from an executable TAP source
28 use TAP::Parser::Source;
29 use TAP::Parser::SourceHandler::Executable;
31 my $source = TAP::Parser::Source->new->raw(['/usr/bin/ruby', 'mytest.rb']);
32 $source->assemble_meta;
34 my $class = 'TAP::Parser::SourceHandler::Executable';
35 my $vote = $class->can_handle( $source );
36 my $iter = $class->make_iterator( $source );
40 This is an I<executable> L<TAP::Parser::SourceHandler> - it has 2 jobs:
42 1. Figure out if the L<TAP::Parser::Source> it's given is an executable
43 command (L</can_handle>).
45 2. Creates an iterator for executable commands (L</make_iterator>).
47 Unless you're writing a plugin or subclassing L<TAP::Parser>, you
48 probably won't need to use this module directly.
56 my $vote = $class->can_handle( $source );
58 Only votes if $source looks like an executable file. Casts the
61 0.9 if it's a hash with an 'exec' key
62 0.8 if it's a .bat file
63 0.75 if it's got an execute bit set
68 my ( $class, $src ) = @_;
69 my $meta = $src->meta;
71 if ( $meta->{is_file} ) {
72 my $file = $meta->{file};
74 return 0.85 if $file->{execute} && $file->{binary};
75 return 0.8 if $file->{lc_ext} eq '.bat';
76 return 0.25 if $file->{execute};
78 elsif ( $meta->{is_hash} ) {
79 return 0.9 if $src->raw->{exec};
85 =head3 C<make_iterator>
87 my $iterator = $class->make_iterator( $source );
89 Returns a new L<TAP::Parser::Iterator::Process> for the source.
90 C<$source-E<gt>raw> must be in one of the following forms:
103 my ( $class, $source ) = @_;
104 my $meta = $source->meta;
107 if ( $meta->{is_hash} ) {
108 @command = @{ $source->raw->{exec} || [] };
110 elsif ( $meta->{is_scalar} ) {
111 @command = ${ $source->raw };
113 elsif ( $meta->{is_array} ) {
114 @command = @{ $source->raw };
117 $class->_croak('No command found in $source->raw!') unless @command;
119 $class->_autoflush( \*STDOUT );
120 $class->_autoflush( \*STDERR );
122 push @command, @{ $source->test_args || [] };
124 return $class->iterator_class->new(
125 { command => \@command,
126 merge => $source->merge
131 =head3 C<iterator_class>
133 The class of iterator to use, override if you're sub-classing. Defaults
134 to L<TAP::Parser::Iterator::Process>.
138 use constant iterator_class => 'TAP::Parser::Iterator::Process';
140 # Turns on autoflush for the handle passed
142 my ( $class, $flushed ) = @_;
143 my $old_fh = select $flushed;
152 Please see L<TAP::Parser/SUBCLASSING> for a subclassing overview.
156 package MyRubySourceHandler;
161 use Carp qw( croak );
162 use TAP::Parser::SourceHandler::Executable;
164 @ISA = qw( TAP::Parser::SourceHandler::Executable );
166 # expect $handler->(['mytest.rb', 'cmdline', 'args']);
168 my ($self, $source) = @_;
169 my @test_args = @{ $source->test_args };
170 my $rb_file = $test_args[0];
171 croak("error: Ruby file '$rb_file' not found!") unless (-f $rb_file);
172 return $self->SUPER::raw_source(['/usr/bin/ruby', @test_args]);
179 L<TAP::Parser::IteratorFactory>,
180 L<TAP::Parser::SourceHandler>,
181 L<TAP::Parser::SourceHandler::Perl>,
182 L<TAP::Parser::SourceHandler::File>,
183 L<TAP::Parser::SourceHandler::Handle>,
184 L<TAP::Parser::SourceHandler::RawTAP>