File Coverage

blib/lib/TAPx/Parser/Source.pm
Criterion Covered Total %
statement 57 73 78.0
branch 7 16 43.7
condition n/a
subroutine 15 18 83.3
pod 6 6 100.0
total 85 113 75.2


line stmt bran cond sub pod time code
1             package TAPx::Parser::Source;
2              
3 13     13   53240 use strict;
  13         24  
  13         449  
4 13     13   66 use vars qw($VERSION);
  13         23  
  13         585  
5              
6 13     13   12138 use IPC::Open3;
  13         65153  
  13         920  
7 13     13   14425 use IO::Select;
  13         23706  
  13         678  
8 13     13   13901 use IO::Handle;
  13         81772  
  13         1195  
9              
10 13     13   296 use constant IS_WIN32 => ( $^O =~ /^(MS)?Win32$/ );
  13         29  
  13         922  
11 13     13   72 use constant IS_MACOS => ( $^O eq 'MacOS' );
  13         41  
  13         671  
12 13     13   71 use constant IS_VMS => ( $^O eq 'VMS' );
  13         29  
  13         573  
13              
14 13     13   7059 use TAPx::Parser::Iterator;
  13         43  
  13         7060  
15              
16             # Causes problem on MacOS and shouldn't be necessary anyway
17             #$SIG{CHLD} = sub { wait };
18              
19             =head1 NAME
20              
21             TAPx::Parser::Source - Stream output from some source
22              
23             =head1 VERSION
24              
25             Version 0.50_07
26              
27             =cut
28              
29             $VERSION = '0.50_07';
30              
31             =head1 DESCRIPTION
32              
33             Takes a command and hopefully returns a stream from it.
34              
35             =head1 SYNOPSIS
36              
37             use TAPx::Parser::Source;
38             my $source = TAPx::Parser::Source->new;
39             my $stream = $source->source(['/usr/bin/ruby', 'mytest.rb'])->get_stream;
40              
41             =head1 METHODS
42              
43             =head2 Class methods
44              
45             =head3 C
46              
47             my $source = TAPx::Parser::Source->new;
48              
49             Returns a new C object.
50              
51             =cut
52              
53             sub new {
54 53     53 1 8302 my $class = shift;
55 53         273 _autoflush( \*STDOUT );
56 53         211 _autoflush( \*STDERR );
57 53         377 bless { switches => [] }, $class;
58             }
59              
60             ##############################################################################
61              
62             =head2 Instance methods
63              
64             =head3 C
65              
66             my $source = $source->source;
67             $source->source(['./some_prog some_test_file']);
68              
69             # or
70             $source->source(['/usr/bin/ruby', 't/ruby_test.rb']);
71              
72             Getter/setter for the source. The source should generally consist of an array
73             reference of strings which, when executed via C<&IPC::Open3::open3>, should
74             return a filehandle which returns successive rows of TAP.
75              
76             =cut
77              
78             sub source {
79 27     27 1 1194 my $self = shift;
80 27 100       157 return $self->{source} unless @_;
81 14 100       99 unless ( 'ARRAY' eq ref $_[0] ) {
82 1         5 $self->_croak("Argument to &source must be an array reference");
83             }
84 13         37 $self->{source} = shift;
85 13         48 return $self;
86             }
87              
88             ##############################################################################
89              
90             =head3 C
91              
92             my $stream = $source->get_stream;
93              
94             Returns a stream of the output generated by executing C.
95              
96             =cut
97              
98             sub get_stream {
99 53     53 1 113 my ($self) = @_;
100 53 50       259 my @command = $self->_get_command
101             or $self->_croak("No command found!");
102              
103 53         909 my $stdout_handle = IO::Handle->new();
104              
105 53         2352 my $pid;
106 53         174 eval { $pid = open3( undef, $stdout_handle, undef, @command ); };
  53         418  
107              
108 53 50       503847 if ($@) {
109              
110             # TODO: Need to do something better with the error info here.
111 0         0 $self->exit( $? >> 8 );
112 0         0 $self->error("Could not execute (@command): $!");
113 0         0 return;
114             }
115             else {
116 53 50       1156 if (IS_WIN32) {
117              
118             # open3 defaults to raw mode, need this for Windows. Maybe
119             # other platforms too?
120             # TODO: What was the first perl version that supports this?
121 0         0 binmode $stdout_handle, ':crlf';
122             }
123              
124 53         2235 my $iter = TAPx::Parser::Iterator->new($stdout_handle);
125 53         395 $iter->pid($pid);
126 53         1449 return $iter;
127             }
128             }
129              
130 13     13   21 sub _get_command { @{ shift->source } }
  13         38  
131              
132             ##############################################################################
133              
134             =head3 C
135              
136             unless ( my $stream = $source->get_stream ) {
137             die $source->error;
138             }
139              
140             If a stream cannot be created, this method will return the error.
141              
142             =cut
143              
144             sub error {
145 0     0 1 0 my $self = shift;
146 0 0       0 return $self->{error} unless @_;
147 0         0 $self->{error} = shift;
148 0         0 return $self;
149             }
150              
151             ##############################################################################
152              
153             =head3 C
154              
155             my $exit = $source->exit;
156              
157             Returns the exit status of the process I an error occurs in
158             opening the file.
159              
160             =cut
161              
162             sub exit {
163 0     0 1 0 my $self = shift;
164 0 0       0 return $self->{exit} unless @_;
165 0         0 $self->{exit} = shift;
166 0         0 return $self;
167             }
168              
169             ##############################################################################
170              
171             =head3 C
172              
173             my $pid = $source->pid;
174              
175             Returns the pid of the command being used to execute the tests.
176              
177             =cut
178              
179             sub pid {
180 0     0 1 0 my $self = shift;
181 0 0       0 return $self->{pid} unless @_;
182 0         0 $self->{pid} = shift;
183 0         0 return $self;
184             }
185              
186             # Turns on autoflush for the handle passed
187             sub _autoflush {
188 106     106   172 my $flushed = shift;
189 106         349 my $old_fh = select $flushed;
190 106         253 $| = 1;
191 106         358 select $old_fh;
192             }
193              
194             sub _croak {
195 1     1   2 my $self = shift;
196 1         11 require Carp;
197 1         197 Carp::croak(@_);
198             }
199              
200             1;