# 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