——————package
TAPx::Parser::Source;
use
strict;
use
IPC::Open3;
use
IO::Select;
use
IO::Handle;
$SIG
{CHLD} =
sub
{
wait
};
=head1 NAME
TAPx::Parser::Source - Stream output from some source
=head1 VERSION
Version 0.50_02
=cut
$VERSION
=
'0.50_02'
;
=head1 DESCRIPTION
Takes a command and hopefully returns a stream from it.
=head1 SYNOPSIS
use TAPx::Parser::Source;
my $source = TAPx::Parser::Source->new;
my $stream = $source->source('/usr/bin/ruby mytest.rb')->get_stream;
##############################################################################
=head1 METHODS
=head2 Class methods
=head3 C<new>
my $source = TAPx::Parser::Source->new;
Returns a new C<TAPx::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');
Getter/setter for the source. The source should generally consist of
something which, when executed with a piped open, should return a filehandle
which returns successive rows of TAP.
=cut
sub
source {
my
$self
=
shift
;
return
$self
->{source}
unless
@_
;
$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;
# redirecting STDERR to STDOUT seems to keep them in sync
# but I lose a bit of formatting for some reason
my
$stdout
= IO::Select->new();
my
$stdout_handle
= IO::Handle->new();
$stdout_handle
->autoflush(1);
$stdout
->add( \
*STDOUT
);
$stdout
->add(
$stdout_handle
);
if
(
my
$pid
= open3(
undef
,
$stdout_handle
,
undef
,
$command
) ) {
return
TAPx::Parser::Iterator->new(
$stdout_handle
);
}
else
{
$self
->
exit
( $? >> 8 );
$self
->error(
"Could not execute ($command): $!"
);
return
;
}
}
sub
_get_command {
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
;
}
# 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
;
Carp::croak(
@_
);
}
1;