package TAP::Parser::Source;
use strict;
use vars qw($VERSION);
use TAP::Parser::Iterator ();
# Causes problem on MacOS and shouldn't be necessary anyway
#$SIG{CHLD} = sub { wait };
=head1 NAME
TAP::Parser::Source - Stream output from some source
=head1 VERSION
Version 3.00
=cut
$VERSION = '3.00';
=head1 DESCRIPTION
Takes a command and hopefully returns a stream from it.
=head1 SYNOPSIS
use TAP::Parser::Source;
my $source = TAP::Parser::Source->new;
my $stream = $source->source(['/usr/bin/ruby', 'mytest.rb'])->get_stream;
=head1 METHODS
=head2 Class Methods
=head3 C<new>
my $source = TAP::Parser::Source->new;
Returns a new C<TAP::Parser::Source> object.
=cut
sub new {
my $class = shift;
_autoflush( \*STDOUT );
_autoflush( \*STDERR );
bless { switches => [] }, $class;
}
##############################################################################
=head2 Instance Methods
=head3 C<source>
my $source = $source->source;
$source->source(['./some_prog some_test_file']);
# or
$source->source(['/usr/bin/ruby', 't/ruby_test.rb']);
Getter/setter for the source. The source should generally consist of an array
reference of strings which, when executed via L<&IPC::Open3::open3|IPC::Open3>, should
return a filehandle which returns successive rows of TAP.
=cut
sub source {
my $self = shift;
return $self->{source} unless @_;
unless ( 'ARRAY' eq ref $_[0] ) {
$self->_croak('Argument to &source must be an array reference');
}
$self->{source} = shift;
return $self;
}
##############################################################################
=head3 C<get_stream>
my $stream = $source->get_stream;
Returns a stream of the output generated by executing C<source>.
=cut
sub get_stream {
my ($self) = @_;
my @command = $self->_get_command
or $self->_croak('No command found!');
return TAP::Parser::Iterator->new(
{ command => \@command,
merge => $self->merge
}
);
}
sub _get_command { return @{ shift->source || [] } }
##############################################################################
=head3 C<error>
unless ( my $stream = $source->get_stream ) {
die $source->error;
}
If a stream cannot be created, this method will return the error.
=cut
sub error {
my $self = shift;
return $self->{error} unless @_;
$self->{error} = shift;
return $self;
}
##############################################################################
=head3 C<exit>
my $exit = $source->exit;
Returns the exit status of the process I<if and only if> an error occurs in
opening the file.
=cut
sub exit {
my $self = shift;
return $self->{exit} unless @_;
$self->{exit} = shift;
return $self;
}
##############################################################################
=head3 C<merge>
my $merge = $source->merge;
Sets or returns the flag that dictates whether STDOUT and STDERR are merged.
=cut
sub merge {
my $self = shift;
return $self->{merge} unless @_;
$self->{merge} = shift;
return $self;
}
# Turns on autoflush for the handle passed
sub _autoflush {
my $flushed = shift;
my $old_fh = select $flushed;
$| = 1;
select $old_fh;
}
sub _croak {
my $self = shift;
require Carp;
Carp::croak(@_);
}
1;