X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2F020_attributes%2F010_attribute_delegation.t;h=45505a11f5984794e3445a291468aa6394c821cd;hb=d03bd989b97597428b460d7f9a021e2931893fa0;hp=9e31583f2c7116232bc919249d992869cc41bb06;hpb=f4f3e701eaa9973098856eee76d199913b000a7e;p=gitmo%2FMoose.git diff --git a/t/020_attributes/010_attribute_delegation.t b/t/020_attributes/010_attribute_delegation.t index 9e31583..45505a1 100644 --- a/t/020_attributes/010_attribute_delegation.t +++ b/t/020_attributes/010_attribute_delegation.t @@ -3,29 +3,27 @@ use strict; use warnings; -use Test::More tests => 58; +use Test::More tests => 88; use Test::Exception; -BEGIN { - use_ok('Moose'); -} + # ------------------------------------------------------------------- # HASH handles # ------------------------------------------------------------------- # the canonical form of of the 'handles' -# option is the hash ref mapping a +# option is the hash ref mapping a # method name to the delegated method name { package Foo; use Moose; - has 'bar' => (is => 'rw', default => 10); + has 'bar' => (is => 'rw', default => 10); package Bar; - use Moose; - + use Moose; + has 'foo' => ( is => 'rw', default => sub { Foo->new }, @@ -39,6 +37,11 @@ isa_ok($bar, 'Bar'); ok($bar->foo, '... we have something in bar->foo'); isa_ok($bar->foo, 'Foo'); +my $meth = Bar->meta->get_method('foo_bar'); +isa_ok($meth, 'Moose::Meta::Method::Delegation'); +is($meth->associated_attribute->name, 'foo', + 'associated_attribute->name for this method is foo'); + is($bar->foo->bar, 10, '... bar->foo->bar returned the right default'); can_ok($bar, 'foo_bar'); @@ -57,7 +60,7 @@ is($bar->foo_bar, 30, '... bar->foo_bar delegated correctly'); $bar->foo_bar(50); -# and make sure everyone sees it +# and make sure everyone sees it is($bar->foo->bar, 50, '... bar->foo->bar returned the right (changed) value'); is($bar->foo_bar, 50, '... bar->foo_bar delegated correctly'); @@ -79,10 +82,10 @@ is($bar->foo->bar, 25, '... bar->foo->bar returned the right result'); is($bar->foo_bar, 25, '... and bar->foo_bar delegated correctly again'); # ------------------------------------------------------------------- -# ARRAY handles +# ARRAY handles # ------------------------------------------------------------------- # we also support an array based format -# which assumes that the name is the same +# which assumes that the name is the same # on either end { @@ -90,11 +93,11 @@ is($bar->foo_bar, 25, '... and bar->foo_bar delegated correctly again'); use Moose; sub go { 'Engine::go' } - sub stop { 'Engine::stop' } + sub stop { 'Engine::stop' } package Car; - use Moose; - + use Moose; + has 'engine' => ( is => 'rw', default => sub { Engine->new }, @@ -119,7 +122,7 @@ is($car->go, 'Engine::go', '... got the right value from ->go'); is($car->stop, 'Engine::stop', '... got the right value from ->stop'); # ------------------------------------------------------------------- -# REGEXP handles +# REGEXP handles # ------------------------------------------------------------------- # and we support regexp delegation @@ -128,38 +131,38 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); use Moose; sub foo { 'Baz::foo' } - sub bar { 'Baz::bar' } - sub boo { 'Baz::boo' } + sub bar { 'Baz::bar' } + sub boo { 'Baz::boo' } package Baz::Proxy1; - use Moose; - + use Moose; + has 'baz' => ( is => 'ro', isa => 'Baz', default => sub { Baz->new }, handles => qr/.*/ ); - + package Baz::Proxy2; - use Moose; - + use Moose; + has 'baz' => ( is => 'ro', isa => 'Baz', default => sub { Baz->new }, handles => qr/.oo/ - ); - + ); + package Baz::Proxy3; - use Moose; - + use Moose; + has 'baz' => ( is => 'ro', isa => 'Baz', default => sub { Baz->new }, handles => qr/b.*/ - ); + ); } { @@ -172,10 +175,10 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); can_ok($baz_proxy, 'foo'); can_ok($baz_proxy, 'bar'); can_ok($baz_proxy, 'boo'); - + is($baz_proxy->foo, 'Baz::foo', '... got the right proxied return value'); is($baz_proxy->bar, 'Baz::bar', '... got the right proxied return value'); - is($baz_proxy->boo, 'Baz::boo', '... got the right proxied return value'); + is($baz_proxy->boo, 'Baz::boo', '... got the right proxied return value'); } { my $baz_proxy = Baz::Proxy2->new; @@ -186,9 +189,9 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); can_ok($baz_proxy, 'foo'); can_ok($baz_proxy, 'boo'); - + is($baz_proxy->foo, 'Baz::foo', '... got the right proxied return value'); - is($baz_proxy->boo, 'Baz::boo', '... got the right proxied return value'); + is($baz_proxy->boo, 'Baz::boo', '... got the right proxied return value'); } { my $baz_proxy = Baz::Proxy3->new; @@ -199,9 +202,9 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); can_ok($baz_proxy, 'bar'); can_ok($baz_proxy, 'boo'); - + is($baz_proxy->bar, 'Baz::bar', '... got the right proxied return value'); - is($baz_proxy->boo, 'Baz::boo', '... got the right proxied return value'); + is($baz_proxy->boo, 'Baz::boo', '... got the right proxied return value'); } # ------------------------------------------------------------------- @@ -211,22 +214,22 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); { package Foo::Bar; use Moose::Role; - + requires 'foo'; requires 'bar'; - + package Foo::Baz; use Moose; - + sub foo { 'Foo::Baz::FOO' } sub bar { 'Foo::Baz::BAR' } - sub baz { 'Foo::Baz::BAZ' } - + sub baz { 'Foo::Baz::BAZ' } + package Foo::Thing; use Moose; - + has 'thing' => ( - is => 'rw', + is => 'rw', isa => 'Foo::Baz', handles => 'Foo::Bar', ); @@ -237,13 +240,173 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); my $foo = Foo::Thing->new(thing => Foo::Baz->new); isa_ok($foo, 'Foo::Thing'); isa_ok($foo->thing, 'Foo::Baz'); - + ok($foo->meta->has_method('foo'), '... we have the method we expect'); ok($foo->meta->has_method('bar'), '... we have the method we expect'); - ok(!$foo->meta->has_method('baz'), '... we dont have the method we expect'); - - is($foo->foo, 'Foo::Baz::FOO', '... got the right value'); + ok(!$foo->meta->has_method('baz'), '... we dont have the method we expect'); + + is($foo->foo, 'Foo::Baz::FOO', '... got the right value'); is($foo->bar, 'Foo::Baz::BAR', '... got the right value'); - is($foo->thing->baz, 'Foo::Baz::BAZ', '... got the right value'); + is($foo->thing->baz, 'Foo::Baz::BAZ', '... got the right value'); +} + +# ------------------------------------------------------------------- +# AUTOLOAD & handles +# ------------------------------------------------------------------- + +{ + package Foo::Autoloaded; + use Moose; + + sub AUTOLOAD { + my $self = shift; + + my $name = our $AUTOLOAD; + $name =~ s/.*://; # strip fully-qualified portion + + if (@_) { + return $self->{$name} = shift; + } else { + return $self->{$name}; + } + } + + package Bar::Autoloaded; + use Moose; + + has 'foo' => ( + is => 'rw', + default => sub { Foo::Autoloaded->new }, + handles => { 'foo_bar' => 'bar' } + ); + + package Baz::Autoloaded; + use Moose; + + has 'foo' => ( + is => 'rw', + default => sub { Foo::Autoloaded->new }, + handles => ['bar'] + ); + + package Goorch::Autoloaded; + use Moose; + + ::dies_ok { + has 'foo' => ( + is => 'rw', + default => sub { Foo::Autoloaded->new }, + handles => qr/bar/ + ); + } '... you cannot delegate to AUTOLOADED class with regexp'; +} + +# check HASH based delegation w/ AUTOLOAD + +{ + my $bar = Bar::Autoloaded->new; + isa_ok($bar, 'Bar::Autoloaded'); + + ok($bar->foo, '... we have something in bar->foo'); + isa_ok($bar->foo, 'Foo::Autoloaded'); + + # change the value ... + + $bar->foo->bar(30); + + # and make sure the delegation picks it up + + is($bar->foo->bar, 30, '... bar->foo->bar returned the right (changed) value'); + is($bar->foo_bar, 30, '... bar->foo_bar delegated correctly'); + + # change the value through the delegation ... + + $bar->foo_bar(50); + + # and make sure everyone sees it + + is($bar->foo->bar, 50, '... bar->foo->bar returned the right (changed) value'); + is($bar->foo_bar, 50, '... bar->foo_bar delegated correctly'); + + # change the object we are delegating too + + my $foo = Foo::Autoloaded->new; + isa_ok($foo, 'Foo::Autoloaded'); + + $foo->bar(25); + + is($foo->bar, 25, '... got the right foo->bar'); + + lives_ok { + $bar->foo($foo); + } '... assigned the new Foo to Bar->foo'; + + is($bar->foo, $foo, '... assigned bar->foo with the new Foo'); + + is($bar->foo->bar, 25, '... bar->foo->bar returned the right result'); + is($bar->foo_bar, 25, '... and bar->foo_bar delegated correctly again'); +} + +# check ARRAY based delegation w/ AUTOLOAD + +{ + my $baz = Baz::Autoloaded->new; + isa_ok($baz, 'Baz::Autoloaded'); + + ok($baz->foo, '... we have something in baz->foo'); + isa_ok($baz->foo, 'Foo::Autoloaded'); + + # change the value ... + + $baz->foo->bar(30); + + # and make sure the delegation picks it up + + is($baz->foo->bar, 30, '... baz->foo->bar returned the right (changed) value'); + is($baz->bar, 30, '... baz->foo_bar delegated correctly'); + + # change the value through the delegation ... + + $baz->bar(50); + + # and make sure everyone sees it + + is($baz->foo->bar, 50, '... baz->foo->bar returned the right (changed) value'); + is($baz->bar, 50, '... baz->foo_bar delegated correctly'); + + # change the object we are delegating too + + my $foo = Foo::Autoloaded->new; + isa_ok($foo, 'Foo::Autoloaded'); + + $foo->bar(25); + + is($foo->bar, 25, '... got the right foo->bar'); + + lives_ok { + $baz->foo($foo); + } '... assigned the new Foo to Baz->foo'; + + is($baz->foo, $foo, '... assigned baz->foo with the new Foo'); + + is($baz->foo->bar, 25, '... baz->foo->bar returned the right result'); + is($baz->bar, 25, '... and baz->foo_bar delegated correctly again'); +} + +# Check that removing attributes removes their handles methods also. +{ + { + package Quux; + use Moose; + has foo => ( + isa => 'Foo', + default => sub { Foo->new }, + handles => { 'foo_bar' => 'bar' } + ); + } + my $i = Quux->new; + ok($i->meta->has_method('foo_bar'), 'handles method foo_bar is present'); + $i->meta->remove_attribute('foo'); + ok(!$i->meta->has_method('foo_bar'), 'handles method foo_bar is removed'); }