File Coverage

blib/lib/Test/MockObject/Extends.pm
Criterion Covered Total %
statement 129 135 95.5
branch 20 24 83.3
condition 4 6 66.6
subroutine 29 30 96.6
pod 10 11 90.9
total 192 206 93.2


line stmt bran cond sub pod time code
1             package Test::MockObject::Extends;
2             $Test::MockObject::Extends::VERSION = '1.20180705';
3 5     6   127842 use strict;
  5         30  
  5         156  
4 5     5   34 use warnings;
  5         12  
  5         173  
5              
6 5     5   2377 use Test::MockObject;
  5         14  
  5         31  
7              
8             # Alias our 'import' to T:MO::import to handle this:
9             # use Test::MockObject::Extends '-debug';
10             *import = \&Test::MockObject::import;
11              
12 5     5   6921 use Devel::Peek 'CvGV';
  5         2306  
  5         29  
13 5     5   496 use Scalar::Util 'blessed';
  5         11  
  5         297  
14              
15 5     5   38 use constant PERL_5_9 => $^V gt v5.9.0;
  5         11  
  5         874  
16              
17             sub new
18             {
19 16     16 1 13972 my ($class, $fake_class) = @_;
20              
21 16 100       68 return Test::MockObject->new() unless defined $fake_class;
22              
23 15         51 my $parent_class = $class->get_class( $fake_class );
24 15         61 $class->check_class_loaded( $parent_class );
25 15 100       37532 my $self = blessed( $fake_class ) ? $fake_class : {};
26              
27             # Fields now locks the hash as of 5.9.0 - #84535
28 15 100 100     81 if (PERL_5_9 && blessed( $fake_class ) && do {
29 5     5   36 no strict 'refs';
  5         39  
  5         1680  
30 10         59 exists ${$parent_class . '::'}{FIELDS} # uses fields
31 10         20 }) {
32             # bypass prototypes
33 1         5 &Hash::Util::unlock_hash(\%$fake_class);
34 1         17 bless $self, $class->gen_package( $parent_class );
35 1         7 &Hash::Util::lock_keys(\%$fake_class,
36             fields::_accessible_keys($parent_class));
37             }
38             else
39             {
40 14         52 bless $self, $class->gen_package( $parent_class );
41             }
42              
43 15         111 return $self;
44             }
45              
46             sub check_class_loaded
47             {
48 15     15 1 36 my ($self, $parent_class) = @_;
49 15         62 my $result = Test::MockObject->check_class_loaded(
50             $parent_class
51             );
52 15 100       53 return $result if $result;
53              
54 1         4 (my $load_class = $parent_class) =~ s/::/\//g;
55 1         862 require $load_class . '.pm';
56             }
57              
58             sub get_class
59             {
60 15     15 1 39 my ($self, $invocant) = @_;
61              
62 15 100       80 return $invocant unless blessed $invocant;
63 10         31 return ref $invocant;
64             }
65              
66             my $packname = 'a';
67              
68             sub gen_package
69             {
70 15     15 1 40 my ($class, $parent) = @_;
71 15         52 my $package = 'T::MO::E::' . $packname++;
72              
73 5     5   39 no strict 'refs';
  5         10  
  5         1015  
74 15         41 *{ $package . '::mock' } = \&mock;
  15         154  
75 15         42 *{ $package . '::unmock' } = \&unmock;
  15         83  
76 15         37 @{ $package . '::ISA' } = ( $parent );
  15         357  
77 15         89 *{ $package . '::can' } = $class->gen_can( $parent );
  15         110  
78 15         70 *{ $package . '::isa' } = $class->gen_isa( $parent );
  15         83  
79 15         57 *{ $package . '::AUTOLOAD' } = $class->gen_autoload( $parent );
  15         100  
80 15         63 *{ $package . '::__get_parents' } = $class->gen_get_parents( $parent );
  15         80  
81 15         54 *{ $package . '::DESTROY' } = $class->gen_destroy( $parent );
  15         95  
82              
83 15         75 return $package;
84             }
85              
86             sub gen_get_parents
87             {
88 15     15 1 42 my ($self, $parent) = @_;
89             return sub
90             {
91 5     5   43 no strict 'refs';
  5         10  
  5         2572  
92 1     1   1833 return @{ $parent . '::ISA' };
  1         8  
93 15         72 };
94             }
95              
96             sub gen_isa
97             {
98 15     15 1 45 my ($class, $parent) = @_;
99              
100             sub
101             {
102 11     11   2796 local *__ANON__ = 'isa';
103 11         35 my ($self, $class) = @_;
104 11 100       52 return 1 if $class eq $parent;
105 4         32 my $isa = $parent->can( 'isa' );
106 4         30 return $isa->( $self, $class );
107 15         85 };
108             }
109              
110             sub gen_can
111             {
112 15     25 1 56 my ($class, $parent) = @_;
113              
114             sub
115             {
116 0     0   0 local *__ANON__ = 'can';
117 0         0 my ($self, $method) = @_;
118 0         0 my $parent_method = $self->SUPER::can( $method );
119 0 0       0 return $parent_method if $parent_method;
120 0         0 return Test::MockObject->can( $method );
121 15         102 };
122             }
123              
124             sub gen_destroy
125             {
126 15     15 0 42 my ($class, $parent) = @_;
127 15         28 my $destroy;
128             $destroy = sub
129             {
130 14     14   2383 my $self = shift;
131 14         137 my $parent_destroy = $parent->can( 'DESTROY' );
132 14 50 33     61 $self->$parent_destroy if $parent_destroy && $parent_destroy != $destroy;
133 14         63 $self->Test::MockObject::DESTROY;
134             }
135 15         81 }
136              
137             sub gen_autoload
138             {
139 15     15 1 39 my ($class, $parent) = @_;
140              
141             sub
142             {
143 83     83   10003 our $AUTOLOAD;
144              
145 83         237 my $method = substr( $AUTOLOAD, rindex( $AUTOLOAD, ':' ) +1 );
146              
147 83         158 my $self = shift;
148              
149 83 50       614 if (my $parent_method = $parent->can( $method ))
    100          
    100          
150             {
151 0         0 return $self->$parent_method( @_ );
152             }
153             elsif (my $mock_method = Test::MockObject->can( $method ))
154             {
155 78         261 return $self->$mock_method( @_ );
156             }
157             elsif (my $parent_al = $parent->can( 'AUTOLOAD' ))
158             {
159 4         47 my ($parent_pack) = CvGV( $parent_al ) =~ /\*(.*)::AUTOLOAD/;
160             {
161 5     5   42 no strict 'refs';
  5         11  
  5         1381  
  4         13  
162 4         13 ${ "${parent_pack}::AUTOLOAD" } = "${parent}::${method}";
  4         18  
163             }
164 4         15 unshift @_, $self;
165 4         23 goto &$parent_al;
166             }
167             else
168             {
169 1         8 die "Undefined method $method at ", join( ' ', caller() ), "\n";
170             }
171 15         100 };
172             }
173              
174             sub mock
175             {
176 9     9 1 1318 my ($self, $name, $sub) = @_;
177              
178 9 100       59 Test::MockObject::_set_log( $self, $name, ( $name =~ s/^-// ? 0 : 1 ) );
179              
180             my $mock_sub = sub
181             {
182 8     8   37 my ($self) = @_;
183 8         63 $self->log_call( $name, @_ );
184 8         32 $sub->( @_ );
185 9         56 };
186              
187             {
188 5     5   39 no strict 'refs';
  5         10  
  5         211  
  9         23  
189 5     5   34 no warnings 'redefine';
  5         13  
  5         593  
190 9         17 *{ ref( $self ) . '::' . $name } = $mock_sub;
  9         66  
191             }
192              
193 9         59 return $self;
194             }
195              
196             sub unmock
197             {
198 1     1 1 4 my ($self, $name) = @_;
199              
200 1         5 Test::MockObject::_set_log( $self, $name, 0 );
201 5     5   37 no strict 'refs';
  5         13  
  5         375  
202 1         2 my $glob = *{ ref( $self ) . '::' };
  1         7  
203 1         9 delete $glob->{ $name };
204 1         5 return $self;
205             }
206              
207             1;
208             __END__