one more spot still referring to compute_all_applicable_attributes
[gitmo/Class-MOP.git] / t / 073_make_mutable.t
1 use strict;
2 use warnings;
3
4 use Test::More tests => 101;
5 use Test::Exception;
6
7 use Scalar::Util;
8
9 use Class::MOP;
10
11 {
12     package Foo;
13
14     use strict;
15     use warnings;
16     use metaclass;
17
18     __PACKAGE__->meta->add_attribute('bar');
19
20     package Bar;
21
22     use strict;
23     use warnings;
24     use metaclass;
25
26     __PACKAGE__->meta->superclasses('Foo');
27
28     __PACKAGE__->meta->add_attribute('baz');
29
30     package Baz;
31
32     use strict;
33     use warnings;
34     use metaclass;
35
36     __PACKAGE__->meta->superclasses('Bar');
37
38     __PACKAGE__->meta->add_attribute('bah');
39 }
40
41 {
42     my $meta = Baz->meta;
43     is($meta->name, 'Baz', '... checking the Baz metaclass');
44     my %orig_keys = map { $_ => 1 } grep { !/^_/ } keys %$meta;
45     # Since this has no default it won't be present yet, but it will
46     # be after the class is made immutable.
47     $orig_keys{immutable_transformer} = 1;
48
49     lives_ok {$meta->make_immutable; } '... changed Baz to be immutable';
50     ok(!$meta->is_mutable,              '... our class is no longer mutable');
51     ok($meta->is_immutable,             '... our class is now immutable');
52     ok(!$meta->make_immutable,          '... make immutable now returns nothing');
53     ok($meta->get_method_map->{new},    '... inlined constructor created');
54     ok($meta->has_method('new'),        '... inlined constructor created for sure');    
55     ok($meta->immutable_transformer->inlined_constructor,
56        '... transformer says it did inline the constructor');
57
58     lives_ok { $meta->make_mutable; }  '... changed Baz to be mutable';
59     ok($meta->is_mutable,               '... our class is mutable');
60     ok(!$meta->is_immutable,            '... our class is not immutable');
61     ok(!$meta->make_mutable,            '... make mutable now returns nothing');
62     ok(!$meta->get_method_map->{new},   '... inlined constructor removed');
63     ok(!$meta->has_method('new'),        '... inlined constructor removed for sure');    
64     ok(!$meta->immutable_transformer->inlined_constructor,
65        '... transformer says it did not inline the constructor');
66
67     my %new_keys = map { $_ => 1 } grep { !/^_/ } keys %$meta;
68     is_deeply(\%orig_keys, \%new_keys, '... no extraneous hashkeys');
69
70     isa_ok($meta, 'Class::MOP::Class', '... Baz->meta isa Class::MOP::Class');
71
72     ok( $meta->add_method('xyz', sub{'xxx'}), '... added method');
73     is( Baz->xyz, 'xxx',                      '... method xyz works');
74
75     ok($meta->add_attribute('fickle', accessor => 'fickle'), '... added attribute');
76     ok(Baz->can('fickle'),                '... Baz can fickle');
77     ok($meta->remove_attribute('fickle'), '... removed attribute');
78
79     my $reef = \ 'reef';
80     ok($meta->add_package_symbol('$ref', $reef),      '... added package symbol');
81     is($meta->get_package_symbol('$ref'), $reef,      '... values match');
82     lives_ok { $meta->remove_package_symbol('$ref') } '... removed it';
83     isnt($meta->get_package_symbol('$ref'), $reef,    '... values match');
84
85     ok( my @supers = $meta->superclasses,       '... got the superclasses okay');
86     ok( $meta->superclasses('Foo'),             '... set the superclasses');
87     is_deeply(['Foo'], [$meta->superclasses],   '... set the superclasses okay');
88     ok( $meta->superclasses( @supers ),         '... reset superclasses');
89     is_deeply([@supers], [$meta->superclasses], '... reset the superclasses okay');
90
91     ok( $meta->$_  , "... ${_} works")
92       for qw(get_meta_instance       get_all_attributes
93              class_precedence_list  get_method_map );
94
95     lives_ok {$meta->make_immutable; } '... changed Baz to be immutable again';
96     ok($meta->get_method_map->{new},    '... inlined constructor recreated');
97 }
98
99 {
100     my $meta = Baz->meta;
101
102     lives_ok { $meta->make_immutable() } 'Changed Baz to be immutable';
103     lives_ok { $meta->make_mutable() }   '... changed Baz to be mutable';
104     lives_ok { $meta->make_immutable() } '... changed Baz to be immutable';
105
106     dies_ok{ $meta->add_method('xyz', sub{'xxx'})  } '... exception thrown as expected';
107
108     dies_ok {
109       $meta->add_attribute('fickle', accessor => 'fickle')
110     }  '... exception thrown as expected';
111     dies_ok { $meta->remove_attribute('fickle') } '... exception thrown as expected';
112
113     my $reef = \ 'reef';
114     dies_ok { $meta->add_package_symbol('$ref', $reef) } '... exception thrown as expected';
115     dies_ok { $meta->remove_package_symbol('$ref')     } '... exception thrown as expected';
116
117     ok( my @supers = $meta->superclasses,  '... got the superclasses okay');
118     dies_ok { $meta->superclasses('Foo') } '... set the superclasses';
119
120     ok( $meta->$_  , "... ${_} works")
121       for qw(get_meta_instance       get_all_attributes
122              class_precedence_list  get_method_map );
123 }
124
125 {
126
127     ok(Baz->meta->is_immutable,  'Superclass is immutable');
128     my $meta = Baz->meta->create_anon_class(superclasses => ['Baz']);
129     my %orig_keys = map { $_ => 1 } grep { !/^_/ } keys %$meta;
130     $orig_keys{immutable_transformer} = 1;
131     my @orig_meths = sort { $a->name cmp $b->name }
132       $meta->get_all_methods;
133     ok($meta->is_anon_class,                  'We have an anon metaclass');
134     ok($meta->is_mutable,  '... our anon class is mutable');
135     ok(!$meta->is_immutable,  '... our anon class is not immutable');
136
137     lives_ok {$meta->make_immutable(
138                                     inline_accessor    => 1,
139                                     inline_destructor  => 0,
140                                     inline_constructor => 1,
141                                    )
142             } '... changed class to be immutable';
143     ok(!$meta->is_mutable,                    '... our class is no longer mutable');
144     ok($meta->is_immutable,                   '... our class is now immutable');
145     ok(!$meta->make_immutable,                '... make immutable now returns nothing');
146
147     lives_ok { $meta->make_mutable }  '... changed Baz to be mutable';
148     ok($meta->is_mutable,             '... our class is mutable');
149     ok(!$meta->is_immutable,          '... our class is not immutable');
150     ok(!$meta->make_mutable,          '... make mutable now returns nothing');
151     ok($meta->is_anon_class,          '... still marked as an anon class');
152     my $instance = $meta->new_object;
153
154     my %new_keys  = map { $_ => 1 } grep { !/^_/ } keys %$meta;
155     my @new_meths = sort { $a->name cmp $b->name }
156       $meta->get_all_methods;
157     is_deeply(\%orig_keys, \%new_keys, '... no extraneous hashkeys');
158     is_deeply(\@orig_meths, \@new_meths, '... no straneous methods');
159
160     isa_ok($meta, 'Class::MOP::Class', '... Anon class isa Class::MOP::Class');
161
162     ok( $meta->add_method('xyz', sub{'xxx'}), '... added method');
163     is( $instance->xyz , 'xxx',               '... method xyz works');
164     ok( $meta->remove_method('xyz'),          '... removed method');
165
166     ok($meta->add_attribute('fickle', accessor => 'fickle'), '... added attribute');
167     ok($instance->can('fickle'),          '... instance can fickle');
168     ok($meta->remove_attribute('fickle'), '... removed attribute');
169
170     my $reef = \ 'reef';
171     ok($meta->add_package_symbol('$ref', $reef),      '... added package symbol');
172     is($meta->get_package_symbol('$ref'), $reef,      '... values match');
173     lives_ok { $meta->remove_package_symbol('$ref') } '... removed it';
174     isnt($meta->get_package_symbol('$ref'), $reef,    '... values match');
175
176     ok( my @supers = $meta->superclasses,       '... got the superclasses okay');
177     ok( $meta->superclasses('Foo'),             '... set the superclasses');
178     is_deeply(['Foo'], [$meta->superclasses],   '... set the superclasses okay');
179     ok( $meta->superclasses( @supers ),         '... reset superclasses');
180     is_deeply([@supers], [$meta->superclasses], '... reset the superclasses okay');
181
182     ok( $meta->$_  , "... ${_} works")
183       for qw(get_meta_instance       get_all_attributes
184              class_precedence_list  get_method_map );
185 };
186
187
188 #rerun the same tests on an anon class.. just cause we can.
189 {
190     my $meta = Baz->meta->create_anon_class(superclasses => ['Baz']);
191
192     lives_ok {$meta->make_immutable(
193                                     inline_accessor    => 1,
194                                     inline_destructor  => 0,
195                                     inline_constructor => 1,
196                                    )
197             } '... changed class to be immutable';
198     lives_ok { $meta->make_mutable() }   '... changed class to be mutable';
199     lives_ok {$meta->make_immutable  } '... changed class to be immutable';
200
201     dies_ok{ $meta->add_method('xyz', sub{'xxx'})  } '... exception thrown as expected';
202
203     dies_ok {
204       $meta->add_attribute('fickle', accessor => 'fickle')
205     }  '... exception thrown as expected';
206     dies_ok { $meta->remove_attribute('fickle') } '... exception thrown as expected';
207
208     my $reef = \ 'reef';
209     dies_ok { $meta->add_package_symbol('$ref', $reef) } '... exception thrown as expected';
210     dies_ok { $meta->remove_package_symbol('$ref')     } '... exception thrown as expected';
211
212     ok( my @supers = $meta->superclasses,  '... got the superclasses okay');
213     dies_ok { $meta->superclasses('Foo') } '... set the superclasses';
214
215     ok( $meta->$_  , "... ${_} works")
216       for qw(get_meta_instance       get_all_attributes
217              class_precedence_list  get_method_map );
218 }
219
220 {
221     Foo->meta->make_immutable;
222     Bar->meta->make_immutable;
223     Bar->meta->make_mutable;
224
225     isnt( Foo->meta->immutable_transformer, Bar->meta->immutable_transformer,
226           'Foo and Bar should have different immutable transformer objects' );
227 }