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