File Coverage

blib/lib/Test/MockCommand/TiedFH.pm
Criterion Covered Total %
statement 27 77 35.0
branch 6 32 18.7
condition n/a
subroutine 7 14 50.0
pod n/a
total 40 123 32.5


line stmt bran cond sub pod time code
1             package Test::MockCommand::TiedFH;
2 18     18   95 use strict;
  18         30  
  18         425  
3 18     18   71 use warnings;
  18         28  
  18         376  
4 18     18   6623 use Errno qw(ESPIPE);
  18         20002  
  18         1550  
5              
6 18     18   6266 use Test::MockCommand::ScalarReadline qw(scalar_readline);
  18         37  
  18         13245  
7              
8             require Tie::Handle;
9             our @ISA = qw(Tie::Handle);
10              
11             sub TIEHANDLE {
12 29     29   221 my $class = shift;
13              
14 29         754 my $self = {
15             recording => $_[0], # 1 if recording, 0 if playing back
16             fh => $_[1], # real filehandle to open() [record mode only]
17             result => $_[2], # object to store/retrieve results
18             offset => 0, # offset in command output [playback only]
19             unique => 0, # have we found a unique result? [playback only]
20             input => '', # input data collected [playback only]
21             };
22 29         243 return bless $self, $class;
23             }
24              
25             # WRITE($buffer, $length, $offset)
26             sub WRITE {
27 0     0   0 my $self = shift;
28             # recording mode: append this data as input, pass it on to the command
29 0 0       0 if ($self->{recording}) {
30 0         0 $self->{result}->append_input_data(substr($_[0], $_[2], $_[1]));
31 0         0 return syswrite($self->{fh}, $_[0], $_[1], $_[2]);
32             }
33              
34             # playback mode
35              
36             # if we haven't pinned down a result yet, collect the input
37             # written to us and look through all possible results
38 0 0       0 if (! $self->{unique}) {
39 0         0 $self->{input} .= substr($_[0], $_[2], $_[1]);
40 0         0 my $count = 0;
41 0         0 my $matched = undef;
42 0         0 for my $result (@{$self->{result}->all_results()}) {
  0         0  
43             next unless substr($result->input_data(), 0,
44 0 0       0 length $self->{input}) eq $self->{input};
45 0         0 $matched = $result;
46 0         0 $count++;
47             }
48              
49             # if what we have for input so far uniquely matches the input
50             # of one of the results, switch over to using that result.
51 0 0       0 if ($count == 1) {
52 0         0 $self->{result} = $matched;
53 0         0 $self->{unique} = 1;
54             }
55              
56             # if none of the results match the input we have so far, trouble
57 0 0       0 if ($count == 0) {
58 0         0 my $cmd = $self->{result}->command();
59 0         0 warn "current input to \"$cmd\" doesn't match any previous result";
60 0         0 $self->{unique} = 1;
61             }
62             }
63            
64             # return number of bytes 'written' (e.g. the length)
65 0         0 return $_[1];
66             }
67              
68             # READ($buffer, $length, $offset)
69             sub READ {
70 0     0   0 my $self = shift;
71              
72             # recording mode
73 0 0       0 if ($self->{recording}) {
74 0         0 my $read = sysread($self->{fh}, $_[0], $_[1], $_[2]);
75 0 0       0 return undef unless defined $read;
76 0         0 $self->{result}->append_output_data(substr($_[0], $_[2], $read));
77 0         0 return $read;
78             }
79              
80             # playback mode
81              
82             # determine how many bytes are requested vs how many are available
83 0         0 my $avail = length($self->{result}->output_data()) - $self->{offset};
84 0 0       0 my $len = ($_[1] < $avail) ? $_[1] : $avail;
85              
86             # write the output data into the requested buffer
87             substr($_[0], $_[2], $len, substr($self->{result}->output_data(),
88 0         0 $self->{offset}, $len));
89 0         0 $self->{offset} += $len;
90 0         0 return $len;
91             }
92              
93             sub READLINE {
94 27     27   288 my $self = shift;
95              
96             # recording mode
97 27 100       207 if ($self->{recording}) {
98 14 50       51 if (wantarray()) {
99 14         809 my @lines = readline $self->{fh};
100 14         151 $self->{result}->append_output_data(join '', @lines);
101 14         126 return @lines;
102             }
103             else {
104 0         0 my $line = readline $self->{fh};
105 0 0       0 $self->{result}->append_output_data($line) if defined $line;
106 0         0 return $line;
107             }
108             }
109              
110             # playback mode
111 13 50       48 if (wantarray()) {
112             my @lines = scalar_readline(substr($self->{result}->output_data(),
113 13         81 $self->{offset}));
114             # everything now read; move the offset to the end of the output data
115 13         83 $self->{offset} = length $self->{result}->output_data();
116 13         101 return @lines;
117             }
118             else {
119 0         0 my $length = undef;
120             my $line = scalar_readline(substr($self->{result}->output_data(),
121 0         0 $self->{offset}), $length);
122 0         0 $self->{offset} += $length;
123 0         0 return $line;
124             }
125             }
126              
127             sub CLOSE {
128 29     29   207 my $self = shift;
129 29 100       525 return $self->{recording} ? close($self->{fh}) : 1;
130             }
131              
132             sub EOF {
133 0     0     my $self = shift;
134 0 0         return eof $self->{fh} if $self->{recording};
135 0           return $self->{offset} >= length($self->{result}->output_data());
136             }
137              
138             sub TELL {
139 0     0     $! = ESPIPE;
140 0           return -1;
141             }
142              
143             sub SEEK {
144 0     0     $! = ESPIPE;
145 0           return '';
146             }
147              
148             sub FILENO {
149 0     0     my $self = shift;
150 0 0         return $self->{recording} ? fileno($self->{fh}) : -1;
151             }
152              
153             sub BINMODE {
154 0     0     my $self = shift;
155 0 0         binmode($self->{fh}) if $self->{recording};
156             }
157              
158             1;
159              
160             __END__