1package TAP::Parser::Source; 2 3use strict; 4use vars qw($VERSION @ISA); 5 6use TAP::Object (); 7use TAP::Parser::IteratorFactory (); 8 9@ISA = qw(TAP::Object); 10 11# Causes problem on MacOS and shouldn't be necessary anyway 12#$SIG{CHLD} = sub { wait }; 13 14=head1 NAME 15 16TAP::Parser::Source - Stream output from some source 17 18=head1 VERSION 19 20Version 3.17 21 22=cut 23 24$VERSION = '3.17'; 25 26=head1 SYNOPSIS 27 28 use TAP::Parser::Source; 29 my $source = TAP::Parser::Source->new; 30 my $stream = $source->source(['/usr/bin/ruby', 'mytest.rb'])->get_stream; 31 32=head1 DESCRIPTION 33 34Takes a command and hopefully returns a stream from it. 35 36=head1 METHODS 37 38=head2 Class Methods 39 40=head3 C<new> 41 42 my $source = TAP::Parser::Source->new; 43 44Returns a new C<TAP::Parser::Source> object. 45 46=cut 47 48# new() implementation supplied by TAP::Object 49 50sub _initialize { 51 my ( $self, $args ) = @_; 52 $self->{switches} = []; 53 _autoflush( \*STDOUT ); 54 _autoflush( \*STDERR ); 55 return $self; 56} 57 58############################################################################## 59 60=head2 Instance Methods 61 62=head3 C<source> 63 64 my $source = $source->source; 65 $source->source(['./some_prog some_test_file']); 66 67 # or 68 $source->source(['/usr/bin/ruby', 't/ruby_test.rb']); 69 70Getter/setter for the source. The source should generally consist of an array 71reference of strings which, when executed via L<&IPC::Open3::open3|IPC::Open3>, 72should return a filehandle which returns successive rows of TAP. C<croaks> if 73it doesn't get an arrayref. 74 75=cut 76 77sub source { 78 my $self = shift; 79 return $self->{source} unless @_; 80 unless ( 'ARRAY' eq ref $_[0] ) { 81 $self->_croak('Argument to &source must be an array reference'); 82 } 83 $self->{source} = shift; 84 return $self; 85} 86 87############################################################################## 88 89=head3 C<get_stream> 90 91 my $stream = $source->get_stream; 92 93Returns a L<TAP::Parser::Iterator> stream of the output generated by executing 94C<source>. C<croak>s if there was no command found. 95 96Must be passed an object that implements a C<make_iterator> method. 97Typically this is a TAP::Parser instance. 98 99=cut 100 101sub get_stream { 102 my ( $self, $factory ) = @_; 103 my @command = $self->_get_command 104 or $self->_croak('No command found!'); 105 106 return $factory->make_iterator( 107 { command => \@command, 108 merge => $self->merge 109 } 110 ); 111} 112 113sub _get_command { return @{ shift->source || [] } } 114 115############################################################################## 116 117=head3 C<merge> 118 119 my $merge = $source->merge; 120 121Sets or returns the flag that dictates whether STDOUT and STDERR are merged. 122 123=cut 124 125sub merge { 126 my $self = shift; 127 return $self->{merge} unless @_; 128 $self->{merge} = shift; 129 return $self; 130} 131 132# Turns on autoflush for the handle passed 133sub _autoflush { 134 my $flushed = shift; 135 my $old_fh = select $flushed; 136 $| = 1; 137 select $old_fh; 138} 139 1401; 141 142=head1 SUBCLASSING 143 144Please see L<TAP::Parser/SUBCLASSING> for a subclassing overview. 145 146=head2 Example 147 148 package MyRubySource; 149 150 use strict; 151 use vars '@ISA'; 152 153 use Carp qw( croak ); 154 use TAP::Parser::Source; 155 156 @ISA = qw( TAP::Parser::Source ); 157 158 # expect $source->(['mytest.rb', 'cmdline', 'args']); 159 sub source { 160 my ($self, $args) = @_; 161 my ($rb_file) = @$args; 162 croak("error: Ruby file '$rb_file' not found!") unless (-f $rb_file); 163 return $self->SUPER::source(['/usr/bin/ruby', @$args]); 164 } 165 166=head1 SEE ALSO 167 168L<TAP::Object>, 169L<TAP::Parser>, 170L<TAP::Parser::Source::Perl>, 171 172=cut 173 174