File Coverage

blib/lib/Test2/Harness/Proc.pm
Criterion Covered Total %
statement 77 87 88.5
branch 22 34 64.7
condition 5 6 83.3
subroutine 16 17 94.1
pod 5 10 50.0
total 125 154 81.1


line stmt bran cond sub pod time code
1             package Test2::Harness::Proc;
2 26     26   246842 use strict;
  26         26  
  26         500  
3 26     26   77 use warnings;
  26         26  
  26         683  
4              
5             our $VERSION = '0.000013';
6              
7 26     26   11757 use IO::Handle;
  26         112470  
  26         934  
8 26     26   104 use Carp qw/croak/;
  26         30  
  26         838  
9 26     26   10305 use POSIX qw/:sys_wait_h/;
  26         106355  
  26         105  
10              
11 26     26   22525 use Test2::Util::HashBase qw/file pid in_fh out_fh err_fh exit lines idx/;
  26         28  
  26         121  
12              
13             sub init {
14 631     631 0 239653 my $self = shift;
15              
16 631         3327 for my $thing (PID(), IN_FH(), OUT_FH(), FILE()) {
17 2500 100       6524 next if $self->{$thing};
18 16         1948 croak "'$thing' is a required attribute";
19             }
20              
21 615         819 for my $fh (@{$self}{OUT_FH(), ERR_FH()}) {
  615         1447  
22 1230 100       2402 next unless $fh;
23 1226         4627 $fh->blocking(0);
24             }
25              
26 615         10331 $self->{+LINES} = {
27             stderr => [],
28             stdout => [],
29             muxed => [],
30             };
31             }
32              
33             sub encoding {
34 327     327 1 1277 my $self = shift;
35 327         525 my ($enc) = @_;
36              
37             # https://rt.perl.org/Public/Bug/Display.html?id=31923
38             # If utf8 is requested we use ':utf8' instead of ':encoding(utf8)' in
39             # order to avoid the thread segfault.
40 327 50       2332 if ($enc =~ m/^utf-?8$/i) {
41 327         1074 binmode($_, ":utf8") for grep {$_} @{$self}{qw/out_fh err_fh in_fh/};
  981         4336  
  327         724  
42             }
43             else {
44 0         0 binmode($_, ":encoding($enc)") for grep {$_} @{$self}{qw/out_fh err_fh in_fh/};
  0         0  
  0         0  
45             }
46             }
47              
48             sub is_done {
49 29509     29509 1 79545 my $self = shift;
50              
51 29509         51071 $self->wait(WNOHANG);
52              
53 29509 100       63084 return 1 if defined $self->{+EXIT};
54 24249         45646 return 0;
55             }
56              
57             sub wait {
58 29511     29511 0 24990 my $self = shift;
59 29511         26687 my ($flags) = @_;
60              
61 29511 100       52144 return if defined $self->{+EXIT};
62              
63 24856 50       38549 my $pid = $self->{+PID} or die "No PID";
64 24856   100     1385668 my $ret = waitpid($pid, $flags || 0);
65 24856         38901 my $exit = $?;
66              
67 24856 100       45453 return if $ret == 0;
68 607 50       2202 die "Process $pid was already reaped!" if $ret == -1;
69              
70 607         734 $exit >>= 8;
71 607         4708 $self->{+EXIT} = $exit;
72              
73 607         1234 return;
74             }
75              
76             sub force_kill {
77 0     0 0 0 my $self = shift;
78              
79 0 0       0 my $pid = $self->{+PID} or die "No PID";
80 0 0       0 kill('INT', $pid) or die "Could not signal process";
81 0         0 $self->{+EXIT} = -1;
82 0         0 for (1 .. 5) {
83 0 0       0 $self->wait(WNOHANG) and last;
84 0 0       0 sleep 1 unless $_ >= 5;
85             }
86             }
87              
88             sub write {
89 6     6 1 13 my $self = shift;
90 6         17 my $fh = $self->{+IN_FH};
91 6         121 print $fh @_;
92             }
93              
94             sub seen_out_lines {
95 2     2 0 6 my $self = shift;
96 2         3 return @{$self->{+LINES}->{stdout}};
  2         12  
97             }
98              
99             sub seen_err_lines {
100 2     2 0 4 my $self = shift;
101 2         5 return @{$self->{+LINES}->{stderr}};
  2         14  
102             }
103              
104             sub get_out_line {
105 41586     41586 1 133525 my $self = shift;
106 41586         93883 return $self->_get_line_for(OUT_FH(), 'stdout', @_);
107             }
108              
109             sub get_err_line {
110 24830     24830 1 463226 my $self = shift;
111 24830         45820 return $self->_get_line_for(ERR_FH(), 'stderr', @_);
112             }
113              
114             sub _get_line_for {
115 66416     66416   48649 my $self = shift;
116 66416         94401 my ($io_name, $stash_name, %params) = @_;
117              
118 66416   50     123406 my $stash = $self->{+LINES}->{$stash_name} ||= [];
119 66416         76745 my $idx = \($self->{+IDX}->{$stash_name});
120 66416   100     140932 $$idx ||= 0;
121              
122 66416 100       101043 if (@$stash > $$idx) {
123 2791         3648 my $line = $stash->[$$idx];
124 2791 100       5776 $$idx++ unless $params{peek};
125 2791         8746 return $line;
126             }
127              
128 63625 50       105871 my $h = $self->{$io_name} or return;
129              
130 63625         125611 seek($h,0,1);
131 63625         209184 my $line = <$h>;
132 63625 100       223956 return unless defined $line;
133              
134 20281         40833 push @$stash => $line;
135              
136 20281 100       32445 $$idx++ unless $params{peek};
137              
138 20281         61969 return $line;
139             }
140              
141             1;
142              
143             __END__