File Coverage

blib/lib/Test/CallFlow/Call.pm
Criterion Covered Total %
statement 80 86 93.0
branch 44 62 70.9
condition 15 22 68.1
subroutine 18 19 94.7
pod 15 15 100.0
total 172 204 84.3


line stmt bran cond sub pod time code
1             package Test::CallFlow::Call;
2 6     6   35 use strict;
  6         12  
  6         259  
3 6     6   36 use UNIVERSAL qw(isa);
  6         11  
  6         36  
4 6     6   7406 use Carp;
  6         17  
  6         14183  
5              
6             =head1 Test::CallFlow::Call
7              
8             =head1 SYNOPSIS
9              
10             my $call = Test::CallFlow::Call->new( args => [ 'My::Pkg::Method', 'an argument' ] )->result(12765);
11              
12             my @mismatch = $call->check( 'My::Pkg::Method', 'an argument' )
13             and die "Argument #$mismatch[0] did not match check #$mismatch[1]\n";
14              
15             my $result = $call->call; # returns 12765
16              
17             print "Enough calls made\n" if $call->satisfied;
18             print "No more calls could be made\n" if $call->over;
19              
20             =head1 PROPERTIES
21              
22             =over 4
23              
24             =item args
25              
26             [ 'Package::Method', "static argument", ... ]
27              
28             Reference to an array containing full method name and argument checkers:
29             static values to compare against or Test::CallFlow:ArgCheck subclasses to use for comparison.
30              
31             =item results
32              
33             [ [ 'first result' ], [ 'second result' ], [ 'result for any subsequent calls' ] ]
34              
35             Reference to an array of arrays, each containing the result returned from a call to this mock.
36              
37             =item min
38              
39             Minimum number of calls required for this call to be satisfied.
40              
41             =item max
42              
43             Maximum number of calls to allow.
44              
45             =item called
46              
47             Number of times this call has been made.
48              
49             =item anytime
50              
51             When true, this call may be made any time rather than at a specific step.
52              
53             =item debug
54              
55             When true, some helpful messages are printed.
56              
57             =back
58              
59             =head1 METHODS
60              
61             =head2 new
62              
63             my $call = Test::CallFlow::Call->new(
64             args => [
65             'full::sub_name',
66             qw(arguments to match),
67             Test::CallFlow::ArgCheck::Regexp->new( qr/arg regex/ )
68             ]
69             );
70              
71             Returns a new C with given properties.
72              
73             =cut
74              
75             sub new {
76 12     12 1 471 my ( $class, %self ) = @_;
77 12         48 bless \%self, $class;
78             }
79              
80             =head2 result
81              
82             $call = $call->result( 'foo', 'bar', 'baz', 'quu' );
83              
84             Adds a result for a call.
85             Multiple values will be returned as an array in array context.
86             Multiple result sets can be defined for a repeated call.
87              
88             Returns self.
89              
90             =cut
91              
92             sub result {
93 5     5 1 12 my ( $self, @values ) = @_;
94 5   100     10 push @{ $self->{results} ||= [] }, \@values;
  5         36  
95 5 50       16 warn "Add result to ", $self->name() if $self->{debug};
96 5         22 $self;
97             }
98              
99             =head2 result_from
100              
101             $call = $call->result_from( \&result_provider_sub );
102              
103             Adds a result provider for a call.
104              
105             A result provider will be called whenever a result is required.
106             It will get as parameters the original call.
107              
108             Returns self.
109              
110             =cut
111              
112             sub result_from {
113 0     0 1 0 my ( $self, $coderef ) = @_;
114 0   0     0 push @{ $self->{results} ||= [] }, $coderef;
  0         0  
115 0 0       0 warn "Add result provider to ", $self->name() if $self->{debug};
116 0         0 $self;
117             }
118              
119             =head2 anytime
120              
121             Causes this call to be callable at any time after its declaration, rather than at that exact point in call order.
122              
123             Returns self.
124              
125             =cut
126              
127             sub anytime {
128 3     3 1 10 $_[0]->{anytime} = 1;
129 3         10 $_[0];
130             }
131              
132             =head2 min
133              
134             $call->min(0)->max(2);
135             die "must be called" if $call->min;
136              
137             When called with a value, set minimum number of calls required to given value and return self.
138             When called without a value, returns the current minimum number of calls; default is number of specified results.
139              
140             =cut
141              
142             sub min {
143 123     123 1 156 my $self = shift;
144 123 100       288 if (@_) {
145 3         10 $self->{min} = shift;
146 3         43 return $self;
147             }
148              
149             defined( $self->{min} )
150             ? $self->{min}
151 120 100 100     811 : ( @{ $self->{results} || [] } || 1 ); # default to single void call
152             }
153              
154             =head2 max
155              
156             $call->max(2)->min(0);
157             die "no results available" unless $call->max;
158              
159             When called with a value, set maximum number of calls possible and return self.
160             When called without a value, returns the current maximum number of calls.
161             Default is 1 or bigger of minimum and number of results.
162              
163             =cut
164              
165             sub max {
166 95     95 1 118 my $self = shift;
167 95 100       206 if (@_) {
168 4         10 $self->{max} = shift;
169 4         13 return $self;
170             }
171 91 100       688 return $self->{max} if defined $self->{max};
172              
173 69 100       74 my $results = @{ $self->{results} || [] };
  69         276  
174 69         153 my $min = $self->min;
175 69 50       760 ( $results > $min ? $results : $min ) || 1;
    100          
176             }
177              
178             =head2 end
179              
180             mock_package( 'Foo' );
181             my @optionals = (
182             Foo->get->anytime->min(0),
183             Foo->set->anytime
184             );
185             Foo->may_be_called->min(0); # ordered, skipped unless called
186             Foo->shall_be_called->end( @optionals ); # will croak about uncalled Foo->set
187              
188             Given calls that could be made at any time are no more callable.
189             If any of them are uncalled when this call is matched, optional ones are discarded silently, required ones cause dying with stack trace in L.
190              
191             Returns self.
192              
193             =cut
194              
195             sub end {
196 1     1 1 3 my ( $self, @end ) = @_;
197 1   50     2 push @{ $self->{end} ||= [] }, @end;
  1         24  
198 1 50       4 warn $self->name, " planned to end @{$self->{end}}" if $self->{debug};
  0         0  
199 1         3 $self;
200             }
201              
202             =head2 satisfied
203              
204             die "Not enough calls made" unless $call->satisfied;
205              
206             Returns true when enough calls have been made.
207              
208             =cut
209              
210             sub satisfied {
211 45     45 1 63 my $self = shift;
212 45 50 0     885 warn $self->name, " satisfied = ", ( $self->{called} || 0 ), " >= ",
213             $self->min
214             if $self->{debug};
215 45   100     281 ( $self->{called} || 0 ) >= $self->min;
216             }
217              
218             =head2 over
219              
220             die "No more calls can be made" if $call->over;
221              
222             Returns true when no more calls can be made.
223              
224             =cut
225              
226             sub over {
227 65     65 1 82 my $self = shift;
228 65   100     611 ( $self->{called} || 0 ) >= $self->max;
229             }
230              
231             =head2 in_order
232              
233             Returns true if this call must be made in order, false if it can be made at any time.
234              
235             =cut
236              
237             sub in_order {
238 64     64 1 480 !$_[0]->{anytime};
239             }
240              
241             =head2 check
242              
243             die "Arg #$arg failed to match arg check #$check"
244             if my ($arg, $check) =
245             $call->check( [ $sub, @args ] );
246              
247             Returns nothing on success.
248             On failure, returns position of failed argument and position of the test it failed against.
249              
250             =cut
251              
252             sub check {
253 72     72 1 111 my ( $self, $args ) = @_;
254 72   50     184 my $arg_tests = $self->{args} || [];
255 72         94 my $test_at = 0;
256 72         86 my $args_at = 0;
257              
258 72   100     88 do {
259 138         220 my $check = $arg_tests->[$test_at];
260 138         705 my $arg = $args->[$args_at];
261              
262 138 50       301 warn
263             "Check argument #$args_at '$arg' of (@$args) against test #$test_at '$check'"
264             if $self->{debug};
265              
266 138 0 66     3550 $args_at = !defined $check
    100          
    100          
    50          
267             ? (
268             !defined $arg
269             ? $args_at + 1 # undef matches undef
270             : -1 - $args_at # should have been undef
271             )
272             : isa( $check, 'Test::CallFlow::ArgCheck' )
273             ? $check->skip_matching( $args_at, $args ) # returns new position
274             : ( defined $args->[$args_at] and $check eq $args->[$args_at] )
275             ? $args_at + 1 # scalars match
276             : -1 - $args_at # undef or mismatching scalar
277              
278             } while ( $args_at > 0 and ++$test_at < @$arg_tests );
279              
280 72 100       548 my @result =
    100          
281             $args_at < @$args
282             ? ( ( $args_at < 0 ? -$args_at - 1 : $args_at ), $test_at )
283             : ();
284              
285 72 0       330 warn "Check ", $self->name(), " at $args_at ",
    50          
286             ( @result ? " mismatch: @result" : " ok" ), "\n"
287             if $self->{debug};
288              
289 72         1086 @result;
290             }
291              
292             =head2 call
293              
294             my $result = $call->call;
295              
296             Returns next result of this call, nothing if result not set.
297              
298             Dies if call has been executed more than maximum times.
299              
300             =cut
301              
302             sub call {
303 26     26 1 39 my $self = shift;
304 26         312 $self->{called_from} = shift;
305 26 50       273 die $self->name, " called too many times ($self->{called} > ", $self->max,
306             ")\n"
307             if ++$self->{called} > $self->max;
308 26 50       69 warn $self->name, " called $self->{called} times" if $self->{debug};
309             return
310 26 100       298 unless my $results = @{ $self->{results} || [] };
  26 100       161  
311 13 100       42 my $at = $self->{called} < $results ? $self->{called} : $results;
312 13         237 return $self->{results}[ $at - 1 ];
313             }
314              
315             =head2 called_from
316              
317             $call->called_from( "subname" );
318              
319             Sets calling context reported by C.
320              
321             Returns self.
322              
323             =cut
324              
325             sub called_from {
326 1     1 1 2 my $self = shift;
327 1         3 $self->{called_from} = shift;
328 1         3 $self;
329             }
330              
331             =head2 name
332              
333             print "Calling ", $call->name, "\n";
334              
335             Returns a user-readable representation of this call.
336              
337             =cut
338              
339             sub name {
340 13     13 1 24 my $self = shift;
341 13 50       20 my ( $name, @args ) = @{ $self->{args} || [] };
  13         65  
342 13 100       73 $name .= _list_to_string(@args) if @args;
343 3 50       16 $name .= "->result"
344             . join "->result",
345 3         7 map { ref $_ eq 'CODE' ? "_from( \\\&{'$_'} )" : _list_to_string(@$_) }
346 13 100       55 @{ $self->{results} }
347             if $self->{results};
348 13 100       42 $name .= "->called_from('$self->{called_from}')"
349             if defined $self->{called_from};
350 13         1360 $name;
351             }
352              
353             sub _list_to_string {
354 15     15   31 "(" . join( ", ", map { "'$_'" } @_ ) . ")";
  35         420  
355             }
356              
357             =head2 reset
358              
359             $call->reset;
360              
361             Resets the call object to pre-run state.
362              
363             =cut
364              
365             sub reset {
366 26     26 1 33 my $self = shift;
367 26 50       384 warn "Reset ", $self->name if $self->{debug};
368 26         291 delete $self->{called};
369             }
370              
371             1;