File Coverage

blib/lib/Test/Future/IO.pm
Criterion Covered Total %
statement 26 26 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod 2 5 40.0
total 37 40 92.5


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 -- leonerd@leonerd.org.uk
5              
6             package Test::Future::IO;
7              
8 4     4   235676 use strict;
  4         29  
  4         126  
9 4     4   22 use warnings;
  4         8  
  4         197  
10              
11             our $VERSION = '0.03';
12              
13 4     4   2100 use Test::ExpectAndCheck::Future;
  4         119390  
  4         141  
14 4     4   33 use Test::Deep ();
  4         10  
  4         1038  
15              
16             =head1 NAME
17              
18             C - unit testing on C
19              
20             =head1 SYNOPSIS
21              
22             use Test::More;
23             use Test::Future::IO;
24              
25             my $controller = Test::Future::IO->controller;
26              
27             {
28             $controller->expect_syswrite( "Hello, world\n" );
29             $controller->expect_sysread( 256 )
30             ->returns( "A string\n");
31              
32             code_under_test();
33              
34             $controller->check_and_clear( 'code under test did correct IO' );
35             }
36              
37             =head1 DESCRIPTION
38              
39             This package provides a means to apply unit testing around code which uses
40             L. It operates in an "expect-and-check" style of mocking,
41             requiring the test script to declare upfront what methods are expected to be
42             called, and what values they return.
43              
44             =cut
45              
46             =head1 EXPECTATIONS
47              
48             Each of the actual C methods has a corresponding expectation
49             method on the controller object, whose name is prefixed with C. A
50             single call to one of these methods by the unit test script represents a
51             single call to a C method that the code under test is expected to
52             make. The arguments to the expectation method should match those given by the
53             code under test. Each expectation method returns an object which has
54             additional methods to control the behaviour of that invocation.
55              
56             $exp = $controller->expect_sleep( $secs )
57              
58             $exp = $controller->expect_sysread( $len )
59             $exp = $controller->expect_syswrite( $bytes )
60              
61             Note that the C and C expectations currently ignore the
62             filehandle argument. This behaviour B be changed in a future version. To
63             keep this behaviour use the following methods instead:
64              
65             $exp = $controller->expect_sysread_anyfh( $len )
66             $exp = $controller->expect_syswrite_anyfh( $bytes )
67              
68             The returned expectation object allows the test script to specify what such an
69             invocation should return.
70              
71             $exp->returns( @result )
72              
73             Expectations can make methods fail instead.
74              
75             $exp->fails( $message )
76             $exp->fails( $message, $category, @details )
77              
78             =cut
79              
80             my ( $controller, $obj ) = Test::ExpectAndCheck::Future->create;
81              
82             require Future::IO;
83             Future::IO->override_impl( $obj );
84              
85             sub expect_sleep
86             {
87 3     3 0 14778 my $self = shift;
88 3         10 my ( $secs ) = @_;
89              
90 3         30 return $controller->expect( sleep => $secs );
91             }
92              
93             sub expect_sysread
94             {
95 1     1 0 1645 my $self = shift;
96 1         4 my ( $len ) = @_;
97              
98 1         4 return $controller->expect( sysread => Test::Deep::ignore(), $len );
99             }
100              
101             *expect_sysread_anyfh = \&expect_sysread;
102              
103             sub expect_syswrite
104             {
105 1     1 0 1775 my $self = shift;
106 1         3 my ( $bytes ) = @_;
107              
108 1         7 return $controller->expect( syswrite => Test::Deep::ignore(), $bytes )
109             ->returns( length $bytes );
110             }
111              
112             *expect_syswrite_anyfh = \&expect_syswrite;
113              
114             =head1 METHODS
115              
116             =cut
117              
118             =head2 controller
119              
120             $controller = Test::Future::IO->controller;
121              
122             Returns the control object, on which the various C methods and
123             C can be invoked.
124              
125             =cut
126              
127 3     3 1 287 sub controller { __PACKAGE__ }
128              
129             =head2 check_and_clear
130              
131             $controller->check_and_clear( $name );
132              
133             Checks that by now, every expected method has been called, and emits a new
134             test output line via L. Regardless, the expectations are also
135             cleared out ready for the start of the next test.
136              
137             =cut
138              
139             sub check_and_clear
140             {
141 6     6 1 42414 shift;
142 6         24 my ( $name ) = @_;
143              
144 6         19 local $Test::Builder::Level = $Test::Builder::Level + 1;
145 6         40 $controller->check_and_clear( $name );
146             }
147              
148             =head1 TODO
149              
150             =over 4
151              
152             =item *
153              
154             Configurable matching on filehandles. Provision of a mock filehandle object to
155             assist unit tests.
156              
157             =back
158              
159             =head1 AUTHOR
160              
161             Paul Evans
162              
163             =cut
164              
165             0x55AA;