File Coverage

blib/lib/Test/MockObject/Extends.pm
Criterion Covered Total %
statement 121 127 95.2
branch 20 24 83.3
condition 2 3 66.6
subroutine 27 28 96.4
pod 10 10 100.0
total 180 192 93.7


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