File Coverage

blib/lib/Test/CallFlow/ArgCheck.pm
Criterion Covered Total %
statement 21 24 87.5
branch 9 20 45.0
condition 6 8 75.0
subroutine 3 3 100.0
pod 2 2 100.0
total 41 57 71.9


line stmt bran cond sub pod time code
1             package Test::CallFlow::ArgCheck;
2 6     6   40 use strict;
  6         11  
  6         2581  
3              
4             =head1 NAME
5              
6             Test::CallFlow::ArgCheck
7              
8             =head1 SYNOPSIS
9              
10             Abstract base class for mock call argument checkers.
11             Implementors should only need to implement check() below.
12              
13             my $checker = Test::CallFlow::ArgCheck::Regexp->new( test => qr/../, max => 9 );
14             my @args = qw(abc ab a abcd);
15             my $at = 0;
16             $at = $checker->skip_matching( $at, \@args );
17             "@args[$at,]" eq "a abcd" or die "checker failed";
18              
19             =head1 PROPERTIES
20              
21             test whatever child class check() method uses to validate an argument
22             min minimum number of matches, 0 means optional, default 1
23             max maximum number of matches, default same as min.
24              
25             =head1 FUNCTIONS
26              
27             =head2 new
28              
29             my $checker = Test::CallFlow::ArgCheck::SUBCLASS->new( $test, $min, $max );
30              
31             or
32              
33             my $checker = Test::CallFlow::ArgCheck::SUBCLASS->new(
34             test => 'whatever SUBCLASS::check() tests an argument against',
35             min => 0,
36             max => 999,
37             );
38              
39             =cut
40              
41             sub new {
42 6     6 1 14 my $class = shift;
43 6 50       22 $class = ref $class if ref $class;
44 6         8 my %self;
45 6 50       15 if ( ref $_[0] ) {
46 0         0 $self{test} = shift;
47 0 0       0 $self{min} = shift if @_;
48 0 0       0 $self{max} = shift if @_;
49             } else {
50 6         21 %self = @_;
51             }
52              
53 6         88 bless \%self, $class;
54             }
55              
56             =head2 check
57              
58             $checker->check( $at, \@args ) ? 1 : undef;
59              
60             Should be implemented in an inherited class to
61             return a boolean result of comparing a single argument against value of C property.
62              
63             =head2 skip_matching
64              
65             die "Mismatch at $at" unless defined
66             $at = $checker->skip_matching( $at, \@args );
67              
68             If arguments on beginning of given list match requirements (test, range) of this checker,
69             new index is returned.
70              
71             Otherwise returns -1 - position of failed argument.
72              
73             =cut
74              
75             sub skip_matching {
76 19     19 1 24 my ( $self, $at, $args ) = @_;
77 19 50       64 my $min = defined $self->{min} ? $self->{min} : 1;
78 19 50       54 my $max = defined $self->{max} ? $self->{max} : $min;
79 19         29 my $matched = 0;
80 19 50       55 my $debug = exists $ENV{DEBUG} and $ENV{DEBUG} =~ /\bArgCheck\b/;
81 19         20 my $len = @$args;
82 19         18 my $match;
83              
84 19   100     20 do {
      100        
85 24         83 $match = $self->check( $at++, $args );
86 24 50 0     957 warn "$self at $at/$len, matched $matched/$min-$max '$args->[$at]': ",
87             ( $match || 'mismatch' )
88             if $debug;
89             } while ( $match and ++$matched < $max and $at < $len );
90              
91 19 50       38 warn "$self end at $at/$len, matched $matched/$min-$max" if $debug;
92 19 100       115 return $matched < $min ? -$at : $at;
93             }
94              
95             1;