#!./perl # This test was originally for pseudo-hashes. It now exists to ensure # they were properly removed in 5.9. BEGIN { chdir 't' if -d 't'; @INC = '../lib'; } require Tie::Array; package Tie::BasicArray; @ISA = 'Tie::Array'; sub TIEARRAY { bless [], $_[0] } sub STORE { $_[0]->[$_[1]] = $_[2] } sub FETCH { $_[0]->[$_[1]] } sub FETCHSIZE { scalar(@{$_[0]})} sub STORESIZE { $#{$_[0]} = $_[1]+1 } package main; require './test.pl'; plan(tests => 40); # Helper function to check the typical error message. sub not_hash { my($err) = shift; like( $err, qr/^Not a HASH reference / ) || printf STDERR "# at %s line %d.\n", (caller)[1,2]; } # Something to place inside if blocks and while loops that won't get # compiled out. my $foo = 42; sub no_op { $foo++ } $sch = { 'abc' => 1, 'def' => 2, 'jkl' => 3, }; # basic normal array $a = []; $a->[0] = $sch; eval { $a->{'abc'} = 'ABC'; }; not_hash($@); eval { $a->{'def'} = 'DEF'; }; not_hash($@); eval { $a->{'jkl'} = 'JKL'; }; not_hash($@); eval { @keys = keys %$a; }; not_hash($@); eval { @values = values %$a; }; not_hash($@); eval { while( my($k,$v) = each %$a ) { no_op; } }; not_hash($@); # quick check with tied array tie @fake, 'Tie::StdArray'; $a = \@fake; $a->[0] = $sch; eval { $a->{'abc'} = 'ABC'; }; not_hash($@); eval { if ($a->{'abc'} eq 'ABC') { no_op(23) } else { no_op(42) } }; not_hash($@); # quick check with tied array tie @fake, 'Tie::BasicArray'; $a = \@fake; $a->[0] = $sch; eval { $a->{'abc'} = 'ABC'; }; not_hash($@); eval { if ($a->{'abc'} eq 'ABC') { no_op(23) } else { no_op(42) } }; not_hash($@); # quick check with tied array & tied hash require Tie::Hash; tie %fake, Tie::StdHash; %fake = %$sch; $a->[0] = \%fake; eval { $a->{'abc'} = 'ABC'; }; not_hash($@); eval { if ($a->{'abc'} eq 'ABC') { no_op(23) } else { no_op(42) } }; not_hash($@); # hash slice eval { my $slice = join('', 'x',@$a{'abc','def'},'x'); }; not_hash($@); # evaluation in scalar context my $avhv = [{}]; eval { () = %$avhv; }; not_hash($@); push @$avhv, "a"; eval { () = %$avhv; }; not_hash($@); $avhv = []; eval { $a = %$avhv }; not_hash($@); $avhv = [{foo=>1, bar=>2}]; eval { %$avhv =~ m,^\d+/\d+,; }; not_hash($@); # check if defelem magic works sub f { print "not " unless $_[0] eq 'a'; $_[0] = 'b'; print "ok 11\n"; } $a = [{key => 1}, 'a']; eval { f($a->{key}); }; not_hash($@); # check if exists() is behaving properly $avhv = [{foo=>1,bar=>2,pants=>3}]; eval { no_op if exists $avhv->{bar}; }; not_hash($@); eval { $avhv->{pants} = undef; }; not_hash($@); eval { no_op if exists $avhv->{pants}; }; not_hash($@); eval { no_op if exists $avhv->{bar}; }; not_hash($@); eval { $avhv->{bar} = 10; }; not_hash($@); eval { no_op unless exists $avhv->{bar} and $avhv->{bar} == 10; }; not_hash($@); eval { $v = delete $avhv->{bar}; }; not_hash($@); eval { no_op if exists $avhv->{bar}; }; not_hash($@); eval { $avhv->{foo} = 'xxx'; }; not_hash($@); eval { $avhv->{bar} = 'yyy'; }; not_hash($@); eval { $avhv->{pants} = 'zzz'; }; not_hash($@); eval { @x = delete @{$avhv}{'foo','pants'}; }; not_hash($@); eval { no_op unless "$avhv->{bar}" eq "yyy"; }; not_hash($@); # hash assignment eval { %$avhv = (); }; not_hash($@); eval { %hv = %$avhv; }; not_hash($@); eval { %$avhv = (foo => 29, pants => 2, bar => 0); }; not_hash($@); my $extra; my @extra; eval { ($extra, %$avhv) = ("moo", foo => 42, pants => 53, bar => "HIKE!"); }; not_hash($@); eval { %$avhv = (); (%$avhv, $extra) = (foo => 42, pants => 53, bar => "HIKE!"); }; not_hash($@); eval { @extra = qw(whatever and stuff); %$avhv = (); }; not_hash($@); eval { (%$avhv, @extra) = (foo => 42, pants => 53, bar => "HIKE!"); }; not_hash($@); eval { (@extra, %$avhv) = (foo => 42, pants => 53, bar => "HIKE!"); }; not_hash($@); # Check hash slices (BUG ID 20010423.002) $avhv = [{foo=>1, bar=>2}]; eval { @$avhv{"foo", "bar"} = (42, 53); }; not_hash($@);