1#!./perl -w 2 3BEGIN { 4 chdir 't' if -d 't'; 5 @INC = '../lib'; 6} 7 8# 9# A couple of simple classes to use as struct elements. 10# 11package aClass; 12sub new { bless {}, shift } 13sub meth { 42 } 14 15package RecClass; 16sub new { bless {}, shift } 17 18# 19# The first of our Class::Struct based objects. 20# 21package MyObj; 22use Class::Struct; 23use Class::Struct 'struct'; # test out both forms 24use Class::Struct SomeClass => { SomeElem => '$' }; 25 26struct( s => '$', a => '@', h => '%', c => 'aClass' ); 27 28# 29# The second Class::Struct objects: 30# test the 'compile-time without package name' feature. 31# 32package MyOther; 33use Class::Struct s => '$', a => '@', h => '%', c => 'aClass'; 34 35# 36# test overriden accessors 37# 38package OverrideAccessor; 39use Class::Struct; 40 41{ 42 no warnings qw(Class::Struct); 43 struct( 'OverrideAccessor', { count => '$' } ); 44} 45 46sub count { 47 my ($self,$count) = @_; 48 49 if ( @_ >= 2 ) { 50 $self->{'OverrideAccessor::count'} = $count + 9; 51 } 52 53 return $self->{'OverrideAccessor::count'}; 54} 55 56# 57# back to main... 58# 59package main; 60 61use Test::More; 62 63my $obj = MyObj->new; 64isa_ok $obj, 'MyObj'; 65 66$obj->s('foo'); 67is $obj->s(), 'foo'; 68 69isa_ok $obj->a, 'ARRAY'; 70$obj->a(2, 'secundus'); 71is $obj->a(2), 'secundus'; 72 73$obj->a([4,5,6]); 74is $obj->a(1), 5; 75 76isa_ok $obj->h, 'HASH'; 77$obj->h('x', 10); 78is $obj->h('x'), 10; 79 80$obj->h({h=>7,r=>8,f=>9}); 81is $obj->h('r'), 8; 82 83is $obj->c, undef; 84 85$obj = MyObj->new( c => aClass->new ); 86isa_ok $obj->c, 'aClass'; 87is $obj->c->meth(), 42; 88 89 90$obj = MyOther->new; 91isa_ok $obj, 'MyOther'; 92 93$obj->s('foo'); 94is $obj->s(), 'foo'; 95 96isa_ok $obj->a, 'ARRAY'; 97$obj->a(2, 'secundus'); 98is $obj->a(2), 'secundus'; 99 100$obj->a([4,5,6]); 101is $obj->a(1), 5; 102 103isa_ok $obj->h, 'HASH'; 104$obj->h('x', 10); 105is $obj->h('x'), 10; 106 107$obj->h({h=>7,r=>8,f=>9}); 108is $obj->h('r'), 8; 109 110is $obj->c, undef; 111 112$obj = MyOther->new( c => aClass->new ); 113isa_ok $obj->c, 'aClass'; 114is $obj->c->meth(), 42; 115 116 117 118my $obk = SomeClass->new(); 119$obk->SomeElem(123); 120is $obk->SomeElem(), 123; 121 122my $recobj = RecClass->new(); 123isa_ok $recobj, 'RecClass'; 124 125my $override_obj = OverrideAccessor->new( count => 3 ); 126is $override_obj->count, 12; 127 128$override_obj->count( 1 ); 129is $override_obj->count, 10; 130 131 132use Class::Struct Kapow => { z_zwap => 'Regexp', sploosh => 'MyObj' }; 133 134is eval { main->new(); }, undef, 135 'No new method injected into current package'; 136 137my $obj3 = Kapow->new(); 138 139isa_ok $obj3, 'Kapow'; 140is $obj3->z_zwap, undef, 'No z_zwap member by default'; 141is $obj3->sploosh, undef, 'No sploosh member by default'; 142$obj3->z_zwap(qr//); 143isa_ok $obj3->z_zwap, 'Regexp', 'Can set z_zwap member'; 144$obj3->sploosh(MyObj->new(s => 'pie')); 145isa_ok $obj3->sploosh, 'MyObj', 146 'Can set sploosh member to object of correct class'; 147is $obj3->sploosh->s, 'pie', 'Can set sploosh member to correct object'; 148 149my $obj4 = Kapow->new( z_zwap => qr//, sploosh => MyObj->new(a => ['Good']) ); 150 151isa_ok $obj4, 'Kapow'; 152isa_ok $obj4->z_zwap, 'Regexp', 'Initialised z_zwap member'; 153isa_ok $obj4->sploosh, 'MyObj', 'Initialised sploosh member'; 154is_deeply $obj4->sploosh->a, ['Good'], 'with correct object'; 155 156my $obj5 = Kapow->new( sploosh => { h => {perl => 'rules'} } ); 157 158isa_ok $obj5, 'Kapow'; 159is $obj5->z_zwap, undef, 'No z_zwap member by default'; 160isa_ok $obj5->sploosh, 'MyObj', 'Initialised sploosh member from hash'; 161is_deeply $obj5->sploosh->h, { perl => 'rules'} , 'with correct object'; 162 163is eval { 164 package MyObj; 165 struct( s => '$', a => '@', h => '%', c => 'aClass' ); 166}, undef, 'Calling struct a second time fails'; 167 168like $@, qr/^function 'new' already defined in package MyObj/, 169 'fails with the expected error'; 170 171is eval { MyObj->new( a => {} ) }, undef, 172 'Using a hash where an array reference is expected'; 173like $@, qr/^Initializer for a must be array reference/, 174 'fails with the expected error'; 175 176is eval { MyObj->new( h => [] ) }, undef, 177 'Using an array where a hash reference is expected'; 178like $@, qr/^Initializer for h must be hash reference/, 179 'fails with the expected error'; 180 181is eval { Kapow->new( sploosh => { h => [perl => 'rules'] } ); }, undef, 182 'Using an array where a hash reference is expected in an initialiser list'; 183like $@, qr/^Initializer for h must be hash reference/, 184 'fails with the expected error'; 185 186is eval { Kapow->new( sploosh => [ h => {perl => 'rules'} ] ); }, undef, 187 "Using an array for a member object's initialiser list"; 188like $@, qr/^Initializer for sploosh must be hash or MyObj reference/, 189 'fails with the expected error'; 190 191is eval { 192 package Crraack; 193 use Class::Struct 'struct'; 194 struct( 'pow' => '@$%!' ); 195}, undef, 'Bad type fails'; 196like $@, qr/^'\@\$\%\!' is not a valid struct element type/, 197 'with the expected error'; 198 199is eval { 200 $obj3->sploosh(MyOther->new(s => 3.14)); 201}, undef, 'Setting member to the wrong class of object fails'; 202like $@, qr/^sploosh argument is wrong class/, 203 'with the expected error'; 204is $obj3->sploosh->s, 'pie', 'Object is unchanged'; 205 206is eval { 207 $obj3->sploosh(MyObj->new(s => 3.14), 'plop'); 208}, undef, 'Too many arguments to setter fails'; 209like $@, qr/^Too many args to sploosh/, 210 'with the expected error'; 211is $obj3->sploosh->s, 'pie', 'Object is unchanged'; 212 213is eval { 214 package Blurp; 215 use Class::Struct 'struct'; 216 struct( Blurp => {}, 'Bonus!' ); 217}, undef, 'hash based class with extra argument fails'; 218like $@, qr/\Astruct usage error.*\n.*\n/, 219 'with the expected confession'; 220 221is eval { 222 package Zamm; 223 use Class::Struct 'struct'; 224 struct( Zamm => [], 'Bonus!' ); 225}, undef, 'array based class with extra argument fails'; 226like $@, qr/\Astruct usage error.*\n.*\n/, 227 'with the expected confession'; 228 229is eval { 230 package Thwapp; 231 use Class::Struct 'struct'; 232 struct( Thwapp => ['Bonus!'] ); 233}, undef, 'array based class with extra constructor argument fails'; 234like $@, qr/\Astruct usage error.*\n.*\n/, 235 'with the expected confession'; 236 237is eval { 238 package Rakkk; 239 use Class::Struct 'struct'; 240 struct( z_zwap => 'Regexp', sploosh => 'MyObj', 'Bonus' ); 241}, undef, 'default array based class with extra constructor argument fails'; 242like $@, qr/\Astruct usage error.*\n.*\n/, 243 'with the expected confession'; 244 245is eval { 246 package Awk; 247 use parent -norequire, 'Urkkk'; 248 use Class::Struct 'struct'; 249 struct( beer => 'foamy' ); 250}, undef, '@ISA is not allowed'; 251like $@, qr/^struct class cannot be a subclass \(\@ISA not allowed\)/, 252 'with the expected error'; 253 254done_testing; 255