File Coverage

blib/lib/Test/Future/IO.pm
Criterion Covered Total %
statement 35 39 89.7
branch 2 4 50.0
condition n/a
subroutine 12 12 100.0
pod 2 7 28.5
total 51 62 82.2


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2020-2022 -- leonerd@leonerd.org.uk
5              
6             package Test::Future::IO;
7              
8 4     4   187343 use strict;
  4         20  
  4         98  
9 4     4   17 use warnings;
  4         7  
  4         121  
10              
11             our $VERSION = '0.04';
12              
13 4     4   18 use Carp;
  4         6  
  4         189  
14              
15 4     4   1626 use Test::ExpectAndCheck::Future 0.04; # ->will_* API
  4         100533  
  4         91  
16 4     4   23 use Test::Deep ();
  4         6  
  4         1340  
17              
18             =head1 NAME
19              
20             C - unit testing on C
21              
22             =head1 SYNOPSIS
23              
24             use Test::More;
25             use Test::Future::IO;
26              
27             my $controller = Test::Future::IO->controller;
28              
29             {
30             $controller->expect_syswrite( "Hello, world\n" );
31             $controller->expect_sysread( 256 )
32             ->will_done( "A string\n");
33              
34             code_under_test();
35              
36             $controller->check_and_clear( 'code under test did correct IO' );
37             }
38              
39             =head1 DESCRIPTION
40              
41             This package provides a means to apply unit testing around code which uses
42             L. It operates in an "expect-and-check" style of mocking,
43             requiring the test script to declare upfront what methods are expected to be
44             called, and what values they return.
45              
46             =cut
47              
48             =head1 EXPECTATIONS
49              
50             Each of the actual C methods has a corresponding expectation
51             method on the controller object, whose name is prefixed with C. A
52             single call to one of these methods by the unit test script represents a
53             single call to a C method that the code under test is expected to
54             make. The arguments to the expectation method should match those given by the
55             code under test. Each expectation method returns an object which has
56             additional methods to control the behaviour of that invocation.
57              
58             $exp = $controller->expect_sleep( $secs );
59              
60             $exp = $controller->expect_sysread( $fh, $len );
61             $exp = $controller->expect_syswrite( $fh, $bytes );
62              
63             $exp = $controller->expect_sysread_anyfh( $len );
64             $exp = $controller->expect_syswrite_anyfh( $bytes );
65              
66             The returned expectation object allows the test script to specify what such an
67             invocation should return.
68              
69             $exp->will_done( @result );
70              
71             Expectations can make methods fail instead.
72              
73             $exp->will_fail( $message );
74             $exp->will_fail( $message, $category, @details );
75              
76             Expectations can be set to remain pending rather than completing.
77              
78             $exp->remains_pending;
79              
80             As a convenience, a C expectation will default to returning a future
81             that will complete yielding its length (as is usual for successful writes),
82             and a C expectation will return a future that completes yielding
83             nothing.
84              
85             =cut
86              
87             my ( $controller, $obj ) = Test::ExpectAndCheck::Future->create;
88              
89             require Future::IO;
90             Future::IO->override_impl( $obj );
91              
92             sub expect_sleep
93             {
94 3     3 0 10783 my $self = shift;
95 3         5 my ( $secs ) = @_;
96              
97 3         11 return $controller->expect( sleep => $secs )
98             ->will_done();
99             }
100              
101             sub expect_sysread
102             {
103 1     1 0 1471 my $self = shift;
104 1         3 my ( $fh, $len ) = @_;
105 1 50       4 if( @_ == 1 ) {
106 0         0 carp "->expect_sysread with one argument is now deprecated";
107 0         0 ( $fh, $len ) = ( Test::Deep::ignore(), @_ );
108             }
109              
110 1         5 return $controller->expect( sysread => $fh, $len );
111             }
112              
113             sub expect_syswrite
114             {
115 1     1 0 1445 my $self = shift;
116 1         3 my ( $fh, $bytes ) = @_;
117 1 50       4 if( @_ == 1 ) {
118 0         0 carp "->expect_syswrite with one argument is now deprecated";
119 0         0 ( $fh, $bytes ) = ( Test::Deep::ignore(), @_ );
120             }
121              
122 1         6 return $controller->expect( syswrite => $fh, $bytes )
123             ->will_done( length $bytes );
124             }
125              
126             sub expect_sysread_anyfh
127             {
128 1     1 0 1409 my $self = shift;
129 1         5 $self->expect_sysread( Test::Deep::ignore() => @_ );
130             }
131              
132             sub expect_syswrite_anyfh
133             {
134 1     1 0 1322 my $self = shift;
135 1         4 $self->expect_syswrite( Test::Deep::ignore() => @_ );
136             }
137              
138             =head1 METHODS
139              
140             =cut
141              
142             =head2 controller
143              
144             $controller = Test::Future::IO->controller;
145              
146             Returns the control object, on which the various C methods and
147             C can be invoked.
148              
149             =cut
150              
151 3     3 1 205 sub controller { __PACKAGE__ }
152              
153             =head2 check_and_clear
154              
155             $controller->check_and_clear( $name );
156              
157             Checks that by now, every expected method has been called, and emits a new
158             test output line via L. Regardless, the expectations are also
159             cleared out ready for the start of the next test.
160              
161             =cut
162              
163             sub check_and_clear
164             {
165 6     6 1 28622 shift;
166 6         13 my ( $name ) = @_;
167              
168 6         24 local $Test::Builder::Level = $Test::Builder::Level + 1;
169 6         26 $controller->check_and_clear( $name );
170             }
171              
172             =head1 TODO
173              
174             =over 4
175              
176             =item *
177              
178             Configurable matching on filehandles. Provision of a mock filehandle object to
179             assist unit tests.
180              
181             =back
182              
183             =head1 AUTHOR
184              
185             Paul Evans
186              
187             =cut
188              
189             0x55AA;