diff options
Diffstat (limited to 't/metaclasses/reinitialize.t')
-rw-r--r-- | t/metaclasses/reinitialize.t | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/t/metaclasses/reinitialize.t b/t/metaclasses/reinitialize.t new file mode 100644 index 0000000..2e6020b --- /dev/null +++ b/t/metaclasses/reinitialize.t @@ -0,0 +1,320 @@ +use strict; +use warnings; +use Test::More; +use Test::Moose; +use Test::Fatal; + +sub check_meta_sanity { + my ($meta, $class) = @_; + local $Test::Builder::Level = $Test::Builder::Level + 1; + isa_ok($meta, 'Moose::Meta::Class'); + is($meta->name, $class); + ok($meta->has_method('foo')); + isa_ok($meta->get_method('foo'), 'Moose::Meta::Method'); + ok($meta->has_attribute('bar')); + isa_ok($meta->get_attribute('bar'), 'Moose::Meta::Attribute'); + + if ( $meta->name eq 'Foo' ) { + ok($meta->does_role('Role1'), 'does Role1'); + ok($meta->does_role('Role2'), 'does Role2'); + + is_deeply( + [ + map { [ $_->role->name, $_->class->name ] } + sort { $a->role->name cmp $b->role->name } + $meta->role_applications + ], + [ + [ 'Role1|Role2', 'Foo' ], + ], + 'role applications for Role1 and Role2' + ); + } +} + +{ + package Role1; + use Moose::Role; +} + +{ + package Role2; + use Moose::Role; +} + +{ + package Foo; + use Moose; + sub foo {} + with 'Role1', 'Role2'; + has bar => (is => 'ro'); +} + +check_meta_sanity(Foo->meta, 'Foo'); + +Moose::Meta::Class->reinitialize('Foo'); +check_meta_sanity(Foo->meta, 'Foo'); + +{ + package Foo::Role::Method; + use Moose::Role; + + has foo => (is => 'rw'); +} + +{ + package Foo::Role::Attribute; + use Moose::Role; + has oof => (is => 'rw'); +} + +Moose::Util::MetaRole::apply_metaroles( + for => 'Foo', + class_metaroles => { + method => ['Foo::Role::Method'], + attribute => ['Foo::Role::Attribute'], + }, +); +check_meta_sanity(Foo->meta, 'Foo'); +does_ok(Foo->meta->get_method('foo'), 'Foo::Role::Method'); +does_ok(Foo->meta->get_attribute('bar'), 'Foo::Role::Attribute'); + +Moose::Meta::Class->reinitialize('Foo'); +check_meta_sanity(Foo->meta, 'Foo'); +does_ok(Foo->meta->get_method('foo'), 'Foo::Role::Method'); +does_ok(Foo->meta->get_attribute('bar'), 'Foo::Role::Attribute'); + +Foo->meta->get_method('foo')->foo('TEST'); +Foo->meta->get_attribute('bar')->oof('TSET'); +is(Foo->meta->get_method('foo')->foo, 'TEST'); +is(Foo->meta->get_attribute('bar')->oof, 'TSET'); +Moose::Meta::Class->reinitialize('Foo'); +check_meta_sanity(Foo->meta, 'Foo'); +is(Foo->meta->get_method('foo')->foo, 'TEST'); +is(Foo->meta->get_attribute('bar')->oof, 'TSET'); + +{ + package Bar::Role::Method; + use Moose::Role; +} + +{ + package Bar::Role::Attribute; + use Moose::Role; +} + +{ + package Bar; + use Moose; + Moose::Util::MetaRole::apply_metaroles( + for => 'Bar', + class_metaroles => { + method => ['Bar::Role::Method'], + attribute => ['Bar::Role::Attribute'], + }, + ); + sub foo {} + has bar => (is => 'ro'); +} + +check_meta_sanity(Bar->meta, 'Bar'); +does_ok(Bar->meta->get_method('foo'), 'Bar::Role::Method'); +does_ok(Bar->meta->get_attribute('bar'), 'Bar::Role::Attribute'); + +Moose::Meta::Class->reinitialize('Bar'); +check_meta_sanity(Bar->meta, 'Bar'); +does_ok(Bar->meta->get_method('foo'), 'Bar::Role::Method'); +does_ok(Bar->meta->get_attribute('bar'), 'Bar::Role::Attribute'); +ok(!Moose::Util::does_role(Bar->meta->get_method('foo'), 'Foo::Role::Method')); +ok(!Moose::Util::does_role(Bar->meta->get_attribute('bar'), 'Foo::Role::Attribute')); + +Moose::Util::MetaRole::apply_metaroles( + for => 'Bar', + class_metaroles => { + method => ['Foo::Role::Method'], + attribute => ['Foo::Role::Attribute'], + }, +); +check_meta_sanity(Bar->meta, 'Bar'); +does_ok(Bar->meta->get_method('foo'), 'Bar::Role::Method'); +does_ok(Bar->meta->get_attribute('bar'), 'Bar::Role::Attribute'); +does_ok(Bar->meta->get_method('foo'), 'Foo::Role::Method'); +does_ok(Bar->meta->get_attribute('bar'), 'Foo::Role::Attribute'); + +{ + package Bar::Meta::Method; + use Moose; + BEGIN { extends 'Moose::Meta::Method' }; +} + +{ + package Bar::Meta::Attribute; + use Moose; + BEGIN { extends 'Moose::Meta::Attribute' }; +} + +like( exception { + Moose::Meta::Class->reinitialize( + 'Bar', + method_metaclass => 'Bar::Meta::Method', + attribute_metaclass => 'Bar::Meta::Attribute', + ); +}, qr/\QAttribute (class_name) is required/ ); + +{ + package Baz::Meta::Class; + use Moose; + BEGIN { extends 'Moose::Meta::Class' }; + + sub initialize { + my $self = shift; + return $self->SUPER::initialize( + @_, + method_metaclass => 'Bar::Meta::Method', + attribute_metaclass => 'Bar::Meta::Attribute' + ); + } +} + +{ + package Baz; + use Moose -metaclass => 'Baz::Meta::Class'; + sub foo {} + has bar => (is => 'ro'); +} + +check_meta_sanity(Baz->meta, 'Baz'); +isa_ok(Baz->meta->get_method('foo'), 'Bar::Meta::Method'); +isa_ok(Baz->meta->get_attribute('bar'), 'Bar::Meta::Attribute'); +Moose::Meta::Class->reinitialize('Baz'); +check_meta_sanity(Baz->meta, 'Baz'); +isa_ok(Baz->meta->get_method('foo'), 'Bar::Meta::Method'); +isa_ok(Baz->meta->get_attribute('bar'), 'Bar::Meta::Attribute'); + +Moose::Util::MetaRole::apply_metaroles( + for => 'Baz', + class_metaroles => { + method => ['Foo::Role::Method'], + attribute => ['Foo::Role::Attribute'], + }, +); +check_meta_sanity(Baz->meta, 'Baz'); +isa_ok(Baz->meta->get_method('foo'), 'Bar::Meta::Method'); +isa_ok(Baz->meta->get_attribute('bar'), 'Bar::Meta::Attribute'); +does_ok(Baz->meta->get_method('foo'), 'Foo::Role::Method'); +does_ok(Baz->meta->get_attribute('bar'), 'Foo::Role::Attribute'); + +{ + package Baz::Meta::Method; + use Moose; + extends 'Moose::Meta::Method'; +} + +{ + package Baz::Meta::Attribute; + use Moose; + extends 'Moose::Meta::Attribute'; +} + +like( exception { + Moose::Meta::Class->reinitialize( + 'Baz', + method_metaclass => 'Baz::Meta::Method', + attribute_metaclass => 'Baz::Meta::Attribute', + ); +}, qr/\QAttribute (class_name) is required/ ); + +{ + package Quux; + use Moose; + sub foo { } + before foo => sub { }; + has bar => (is => 'ro'); + sub DEMOLISH { } + __PACKAGE__->meta->make_immutable; +} + +ok(Quux->meta->has_method('new')); +isa_ok(Quux->meta->get_method('new'), 'Moose::Meta::Method::Constructor'); +ok(Quux->meta->has_method('meta')); +isa_ok(Quux->meta->get_method('meta'), 'Moose::Meta::Method::Meta'); +ok(Quux->meta->has_method('foo')); +isa_ok(Quux->meta->get_method('foo'), 'Class::MOP::Method::Wrapped'); +ok(Quux->meta->has_method('bar')); +isa_ok(Quux->meta->get_method('bar'), 'Moose::Meta::Method::Accessor'); +ok(Quux->meta->has_method('DESTROY')); +isa_ok(Quux->meta->get_method('DESTROY'), 'Moose::Meta::Method::Destructor'); +ok(Quux->meta->has_method('DEMOLISH')); +isa_ok(Quux->meta->get_method('DEMOLISH'), 'Moose::Meta::Method'); + +Quux->meta->make_mutable; +Moose::Meta::Class->reinitialize('Quux'); +Quux->meta->make_immutable; + +ok(Quux->meta->has_method('new')); +isa_ok(Quux->meta->get_method('new'), 'Moose::Meta::Method::Constructor'); +ok(Quux->meta->has_method('meta')); +isa_ok(Quux->meta->get_method('meta'), 'Moose::Meta::Method::Meta'); +ok(Quux->meta->has_method('foo')); +isa_ok(Quux->meta->get_method('foo'), 'Class::MOP::Method::Wrapped'); +ok(Quux->meta->has_method('bar')); +isa_ok(Quux->meta->get_method('bar'), 'Moose::Meta::Method::Accessor'); +ok(Quux->meta->has_method('DESTROY')); +isa_ok(Quux->meta->get_method('DESTROY'), 'Moose::Meta::Method::Destructor'); +ok(Quux->meta->has_method('DEMOLISH')); +isa_ok(Quux->meta->get_method('DEMOLISH'), 'Moose::Meta::Method'); + +Quux->meta->make_mutable; +Moose::Util::MetaRole::apply_metaroles( + for => 'Quux', + class_metaroles => { + method => ['Foo::Role::Method'], + attribute => ['Foo::Role::Attribute'], + }, +); +Quux->meta->make_immutable; + +ok(Quux->meta->has_method('new')); +isa_ok(Quux->meta->get_method('new'), 'Moose::Meta::Method::Constructor'); +{ local $TODO = "constructor methods don't get metaroles yet"; +does_ok(Quux->meta->get_method('new'), 'Foo::Role::Method'); +} +ok(Quux->meta->has_method('meta')); +isa_ok(Quux->meta->get_method('meta'), 'Moose::Meta::Method::Meta'); +{ local $TODO = "meta methods don't get metaroles yet"; +does_ok(Quux->meta->get_method('meta'), 'Foo::Role::Method'); +} +ok(Quux->meta->has_method('foo')); +isa_ok(Quux->meta->get_method('foo'), 'Class::MOP::Method::Wrapped'); +{ local $TODO = "modified methods don't get metaroles yet"; +does_ok(Quux->meta->get_method('foo'), 'Foo::Role::Method'); +} +ok(Quux->meta->has_method('bar')); +isa_ok(Quux->meta->get_method('bar'), 'Moose::Meta::Method::Accessor'); +{ local $TODO = "accessor methods don't get metaroles yet"; +does_ok(Quux->meta->get_method('bar'), 'Foo::Role::Method'); +} +ok(Quux->meta->has_method('DESTROY')); +isa_ok(Quux->meta->get_method('DESTROY'), 'Moose::Meta::Method::Destructor'); +{ local $TODO = "destructor methods don't get metaroles yet"; +does_ok(Quux->meta->get_method('DESTROY'), 'Foo::Role::Method'); +} +ok(Quux->meta->has_method('DEMOLISH')); +isa_ok(Quux->meta->get_method('DEMOLISH'), 'Moose::Meta::Method'); +does_ok(Quux->meta->get_method('DEMOLISH'), 'Foo::Role::Method'); + +{ + package Role3; + use Moose::Role; + with 'Role1', 'Role2'; +} + +ok( Role3->meta->does_role('Role1'), 'Role3 does Role1' ); +ok( Role3->meta->does_role('Role2'), 'Role3 does Role2' ); + +Moose::Meta::Role->reinitialize('Role3'); + +ok( Role3->meta->does_role('Role1'), 'Role3 does Role1 after reinitialize' ); +ok( Role3->meta->does_role('Role2'), 'Role3 does Role2 after reinitialize' ); + +done_testing; |