File Coverage

blib/lib/DBD/Mock/Session.pm
Criterion Covered Total %
statement 81 82 98.7
branch 33 34 97.0
condition 25 27 92.5
subroutine 17 17 100.0
pod 0 8 0.0
total 156 168 92.8


line stmt bran cond sub pod time code
1             package DBD::Mock::Session;
2              
3 40     40   275 use strict;
  40         83  
  40         1143  
4 40     40   194 use warnings;
  40         77  
  40         42069  
5              
6             my $INSTANCE_COUNT = 1;
7              
8             # - Class - #
9              
10             sub new {
11 35     35 0 12363 my $class = shift;
12 35 100       120 my $name = ref( $_[0] ) ? "Session $INSTANCE_COUNT" : shift;
13 35         61 $INSTANCE_COUNT++;
14              
15 35         454 $class->_verify_states( $name, @_ );
16              
17 26         172 bless {
18             name => $name,
19             states => \@_,
20             state_index => 0
21             }, $class;
22             }
23              
24             sub _verify_state {
25 55     55   119 my ( $class, $state, $index, $name ) = @_;
26              
27 55 100       151 die "You must specify session states as HASH refs"
28             if ref($state) ne 'HASH';
29              
30             die "Bad state '$index' in DBD::Mock::Session ($name)"
31             if not exists $state->{statement}
32 52 100 100     305 or not exists $state->{results};
33              
34 49         88 my $stmt = $state->{statement};
35 49         80 my $ref = ref $stmt;
36              
37 49 100 100     201 die "Bad 'statement' value '$stmt' in DBD::Mock::Session ($name)",
      100        
38             if ref($stmt) ne ''
39             and $ref ne 'CODE'
40             and $ref ne 'Regexp';
41             }
42              
43             sub _verify_states {
44 35     35   104 my ( $class, $name, @states ) = @_;
45              
46 35 100       198 die "You must specify at least one session state"
47             if scalar @states == 0;
48              
49 33         155 for ( 0 .. scalar @states - 1 ) {
50 55         179 $class->_verify_state( $states[$_], $_, $name );
51             }
52             }
53              
54             # - Instance - #
55              
56             sub name {
57 6     6 0 2348 my $self = shift;
58 6         38 $self->{name};
59             }
60              
61             sub reset {
62 1     1 0 911 my $self = shift;
63 1         3 $self->{state_index} = 0;
64             }
65              
66             sub current_state {
67 138     138 0 776 my $self = shift;
68 138         185 my $idx = $self->{state_index};
69 138         241 return $self->{states}[$idx];
70             }
71              
72             sub has_states_left {
73 66     66 0 122 my $self = shift;
74 66         151 return $self->{state_index} < $self->_num_states;
75             }
76              
77             sub verify_statement {
78 52     52 0 120 my ( $self, $got ) = @_;
79              
80 52 100       108 unless ( $self->has_states_left ) {
81 6         16 die "Session states exhausted, only '"
82             . $self->_num_states
83             . "' in DBD::Mock::Session ($self->name})";
84             }
85              
86 46         102 my $state = $self->current_state;
87 46         93 my $expected = $state->{statement};
88 46         80 my $ref = ref($expected);
89              
90 46 100 100     190 if ( $ref eq 'Regexp' and $got !~ /$expected/ ) {
91 1         16 die "Statement does not match current state (with Regexp) in "
92             . "DBD::Mock::Session ($self->{name})\n"
93             . " got: $got\n"
94             . " expected: $expected",
95              
96             }
97              
98 45 100 100     151 if ( $ref eq 'CODE' and not $expected->( $got, $state ) ) {
99 1         16 die "Statement does not match current state (with CODE ref) in "
100             . "DBD::Mock::Session ($self->{name})";
101             }
102              
103 44 100 100     254 if ( not $ref and $got ne $expected ) {
104 1         14 die "Statement does not match current state in "
105             . "DBD::Mock::Session ($self->{name})\n"
106             . " got: $got\n"
107             . " expected: $expected";
108             }
109             }
110              
111             sub results_for {
112 46     46 0 108 my ( $self, $statment ) = @_;
113 46         117 $self->_find_state_for($statment)->{results};
114             }
115              
116             sub verify_bound_params {
117 43     43 0 80 my ( $self, $params ) = @_;
118              
119 43         86 my $current_state = $self->current_state;
120 43 100       67 if ( exists ${$current_state}{bound_params} ) {
  43         115  
121 21         48 my $expected = $current_state->{bound_params};
122              
123 21 100       72 if ( scalar @$expected != scalar @$params ) {
124 1         5 die "Not the same number of bound params in current state in "
125             . "DBD::Mock::Session ($self->{name})\n"
126 1         6 . " got: @{$params}"
127 1         11 . " expected: @{$expected}";
128             }
129              
130 20         34 for ( 0 .. scalar @{$params} - 1 ) {
  20         62  
131 26         85 $self->_verify_bound_param( $params->[$_], $expected->[$_], $_ );
132             }
133              
134             }
135              
136             # and make sure we go to
137             # the next statement
138 40         99 $self->{state_index}++;
139             }
140              
141             sub _find_state_for {
142 46     46   82 my ( $self, $statement ) = @_;
143              
144 46         114 foreach ( $self->_remaining_states ) {
145 42         78 my $stmt = $_->{statement};
146 42         159 my $ref = ref($stmt);
147              
148 42 100 100     223 return $_ if ( $ref eq 'Regexp' and $statement =~ /$stmt/ );
149 35 100 66     106 return $_ if ( $ref eq 'CODE' and $stmt->( $statement, $_ ) );
150 31 100 66     215 return $_ if ( not $ref and $stmt eq $statement );
151             }
152              
153 5         50 die "Statement '$statement' not found in session ($self->{name})";
154             }
155              
156             sub _num_states {
157 118     118   168 my $self = shift;
158 118         150 scalar @{ $self->{states} };
  118         1519  
159             }
160              
161             sub _remaining_states {
162 46     46   87 my $self = shift;
163 46         73 my $start_index = $self->{state_index};
164 46         111 my $end_index = $self->_num_states - 1;
165 46         113 @{ $self->{states} }[ $start_index .. $end_index ];
  46         145  
166             }
167              
168             sub _verify_bound_param {
169 26     26   56 my ( $self, $got, $expected, $index ) = @_;
170 40     40   341 no warnings;
  40         99  
  40         7696  
171              
172 26         57 my $ref = ref $expected;
173              
174 26 100       135 if ( $ref eq 'Regexp' ) {
    100          
175              
176 1 50       9 if ( $got !~ /$expected/ ) {
177 0         0 die "Bound param $index do not match (using regexp) "
178             . "in current state in DBD::Mock::Session ($self->{name})"
179             . " got: $got\n"
180             . " expected: $expected";
181             }
182              
183             } elsif ( $got ne $expected ) {
184 2         26 die "Bound param $index do not match "
185             . "in current state in DBD::Mock::Session ($self->{name})\n"
186             . " got: $got\n"
187             . " expected: $expected";
188             }
189             }
190              
191             1;