#!perl use strict; use warnings; use Test::More 'no_plan'; use Pad::Tie; package PT; use Test::More; sub scalar_foo { $_[0]->{foo} = $_[1] if @_ > 1; $_[0]->{foo}; } sub bar { return $_[0]->{bar} ||= []; } sub bar_list { my $self = shift; push @{ $self->bar }, @_ if @_; return @{ $self->bar }; } sub hash { $_[0]->{hash} ||= {}; } { my ($self, $foo, @bar, @list, %hash, $color); my (@bar_attr, %hash_attr);; sub test_self { isa_ok $self, 'PT'; $self->scalar_foo("pony"); $self->hash->{one} = 1; $self->hash->{two} = 2; $self->{color} = 'red'; } sub test_scalar { is $foo, 'pony', "scalar content"; is $self->scalar_foo, 'pony', 'self->content'; $foo = 13; is $self->scalar_foo, 13, 'self->content after write'; } sub test_scalar_attr { is $color, 'red', 'scalar attr content'; is $self->{color}, 'red', 'self->content'; $color = 'blue'; is $self->{color}, 'blue', 'self->content after write'; } sub test_array_ref { @{ $self->bar } = (1, 5, 17); is_deeply \@bar, [ 1, 5, 17 ], "array_ref content"; unshift @bar, 23; is_deeply $self->bar, [ 23, 1, 5, 17 ], "self->content after write"; is \@bar, $self->bar, "array_ref and method share ref"; @bar = qw(cheez doodle); is_deeply $self->bar, [ qw(cheez doodle) ], "self->content after write"; shift @{ $self->bar }; is_deeply \@bar, [ qw(doodle) ], "array_ref content after write"; } sub test_array_attr { is_deeply $self->{bar}, [], "empty but existing arrayref"; # assigning $self->{bar} = [ ... ] would break the binding @{$self->{bar}} = qw(lions tigers bears); is_deeply \@bar_attr, [ qw(lions tigers bears) ], "oh my"; is pop @bar_attr, 'bears', "phew, no more bears"; is_deeply $self->{bar}, [ qw(lions tigers) ], "only felines"; @bar_attr = qw(dogs cats); is_deeply $self->{bar}, [ qw(dogs cats) ], "mass hysteria"; } sub test_list { @{$self->bar} = qw(your face); is_deeply [ @list ], [ qw(your face) ], "content from list"; is_deeply [ $self->bar_list ], [ qw(your face) ], "self->content"; # XXX test unsupported behavior: push, shift, etc. is @list, 2, "list size unchanged by read"; eval { $list[1] = 17 }; like $@, qr/do not assign/, "error on single STORE"; @list = qw(my face); is $list[2], 'my', "list content after write" ; is_deeply [ $self->bar_list ], [qw(your face my face)], "self->content after write"; } sub test_hash_ref { is_deeply \%hash, { one => 1, two => 2 }; is \%hash, $self->hash; $self->hash->{three} = 3; is $hash{three}, 3; delete $hash{one}; ok ! exists $self->{hash}->{one}; } sub test_hash_attr { is_deeply $self->{hash}, {}, "empty but existing hashref"; %{ $self->{hash} } = ( apples => 3, oranges => 17, ); is_deeply \%hash_attr, { apples => 3, oranges => 17 }, "correct produce"; delete $hash_attr{apples}; ok ! exists $self->{hash}->{apples}, "apples are gone"; $hash_attr{bananas}++; is $self->{hash}->{bananas}, 1, "we have one banana"; } } package main; my $obj = bless {} => 'PT'; my $pad_tie = Pad::Tie->new( $obj, [ scalar => [ scalar_foo => { -as => 'foo' } ], scalar_attr => [ 'color', ], array_ref => [ 'bar' ], array_attr => [ bar => { -as => 'bar_attr' }, ], hash_ref => [ 'hash' ], hash_attr => [ hash => { -as => 'hash_attr' }, ], list => [ bar_list => { -as => 'list' } ], 'self', ], ); isa_ok $pad_tie, 'Pad::Tie'; $pad_tie->call(\&PT::test_self); $pad_tie->call(\&PT::test_scalar); $pad_tie->call(\&PT::test_scalar_attr); $pad_tie->call(\&PT::test_array_ref); delete $obj->{bar}; $pad_tie->call(\&PT::test_array_attr); $pad_tie->call(\&PT::test_list); $pad_tie->call(\&PT::test_hash_ref); delete $obj->{hash}; $pad_tie->call(\&PT::test_hash_attr); { local $SIG{__WARN__} = sub { unlike $_[0], qr/Odd number of elements/, "no odd elements warning"; }; $pad_tie->call(sub { is @_, 1, "got 1 arg" }, 1); }