1*0Sstevel@tonic-gate#!./perl 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gate# Add new tests to the end with format: 4*0Sstevel@tonic-gate# ######## 5*0Sstevel@tonic-gate# 6*0Sstevel@tonic-gate# # test description 7*0Sstevel@tonic-gate# Test code 8*0Sstevel@tonic-gate# EXPECT 9*0Sstevel@tonic-gate# Warn or die msgs (if any) at - line 1234 10*0Sstevel@tonic-gate# 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gatechdir 't' if -d 't'; 13*0Sstevel@tonic-gate@INC = '../lib'; 14*0Sstevel@tonic-gate$ENV{PERL5LIB} = "../lib"; 15*0Sstevel@tonic-gate 16*0Sstevel@tonic-gate$|=1; 17*0Sstevel@tonic-gate 18*0Sstevel@tonic-gateundef $/; 19*0Sstevel@tonic-gate@prgs = split /^########\n/m, <DATA>; 20*0Sstevel@tonic-gate 21*0Sstevel@tonic-gaterequire './test.pl'; 22*0Sstevel@tonic-gateplan(tests => scalar @prgs); 23*0Sstevel@tonic-gatefor (@prgs){ 24*0Sstevel@tonic-gate ++$i; 25*0Sstevel@tonic-gate my($prog,$expected) = split(/\nEXPECT\n/, $_, 2); 26*0Sstevel@tonic-gate print("not ok $i # bad test format\n"), next 27*0Sstevel@tonic-gate unless defined $expected; 28*0Sstevel@tonic-gate my ($testname) = $prog =~ /^# (.*)\n/m; 29*0Sstevel@tonic-gate $testname ||= ''; 30*0Sstevel@tonic-gate $TODO = $testname =~ s/^TODO //; 31*0Sstevel@tonic-gate $results =~ s/\n+$//; 32*0Sstevel@tonic-gate $expected =~ s/\n+$//; 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate fresh_perl_is($prog, $expected, {}, $testname); 35*0Sstevel@tonic-gate} 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate__END__ 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate# standard behaviour, without any extra references 40*0Sstevel@tonic-gateuse Tie::Hash ; 41*0Sstevel@tonic-gatetie %h, Tie::StdHash; 42*0Sstevel@tonic-gateuntie %h; 43*0Sstevel@tonic-gateEXPECT 44*0Sstevel@tonic-gate######## 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate# standard behaviour, without any extra references 47*0Sstevel@tonic-gateuse Tie::Hash ; 48*0Sstevel@tonic-gate{package Tie::HashUntie; 49*0Sstevel@tonic-gate use base 'Tie::StdHash'; 50*0Sstevel@tonic-gate sub UNTIE 51*0Sstevel@tonic-gate { 52*0Sstevel@tonic-gate warn "Untied\n"; 53*0Sstevel@tonic-gate } 54*0Sstevel@tonic-gate} 55*0Sstevel@tonic-gatetie %h, Tie::HashUntie; 56*0Sstevel@tonic-gateuntie %h; 57*0Sstevel@tonic-gateEXPECT 58*0Sstevel@tonic-gateUntied 59*0Sstevel@tonic-gate######## 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate# standard behaviour, with 1 extra reference 62*0Sstevel@tonic-gateuse Tie::Hash ; 63*0Sstevel@tonic-gate$a = tie %h, Tie::StdHash; 64*0Sstevel@tonic-gateuntie %h; 65*0Sstevel@tonic-gateEXPECT 66*0Sstevel@tonic-gate######## 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate# standard behaviour, with 1 extra reference via tied 69*0Sstevel@tonic-gateuse Tie::Hash ; 70*0Sstevel@tonic-gatetie %h, Tie::StdHash; 71*0Sstevel@tonic-gate$a = tied %h; 72*0Sstevel@tonic-gateuntie %h; 73*0Sstevel@tonic-gateEXPECT 74*0Sstevel@tonic-gate######## 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate# standard behaviour, with 1 extra reference which is destroyed 77*0Sstevel@tonic-gateuse Tie::Hash ; 78*0Sstevel@tonic-gate$a = tie %h, Tie::StdHash; 79*0Sstevel@tonic-gate$a = 0 ; 80*0Sstevel@tonic-gateuntie %h; 81*0Sstevel@tonic-gateEXPECT 82*0Sstevel@tonic-gate######## 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate# standard behaviour, with 1 extra reference via tied which is destroyed 85*0Sstevel@tonic-gateuse Tie::Hash ; 86*0Sstevel@tonic-gatetie %h, Tie::StdHash; 87*0Sstevel@tonic-gate$a = tied %h; 88*0Sstevel@tonic-gate$a = 0 ; 89*0Sstevel@tonic-gateuntie %h; 90*0Sstevel@tonic-gateEXPECT 91*0Sstevel@tonic-gate######## 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate# strict behaviour, without any extra references 94*0Sstevel@tonic-gateuse warnings 'untie'; 95*0Sstevel@tonic-gateuse Tie::Hash ; 96*0Sstevel@tonic-gatetie %h, Tie::StdHash; 97*0Sstevel@tonic-gateuntie %h; 98*0Sstevel@tonic-gateEXPECT 99*0Sstevel@tonic-gate######## 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate# strict behaviour, with 1 extra references generating an error 102*0Sstevel@tonic-gateuse warnings 'untie'; 103*0Sstevel@tonic-gateuse Tie::Hash ; 104*0Sstevel@tonic-gate$a = tie %h, Tie::StdHash; 105*0Sstevel@tonic-gateuntie %h; 106*0Sstevel@tonic-gateEXPECT 107*0Sstevel@tonic-gateuntie attempted while 1 inner references still exist at - line 6. 108*0Sstevel@tonic-gate######## 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate# strict behaviour, with 1 extra references via tied generating an error 111*0Sstevel@tonic-gateuse warnings 'untie'; 112*0Sstevel@tonic-gateuse Tie::Hash ; 113*0Sstevel@tonic-gatetie %h, Tie::StdHash; 114*0Sstevel@tonic-gate$a = tied %h; 115*0Sstevel@tonic-gateuntie %h; 116*0Sstevel@tonic-gateEXPECT 117*0Sstevel@tonic-gateuntie attempted while 1 inner references still exist at - line 7. 118*0Sstevel@tonic-gate######## 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate# strict behaviour, with 1 extra references which are destroyed 121*0Sstevel@tonic-gateuse warnings 'untie'; 122*0Sstevel@tonic-gateuse Tie::Hash ; 123*0Sstevel@tonic-gate$a = tie %h, Tie::StdHash; 124*0Sstevel@tonic-gate$a = 0 ; 125*0Sstevel@tonic-gateuntie %h; 126*0Sstevel@tonic-gateEXPECT 127*0Sstevel@tonic-gate######## 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate# strict behaviour, with extra 1 references via tied which are destroyed 130*0Sstevel@tonic-gateuse warnings 'untie'; 131*0Sstevel@tonic-gateuse Tie::Hash ; 132*0Sstevel@tonic-gatetie %h, Tie::StdHash; 133*0Sstevel@tonic-gate$a = tied %h; 134*0Sstevel@tonic-gate$a = 0 ; 135*0Sstevel@tonic-gateuntie %h; 136*0Sstevel@tonic-gateEXPECT 137*0Sstevel@tonic-gate######## 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate# strict error behaviour, with 2 extra references 140*0Sstevel@tonic-gateuse warnings 'untie'; 141*0Sstevel@tonic-gateuse Tie::Hash ; 142*0Sstevel@tonic-gate$a = tie %h, Tie::StdHash; 143*0Sstevel@tonic-gate$b = tied %h ; 144*0Sstevel@tonic-gateuntie %h; 145*0Sstevel@tonic-gateEXPECT 146*0Sstevel@tonic-gateuntie attempted while 2 inner references still exist at - line 7. 147*0Sstevel@tonic-gate######## 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate# strict behaviour, check scope of strictness. 150*0Sstevel@tonic-gateno warnings 'untie'; 151*0Sstevel@tonic-gateuse Tie::Hash ; 152*0Sstevel@tonic-gate$A = tie %H, Tie::StdHash; 153*0Sstevel@tonic-gate$C = $B = tied %H ; 154*0Sstevel@tonic-gate{ 155*0Sstevel@tonic-gate use warnings 'untie'; 156*0Sstevel@tonic-gate use Tie::Hash ; 157*0Sstevel@tonic-gate tie %h, Tie::StdHash; 158*0Sstevel@tonic-gate untie %h; 159*0Sstevel@tonic-gate} 160*0Sstevel@tonic-gateuntie %H; 161*0Sstevel@tonic-gateEXPECT 162*0Sstevel@tonic-gate######## 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate# Forbidden aggregate self-ties 165*0Sstevel@tonic-gatesub Self::TIEHASH { bless $_[1], $_[0] } 166*0Sstevel@tonic-gate{ 167*0Sstevel@tonic-gate my %c; 168*0Sstevel@tonic-gate tie %c, 'Self', \%c; 169*0Sstevel@tonic-gate} 170*0Sstevel@tonic-gateEXPECT 171*0Sstevel@tonic-gateSelf-ties of arrays and hashes are not supported at - line 6. 172*0Sstevel@tonic-gate######## 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate# Allowed scalar self-ties 175*0Sstevel@tonic-gatemy $destroyed = 0; 176*0Sstevel@tonic-gatesub Self::TIESCALAR { bless $_[1], $_[0] } 177*0Sstevel@tonic-gatesub Self::DESTROY { $destroyed = 1; } 178*0Sstevel@tonic-gate{ 179*0Sstevel@tonic-gate my $c = 42; 180*0Sstevel@tonic-gate tie $c, 'Self', \$c; 181*0Sstevel@tonic-gate} 182*0Sstevel@tonic-gatedie "self-tied scalar not DESTROYed" unless $destroyed == 1; 183*0Sstevel@tonic-gateEXPECT 184*0Sstevel@tonic-gate######## 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate# Allowed glob self-ties 187*0Sstevel@tonic-gatemy $destroyed = 0; 188*0Sstevel@tonic-gatemy $printed = 0; 189*0Sstevel@tonic-gatesub Self2::TIEHANDLE { bless $_[1], $_[0] } 190*0Sstevel@tonic-gatesub Self2::DESTROY { $destroyed = 1; } 191*0Sstevel@tonic-gatesub Self2::PRINT { $printed = 1; } 192*0Sstevel@tonic-gate{ 193*0Sstevel@tonic-gate use Symbol; 194*0Sstevel@tonic-gate my $c = gensym; 195*0Sstevel@tonic-gate tie *$c, 'Self2', $c; 196*0Sstevel@tonic-gate print $c 'Hello'; 197*0Sstevel@tonic-gate} 198*0Sstevel@tonic-gatedie "self-tied glob not PRINTed" unless $printed == 1; 199*0Sstevel@tonic-gatedie "self-tied glob not DESTROYed" unless $destroyed == 1; 200*0Sstevel@tonic-gateEXPECT 201*0Sstevel@tonic-gate######## 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate# Allowed IO self-ties 204*0Sstevel@tonic-gatemy $destroyed = 0; 205*0Sstevel@tonic-gatesub Self3::TIEHANDLE { bless $_[1], $_[0] } 206*0Sstevel@tonic-gatesub Self3::DESTROY { $destroyed = 1; } 207*0Sstevel@tonic-gatesub Self3::PRINT { $printed = 1; } 208*0Sstevel@tonic-gate{ 209*0Sstevel@tonic-gate use Symbol 'geniosym'; 210*0Sstevel@tonic-gate my $c = geniosym; 211*0Sstevel@tonic-gate tie *$c, 'Self3', $c; 212*0Sstevel@tonic-gate print $c 'Hello'; 213*0Sstevel@tonic-gate} 214*0Sstevel@tonic-gatedie "self-tied IO not PRINTed" unless $printed == 1; 215*0Sstevel@tonic-gatedie "self-tied IO not DESTROYed" unless $destroyed == 1; 216*0Sstevel@tonic-gateEXPECT 217*0Sstevel@tonic-gate######## 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate# TODO IO "self-tie" via TEMP glob 220*0Sstevel@tonic-gatemy $destroyed = 0; 221*0Sstevel@tonic-gatesub Self3::TIEHANDLE { bless $_[1], $_[0] } 222*0Sstevel@tonic-gatesub Self3::DESTROY { $destroyed = 1; } 223*0Sstevel@tonic-gatesub Self3::PRINT { $printed = 1; } 224*0Sstevel@tonic-gate{ 225*0Sstevel@tonic-gate use Symbol 'geniosym'; 226*0Sstevel@tonic-gate my $c = geniosym; 227*0Sstevel@tonic-gate tie *$c, 'Self3', \*$c; 228*0Sstevel@tonic-gate print $c 'Hello'; 229*0Sstevel@tonic-gate} 230*0Sstevel@tonic-gatedie "IO tied to TEMP glob not PRINTed" unless $printed == 1; 231*0Sstevel@tonic-gatedie "IO tied to TEMP glob not DESTROYed" unless $destroyed == 1; 232*0Sstevel@tonic-gateEXPECT 233*0Sstevel@tonic-gate######## 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate# Interaction of tie and vec 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gatemy ($a, $b); 238*0Sstevel@tonic-gateuse Tie::Scalar; 239*0Sstevel@tonic-gatetie $a,Tie::StdScalar or die; 240*0Sstevel@tonic-gatevec($b,1,1)=1; 241*0Sstevel@tonic-gate$a = $b; 242*0Sstevel@tonic-gatevec($a,1,1)=0; 243*0Sstevel@tonic-gatevec($b,1,1)=0; 244*0Sstevel@tonic-gatedie unless $a eq $b; 245*0Sstevel@tonic-gateEXPECT 246*0Sstevel@tonic-gate######## 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate# correct unlocalisation of tied hashes (patch #16431) 249*0Sstevel@tonic-gateuse Tie::Hash ; 250*0Sstevel@tonic-gatetie %tied, Tie::StdHash; 251*0Sstevel@tonic-gate{ local $hash{'foo'} } warn "plain hash bad unlocalize" if exists $hash{'foo'}; 252*0Sstevel@tonic-gate{ local $tied{'foo'} } warn "tied hash bad unlocalize" if exists $tied{'foo'}; 253*0Sstevel@tonic-gate{ local $ENV{'foo'} } warn "%ENV bad unlocalize" if exists $ENV{'foo'}; 254*0Sstevel@tonic-gateEXPECT 255*0Sstevel@tonic-gate######## 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate# An attempt at lvalueable barewords broke this 258*0Sstevel@tonic-gatetie FH, 'main'; 259*0Sstevel@tonic-gateEXPECT 260*0Sstevel@tonic-gateCan't modify constant item in tie at - line 3, near "'main';" 261*0Sstevel@tonic-gateExecution of - aborted due to compilation errors. 262*0Sstevel@tonic-gate######## 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate# localizing tied hash slices 265*0Sstevel@tonic-gate$ENV{FooA} = 1; 266*0Sstevel@tonic-gate$ENV{FooB} = 2; 267*0Sstevel@tonic-gateprint exists $ENV{FooA} ? 1 : 0, "\n"; 268*0Sstevel@tonic-gateprint exists $ENV{FooB} ? 2 : 0, "\n"; 269*0Sstevel@tonic-gateprint exists $ENV{FooC} ? 3 : 0, "\n"; 270*0Sstevel@tonic-gate{ 271*0Sstevel@tonic-gate local @ENV{qw(FooA FooC)}; 272*0Sstevel@tonic-gate print exists $ENV{FooA} ? 4 : 0, "\n"; 273*0Sstevel@tonic-gate print exists $ENV{FooB} ? 5 : 0, "\n"; 274*0Sstevel@tonic-gate print exists $ENV{FooC} ? 6 : 0, "\n"; 275*0Sstevel@tonic-gate} 276*0Sstevel@tonic-gateprint exists $ENV{FooA} ? 7 : 0, "\n"; 277*0Sstevel@tonic-gateprint exists $ENV{FooB} ? 8 : 0, "\n"; 278*0Sstevel@tonic-gateprint exists $ENV{FooC} ? 9 : 0, "\n"; # this should not exist 279*0Sstevel@tonic-gateEXPECT 280*0Sstevel@tonic-gate1 281*0Sstevel@tonic-gate2 282*0Sstevel@tonic-gate0 283*0Sstevel@tonic-gate4 284*0Sstevel@tonic-gate5 285*0Sstevel@tonic-gate6 286*0Sstevel@tonic-gate7 287*0Sstevel@tonic-gate8 288*0Sstevel@tonic-gate0 289*0Sstevel@tonic-gate######## 290*0Sstevel@tonic-gate# 291*0Sstevel@tonic-gate# FETCH freeing tie'd SV 292*0Sstevel@tonic-gatesub TIESCALAR { bless [] } 293*0Sstevel@tonic-gatesub FETCH { *a = \1; 1 } 294*0Sstevel@tonic-gatetie $a, 'main'; 295*0Sstevel@tonic-gateprint $a; 296*0Sstevel@tonic-gateEXPECT 297*0Sstevel@tonic-gateTied variable freed while still in use at - line 6. 298*0Sstevel@tonic-gate######## 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate# [20020716.007] - nested FETCHES 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gatesub F1::TIEARRAY { bless [], 'F1' } 303*0Sstevel@tonic-gatesub F1::FETCH { 1 } 304*0Sstevel@tonic-gatemy @f1; 305*0Sstevel@tonic-gatetie @f1, 'F1'; 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gatesub F2::TIEARRAY { bless [2], 'F2' } 308*0Sstevel@tonic-gatesub F2::FETCH { my $self = shift; my $x = $f1[3]; $self } 309*0Sstevel@tonic-gatemy @f2; 310*0Sstevel@tonic-gatetie @f2, 'F2'; 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gateprint $f2[4][0],"\n"; 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gatesub F3::TIEHASH { bless [], 'F3' } 315*0Sstevel@tonic-gatesub F3::FETCH { 1 } 316*0Sstevel@tonic-gatemy %f3; 317*0Sstevel@tonic-gatetie %f3, 'F3'; 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gatesub F4::TIEHASH { bless [3], 'F4' } 320*0Sstevel@tonic-gatesub F4::FETCH { my $self = shift; my $x = $f3{3}; $self } 321*0Sstevel@tonic-gatemy %f4; 322*0Sstevel@tonic-gatetie %f4, 'F4'; 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gateprint $f4{'foo'}[0],"\n"; 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gateEXPECT 327*0Sstevel@tonic-gate2 328*0Sstevel@tonic-gate3 329*0Sstevel@tonic-gate######## 330*0Sstevel@tonic-gate# test untie() from within FETCH 331*0Sstevel@tonic-gatepackage Foo; 332*0Sstevel@tonic-gatesub TIESCALAR { my $pkg = shift; return bless [@_], $pkg; } 333*0Sstevel@tonic-gatesub FETCH { 334*0Sstevel@tonic-gate my $self = shift; 335*0Sstevel@tonic-gate my ($obj, $field) = @$self; 336*0Sstevel@tonic-gate untie $obj->{$field}; 337*0Sstevel@tonic-gate $obj->{$field} = "Bar"; 338*0Sstevel@tonic-gate} 339*0Sstevel@tonic-gatepackage main; 340*0Sstevel@tonic-gatetie $a->{foo}, "Foo", $a, "foo"; 341*0Sstevel@tonic-gate$a->{foo}; # access once 342*0Sstevel@tonic-gate# the hash element should not be tied anymore 343*0Sstevel@tonic-gateprint defined tied $a->{foo} ? "not ok" : "ok"; 344*0Sstevel@tonic-gateEXPECT 345*0Sstevel@tonic-gateok 346*0Sstevel@tonic-gate######## 347*0Sstevel@tonic-gate# the tmps returned by FETCH should appear to be SCALAR 348*0Sstevel@tonic-gate# (even though they are now implemented using PVLVs.) 349*0Sstevel@tonic-gatepackage X; 350*0Sstevel@tonic-gatesub TIEHASH { bless {} } 351*0Sstevel@tonic-gatesub TIEARRAY { bless {} } 352*0Sstevel@tonic-gatesub FETCH {1} 353*0Sstevel@tonic-gatemy (%h, @a); 354*0Sstevel@tonic-gatetie %h, 'X'; 355*0Sstevel@tonic-gatetie @a, 'X'; 356*0Sstevel@tonic-gatemy $r1 = \$h{1}; 357*0Sstevel@tonic-gatemy $r2 = \$a[0]; 358*0Sstevel@tonic-gatemy $s = "$r1 ". ref($r1) . " $r2 " . ref($r2); 359*0Sstevel@tonic-gate$s=~ s/\(0x\w+\)//g; 360*0Sstevel@tonic-gateprint $s, "\n"; 361*0Sstevel@tonic-gateEXPECT 362*0Sstevel@tonic-gateSCALAR SCALAR SCALAR SCALAR 363*0Sstevel@tonic-gate######## 364*0Sstevel@tonic-gate# [perl #23287] segfault in untie 365*0Sstevel@tonic-gatesub TIESCALAR { bless $_[1], $_[0] } 366*0Sstevel@tonic-gatemy $var; 367*0Sstevel@tonic-gatetie $var, 'main', \$var; 368*0Sstevel@tonic-gateuntie $var; 369*0Sstevel@tonic-gateEXPECT 370*0Sstevel@tonic-gate######## 371*0Sstevel@tonic-gate# Test case from perlmonks by runrig 372*0Sstevel@tonic-gate# http://www.perlmonks.org/index.pl?node_id=273490 373*0Sstevel@tonic-gate# "Here is what I tried. I think its similar to what you've tried 374*0Sstevel@tonic-gate# above. Its odd but convienient that after untie'ing you are left with 375*0Sstevel@tonic-gate# a variable that has the same value as was last returned from 376*0Sstevel@tonic-gate# FETCH. (At least on my perl v5.6.1). So you don't need to pass a 377*0Sstevel@tonic-gate# reference to the variable in order to set it after the untie (here it 378*0Sstevel@tonic-gate# is accessed through a closure)." 379*0Sstevel@tonic-gateuse strict; 380*0Sstevel@tonic-gateuse warnings; 381*0Sstevel@tonic-gatepackage MyTied; 382*0Sstevel@tonic-gatesub TIESCALAR { 383*0Sstevel@tonic-gate my ($class,$code) = @_; 384*0Sstevel@tonic-gate bless $code, $class; 385*0Sstevel@tonic-gate} 386*0Sstevel@tonic-gatesub FETCH { 387*0Sstevel@tonic-gate my $self = shift; 388*0Sstevel@tonic-gate print "Untie\n"; 389*0Sstevel@tonic-gate $self->(); 390*0Sstevel@tonic-gate} 391*0Sstevel@tonic-gatepackage main; 392*0Sstevel@tonic-gatemy $var; 393*0Sstevel@tonic-gatetie $var, 'MyTied', sub { untie $var; 4 }; 394*0Sstevel@tonic-gateprint "One\n"; 395*0Sstevel@tonic-gateprint "$var\n"; 396*0Sstevel@tonic-gateprint "Two\n"; 397*0Sstevel@tonic-gateprint "$var\n"; 398*0Sstevel@tonic-gateprint "Three\n"; 399*0Sstevel@tonic-gateprint "$var\n"; 400*0Sstevel@tonic-gateEXPECT 401*0Sstevel@tonic-gateOne 402*0Sstevel@tonic-gateUntie 403*0Sstevel@tonic-gate4 404*0Sstevel@tonic-gateTwo 405*0Sstevel@tonic-gate4 406*0Sstevel@tonic-gateThree 407*0Sstevel@tonic-gate4 408*0Sstevel@tonic-gate######## 409*0Sstevel@tonic-gate# [perl #22297] cannot untie scalar from within tied FETCH 410*0Sstevel@tonic-gatemy $counter = 0; 411*0Sstevel@tonic-gatemy $x = 7; 412*0Sstevel@tonic-gatemy $ref = \$x; 413*0Sstevel@tonic-gatetie $x, 'Overlay', $ref, $x; 414*0Sstevel@tonic-gatemy $y; 415*0Sstevel@tonic-gate$y = $x; 416*0Sstevel@tonic-gate$y = $x; 417*0Sstevel@tonic-gate$y = $x; 418*0Sstevel@tonic-gate$y = $x; 419*0Sstevel@tonic-gate#print "WILL EXTERNAL UNTIE $ref\n"; 420*0Sstevel@tonic-gateuntie $$ref; 421*0Sstevel@tonic-gate$y = $x; 422*0Sstevel@tonic-gate$y = $x; 423*0Sstevel@tonic-gate$y = $x; 424*0Sstevel@tonic-gate$y = $x; 425*0Sstevel@tonic-gate#print "counter = $counter\n"; 426*0Sstevel@tonic-gate 427*0Sstevel@tonic-gateprint (($counter == 1) ? "ok\n" : "not ok\n"); 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gatepackage Overlay; 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gatesub TIESCALAR 432*0Sstevel@tonic-gate{ 433*0Sstevel@tonic-gate my $pkg = shift; 434*0Sstevel@tonic-gate my ($ref, $val) = @_; 435*0Sstevel@tonic-gate return bless [ $ref, $val ], $pkg; 436*0Sstevel@tonic-gate} 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gatesub FETCH 439*0Sstevel@tonic-gate{ 440*0Sstevel@tonic-gate my $self = shift; 441*0Sstevel@tonic-gate my ($ref, $val) = @$self; 442*0Sstevel@tonic-gate #print "WILL INTERNAL UNITE $ref\n"; 443*0Sstevel@tonic-gate $counter++; 444*0Sstevel@tonic-gate untie $$ref; 445*0Sstevel@tonic-gate return $val; 446*0Sstevel@tonic-gate} 447*0Sstevel@tonic-gateEXPECT 448*0Sstevel@tonic-gateok 449*0Sstevel@tonic-gate######## 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate# test SCALAR method 452*0Sstevel@tonic-gatepackage TieScalar; 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gatesub TIEHASH { 455*0Sstevel@tonic-gate my $pkg = shift; 456*0Sstevel@tonic-gate bless { } => $pkg; 457*0Sstevel@tonic-gate} 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gatesub STORE { 460*0Sstevel@tonic-gate $_[0]->{$_[1]} = $_[2]; 461*0Sstevel@tonic-gate} 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gatesub FETCH { 464*0Sstevel@tonic-gate $_[0]->{$_[1]} 465*0Sstevel@tonic-gate} 466*0Sstevel@tonic-gate 467*0Sstevel@tonic-gatesub CLEAR { 468*0Sstevel@tonic-gate %{ $_[0] } = (); 469*0Sstevel@tonic-gate} 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gatesub SCALAR { 472*0Sstevel@tonic-gate print "SCALAR\n"; 473*0Sstevel@tonic-gate return 0 if ! keys %{$_[0]}; 474*0Sstevel@tonic-gate sprintf "%i/%i", scalar keys %{$_[0]}, scalar keys %{$_[0]}; 475*0Sstevel@tonic-gate} 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gatepackage main; 478*0Sstevel@tonic-gatetie my %h => "TieScalar"; 479*0Sstevel@tonic-gate$h{key1} = "val1"; 480*0Sstevel@tonic-gate$h{key2} = "val2"; 481*0Sstevel@tonic-gateprint scalar %h, "\n"; 482*0Sstevel@tonic-gate%h = (); 483*0Sstevel@tonic-gateprint scalar %h, "\n"; 484*0Sstevel@tonic-gateEXPECT 485*0Sstevel@tonic-gateSCALAR 486*0Sstevel@tonic-gate2/2 487*0Sstevel@tonic-gateSCALAR 488*0Sstevel@tonic-gate0 489*0Sstevel@tonic-gate######## 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate# test scalar on tied hash when no SCALAR method has been given 492*0Sstevel@tonic-gatepackage TieScalar; 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gatesub TIEHASH { 495*0Sstevel@tonic-gate my $pkg = shift; 496*0Sstevel@tonic-gate bless { } => $pkg; 497*0Sstevel@tonic-gate} 498*0Sstevel@tonic-gatesub STORE { 499*0Sstevel@tonic-gate $_[0]->{$_[1]} = $_[2]; 500*0Sstevel@tonic-gate} 501*0Sstevel@tonic-gatesub FETCH { 502*0Sstevel@tonic-gate $_[0]->{$_[1]} 503*0Sstevel@tonic-gate} 504*0Sstevel@tonic-gatesub CLEAR { 505*0Sstevel@tonic-gate %{ $_[0] } = (); 506*0Sstevel@tonic-gate} 507*0Sstevel@tonic-gatesub FIRSTKEY { 508*0Sstevel@tonic-gate my $a = keys %{ $_[0] }; 509*0Sstevel@tonic-gate print "FIRSTKEY\n"; 510*0Sstevel@tonic-gate each %{ $_[0] }; 511*0Sstevel@tonic-gate} 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gatepackage main; 514*0Sstevel@tonic-gatetie my %h => "TieScalar"; 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gateif (!%h) { 517*0Sstevel@tonic-gate print "empty\n"; 518*0Sstevel@tonic-gate} else { 519*0Sstevel@tonic-gate print "not empty\n"; 520*0Sstevel@tonic-gate} 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate$h{key1} = "val1"; 523*0Sstevel@tonic-gateprint "not empty\n" if %h; 524*0Sstevel@tonic-gateprint "not empty\n" if %h; 525*0Sstevel@tonic-gateprint "-->\n"; 526*0Sstevel@tonic-gatemy ($k,$v) = each %h; 527*0Sstevel@tonic-gateprint "<--\n"; 528*0Sstevel@tonic-gateprint "not empty\n" if %h; 529*0Sstevel@tonic-gate%h = (); 530*0Sstevel@tonic-gateprint "empty\n" if ! %h; 531*0Sstevel@tonic-gateEXPECT 532*0Sstevel@tonic-gateFIRSTKEY 533*0Sstevel@tonic-gateempty 534*0Sstevel@tonic-gateFIRSTKEY 535*0Sstevel@tonic-gatenot empty 536*0Sstevel@tonic-gateFIRSTKEY 537*0Sstevel@tonic-gatenot empty 538*0Sstevel@tonic-gate--> 539*0Sstevel@tonic-gateFIRSTKEY 540*0Sstevel@tonic-gate<-- 541*0Sstevel@tonic-gatenot empty 542*0Sstevel@tonic-gateFIRSTKEY 543*0Sstevel@tonic-gateempty 544