# 03_properties.t # # Tests the various property types and scoping use Test::More tests => 92; use strict; use warnings; package Foo; use vars qw(@ISA); use Class::EHierarchy qw(:all); @ISA = qw(Class::EHierarchy); sub _initialize ($@) { my $self = shift; my @args = @_; _declProp( $self, CEH_PRIV | CEH_SCALAR, qw(PrivFoo) ); _declProp( $self, CEH_PRIV | CEH_ARRAY, qw(PrivFooArray) ); _declProp( $self, CEH_PRIV | CEH_HASH, qw(PrivFooHash) ); _declProp( $self, CEH_RESTR | CEH_SCALAR, qw(RestrFoo) ); _declProp( $self, CEH_RESTR | CEH_ARRAY, qw(RestrFooArray) ); _declProp( $self, CEH_PUB | CEH_SCALAR, qw(PubFoo) ); $self->property( 'PrivFoo', 'foo!' ); $self->property( 'RestrFoo', 'rfoo!' ); $self->property( 'PubFoo', 'pfoo!' ); $self->property( 'PrivFooArray', qw(f1 f2 f3) ); $self->property( 'RestrFooArray', qw(f11 f12 f13) ); $self->property( 'PrivFooHash', qw(f1 one f2 two f3 three) ); return 1; } sub call ($$$) { my $self = shift; my $obj = shift; my $prop = shift; return $obj->property( $prop, @_ ); } sub cpurge ($$) { my $self = shift; my $prop = shift; return $self->purge($prop); } 1; package Bar; use vars qw(@ISA); use Class::EHierarchy qw(:all); @ISA = qw(Class::EHierarchy); sub _initialize ($@) { my $self = shift; my @args = @_; _declProp( $self, CEH_PRIV | CEH_SCALAR, qw(PrivBar) ); _declProp( $self, CEH_PRIV | CEH_ARRAY, qw(PrivBarArray) ); _declProp( $self, CEH_PRIV | CEH_HASH, qw(PrivBarHash) ); _declProp( $self, CEH_RESTR | CEH_SCALAR, qw(RestrBar) ); _declProp( $self, CEH_RESTR | CEH_ARRAY, qw(RestrBarArray) ); _declProp( $self, CEH_RESTR | CEH_HASH, qw(RestrBarHash) ); _declProp( $self, CEH_PUB | CEH_CODE, qw(PubBar) ); $self->property( 'PrivBar', 'bar!' ); $self->property( 'RestrBar', 'rbar!' ); $self->property( 'PubBar', 'pbar!' ); $self->property( 'PrivBarArray', qw(b1 b2 b3 b4) ); $self->property( 'RestrBarArray', qw(b11 b12 b13 b14) ); $self->property( 'PrivBarHash', qw(b1 one b2 two b3 three) ); $self->property( 'RestrBarHash', qw(b11 one b12 two b13 three) ); return 1; } sub call ($$$) { my $self = shift; my $obj = shift; my $prop = shift; return $obj->property( $prop, @_ ); } sub callNames ($$) { my $self = shift; my $obj = shift; return $obj->propertyNames; } sub cpurge ($$) { my $self = shift; my $prop = shift; return $self->purge($prop); } 1; package Roo; use vars qw(@ISA); use Class::EHierarchy qw(:all); @ISA = qw(Bar); sub _initialize ($@) { my $self = shift; my @args = @_; _declProp( $self, CEH_PRIV | CEH_SCALAR, qw(PrivRoo PrivBar) ); _declProp( $self, CEH_PRIV | CEH_ARRAY, qw(PrivBarArray) ); _declProp( $self, CEH_RESTR | CEH_HASH, qw(RestrRooHash) ); _declProp( $self, CEH_PUB | CEH_ARRAY, qw(PubArray) ); _declProp( $self, CEH_PUB | CEH_HASH, qw(PubHash) ); _declProp( $self, CEH_PUB | CEH_REF | CEH_NO_UNDEF, qw(PubRef) ); $self->property( 'PrivRoo', 'roo!' ); $self->property( 'PrivBar', 'roo-bar!' ); $self->property( 'PrivBarArray', qw(r1) ); $self->property( 'RestrRooHash', qw(r11 one r12 two r13 three) ); return 1; } sub call ($$$) { my $self = shift; my $obj = shift; my $prop = shift; return $obj->property( $prop, @_ ); } sub callNames ($$) { my $self = shift; my $obj = shift; return $obj->propertyNames; } sub cpurge ($$) { my $self = shift; my $prop = shift; return $self->purge($prop); } 1; package main; my $class1a = new Foo; my $class1b = new Foo; my $class2a = new Bar; my $class2b = new Bar; my $class3a = new Roo; my $class3b = new Roo; my $rv; # Test subclass instantiation ok( defined $class1a, 'Created object for class Foo 1' ); ok( defined $class1b, 'Created object for class Foo 2' ); ok( $class1a->isa('Foo'), 'Verify class Foo 1' ); ok( $class1a->isa('Class::EHierarchy'), 'Verify class Foo inheritance 1' ); ok( defined $class2a, 'Created object for class Bar 1' ); ok( defined $class2b, 'Created object for class Bar 2' ); ok( $class2a->isa('Bar'), 'Verify class Bar 1' ); ok( $class2a->isa('Class::EHierarchy'), 'Verify class Bar inheritance 1' ); ok( defined $class3a, 'Created object for class Roo 1' ); ok( defined $class3b, 'Created object for class Roo 2' ); ok( $class3a->isa('Roo'), 'Verify class Roo 1' ); ok( $class3a->isa('Class::EHierarchy'), 'Verify class Roo inheritance 1' ); ok( $class3a->isa('Bar'), 'Verify class Roo inheritance 2' ); # Set extra copies of objects to different property values ok( $class1b->call( $class1b, qw(PrivFoo nope!) ), 'Foo prep 1' ); is( $class1b->call( $class1b, qw(PrivFoo) ), 'nope!', 'Foo prep validate 1' ); ok( $class1b->call( $class1b, qw(RestrFoo nope) ), 'Foo prep 2' ); is( $class1b->call( $class1b, qw(RestrFoo) ), 'nope', 'Foo prep validate 2' ); ok( $class2b->call( $class2b, qw(PrivBar nope!) ), 'Bar prep 1' ); is( $class2b->call( $class2b, qw(PrivBar) ), 'nope!', 'Bar prep validate 1' ); ok( $class2b->call( $class2b, qw(RestrBar nope) ), 'Bar prep 2' ); is( $class2b->call( $class2b, qw(RestrBar) ), 'nope', 'Bar prep validate 2' ); ok( $class3b->call( $class3b, qw(PrivRoo nope!) ), 'Roo prep 1' ); is( $class3b->call( $class3b, qw(PrivRoo) ), 'nope!', 'Roo prep validate 1' ); ok( $class3b->call( $class3b, qw(PrivBar nope!) ), 'Roo prep 2' ); is( $class3b->call( $class3b, qw(PrivBar) ), 'nope!', 'Roo prep validate 2' ); # Scalar Private Property tests # # Call from same class should succeed is( $class1b->call( $class1a, qw(PrivFoo) ) , 'foo!', 'Foo Private Scalar Property Get 1' ); is( $class2b->call( $class2a, qw(PrivBar) ) , 'bar!', 'Bar Private Scalar Property Get 1' ); is( $class3b->call( $class3a, qw(PrivRoo) ) , 'roo!', 'Roo Private Scalar Property Get 1' ); # Call from different class shoud fail $rv = eval '$class2a->call($class1a, qw(PrivFoo)); 1;'; ok( !$rv, 'Bar calling Foo Private Scalar 1' ); $rv = eval '$class1a->call($class2a, qw(PrivBar)); 1;'; ok( !$rv, 'Foo calling Bar Private Scalar 1' ); $rv = eval '$class3a->call($class2a, qw(PrivBar)); 1;'; ok( !$rv, 'Roo calling Bar Private Scalar 1' ); # Check class protection of private name collisions is( $class2b->call( $class3a, qw(PrivBar)), 'bar!', 'Class Collision 1' ); is( $class3b->call( $class3a, qw(PrivBar)), 'roo-bar!', 'Class Collision 2' ); ok( $class3b->call( $class3a, qw(PrivBar nrp-bar!) ), 'Class Collision 3' ); ok( $class2b->call( $class3a, qw(PrivBar nbp-bar!) ), 'Class Collision 4' ); is( $class2b->call( $class3a, qw(PrivBar)), 'nbp-bar!', 'Class Collision 5' ); is( $class3b->call( $class3a, qw(PrivBar)), 'nrp-bar!', 'Class Collision 6' ); # Scalar Restricted Property tests # # Calls from same class should succeed is( $class1b->call( $class1a, qw(RestrFoo) ) , 'rfoo!', 'Foo Restricted Scalar Property Get 1' ); is( $class2b->call( $class2a, qw(RestrBar) ) , 'rbar!', 'Bar Restricted Scalar Property Get 1' ); # Calls from subclasses should succeed is( $class3b->call( $class2a, qw(RestrBar) ) , 'rbar!', 'Bar Restricted Property Get 2' ); is( $class3b->call( $class3a, qw(RestrBar) ) , 'rbar!', 'Bar Restricted Property Get 3' ); # Calls from elsewhere should fail $rv = eval '$class1a->call($class2a, qw(RestrBar)); 1;'; ok( !$rv, 'Foo calling Bar Restricted Scalar 1' ); $rv = eval '$class2a->property(qw(RestrBar)); 1;'; ok( !$rv, 'Main calling Bar Restricted Scalar 1' ); # Set extra copies of objects to different property values ok( $class1b->cpurge( qw(PrivFooArray)), 'Foo prep 3' ); $rv = [ $class1b->call( $class1b, qw(PrivFooArray)) ]; is( scalar @$rv, 0, 'Foo prep validate 3' ); ok( $class2b->cpurge( qw(PrivBarArray)), 'Bar prep 3' ); $rv = [ $class2b->call( $class2b, qw(PrivBarArray)) ]; is( scalar @$rv, 0, 'Bar prep validate 3' ); ok( $class3b->cpurge( qw(PrivBarArray)), 'Roo prep 3' ); $rv = [ $class3b->call( $class3b, qw(PrivBarArray)) ]; is( scalar @$rv, 0, 'Roo prep validate 3' ); # Array Private Property tests # # Call from same class should succeed $rv = [ $class1b->call( $class1a, qw(PrivFooArray)) ]; is( scalar @$rv, 3, 'Foo Private Array Property Get 1' ); is( $$rv[1], 'f2', 'Foo Private Array Property Get 2' ); $rv = [ $class2b->call( $class2a, qw(PrivBarArray)) ]; is( scalar @$rv, 4, 'Bar Private Array Property Get 1' ); is( $$rv[1], 'b2', 'Bar Private Array Property Get 2' ); $rv = [ $class3b->call( $class3a, qw(PrivBarArray)) ]; is( scalar @$rv, 1, 'Roo Private Array Property Get 1' ); is( $$rv[0], 'r1', 'Roo Private Array Property Get 2' ); # Call from different class shoud fail $rv = eval '$class2a->call($class1a, qw(PrivFooArray)); 1;'; ok( !$rv, 'Bar calling Foo Private Array 1' ); $rv = eval '$class1a->call($class2a, qw(PrivBarArray)); 1;'; ok( !$rv, 'Foo calling Bar Private Array 1' ); $rv = eval '$class3a->call($class2a, qw(PrivBarArray)); 1;'; ok( !$rv, 'Roo calling Bar Private Array 1' ); # Array Restricted Property tests # # Calls from same class should succeed $rv = [ $class1b->call( $class1a, qw(RestrFooArray)) ]; is( scalar @$rv, 3, 'Foo Restricted Array Property Get 1' ); is( $$rv[1], 'f12', 'Foo Restricted Array Property Get 2' ); $rv = [ $class2b->call( $class2a, qw(RestrBarArray)) ]; is( scalar @$rv, 4, 'Bar Restricted Array Property Get 1' ); is( $$rv[1], 'b12', 'Bar Restricted Array Property Get 2' ); # Calls from subclasses should succeed $rv = [ $class3b->call( $class2a, qw(RestrBarArray)) ]; is( scalar @$rv, 4, 'Bar from Roo Restricted Array Property Get 1' ); is( $$rv[1], 'b12', 'Bar from Roo Restricted Array Property Get 2' ); # Calls from elsewhere should fail $rv = eval '$class1b->call( $class2a, qw(RestrBarArray)); 1;'; ok( !$rv, 'Foo calling Bar Restricted Array 1' ); $rv = eval '$class3a->property(qw(RestrBarArray)); 1;'; ok( !$rv, 'Main calling Roo Restricted Array 1' ); # Set extra copies of objects to different property values ok( $class1b->cpurge( qw(PrivFooHash)), 'Foo prep 4' ); $rv = [ $class1b->call( $class1b, qw(PrivFooHash)) ]; is( scalar @$rv, 0, 'Foo prep validate 4' ); ok( $class2b->cpurge( qw(PrivBarHash)), 'Bar prep 4' ); $rv = [ $class2b->call( $class2b, qw(PrivBarHash)) ]; is( scalar @$rv, 0, 'Bar prep validate 4' ); # Hash Private Property tests # # Calls from same class should succeed $rv = { $class1b->call( $class1a, qw(PrivFooHash)) }; is( $$rv{f1}, 'one', 'Foo Private Hash Property Get 1' ); $rv = { $class2b->call( $class2a, qw(PrivBarHash)) }; is( $$rv{b3}, 'three', 'Bar Private Hash Property Get 1' ); # Call from different class shoud fail $rv = eval '$class2a->call($class1a, qw(PrivFooHash)); 1;'; ok( !$rv, 'Bar calling Foo Private Hash 1' ); $rv = eval '$class3a->call($class2a, qw(PrivBarHash)); 1;'; ok( !$rv, 'Roo calling Bar Private Hash 1' ); # Hash Restricted Property tests # # Calls from same class should succeed $rv = { $class3b->call( $class2a, qw(RestrBarHash)) }; is( $$rv{b12}, 'two', 'Bar Restricted Hash Property Get 1' ); # Calls from elsewhere should fail $rv = eval '$class1b->call( $class2a, qw(RestrBarHash)); 1;'; ok( !$rv, 'Foo calling Bar Restricted Hash 1' ); $rv = eval '$class2b->call( $class3a, qw(RestrRooHash)); 1;'; ok( !$rv, 'Bar calling Roo Restricted Hash 1' ); # Public array tests $rv = [ $class3a->property('PubArray') ]; is( scalar @$rv, 0, 'Public Array Get 1' ); $rv = $class3a->property( 'PubArray', qw(three two one) ); ok( $rv, 'Public Array Set 1' ); $rv = [ $class3a->property('PubArray') ]; is( $$rv[0], 'three', 'Public Array Get 2' ); # Public hash tests $rv = { $class3a->property('PubHash') }; is( scalar keys %$rv, 0, 'Public Hash Get 1' ); $rv = $class3a->property( 'PubHash', foo => 'bar' ); ok( $rv, 'Public Hash Set 1' ); $rv = { $class3a->property('PubHash') }; is( scalar keys %$rv, 1, 'Public Hash Get 2' ); is( $$rv{foo}, 'bar', 'Public Hash Get 3' ); # Public ref tests $rv = $class3a->property('PubRef'); is( $rv, undef, 'Public Ref Get 1' ); $rv = $class3a->property( 'PubRef', qr/foo/ ); ok( $rv, 'Public Ref Set 1' ); $rv = $class3a->property('PubRef'); is( $rv, qr/foo/, 'Public Ref Get 2' ); $rv = $class3a->property( 'PubRef', undef ); ok( !$rv, 'Public Ref Set 2' ); $rv = $class3a->property('PubRef'); is( $rv, qr/foo/, 'Public Ref Get 3' ); # Test propertyNames my @names = $class1a->propertyNames; is( scalar @names, 1, 'Public Property Names 1' ); @names = $class3b->callNames($class2a); is( scalar @names, 4, 'Restricted Property Names 1' ); @names = $class2b->callNames($class2a); is( scalar @names, 7, 'Private Property Names 1' ); # end 03_properties.t