Commit | Line | Data |
0882828e |
1 | use strict; |
2 | use warnings; |
3 | |
1c9bf107 |
4 | use Test::More tests => 67; |
0882828e |
5 | use Test::Exception; |
6 | |
16e960bd |
7 | use Scalar::Util qw/reftype/; |
2e13df84 |
8 | use Sub::Name; |
16e960bd |
9 | |
7d682ca2 |
10 | use Class::MOP; |
11 | use Class::MOP::Class; |
12 | use Class::MOP::Method; |
0882828e |
13 | |
bfe4d0fc |
14 | { # This package tries to test &has_method |
15 | # as exhaustively as possible. More corner |
16 | # cases are welcome :) |
0882828e |
17 | package Foo; |
18 | |
19 | # import a sub |
20 | use Scalar::Util 'blessed'; |
21 | |
823a5d31 |
22 | sub pie; |
23 | sub cake (); |
24 | |
bfe4d0fc |
25 | use constant FOO_CONSTANT => 'Foo-CONSTANT'; |
26 | |
0882828e |
27 | # define a sub in package |
28 | sub bar { 'Foo::bar' } |
60d90bbc |
29 | *baz = \&bar; |
46b23b44 |
30 | |
31 | # create something with the typeglob inside the package |
32 | *baaz = sub { 'Foo::baaz' }; |
bfe4d0fc |
33 | |
34 | { # method named with Sub::Name inside the package scope |
35 | no strict 'refs'; |
36 | *{'Foo::floob'} = Sub::Name::subname 'floob' => sub { '!floob!' }; |
37 | } |
38 | |
60d90bbc |
39 | # We hateses the "used only once" warnings |
46b23b44 |
40 | { |
41 | my $temp1 = \&Foo::baz; |
42 | my $temp2 = \&Foo::baaz; |
43 | } |
16e960bd |
44 | |
45 | package OinkyBoinky; |
46 | our @ISA = "Foo"; |
47 | |
48 | sub elk { 'OinkyBoinky::elk' } |
60d90bbc |
49 | |
50 | package main; |
51 | |
52 | sub Foo::blah { $_[0]->Foo::baz() } |
53 | |
54 | { |
55 | no strict 'refs'; |
56 | *{'Foo::bling'} = sub { '$$Bling$$' }; |
bfe4d0fc |
57 | *{'Foo::bang'} = Sub::Name::subname 'Foo::bang' => sub { '!BANG!' }; |
58 | *{'Foo::boom'} = Sub::Name::subname 'boom' => sub { '!BOOM!' }; |
59 | |
60 | eval "package Foo; sub evaled_foo { 'Foo::evaled_foo' }"; |
60d90bbc |
61 | } |
0882828e |
62 | } |
63 | |
bfe4d0fc |
64 | my $Foo = Class::MOP::Class->initialize('Foo'); |
0882828e |
65 | |
c3b8d5ad |
66 | ok($Foo->has_method('pie'), '... got the method stub pie'); |
67 | ok($Foo->has_method('cake'), '... got the constant method stub cake'); |
823a5d31 |
68 | |
0882828e |
69 | my $foo = sub { 'Foo::foo' }; |
70 | |
de19f115 |
71 | ok(!UNIVERSAL::isa($foo, 'Class::MOP::Method'), '... our method is not yet blessed'); |
72 | |
0882828e |
73 | lives_ok { |
74 | $Foo->add_method('foo' => $foo); |
75 | } '... we added the method successfully'; |
76 | |
7855ddba |
77 | my $foo_method = $Foo->get_method('foo'); |
de19f115 |
78 | |
7855ddba |
79 | isa_ok($foo_method, 'Class::MOP::Method'); |
80 | |
81 | is($foo_method->name, 'foo', '... got the right name for the method'); |
82 | is($foo_method->package_name, 'Foo', '... got the right package name for the method'); |
de19f115 |
83 | |
0882828e |
84 | ok($Foo->has_method('foo'), '... Foo->has_method(foo) (defined with Sub::Name)'); |
bfe4d0fc |
85 | |
7855ddba |
86 | is($Foo->get_method('foo')->body, $foo, '... Foo->get_method(foo) == \&foo'); |
25a5f083 |
87 | is($Foo->get_method('foo')->execute, 'Foo::foo', '... _method_foo->execute returns "Foo::foo"'); |
bfe4d0fc |
88 | is(Foo->foo(), 'Foo::foo', '... Foo->foo() returns "Foo::foo"'); |
89 | |
90 | # now check all our other items ... |
91 | |
d7d3f3cb |
92 | ok($Foo->has_method('FOO_CONSTANT'), '... not Foo->has_method(FOO_CONSTANT) (defined w/ use constant)'); |
93 | ok(!$Foo->has_method('bling'), '... not Foo->has_method(bling) (defined in main:: using symbol tables (no Sub::Name))'); |
46b23b44 |
94 | |
0882828e |
95 | ok($Foo->has_method('bar'), '... Foo->has_method(bar) (defined in Foo)'); |
60d90bbc |
96 | ok($Foo->has_method('baz'), '... Foo->has_method(baz) (typeglob aliased within Foo)'); |
46b23b44 |
97 | ok($Foo->has_method('baaz'), '... Foo->has_method(baaz) (typeglob aliased within Foo)'); |
bfe4d0fc |
98 | ok($Foo->has_method('floob'), '... Foo->has_method(floob) (defined in Foo:: using symbol tables and Sub::Name w/out package name)'); |
60d90bbc |
99 | ok($Foo->has_method('blah'), '... Foo->has_method(blah) (defined in main:: using fully qualified package name)'); |
60d90bbc |
100 | ok($Foo->has_method('bang'), '... Foo->has_method(bang) (defined in main:: using symbol tables and Sub::Name)'); |
bfe4d0fc |
101 | ok($Foo->has_method('evaled_foo'), '... Foo->has_method(evaled_foo) (evaled in main::)'); |
0882828e |
102 | |
16e960bd |
103 | my $OinkyBoinky = Class::MOP::Class->initialize('OinkyBoinky'); |
104 | |
105 | ok($OinkyBoinky->has_method('elk'), "the method 'elk' is defined in OinkyBoinky"); |
106 | |
107 | ok(!$OinkyBoinky->has_method('bar'), "the method 'bar' is not defined in OinkyBoinky"); |
108 | |
109 | ok(my $bar = $OinkyBoinky->find_method_by_name('bar'), "but if you look in the inheritence chain then 'bar' does exist"); |
110 | |
b9575695 |
111 | is( reftype($bar->body), "CODE", "the returned value is a code ref" ); |
16e960bd |
112 | |
113 | |
de19f115 |
114 | # calling get_method blessed them all |
46b23b44 |
115 | for my $method_name (qw/baaz |
116 | bar |
7855ddba |
117 | baz |
118 | floob |
46b23b44 |
119 | blah |
120 | bang |
d7d3f3cb |
121 | evaled_foo |
122 | FOO_CONSTANT/) { |
7855ddba |
123 | isa_ok($Foo->get_method($method_name), 'Class::MOP::Method'); |
124 | { |
125 | no strict 'refs'; |
187c832e |
126 | is($Foo->get_method($method_name)->body, \&{'Foo::' . $method_name}, '... body matches CODE ref in package for ' . $method_name); |
7855ddba |
127 | } |
128 | } |
de19f115 |
129 | |
46b23b44 |
130 | for my $method_name (qw/ |
46b23b44 |
131 | bling |
132 | /) { |
133 | is(ref($Foo->get_package_symbol('&' . $method_name)), 'CODE', '... got the __ANON__ methods'); |
134 | { |
135 | no strict 'refs'; |
136 | is($Foo->get_package_symbol('&' . $method_name), \&{'Foo::' . $method_name}, '... symbol matches CODE ref in package for ' . $method_name); |
137 | } |
138 | } |
139 | |
663f8198 |
140 | { |
141 | package Foo::Aliasing; |
142 | use metaclass; |
143 | sub alias_me { '...' } |
144 | } |
145 | |
146 | $Foo->alias_method('alias_me' => Foo::Aliasing->meta->get_method('alias_me')); |
147 | |
91b73829 |
148 | ok($Foo->has_method('alias_me'), '... Foo->has_method(alias_me) (aliased from Foo::Aliasing)'); |
663f8198 |
149 | ok(defined &Foo::alias_me, '... Foo does have a symbol table slow for alias_me though'); |
150 | |
bfe4d0fc |
151 | ok(!$Foo->has_method('blessed'), '... !Foo->has_method(blessed) (imported into Foo)'); |
152 | ok(!$Foo->has_method('boom'), '... !Foo->has_method(boom) (defined in main:: using symbol tables and Sub::Name w/out package name)'); |
0882828e |
153 | |
bfe4d0fc |
154 | ok(!$Foo->has_method('not_a_real_method'), '... !Foo->has_method(not_a_real_method) (does not exist)'); |
155 | is($Foo->get_method('not_a_real_method'), undef, '... Foo->get_method(not_a_real_method) == undef'); |
156 | |
c9b8b7f9 |
157 | is_deeply( |
158 | [ sort $Foo->get_method_list ], |
c3b8d5ad |
159 | [ qw(FOO_CONSTANT alias_me baaz bang bar baz blah cake evaled_foo floob foo pie) ], |
c9b8b7f9 |
160 | '... got the right method list for Foo'); |
161 | |
a5eca695 |
162 | is_deeply( |
77ff94df |
163 | [ sort { $a->name cmp $b->name } $Foo->get_all_methods() ], |
a5eca695 |
164 | [ |
77ff94df |
165 | map { $Foo->get_method($_) } qw( |
d7d3f3cb |
166 | FOO_CONSTANT |
91b73829 |
167 | alias_me |
46b23b44 |
168 | baaz |
a5eca695 |
169 | bang |
170 | bar |
171 | baz |
172 | blah |
c3b8d5ad |
173 | cake |
a5eca695 |
174 | evaled_foo |
175 | floob |
176 | foo |
c3b8d5ad |
177 | pie |
a5eca695 |
178 | ) |
179 | ], |
180 | '... got the right list of applicable methods for Foo'); |
181 | |
7855ddba |
182 | is($Foo->remove_method('foo')->body, $foo, '... removed the foo method'); |
c9b8b7f9 |
183 | ok(!$Foo->has_method('foo'), '... !Foo->has_method(foo) we just removed it'); |
1c9bf107 |
184 | ok(!$Foo->get_method_map->{foo}, 'foo is not in the method map'); |
c9b8b7f9 |
185 | dies_ok { Foo->foo } '... cannot call Foo->foo because it is not there'; |
186 | |
187 | is_deeply( |
188 | [ sort $Foo->get_method_list ], |
c3b8d5ad |
189 | [ qw(FOO_CONSTANT alias_me baaz bang bar baz blah cake evaled_foo floob pie) ], |
c9b8b7f9 |
190 | '... got the right method list for Foo'); |
191 | |
c9b8b7f9 |
192 | |
bfe4d0fc |
193 | # ... test our class creator |
194 | |
195 | my $Bar = Class::MOP::Class->create( |
99b84658 |
196 | package => 'Bar', |
3976fb78 |
197 | superclasses => [ 'Foo' ], |
198 | methods => { |
199 | foo => sub { 'Bar::foo' }, |
200 | bar => sub { 'Bar::bar' }, |
201 | } |
202 | ); |
bfe4d0fc |
203 | isa_ok($Bar, 'Class::MOP::Class'); |
204 | |
205 | ok($Bar->has_method('foo'), '... Bar->has_method(foo)'); |
206 | ok($Bar->has_method('bar'), '... Bar->has_method(bar)'); |
207 | |
208 | is(Bar->foo, 'Bar::foo', '... Bar->foo == Bar::foo'); |
209 | is(Bar->bar, 'Bar::bar', '... Bar->bar == Bar::bar'); |
210 | |
211 | lives_ok { |
212 | $Bar->add_method('foo' => sub { 'Bar::foo v2' }); |
213 | } '... overwriting a method is fine'; |
214 | |
215 | ok($Bar->has_method('foo'), '... Bar-> (still) has_method(foo)'); |
216 | is(Bar->foo, 'Bar::foo v2', '... Bar->foo == "Bar::foo v2"'); |
c9b8b7f9 |
217 | |
218 | is_deeply( |
219 | [ sort $Bar->get_method_list ], |
aa448b16 |
220 | [ qw(bar foo meta) ], |
a5eca695 |
221 | '... got the right method list for Bar'); |
222 | |
223 | is_deeply( |
77ff94df |
224 | [ sort { $a->name cmp $b->name } $Bar->get_all_methods() ], |
a5eca695 |
225 | [ |
77ff94df |
226 | $Foo->get_method('FOO_CONSTANT'), |
91b73829 |
227 | $Foo->get_method('alias_me'), |
77ff94df |
228 | $Foo->get_method('baaz'), |
229 | $Foo->get_method('bang'), |
230 | $Bar->get_method('bar'), |
231 | (map { $Foo->get_method($_) } qw( |
a5eca695 |
232 | baz |
233 | blah |
c3b8d5ad |
234 | cake |
a5eca695 |
235 | evaled_foo |
236 | floob |
237 | )), |
77ff94df |
238 | $Bar->get_method('foo'), |
239 | $Bar->get_method('meta'), |
c3b8d5ad |
240 | $Foo->get_method('pie'), |
a5eca695 |
241 | ], |
242 | '... got the right list of applicable methods for Bar'); |
243 | |
7d682ca2 |
244 | my $method = Class::MOP::Method->wrap( |
245 | name => 'objecty', |
246 | package_name => 'Whatever', |
247 | body => sub {q{I am an object, and I feel an object's pain}}, |
248 | ); |
249 | |
250 | Bar->meta->add_method( $method->name, $method ); |
251 | |
252 | my $new_method = Bar->meta->get_method('objecty'); |
a5eca695 |
253 | |
7d682ca2 |
254 | isnt( $method, $new_method, 'add_method clones method objects as they are added' ); |
255 | is( $new_method->original_method, $method, '... the cloned method has the correct original method' ); |