Require Dist::Zilla 4.200016+
[gitmo/Moose.git] / t / metaclasses / reinitialize.t
1 #!/usr/bin/env perl
2 use strict;
3 use warnings;
4 use Test::More;
5 use Test::Moose;
6 use Test::Fatal;
7
8 sub check_meta_sanity {
9     my ($meta, $class) = @_;
10     local $Test::Builder::Level = $Test::Builder::Level + 1;
11     isa_ok($meta, 'Moose::Meta::Class');
12     is($meta->name, $class);
13     ok($meta->has_method('foo'));
14     isa_ok($meta->get_method('foo'), 'Moose::Meta::Method');
15     ok($meta->has_attribute('bar'));
16     isa_ok($meta->get_attribute('bar'), 'Moose::Meta::Attribute');
17
18     if ( $meta->name eq 'Foo' ) {
19         ok($meta->does_role('Role1'), 'does Role1');
20         ok($meta->does_role('Role2'), 'does Role2');
21
22         is_deeply(
23             [
24                 map { [ $_->role->name, $_->class->name ] }
25                     sort { $a->role->name cmp $b->role->name }
26                     $meta->role_applications
27             ],
28             [
29                 [ 'Role1|Role2', 'Foo' ],
30             ],
31             'role applications for Role1 and Role2'
32         );
33     }
34 }
35
36 {
37     package Role1;
38     use Moose::Role;
39 }
40
41 {
42     package Role2;
43     use Moose::Role;
44 }
45
46 {
47     package Foo;
48     use Moose;
49     sub foo {}
50     with 'Role1', 'Role2';
51     has bar => (is => 'ro');
52 }
53
54 check_meta_sanity(Foo->meta, 'Foo');
55
56 Moose::Meta::Class->reinitialize('Foo');
57 check_meta_sanity(Foo->meta, 'Foo');
58
59 {
60     package Foo::Role::Method;
61     use Moose::Role;
62
63     has foo => (is => 'rw');
64 }
65
66 {
67     package Foo::Role::Attribute;
68     use Moose::Role;
69     has oof => (is => 'rw');
70 }
71
72 Moose::Util::MetaRole::apply_metaroles(
73     for => 'Foo',
74     class_metaroles => {
75         method    => ['Foo::Role::Method'],
76         attribute => ['Foo::Role::Attribute'],
77     },
78 );
79 check_meta_sanity(Foo->meta, 'Foo');
80 does_ok(Foo->meta->get_method('foo'), 'Foo::Role::Method');
81 does_ok(Foo->meta->get_attribute('bar'), 'Foo::Role::Attribute');
82
83 Moose::Meta::Class->reinitialize('Foo');
84 check_meta_sanity(Foo->meta, 'Foo');
85 does_ok(Foo->meta->get_method('foo'), 'Foo::Role::Method');
86 does_ok(Foo->meta->get_attribute('bar'), 'Foo::Role::Attribute');
87
88 Foo->meta->get_method('foo')->foo('TEST');
89 Foo->meta->get_attribute('bar')->oof('TSET');
90 is(Foo->meta->get_method('foo')->foo, 'TEST');
91 is(Foo->meta->get_attribute('bar')->oof, 'TSET');
92 Moose::Meta::Class->reinitialize('Foo');
93 check_meta_sanity(Foo->meta, 'Foo');
94 is(Foo->meta->get_method('foo')->foo, 'TEST');
95 is(Foo->meta->get_attribute('bar')->oof, 'TSET');
96
97 {
98     package Bar::Role::Method;
99     use Moose::Role;
100 }
101
102 {
103     package Bar::Role::Attribute;
104     use Moose::Role;
105 }
106
107 {
108     package Bar;
109     use Moose;
110     Moose::Util::MetaRole::apply_metaroles(
111         for => 'Bar',
112         class_metaroles => {
113             method    => ['Bar::Role::Method'],
114             attribute => ['Bar::Role::Attribute'],
115         },
116     );
117     sub foo {}
118     has bar => (is => 'ro');
119 }
120
121 check_meta_sanity(Bar->meta, 'Bar');
122 does_ok(Bar->meta->get_method('foo'), 'Bar::Role::Method');
123 does_ok(Bar->meta->get_attribute('bar'), 'Bar::Role::Attribute');
124
125 Moose::Meta::Class->reinitialize('Bar');
126 check_meta_sanity(Bar->meta, 'Bar');
127 does_ok(Bar->meta->get_method('foo'), 'Bar::Role::Method');
128 does_ok(Bar->meta->get_attribute('bar'), 'Bar::Role::Attribute');
129 ok(!Moose::Util::does_role(Bar->meta->get_method('foo'), 'Foo::Role::Method'));
130 ok(!Moose::Util::does_role(Bar->meta->get_attribute('bar'), 'Foo::Role::Attribute'));
131
132 Moose::Util::MetaRole::apply_metaroles(
133     for => 'Bar',
134     class_metaroles => {
135         method    => ['Foo::Role::Method'],
136         attribute => ['Foo::Role::Attribute'],
137     },
138 );
139 check_meta_sanity(Bar->meta, 'Bar');
140 does_ok(Bar->meta->get_method('foo'), 'Bar::Role::Method');
141 does_ok(Bar->meta->get_attribute('bar'), 'Bar::Role::Attribute');
142 does_ok(Bar->meta->get_method('foo'), 'Foo::Role::Method');
143 does_ok(Bar->meta->get_attribute('bar'), 'Foo::Role::Attribute');
144
145 {
146     package Bar::Meta::Method;
147     use Moose;
148     BEGIN { extends 'Moose::Meta::Method' };
149 }
150
151 {
152     package Bar::Meta::Attribute;
153     use Moose;
154     BEGIN { extends 'Moose::Meta::Attribute' };
155 }
156
157 like( exception {
158     Moose::Meta::Class->reinitialize(
159         'Bar',
160         method_metaclass    => 'Bar::Meta::Method',
161         attribute_metaclass => 'Bar::Meta::Attribute',
162     );
163 }, qr/compatible/ );
164
165 {
166     package Baz::Meta::Class;
167     use Moose;
168     BEGIN { extends 'Moose::Meta::Class' };
169
170     sub initialize {
171         my $self = shift;
172         return $self->SUPER::initialize(
173             @_,
174             method_metaclass    => 'Bar::Meta::Method',
175             attribute_metaclass => 'Bar::Meta::Attribute'
176         );
177     }
178 }
179
180 {
181     package Baz;
182     use Moose -metaclass => 'Baz::Meta::Class';
183     sub foo {}
184     has bar => (is => 'ro');
185 }
186
187 check_meta_sanity(Baz->meta, 'Baz');
188 isa_ok(Baz->meta->get_method('foo'), 'Bar::Meta::Method');
189 isa_ok(Baz->meta->get_attribute('bar'), 'Bar::Meta::Attribute');
190 Moose::Meta::Class->reinitialize('Baz');
191 check_meta_sanity(Baz->meta, 'Baz');
192 isa_ok(Baz->meta->get_method('foo'), 'Bar::Meta::Method');
193 isa_ok(Baz->meta->get_attribute('bar'), 'Bar::Meta::Attribute');
194
195 Moose::Util::MetaRole::apply_metaroles(
196     for => 'Baz',
197     class_metaroles => {
198         method    => ['Foo::Role::Method'],
199         attribute => ['Foo::Role::Attribute'],
200     },
201 );
202 check_meta_sanity(Baz->meta, 'Baz');
203 isa_ok(Baz->meta->get_method('foo'), 'Bar::Meta::Method');
204 isa_ok(Baz->meta->get_attribute('bar'), 'Bar::Meta::Attribute');
205 does_ok(Baz->meta->get_method('foo'), 'Foo::Role::Method');
206 does_ok(Baz->meta->get_attribute('bar'), 'Foo::Role::Attribute');
207
208 {
209     package Baz::Meta::Method;
210     use Moose;
211     extends 'Moose::Meta::Method';
212 }
213
214 {
215     package Baz::Meta::Attribute;
216     use Moose;
217     extends 'Moose::Meta::Attribute';
218 }
219
220 like( exception {
221     Moose::Meta::Class->reinitialize(
222         'Baz',
223         method_metaclass    => 'Baz::Meta::Method',
224         attribute_metaclass => 'Baz::Meta::Attribute',
225     );
226 }, qr/compatible/ );
227
228 {
229     package Quux;
230     use Moose;
231     sub foo { }
232     before foo => sub { };
233     has bar => (is => 'ro');
234     sub DEMOLISH { }
235     __PACKAGE__->meta->make_immutable;
236 }
237
238 ok(Quux->meta->has_method('new'));
239 isa_ok(Quux->meta->get_method('new'), 'Moose::Meta::Method::Constructor');
240 ok(Quux->meta->has_method('meta'));
241 isa_ok(Quux->meta->get_method('meta'), 'Moose::Meta::Method::Meta');
242 ok(Quux->meta->has_method('foo'));
243 isa_ok(Quux->meta->get_method('foo'), 'Class::MOP::Method::Wrapped');
244 ok(Quux->meta->has_method('bar'));
245 isa_ok(Quux->meta->get_method('bar'), 'Moose::Meta::Method::Accessor');
246 ok(Quux->meta->has_method('DESTROY'));
247 isa_ok(Quux->meta->get_method('DESTROY'), 'Moose::Meta::Method::Destructor');
248 ok(Quux->meta->has_method('DEMOLISH'));
249 isa_ok(Quux->meta->get_method('DEMOLISH'), 'Moose::Meta::Method');
250
251 Quux->meta->make_mutable;
252 Moose::Meta::Class->reinitialize('Quux');
253 Quux->meta->make_immutable;
254
255 ok(Quux->meta->has_method('new'));
256 isa_ok(Quux->meta->get_method('new'), 'Moose::Meta::Method::Constructor');
257 ok(Quux->meta->has_method('meta'));
258 isa_ok(Quux->meta->get_method('meta'), 'Moose::Meta::Method::Meta');
259 ok(Quux->meta->has_method('foo'));
260 isa_ok(Quux->meta->get_method('foo'), 'Class::MOP::Method::Wrapped');
261 ok(Quux->meta->has_method('bar'));
262 isa_ok(Quux->meta->get_method('bar'), 'Moose::Meta::Method::Accessor');
263 ok(Quux->meta->has_method('DESTROY'));
264 isa_ok(Quux->meta->get_method('DESTROY'), 'Moose::Meta::Method::Destructor');
265 ok(Quux->meta->has_method('DEMOLISH'));
266 isa_ok(Quux->meta->get_method('DEMOLISH'), 'Moose::Meta::Method');
267
268 Quux->meta->make_mutable;
269 Moose::Util::MetaRole::apply_metaroles(
270     for => 'Quux',
271     class_metaroles => {
272         method    => ['Foo::Role::Method'],
273         attribute => ['Foo::Role::Attribute'],
274     },
275 );
276 Quux->meta->make_immutable;
277
278 ok(Quux->meta->has_method('new'));
279 isa_ok(Quux->meta->get_method('new'), 'Moose::Meta::Method::Constructor');
280 { local $TODO = "constructor methods don't get metaroles yet";
281 does_ok(Quux->meta->get_method('new'), 'Foo::Role::Method');
282 }
283 ok(Quux->meta->has_method('meta'));
284 isa_ok(Quux->meta->get_method('meta'), 'Moose::Meta::Method::Meta');
285 { local $TODO = "meta methods don't get metaroles yet";
286 does_ok(Quux->meta->get_method('meta'), 'Foo::Role::Method');
287 }
288 ok(Quux->meta->has_method('foo'));
289 isa_ok(Quux->meta->get_method('foo'), 'Class::MOP::Method::Wrapped');
290 { local $TODO = "modified methods don't get metaroles yet";
291 does_ok(Quux->meta->get_method('foo'), 'Foo::Role::Method');
292 }
293 ok(Quux->meta->has_method('bar'));
294 isa_ok(Quux->meta->get_method('bar'), 'Moose::Meta::Method::Accessor');
295 { local $TODO = "accessor methods don't get metaroles yet";
296 does_ok(Quux->meta->get_method('bar'), 'Foo::Role::Method');
297 }
298 ok(Quux->meta->has_method('DESTROY'));
299 isa_ok(Quux->meta->get_method('DESTROY'), 'Moose::Meta::Method::Destructor');
300 { local $TODO = "destructor methods don't get metaroles yet";
301 does_ok(Quux->meta->get_method('DESTROY'), 'Foo::Role::Method');
302 }
303 ok(Quux->meta->has_method('DEMOLISH'));
304 isa_ok(Quux->meta->get_method('DEMOLISH'), 'Moose::Meta::Method');
305 does_ok(Quux->meta->get_method('DEMOLISH'), 'Foo::Role::Method');
306
307 {
308     package Role3;
309     use Moose::Role;
310     with 'Role1', 'Role2';
311 }
312
313 ok( Role3->meta->does_role('Role1'), 'Role3 does Role1' );
314 ok( Role3->meta->does_role('Role2'), 'Role3 does Role2' );
315
316 Moose::Meta::Role->reinitialize('Role3');
317
318 ok( Role3->meta->does_role('Role1'), 'Role3 does Role1 after reinitialize' );
319 ok( Role3->meta->does_role('Role2'), 'Role3 does Role2 after reinitialize' );
320
321 done_testing;