1*898184e3Ssthen#!perl 2*898184e3SsthenBEGIN { 3*898184e3Ssthen} 4*898184e3Ssthen 5*898184e3Ssthenuse strict; 6*898184e3Ssthenuse warnings; 7*898184e3Ssthen 8*898184e3Ssthenuse Test::More; 9*898184e3Ssthenuse Config; 10*898184e3Ssthen 11*898184e3Ssthenour $DBM_Class; 12*898184e3Ssthen 13*898184e3Ssthenmy ($create, $write); 14*898184e3SsthenBEGIN { 15*898184e3Ssthen plan(skip_all => "$DBM_Class was not built") 16*898184e3Ssthen unless $Config{extensions} =~ /\b$DBM_Class\b/; 17*898184e3Ssthen plan(skip_all => "$DBM_Class not compatible with C++") 18*898184e3Ssthen if $DBM_Class eq 'ODBM_File' && $Config{d_cplusplus}; 19*898184e3Ssthen 20*898184e3Ssthen use_ok($DBM_Class); 21*898184e3Ssthen 22*898184e3Ssthen if ($::Create_and_Write) { 23*898184e3Ssthen ($create, $write) = eval $::Create_and_Write; 24*898184e3Ssthen isnt($create, undef, "(eval q{$::Create_and_Write})[0]"); 25*898184e3Ssthen isnt($write, undef, "(eval q{$::Create_and_Write})[1]"); 26*898184e3Ssthen } else { 27*898184e3Ssthen #If Fcntl is not available, try 0x202 or 0x102 for O_RDWR|O_CREAT 28*898184e3Ssthen use_ok('Fcntl'); 29*898184e3Ssthen $create = O_RDWR()|O_CREAT(); 30*898184e3Ssthen $write = O_RDWR(); 31*898184e3Ssthen } 32*898184e3Ssthen} 33*898184e3Ssthen 34*898184e3Ssthenunlink <Op_dbmx.*>; 35*898184e3Ssthen 36*898184e3Ssthenumask(0); 37*898184e3Ssthenmy %h; 38*898184e3Ssthenisa_ok(tie(%h, $DBM_Class, 'Op_dbmx', $create, 0640), $DBM_Class); 39*898184e3Ssthen 40*898184e3Ssthenmy $Dfile = "Op_dbmx.pag"; 41*898184e3Ssthenif (! -e $Dfile) { 42*898184e3Ssthen ($Dfile) = <Op_dbmx*>; 43*898184e3Ssthen} 44*898184e3SsthenSKIP: { 45*898184e3Ssthen skip "different file permission semantics on $^O", 1 46*898184e3Ssthen if $^O eq 'amigaos' || $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'NetWare' || $^O eq 'dos' || $^O eq 'cygwin' || $^O eq 'vos'; 47*898184e3Ssthen my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, 48*898184e3Ssthen $blksize,$blocks) = stat($Dfile); 49*898184e3Ssthen is($mode & 0777, 0640); 50*898184e3Ssthen} 51*898184e3Ssthenmy $i = 0; 52*898184e3Ssthenwhile (my ($key,$value) = each(%h)) { 53*898184e3Ssthen $i++; 54*898184e3Ssthen} 55*898184e3Ssthenis($i, 0); 56*898184e3Ssthen 57*898184e3Ssthen$h{'goner1'} = 'snork'; 58*898184e3Ssthen 59*898184e3Ssthen$h{'abc'} = 'ABC'; 60*898184e3Ssthen$h{'def'} = 'DEF'; 61*898184e3Ssthen$h{'jkl','mno'} = "JKL\034MNO"; 62*898184e3Ssthen$h{'a',2,3,4,5} = join("\034",'A',2,3,4,5); 63*898184e3Ssthen$h{'a'} = 'A'; 64*898184e3Ssthen$h{'b'} = 'B'; 65*898184e3Ssthen$h{'c'} = 'C'; 66*898184e3Ssthen$h{'d'} = 'D'; 67*898184e3Ssthen$h{'e'} = 'E'; 68*898184e3Ssthen$h{'f'} = 'F'; 69*898184e3Ssthen$h{'g'} = 'G'; 70*898184e3Ssthen$h{'h'} = 'H'; 71*898184e3Ssthen$h{'i'} = 'I'; 72*898184e3Ssthen 73*898184e3Ssthen$h{'goner2'} = 'snork'; 74*898184e3Ssthendelete $h{'goner2'}; 75*898184e3Ssthen 76*898184e3Ssthenuntie(%h); 77*898184e3Ssthenisa_ok(tie(%h, $DBM_Class, 'Op_dbmx', $write, 0640), $DBM_Class); 78*898184e3Ssthen 79*898184e3Ssthen$h{'j'} = 'J'; 80*898184e3Ssthen$h{'k'} = 'K'; 81*898184e3Ssthen$h{'l'} = 'L'; 82*898184e3Ssthen$h{'m'} = 'M'; 83*898184e3Ssthen$h{'n'} = 'N'; 84*898184e3Ssthen$h{'o'} = 'O'; 85*898184e3Ssthen$h{'p'} = 'P'; 86*898184e3Ssthen$h{'q'} = 'Q'; 87*898184e3Ssthen$h{'r'} = 'R'; 88*898184e3Ssthen$h{'s'} = 'S'; 89*898184e3Ssthen$h{'t'} = 'T'; 90*898184e3Ssthen$h{'u'} = 'U'; 91*898184e3Ssthen$h{'v'} = 'V'; 92*898184e3Ssthen$h{'w'} = 'W'; 93*898184e3Ssthen$h{'x'} = 'X'; 94*898184e3Ssthen$h{'y'} = 'Y'; 95*898184e3Ssthen$h{'z'} = 'Z'; 96*898184e3Ssthen 97*898184e3Ssthen$h{'goner3'} = 'snork'; 98*898184e3Ssthen 99*898184e3Ssthendelete $h{'goner1'}; 100*898184e3Ssthendelete $h{'goner3'}; 101*898184e3Ssthen 102*898184e3Ssthenmy @keys = keys(%h); 103*898184e3Ssthenmy @values = values(%h); 104*898184e3Ssthen 105*898184e3Ssthenis($#keys, 29); 106*898184e3Ssthenis($#values, 29); 107*898184e3Ssthen 108*898184e3Ssthenwhile (my ($key, $value) = each(%h)) { 109*898184e3Ssthen if ($key eq $keys[$i] && $value eq $values[$i] && $key eq lc($value)) { 110*898184e3Ssthen $key =~ y/a-z/A-Z/; 111*898184e3Ssthen $i++ if $key eq $value; 112*898184e3Ssthen } 113*898184e3Ssthen} 114*898184e3Ssthen 115*898184e3Ssthenis($i, 30); 116*898184e3Ssthen 117*898184e3Ssthen@keys = ('blurfl', keys(%h), 'dyick'); 118*898184e3Ssthenis($#keys, 31); 119*898184e3Ssthen 120*898184e3Ssthen$h{'foo'} = ''; 121*898184e3Ssthen$h{''} = 'bar'; 122*898184e3Ssthen 123*898184e3Ssthenmy $ok = 1; 124*898184e3Ssthenfor ($i = 1; $i < 200; $i++) { $h{$i + 0} = $i + 0; } 125*898184e3Ssthenfor ($i = 1; $i < 200; $i++) { $ok = 0 unless $h{$i} == $i; } 126*898184e3Ssthenis($ok, 1, 'check cache overflow and numeric keys and contents'); 127*898184e3Ssthen 128*898184e3Ssthenmy ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, 129*898184e3Ssthen $blksize,$blocks) = stat($Dfile); 130*898184e3Ssthencmp_ok($size, '>', 0); 131*898184e3Ssthen 132*898184e3Ssthen@h{0..200} = 200..400; 133*898184e3Ssthenmy @foo = @h{0..200}; 134*898184e3Ssthenis(join(':',200..400), join(':',@foo)); 135*898184e3Ssthen 136*898184e3Ssthenis($h{'foo'}, ''); 137*898184e3Ssthenis($h{''}, 'bar'); 138*898184e3Ssthen 139*898184e3Ssthenif($DBM_Class eq 'SDBM_File') { 140*898184e3Ssthen is(exists $h{goner1}, ''); 141*898184e3Ssthen is(exists $h{foo}, 1); 142*898184e3Ssthen} 143*898184e3Ssthen 144*898184e3Ssthenuntie %h; 145*898184e3Ssthenunlink <Op_dbmx*>, $Dfile; 146*898184e3Ssthen 147*898184e3Ssthen{ 148*898184e3Ssthen # sub-class test 149*898184e3Ssthen 150*898184e3Ssthen package Another; 151*898184e3Ssthen 152*898184e3Ssthen open my $file, '>', 'SubDB.pm' or die "Cannot open SubDB.pm: $!\n"; 153*898184e3Ssthen printf $file <<'EOM', $DBM_Class, $DBM_Class, $DBM_Class; 154*898184e3Ssthen 155*898184e3Ssthen package SubDB; 156*898184e3Ssthen 157*898184e3Ssthen use strict; 158*898184e3Ssthen use warnings; 159*898184e3Ssthen use vars qw(@ISA @EXPORT); 160*898184e3Ssthen 161*898184e3Ssthen require Exporter; 162*898184e3Ssthen use %s; 163*898184e3Ssthen @ISA=qw(%s); 164*898184e3Ssthen @EXPORT = @%s::EXPORT; 165*898184e3Ssthen 166*898184e3Ssthen sub STORE { 167*898184e3Ssthen my $self = shift; 168*898184e3Ssthen my $key = shift; 169*898184e3Ssthen my $value = shift; 170*898184e3Ssthen $self->SUPER::STORE($key, $value * 2); 171*898184e3Ssthen } 172*898184e3Ssthen 173*898184e3Ssthen sub FETCH { 174*898184e3Ssthen my $self = shift; 175*898184e3Ssthen my $key = shift; 176*898184e3Ssthen $self->SUPER::FETCH($key) - 1; 177*898184e3Ssthen } 178*898184e3Ssthen 179*898184e3Ssthen sub A_new_method 180*898184e3Ssthen { 181*898184e3Ssthen my $self = shift; 182*898184e3Ssthen my $key = shift; 183*898184e3Ssthen my $value = $self->FETCH($key); 184*898184e3Ssthen return "[[$value]]"; 185*898184e3Ssthen } 186*898184e3Ssthen 187*898184e3Ssthen 1; 188*898184e3SsthenEOM 189*898184e3Ssthen 190*898184e3Ssthen close $file or die "Could not close: $!"; 191*898184e3Ssthen 192*898184e3Ssthen BEGIN { push @INC, '.'; } 193*898184e3Ssthen unlink <dbhash_tmp*>; 194*898184e3Ssthen 195*898184e3Ssthen main::use_ok('SubDB'); 196*898184e3Ssthen my %h; 197*898184e3Ssthen my $X; 198*898184e3Ssthen eval ' 199*898184e3Ssthen $X = tie(%h, "SubDB", "dbhash_tmp", $create, 0640 ); 200*898184e3Ssthen '; 201*898184e3Ssthen 202*898184e3Ssthen main::is($@, ""); 203*898184e3Ssthen 204*898184e3Ssthen my $ret = eval '$h{"fred"} = 3; return $h{"fred"} '; 205*898184e3Ssthen main::is($@, ""); 206*898184e3Ssthen main::is($ret, 5); 207*898184e3Ssthen 208*898184e3Ssthen $ret = eval '$X->A_new_method("fred") '; 209*898184e3Ssthen main::is($@, ""); 210*898184e3Ssthen main::is($ret, "[[5]]"); 211*898184e3Ssthen 212*898184e3Ssthen if ($DBM_Class eq 'GDBM_File') { 213*898184e3Ssthen $ret = eval 'GDBM_WRCREAT eq main::GDBM_WRCREAT'; 214*898184e3Ssthen main::is($@, ""); 215*898184e3Ssthen main::is($ret, 1); 216*898184e3Ssthen } 217*898184e3Ssthen 218*898184e3Ssthen undef $X; 219*898184e3Ssthen untie(%h); 220*898184e3Ssthen unlink "SubDB.pm", <dbhash_tmp*>; 221*898184e3Ssthen 222*898184e3Ssthen} 223*898184e3Ssthen 224*898184e3Ssthenuntie %h; 225*898184e3Ssthenunlink <Op_dbmx*>, $Dfile; 226*898184e3Ssthen 227*898184e3Ssthen{ 228*898184e3Ssthen # DBM Filter tests 229*898184e3Ssthen my (%h, $db); 230*898184e3Ssthen my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 231*898184e3Ssthen 232*898184e3Ssthen sub checkOutput 233*898184e3Ssthen { 234*898184e3Ssthen my($fk, $sk, $fv, $sv) = @_; 235*898184e3Ssthen local $Test::Builder::Level = $Test::Builder::Level + 1; 236*898184e3Ssthen is($fetch_key, $fk); 237*898184e3Ssthen is($store_key, $sk); 238*898184e3Ssthen is($fetch_value, $fv); 239*898184e3Ssthen is($store_value, $sv); 240*898184e3Ssthen is($_, 'original'); 241*898184e3Ssthen } 242*898184e3Ssthen 243*898184e3Ssthen unlink <Op_dbmx*>; 244*898184e3Ssthen $db = tie %h, $DBM_Class, 'Op_dbmx', $create, 0640; 245*898184e3Ssthen isa_ok($db, $DBM_Class); 246*898184e3Ssthen 247*898184e3Ssthen $db->filter_fetch_key (sub { $fetch_key = $_ }); 248*898184e3Ssthen $db->filter_store_key (sub { $store_key = $_ }); 249*898184e3Ssthen $db->filter_fetch_value (sub { $fetch_value = $_}); 250*898184e3Ssthen $db->filter_store_value (sub { $store_value = $_ }); 251*898184e3Ssthen 252*898184e3Ssthen $_ = "original"; 253*898184e3Ssthen 254*898184e3Ssthen $h{"fred"} = "joe"; 255*898184e3Ssthen # fk sk fv sv 256*898184e3Ssthen checkOutput("", "fred", "", "joe"); 257*898184e3Ssthen 258*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 259*898184e3Ssthen is($h{"fred"}, "joe"); 260*898184e3Ssthen # fk sk fv sv 261*898184e3Ssthen checkOutput("", "fred", "joe", ""); 262*898184e3Ssthen 263*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 264*898184e3Ssthen is($db->FIRSTKEY(), "fred"); 265*898184e3Ssthen # fk sk fv sv 266*898184e3Ssthen checkOutput("fred", "", "", ""); 267*898184e3Ssthen 268*898184e3Ssthen # replace the filters, but remember the previous set 269*898184e3Ssthen my ($old_fk) = $db->filter_fetch_key 270*898184e3Ssthen (sub { $_ = uc $_; $fetch_key = $_ }); 271*898184e3Ssthen my ($old_sk) = $db->filter_store_key 272*898184e3Ssthen (sub { $_ = lc $_; $store_key = $_ }); 273*898184e3Ssthen my ($old_fv) = $db->filter_fetch_value 274*898184e3Ssthen (sub { $_ = "[$_]"; $fetch_value = $_ }); 275*898184e3Ssthen my ($old_sv) = $db->filter_store_value 276*898184e3Ssthen (sub { s/o/x/g; $store_value = $_ }); 277*898184e3Ssthen 278*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 279*898184e3Ssthen $h{"Fred"} = "Joe"; 280*898184e3Ssthen # fk sk fv sv 281*898184e3Ssthen checkOutput("", "fred", "", "Jxe"); 282*898184e3Ssthen 283*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 284*898184e3Ssthen is($h{"Fred"}, "[Jxe]"); 285*898184e3Ssthen # fk sk fv sv 286*898184e3Ssthen checkOutput("", "fred", "[Jxe]", ""); 287*898184e3Ssthen 288*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 289*898184e3Ssthen is($db->FIRSTKEY(), "FRED"); 290*898184e3Ssthen # fk sk fv sv 291*898184e3Ssthen checkOutput("FRED", "", "", ""); 292*898184e3Ssthen 293*898184e3Ssthen # put the original filters back 294*898184e3Ssthen $db->filter_fetch_key ($old_fk); 295*898184e3Ssthen $db->filter_store_key ($old_sk); 296*898184e3Ssthen $db->filter_fetch_value ($old_fv); 297*898184e3Ssthen $db->filter_store_value ($old_sv); 298*898184e3Ssthen 299*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 300*898184e3Ssthen $h{"fred"} = "joe"; 301*898184e3Ssthen checkOutput("", "fred", "", "joe"); 302*898184e3Ssthen 303*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 304*898184e3Ssthen is($h{"fred"}, "joe"); 305*898184e3Ssthen checkOutput("", "fred", "joe", ""); 306*898184e3Ssthen 307*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 308*898184e3Ssthen is($db->FIRSTKEY(), "fred"); 309*898184e3Ssthen checkOutput("fred", "", "", ""); 310*898184e3Ssthen 311*898184e3Ssthen # delete the filters 312*898184e3Ssthen $db->filter_fetch_key (undef); 313*898184e3Ssthen $db->filter_store_key (undef); 314*898184e3Ssthen $db->filter_fetch_value (undef); 315*898184e3Ssthen $db->filter_store_value (undef); 316*898184e3Ssthen 317*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 318*898184e3Ssthen $h{"fred"} = "joe"; 319*898184e3Ssthen checkOutput("", "", "", ""); 320*898184e3Ssthen 321*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 322*898184e3Ssthen is($h{"fred"}, "joe"); 323*898184e3Ssthen checkOutput("", "", "", ""); 324*898184e3Ssthen 325*898184e3Ssthen ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4; 326*898184e3Ssthen is($db->FIRSTKEY(), "fred"); 327*898184e3Ssthen checkOutput("", "", "", ""); 328*898184e3Ssthen 329*898184e3Ssthen undef $db; 330*898184e3Ssthen untie %h; 331*898184e3Ssthen unlink <Op_dbmx*>; 332*898184e3Ssthen} 333*898184e3Ssthen 334*898184e3Ssthen{ 335*898184e3Ssthen # DBM Filter with a closure 336*898184e3Ssthen 337*898184e3Ssthen my (%h, $db); 338*898184e3Ssthen 339*898184e3Ssthen unlink <Op_dbmx*>; 340*898184e3Ssthen $db = tie %h, $DBM_Class, 'Op_dbmx', $create, 0640; 341*898184e3Ssthen isa_ok($db, $DBM_Class); 342*898184e3Ssthen 343*898184e3Ssthen my %result = (); 344*898184e3Ssthen 345*898184e3Ssthen sub Closure 346*898184e3Ssthen { 347*898184e3Ssthen my ($name) = @_; 348*898184e3Ssthen my $count = 0; 349*898184e3Ssthen my @kept = (); 350*898184e3Ssthen 351*898184e3Ssthen return sub { ++$count; 352*898184e3Ssthen push @kept, $_; 353*898184e3Ssthen $result{$name} = "$name - $count: [@kept]"; 354*898184e3Ssthen } 355*898184e3Ssthen } 356*898184e3Ssthen 357*898184e3Ssthen $db->filter_store_key(Closure("store key")); 358*898184e3Ssthen $db->filter_store_value(Closure("store value")); 359*898184e3Ssthen $db->filter_fetch_key(Closure("fetch key")); 360*898184e3Ssthen $db->filter_fetch_value(Closure("fetch value")); 361*898184e3Ssthen 362*898184e3Ssthen $_ = "original"; 363*898184e3Ssthen 364*898184e3Ssthen $h{"fred"} = "joe"; 365*898184e3Ssthen is($result{"store key"}, "store key - 1: [fred]"); 366*898184e3Ssthen is($result{"store value"}, "store value - 1: [joe]"); 367*898184e3Ssthen is($result{"fetch key"}, undef); 368*898184e3Ssthen is($result{"fetch value"}, undef); 369*898184e3Ssthen is($_, "original"); 370*898184e3Ssthen 371*898184e3Ssthen is($db->FIRSTKEY(), "fred"); 372*898184e3Ssthen is($result{"store key"}, "store key - 1: [fred]"); 373*898184e3Ssthen is($result{"store value"}, "store value - 1: [joe]"); 374*898184e3Ssthen is($result{"fetch key"}, "fetch key - 1: [fred]"); 375*898184e3Ssthen is($result{"fetch value"}, undef); 376*898184e3Ssthen is($_, "original"); 377*898184e3Ssthen 378*898184e3Ssthen $h{"jim"} = "john"; 379*898184e3Ssthen is($result{"store key"}, "store key - 2: [fred jim]"); 380*898184e3Ssthen is($result{"store value"}, "store value - 2: [joe john]"); 381*898184e3Ssthen is($result{"fetch key"}, "fetch key - 1: [fred]"); 382*898184e3Ssthen is($result{"fetch value"}, undef); 383*898184e3Ssthen is($_, "original"); 384*898184e3Ssthen 385*898184e3Ssthen is($h{"fred"}, "joe"); 386*898184e3Ssthen is($result{"store key"}, "store key - 3: [fred jim fred]"); 387*898184e3Ssthen is($result{"store value"}, "store value - 2: [joe john]"); 388*898184e3Ssthen is($result{"fetch key"}, "fetch key - 1: [fred]"); 389*898184e3Ssthen is($result{"fetch value"}, "fetch value - 1: [joe]"); 390*898184e3Ssthen is($_, "original"); 391*898184e3Ssthen 392*898184e3Ssthen undef $db; 393*898184e3Ssthen untie %h; 394*898184e3Ssthen unlink <Op_dbmx*>; 395*898184e3Ssthen} 396*898184e3Ssthen 397*898184e3Ssthen{ 398*898184e3Ssthen # DBM Filter recursion detection 399*898184e3Ssthen my (%h, $db); 400*898184e3Ssthen unlink <Op_dbmx*>; 401*898184e3Ssthen 402*898184e3Ssthen $db = tie %h, $DBM_Class, 'Op_dbmx', $create, 0640; 403*898184e3Ssthen isa_ok($db, $DBM_Class); 404*898184e3Ssthen 405*898184e3Ssthen $db->filter_store_key (sub { $_ = $h{$_} }); 406*898184e3Ssthen 407*898184e3Ssthen eval '$h{1} = 1234'; 408*898184e3Ssthen like($@, qr/^recursion detected in filter_store_key at/); 409*898184e3Ssthen 410*898184e3Ssthen undef $db; 411*898184e3Ssthen untie %h; 412*898184e3Ssthen unlink <Op_dbmx*>; 413*898184e3Ssthen} 414*898184e3Ssthen 415*898184e3Ssthen{ 416*898184e3Ssthen # Bug ID 20001013.009 417*898184e3Ssthen # 418*898184e3Ssthen # test that $hash{KEY} = undef doesn't produce the warning 419*898184e3Ssthen # Use of uninitialized value in null operation 420*898184e3Ssthen 421*898184e3Ssthen unlink <Op_dbmx*>; 422*898184e3Ssthen my %h; 423*898184e3Ssthen my $a = ""; 424*898184e3Ssthen local $SIG{__WARN__} = sub {$a = $_[0]}; 425*898184e3Ssthen 426*898184e3Ssthen isa_ok(tie(%h, $DBM_Class, 'Op_dbmx', $create, 0640), $DBM_Class); 427*898184e3Ssthen $h{ABC} = undef; 428*898184e3Ssthen is($a, ""); 429*898184e3Ssthen untie %h; 430*898184e3Ssthen unlink <Op_dbmx*>; 431*898184e3Ssthen} 432*898184e3Ssthen 433*898184e3Ssthen{ 434*898184e3Ssthen # When iterating over a tied hash using "each", the key passed to FETCH 435*898184e3Ssthen # will be recycled and passed to NEXTKEY. If a Source Filter modifies the 436*898184e3Ssthen # key in FETCH via a filter_fetch_key method we need to check that the 437*898184e3Ssthen # modified key doesn't get passed to NEXTKEY. 438*898184e3Ssthen # Also Test "keys" & "values" while we are at it. 439*898184e3Ssthen 440*898184e3Ssthen unlink <Op_dbmx*>; 441*898184e3Ssthen my $bad_key = 0; 442*898184e3Ssthen my %h = (); 443*898184e3Ssthen my $db = tie %h, $DBM_Class, 'Op_dbmx', $create, 0640; 444*898184e3Ssthen isa_ok($db, $DBM_Class); 445*898184e3Ssthen $db->filter_fetch_key (sub { $_ =~ s/^Beta_/Alpha_/ if defined $_}); 446*898184e3Ssthen $db->filter_store_key (sub { $bad_key = 1 if /^Beta_/; $_ =~ s/^Alpha_/Beta_/}); 447*898184e3Ssthen 448*898184e3Ssthen $h{'Alpha_ABC'} = 2; 449*898184e3Ssthen $h{'Alpha_DEF'} = 5; 450*898184e3Ssthen 451*898184e3Ssthen is($h{'Alpha_ABC'}, 2); 452*898184e3Ssthen is($h{'Alpha_DEF'}, 5); 453*898184e3Ssthen 454*898184e3Ssthen my ($k, $v) = ("", ""); 455*898184e3Ssthen while (($k, $v) = each %h) {} 456*898184e3Ssthen is($bad_key, 0); 457*898184e3Ssthen 458*898184e3Ssthen $bad_key = 0; 459*898184e3Ssthen foreach $k (keys %h) {} 460*898184e3Ssthen is($bad_key, 0); 461*898184e3Ssthen 462*898184e3Ssthen $bad_key = 0; 463*898184e3Ssthen foreach $v (values %h) {} 464*898184e3Ssthen is($bad_key, 0); 465*898184e3Ssthen 466*898184e3Ssthen undef $db; 467*898184e3Ssthen untie %h; 468*898184e3Ssthen unlink <Op_dbmx*>; 469*898184e3Ssthen} 470*898184e3Ssthen 471*898184e3Ssthen{ 472*898184e3Ssthen # Check that DBM Filter can cope with read-only $_ 473*898184e3Ssthen 474*898184e3Ssthen my %h; 475*898184e3Ssthen unlink <Op1_dbmx*>; 476*898184e3Ssthen 477*898184e3Ssthen my $db = tie %h, $DBM_Class, 'Op1_dbmx', $create, 0640; 478*898184e3Ssthen isa_ok($db, $DBM_Class); 479*898184e3Ssthen 480*898184e3Ssthen $db->filter_fetch_key (sub { }); 481*898184e3Ssthen $db->filter_store_key (sub { }); 482*898184e3Ssthen $db->filter_fetch_value (sub { }); 483*898184e3Ssthen $db->filter_store_value (sub { }); 484*898184e3Ssthen 485*898184e3Ssthen $_ = "original"; 486*898184e3Ssthen 487*898184e3Ssthen $h{"fred"} = "joe"; 488*898184e3Ssthen is($h{"fred"}, "joe"); 489*898184e3Ssthen 490*898184e3Ssthen is_deeply([eval { map { $h{$_} } (1, 2, 3) }], [undef, undef, undef]); 491*898184e3Ssthen is($@, ''); 492*898184e3Ssthen 493*898184e3Ssthen 494*898184e3Ssthen # delete the filters 495*898184e3Ssthen $db->filter_fetch_key (undef); 496*898184e3Ssthen $db->filter_store_key (undef); 497*898184e3Ssthen $db->filter_fetch_value (undef); 498*898184e3Ssthen $db->filter_store_value (undef); 499*898184e3Ssthen 500*898184e3Ssthen $h{"fred"} = "joe"; 501*898184e3Ssthen 502*898184e3Ssthen is($h{"fred"}, "joe"); 503*898184e3Ssthen 504*898184e3Ssthen is($db->FIRSTKEY(), "fred"); 505*898184e3Ssthen 506*898184e3Ssthen is_deeply([eval { map { $h{$_} } (1, 2, 3) }], [undef, undef, undef]); 507*898184e3Ssthen is($@, ''); 508*898184e3Ssthen 509*898184e3Ssthen undef $db; 510*898184e3Ssthen untie %h; 511*898184e3Ssthen unlink <Op1_dbmx*>; 512*898184e3Ssthen} 513*898184e3Ssthen 514*898184e3Ssthendone_testing(); 515*898184e3Ssthen1; 516