1#!/usr/bin/perl -w 2 3# We skip this on 5.9.0 and up since pseudohashes were removed and a lot of 4# it won't work. 5if( $] >= 5.009 ) { 6 print "1..0 # skip pseudo-hashes removed in 5.9.0\n"; 7 exit; 8} 9 10 11my $w; 12 13BEGIN { 14 $SIG{__WARN__} = sub { 15 if ($_[0] =~ /^Hides field 'b1' in base class/) { 16 $w++; 17 } 18 else { 19 print STDERR $_[0]; 20 } 21 }; 22} 23 24use strict; 25our $DEBUG; 26 27package B1; 28use fields qw(b1 b2 b3); 29 30package B2; 31use fields '_b1'; 32use fields qw(b1 _b2 b2); 33 34sub new { bless [], shift } 35 36package D1; 37use base 'B1'; 38use fields qw(d1 d2 d3); 39 40package D2; 41use base 'B1'; 42use fields qw(_d1 _d2); 43use fields qw(d1 d2); 44 45package D3; 46use base 'B2'; 47use fields qw(b1 d1 _b1 _d1); # hide b1 48 49package D4; 50use base 'D3'; 51use fields qw(_d3 d3); 52 53package M; 54sub m {} 55 56package D5; 57use base qw(M B2); 58 59package Foo::Bar; 60use base 'B1'; 61 62package Foo::Bar::Baz; 63use base 'Foo::Bar'; 64use fields qw(foo bar baz); 65 66# Test repeatability for when modules get reloaded. 67package B1; 68use fields qw(b1 b2 b3); 69 70package D3; 71use base 'B2'; 72use fields qw(b1 d1 _b1 _d1); # hide b1 73 74package main; 75 76sub fstr { 77 local $SIG{__WARN__} = sub { 78 return if $_[0] =~ /^Pseudo-hashes are deprecated/ 79 }; 80 81 my $h = shift; 82 my @tmp; 83 for my $k (sort {$h->{$a} <=> $h->{$b}} keys %$h) { 84 my $v = $h->{$k}; 85 push(@tmp, "$k:$v"); 86 } 87 my $str = join(",", @tmp); 88 print "$h => $str\n" if $DEBUG; 89 $str; 90} 91 92my %expect = ( 93 B1 => "b1:1,b2:2,b3:3", 94 B2 => "_b1:1,b1:2,_b2:3,b2:4", 95 D1 => "b1:1,b2:2,b3:3,d1:4,d2:5,d3:6", 96 D2 => "b1:1,b2:2,b3:3,_d1:4,_d2:5,d1:6,d2:7", 97 D3 => "b2:4,b1:5,d1:6,_b1:7,_d1:8", 98 D4 => "b2:4,b1:5,d1:6,_d3:9,d3:10", 99 D5 => "b1:2,b2:4", 100 'Foo::Bar::Baz' => 'b1:1,b2:2,b3:3,foo:4,bar:5,baz:6', 101); 102 103print "1..", int(keys %expect)+20, "\n"; 104my $testno = 0; 105while (my($class, $exp) = each %expect) { 106 no strict 'refs'; 107 my $fstr = fstr(\%{$class."::FIELDS"}); 108 print "EXP: $exp\nGOT: $fstr\nnot " unless $fstr eq $exp; 109 print "ok ", ++$testno, "\n"; 110} 111 112# Did we get the appropriate amount of warnings? 113print "not " unless $w == 1; 114print "ok ", ++$testno, "\n"; 115 116# A simple object creation and AVHV attribute access test 117my B2 $obj1 = D3->new; 118$obj1->{b1} = "B2"; 119my D3 $obj2 = $obj1; 120$obj2->{b1} = "D3"; 121 122print "not " unless $obj1->[2] eq "B2" && $obj1->[5] eq "D3"; 123print "ok ", ++$testno, "\n"; 124 125# We should get compile time failures field name typos 126eval q(my D3 $obj3 = $obj2; $obj3->{notthere} = ""); 127print "not " unless $@ && $@ =~ /^No such pseudo-hash field "notthere"/; 128print "ok ", ++$testno, "\n"; 129 130# Slices 131@$obj1{"_b1", "b1"} = (17, 29); 132print "not " unless "@$obj1[1,2]" eq "17 29"; 133print "ok ", ++$testno, "\n"; 134@$obj1[1,2] = (44,28); 135print "not " unless "@$obj1{'b1','_b1','b1'}" eq "28 44 28"; 136print "ok ", ++$testno, "\n"; 137 138{ 139 local $SIG{__WARN__} = sub { 140 return if $_[0] =~ /^Pseudo-hashes are deprecated/ 141 }; 142 143 my $ph = fields::phash(a => 1, b => 2, c => 3); 144 print "not " unless fstr($ph) eq 'a:1,b:2,c:3'; 145 print "ok ", ++$testno, "\n"; 146 147 $ph = fields::phash([qw/a b c/], [1, 2, 3]); 148 print "not " unless fstr($ph) eq 'a:1,b:2,c:3'; 149 print "ok ", ++$testno, "\n"; 150 151 $ph = fields::phash([qw/a b c/], [1]); 152 print "not " if exists $ph->{b} or exists $ph->{c} or !exists $ph->{a}; 153 print "ok ", ++$testno, "\n"; 154 155 eval '$ph = fields::phash("odd")'; 156 print "not " unless $@ && $@ =~ /^Odd number of/; 157 print "ok ", ++$testno, "\n"; 158} 159 160#fields::_dump(); 161 162# check if fields autovivify 163{ 164 package Foo; 165 use fields qw(foo bar); 166 sub new { bless [], $_[0]; } 167 168 package main; 169 my Foo $a = Foo->new(); 170 $a->{foo} = ['a', 'ok ' . ++$testno, 'c']; 171 $a->{bar} = { A => 'ok ' . ++$testno }; 172 print $a->{foo}[1], "\n"; 173 print $a->{bar}->{A}, "\n"; 174} 175 176# check if fields autovivify 177{ 178 package Bar; 179 use fields qw(foo bar); 180 sub new { return fields::new($_[0]) } 181 182 package main; 183 my Bar $a = Bar::->new(); 184 $a->{foo} = ['a', 'ok ' . ++$testno, 'c']; 185 $a->{bar} = { A => 'ok ' . ++$testno }; 186 print $a->{foo}[1], "\n"; 187 print $a->{bar}->{A}, "\n"; 188} 189 190# Test Inverse of $VERSION bug base.pm should not clobber existing $VERSION 191package Has::Version; 192 193BEGIN { $Has::Version::VERSION = '42' }; 194 195package Test::Version2; 196 197use base qw(Has::Version); 198print "#$Has::Version::VERSION\nnot " unless $Has::Version::VERSION eq '42'; 199print "ok ", ++$testno ," # Has::Version\n"; 200 201package main; 202 203my $eval1 = q{ 204 { 205 package Eval1; 206 { 207 package Eval2; 208 use base 'Eval1'; 209 $Eval2::VERSION = "1.02"; 210 } 211 $Eval1::VERSION = "1.01"; 212 } 213}; 214 215eval $eval1; 216printf "# %s\nnot ", $@ if $@; 217print "ok ", ++$testno ," # eval1\n"; 218 219print "# $Eval1::VERSION\nnot " unless $Eval1::VERSION == 1.01; 220print "ok ", ++$testno ," # Eval1::VERSION\n"; 221 222print "# $Eval2::VERSION\nnot " unless $Eval2::VERSION == 1.02; 223print "ok ", ++$testno ," # Eval2::VERSION\n"; 224 225 226eval q{use base reallyReAlLyNotexists;}; 227print "not " unless $@; 228print "ok ", ++$testno, " # really not I\n"; 229 230eval q{use base reallyReAlLyNotexists;}; 231print "not " unless $@; 232print "ok ", ++$testno, " # really not II\n"; 233 234BEGIN { $Has::Version_0::VERSION = 0 } 235 236package Test::Version3; 237 238use base qw(Has::Version_0); 239print "#$Has::Version_0::VERSION\nnot " unless $Has::Version_0::VERSION == 0; 240print "ok ", ++$testno ," # Version_0\n"; 241 242