1#!./perl 2 3use warnings; 4use strict; 5use Config; 6use File::Temp qw(tempdir) ; 7 8BEGIN { 9 if(-d "lib" && -f "TEST") { 10 if ($Config{'extensions'} !~ /\bDB_File\b/ ) { 11 print "1..0 # Skip: DB_File was not built\n"; 12 exit 0; 13 } 14 } 15} 16 17use DB_File; 18use Fcntl; 19 20print "1..166\n"; 21 22unlink glob "__db.*"; 23 24sub ok 25{ 26 my $no = shift ; 27 my $result = shift ; 28 29 print "not " unless $result ; 30 print "ok $no\n" ; 31 32 return $result ; 33} 34 35{ 36 package Redirect ; 37 use Symbol ; 38 39 sub new 40 { 41 my $class = shift ; 42 my $filename = shift ; 43 my $fh = gensym ; 44 open ($fh, ">$filename") || die "Cannot open $filename: $!" ; 45 my $real_stdout = select($fh) ; 46 return bless [$fh, $real_stdout ] ; 47 48 } 49 sub DESTROY 50 { 51 my $self = shift ; 52 close $self->[0] ; 53 select($self->[1]) ; 54 } 55} 56 57sub docat_del 58{ 59 my $file = shift; 60 local $/ = undef; 61 open(CAT,$file) || die "Cannot open $file: $!"; 62 my $result = <CAT>; 63 close(CAT); 64 $result = normalise($result) ; 65 unlink $file ; 66 return $result; 67} 68 69sub normalise 70{ 71 my $data = shift ; 72 $data =~ s#\r\n#\n#g 73 if $^O eq 'cygwin' ; 74 return $data ; 75} 76 77sub safeUntie 78{ 79 my $hashref = shift ; 80 my $no_inner = 1; 81 local $SIG{__WARN__} = sub {-- $no_inner } ; 82 untie %$hashref; 83 return $no_inner; 84} 85 86my $TEMPDIR = tempdir( CLEANUP => 1 ); 87chdir $TEMPDIR; 88 89my $Dfile = "dbhash.tmp"; 90my $Dfile2 = "dbhash2.tmp"; 91my $null_keys_allowed = ($DB_File::db_ver < 2.004010 92 || $DB_File::db_ver >= 3.1 ); 93 94unlink $Dfile; 95 96umask(0); 97 98# Check the interface to HASHINFO 99 100my $dbh = DB_File::HASHINFO->new(); 101 102ok(1, ! defined $dbh->{bsize}) ; 103ok(2, ! defined $dbh->{ffactor}) ; 104ok(3, ! defined $dbh->{nelem}) ; 105ok(4, ! defined $dbh->{cachesize}) ; 106ok(5, ! defined $dbh->{hash}) ; 107ok(6, ! defined $dbh->{lorder}) ; 108 109$dbh->{bsize} = 3000 ; 110ok(7, $dbh->{bsize} == 3000 ); 111 112$dbh->{ffactor} = 9000 ; 113ok(8, $dbh->{ffactor} == 9000 ); 114 115$dbh->{nelem} = 400 ; 116ok(9, $dbh->{nelem} == 400 ); 117 118$dbh->{cachesize} = 65 ; 119ok(10, $dbh->{cachesize} == 65 ); 120 121my $some_sub = sub {} ; 122$dbh->{hash} = $some_sub; 123ok(11, $dbh->{hash} eq $some_sub ); 124 125$dbh->{lorder} = 1234 ; 126ok(12, $dbh->{lorder} == 1234 ); 127 128# Check that an invalid entry is caught both for store & fetch 129eval '$dbh->{fred} = 1234' ; 130ok(13, $@ =~ /^DB_File::HASHINFO::STORE - Unknown element 'fred' at/ ); 131eval 'my $q = $dbh->{fred}' ; 132ok(14, $@ =~ /^DB_File::HASHINFO::FETCH - Unknown element 'fred' at/ ); 133 134 135# Now check the interface to HASH 136my ($X, %h); 137ok(15, $X = tie(%h, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 138die "Could not tie: $!" unless defined $X; 139 140my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, 141 $blksize,$blocks) = stat($Dfile); 142 143my %noMode = map { $_, 1} qw( amigaos MSWin32 NetWare cygwin ) ; 144 145ok(16, ($mode & 0777) == (($^O eq 'os2' || $^O eq 'MacOS') ? 0666 : 0640) || 146 $noMode{$^O} ); 147 148my ($key, $value, $i); 149while (($key,$value) = each(%h)) { 150 $i++; 151} 152ok(17, !$i ); 153 154$h{'goner1'} = 'snork'; 155 156$h{'abc'} = 'ABC'; 157ok(18, $h{'abc'} eq 'ABC' ); 158ok(19, !defined $h{'jimmy'} ); 159ok(20, !exists $h{'jimmy'} ); 160ok(21, exists $h{'abc'} ); 161 162$h{'def'} = 'DEF'; 163$h{'jkl','mno'} = "JKL\034MNO"; 164$h{'a',2,3,4,5} = join("\034",'A',2,3,4,5); 165$h{'a'} = 'A'; 166 167#$h{'b'} = 'B'; 168$X->STORE('b', 'B') ; 169 170$h{'c'} = 'C'; 171 172#$h{'d'} = 'D'; 173$X->put('d', 'D') ; 174 175$h{'e'} = 'E'; 176$h{'f'} = 'F'; 177$h{'g'} = 'X'; 178$h{'h'} = 'H'; 179$h{'i'} = 'I'; 180 181$h{'goner2'} = 'snork'; 182delete $h{'goner2'}; 183 184 185# IMPORTANT - $X must be undefined before the untie otherwise the 186# underlying DB close routine will not get called. 187undef $X ; 188untie(%h); 189 190 191# tie to the same file again, do not supply a type - should default to HASH 192ok(22, $X = tie(%h,'DB_File',$Dfile, O_RDWR, 0640) ); 193 194# Modify an entry from the previous tie 195$h{'g'} = 'G'; 196 197$h{'j'} = 'J'; 198$h{'k'} = 'K'; 199$h{'l'} = 'L'; 200$h{'m'} = 'M'; 201$h{'n'} = 'N'; 202$h{'o'} = 'O'; 203$h{'p'} = 'P'; 204$h{'q'} = 'Q'; 205$h{'r'} = 'R'; 206$h{'s'} = 'S'; 207$h{'t'} = 'T'; 208$h{'u'} = 'U'; 209$h{'v'} = 'V'; 210$h{'w'} = 'W'; 211$h{'x'} = 'X'; 212$h{'y'} = 'Y'; 213$h{'z'} = 'Z'; 214 215$h{'goner3'} = 'snork'; 216 217delete $h{'goner1'}; 218$X->DELETE('goner3'); 219 220my @keys = keys(%h); 221my @values = values(%h); 222 223ok(23, $#keys == 29 && $#values == 29) ; 224 225$i = 0 ; 226while (($key,$value) = each(%h)) { 227 if ($key eq $keys[$i] && $value eq $values[$i] && $key eq lc($value)) { 228 $key =~ y/a-z/A-Z/; 229 $i++ if $key eq $value; 230 } 231} 232 233ok(24, $i == 30) ; 234 235@keys = ('blurfl', keys(%h), 'dyick'); 236ok(25, $#keys == 31) ; 237 238$h{'foo'} = ''; 239ok(26, $h{'foo'} eq '' ); 240 241# Berkeley DB from version 2.4.10 to 3.0 does not allow null keys. 242# This feature was reenabled in version 3.1 of Berkeley DB. 243my $result = 0 ; 244if ($null_keys_allowed) { 245 $h{''} = 'bar'; 246 $result = ( $h{''} eq 'bar' ); 247} 248else 249 { $result = 1 } 250ok(27, $result) ; 251 252# check cache overflow and numeric keys and contents 253my $ok = 1; 254for ($i = 1; $i < 200; $i++) { $h{$i + 0} = $i + 0; } 255for ($i = 1; $i < 200; $i++) { $ok = 0 unless $h{$i} == $i; } 256ok(28, $ok ); 257 258($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, 259 $blksize,$blocks) = stat($Dfile); 260ok(29, $size > 0 ); 261 262@h{0..200} = 200..400; 263my @foo = @h{0..200}; 264ok(30, join(':',200..400) eq join(':',@foo) ); 265 266 267# Now check all the non-tie specific stuff 268 269# Check NOOVERWRITE will make put fail when attempting to overwrite 270# an existing record. 271 272my $status = $X->put( 'x', 'newvalue', R_NOOVERWRITE) ; 273ok(31, $status == 1 ); 274 275# check that the value of the key 'x' has not been changed by the 276# previous test 277ok(32, $h{'x'} eq 'X' ); 278 279# standard put 280$status = $X->put('key', 'value') ; 281ok(33, $status == 0 ); 282 283#check that previous put can be retrieved 284$value = 0 ; 285$status = $X->get('key', $value) ; 286ok(34, $status == 0 ); 287ok(35, $value eq 'value' ); 288 289# Attempting to delete an existing key should work 290 291$status = $X->del('q') ; 292ok(36, $status == 0 ); 293 294# Make sure that the key deleted, cannot be retrieved 295{ 296 no warnings 'uninitialized' ; 297 ok(37, $h{'q'} eq undef ); 298} 299 300# Attempting to delete a non-existent key should fail 301 302$status = $X->del('joe') ; 303ok(38, $status == 1 ); 304 305# Check the get interface 306 307# First a non-existing key 308$status = $X->get('aaaa', $value) ; 309ok(39, $status == 1 ); 310 311# Next an existing key 312$status = $X->get('a', $value) ; 313ok(40, $status == 0 ); 314ok(41, $value eq 'A' ); 315 316# seq 317# ### 318 319# ditto, but use put to replace the key/value pair. 320 321# use seq to walk backwards through a file - check that this reversed is 322 323# check seq FIRST/LAST 324 325# sync 326# #### 327 328$status = $X->sync ; 329ok(42, $status == 0 ); 330 331 332# fd 333# ## 334 335$status = $X->fd ; 336ok(43, 1 ); 337#ok(43, $status != 0 ); 338 339undef $X ; 340untie %h ; 341 342unlink $Dfile; 343 344# clear 345# ##### 346 347ok(44, tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 348foreach (1 .. 10) 349 { $h{$_} = $_ * 100 } 350 351# check that there are 10 elements in the hash 352$i = 0 ; 353while (($key,$value) = each(%h)) { 354 $i++; 355} 356ok(45, $i == 10); 357 358# now clear the hash 359%h = () ; 360 361# check it is empty 362$i = 0 ; 363while (($key,$value) = each(%h)) { 364 $i++; 365} 366ok(46, $i == 0); 367 368untie %h ; 369unlink $Dfile ; 370 371 372# Now try an in memory file 373ok(47, $X = tie(%h, 'DB_File',undef, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 374 375# fd with an in memory file should return fail 376$status = $X->fd ; 377ok(48, $status == -1 ); 378 379undef $X ; 380untie %h ; 381 382{ 383 # check ability to override the default hashing 384 my %x ; 385 my $filename = "xyz" ; 386 my $hi = DB_File::HASHINFO->new(); 387 $::count = 0 ; 388 $hi->{hash} = sub { ++$::count ; length $_[0] } ; 389 ok(49, tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $hi ) ; 390 $h{"abc"} = 123 ; 391 ok(50, $h{"abc"} == 123) ; 392 untie %x ; 393 unlink $filename ; 394 ok(51, $::count >0) ; 395} 396 397{ 398 # check that attempting to tie an array to a DB_HASH will fail 399 400 my $filename = "xyz" ; 401 my @x ; 402 eval { tie @x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $DB_HASH ; } ; 403 ok(52, $@ =~ /^DB_File can only tie an associative array to a DB_HASH database/) ; 404 unlink $filename ; 405} 406 407{ 408 # sub-class test 409 410 package Another ; 411 412 use warnings ; 413 use strict ; 414 415 open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ; 416 print FILE <<'EOM' ; 417 418 package SubDB ; 419 420 use warnings ; 421 use strict ; 422 our (@ISA, @EXPORT); 423 424 require Exporter ; 425 use DB_File; 426 @ISA=qw(DB_File); 427 @EXPORT = @DB_File::EXPORT ; 428 429 sub STORE { 430 my $self = shift ; 431 my $key = shift ; 432 my $value = shift ; 433 $self->SUPER::STORE($key, $value * 2) ; 434 } 435 436 sub FETCH { 437 my $self = shift ; 438 my $key = shift ; 439 $self->SUPER::FETCH($key) - 1 ; 440 } 441 442 sub put { 443 my $self = shift ; 444 my $key = shift ; 445 my $value = shift ; 446 $self->SUPER::put($key, $value * 3) ; 447 } 448 449 sub get { 450 my $self = shift ; 451 $self->SUPER::get($_[0], $_[1]) ; 452 $_[1] -= 2 ; 453 } 454 455 sub A_new_method 456 { 457 my $self = shift ; 458 my $key = shift ; 459 my $value = $self->FETCH($key) ; 460 return "[[$value]]" ; 461 } 462 463 1 ; 464EOM 465 466 close FILE ; 467 468 BEGIN { push @INC, '.'; } 469 eval 'use SubDB ; '; 470 main::ok(53, $@ eq "") ; 471 my %h ; 472 my $X ; 473 eval ' 474 $X = tie(%h, "SubDB","dbhash.tmp", O_RDWR|O_CREAT, 0640, $DB_HASH ); 475 ' ; 476 477 main::ok(54, $@ eq "") ; 478 479 my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ; 480 main::ok(55, $@ eq "") ; 481 main::ok(56, $ret == 5) ; 482 483 my $value = 0; 484 $ret = eval '$X->put("joe", 4) ; $X->get("joe", $value) ; return $value' ; 485 main::ok(57, $@ eq "") ; 486 main::ok(58, $ret == 10) ; 487 488 $ret = eval ' R_NEXT eq main::R_NEXT ' ; 489 main::ok(59, $@ eq "" ) ; 490 main::ok(60, $ret == 1) ; 491 492 $ret = eval '$X->A_new_method("joe") ' ; 493 main::ok(61, $@ eq "") ; 494 main::ok(62, $ret eq "[[11]]") ; 495 496 undef $X; 497 untie(%h); 498 unlink "SubDB.pm", "dbhash.tmp" ; 499 500} 501 502{ 503 # DBM Filter tests 504 use warnings ; 505 use strict ; 506 my (%h, $db) ; 507 my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 508 unlink $Dfile; 509 510 sub checkOutput 511 { 512 no warnings 'uninitialized'; 513 my($fk, $sk, $fv, $sv) = @_ ; 514 515 print "# Fetch Key : expected '$fk' got '$fetch_key'\n" 516 if $fetch_key ne $fk ; 517 print "# Fetch Value : expected '$fv' got '$fetch_value'\n" 518 if $fetch_value ne $fv ; 519 print "# Store Key : expected '$sk' got '$store_key'\n" 520 if $store_key ne $sk ; 521 print "# Store Value : expected '$sv' got '$store_value'\n" 522 if $store_value ne $sv ; 523 print "# \$_ : expected 'original' got '$_'\n" 524 if $_ ne 'original' ; 525 526 return 527 $fetch_key eq $fk && $store_key eq $sk && 528 $fetch_value eq $fv && $store_value eq $sv && 529 $_ eq 'original' ; 530 } 531 532 ok(63, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 533 534 $db->filter_fetch_key (sub { $fetch_key = $_ }) ; 535 $db->filter_store_key (sub { $store_key = $_ }) ; 536 $db->filter_fetch_value (sub { $fetch_value = $_}) ; 537 $db->filter_store_value (sub { $store_value = $_ }) ; 538 539 $_ = "original" ; 540 541 $h{"fred"} = "joe" ; 542 # fk sk fv sv 543 ok(64, checkOutput( "", "fred", "", "joe")) ; 544 545 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 546 ok(65, $h{"fred"} eq "joe"); 547 # fk sk fv sv 548 ok(66, checkOutput( "", "fred", "joe", "")) ; 549 550 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 551 my ($k, $v) ; 552 $k = 'fred'; 553 ok(67, ! $db->seq($k, $v, R_FIRST) ) ; 554 ok(68, $k eq "fred") ; 555 ok(69, $v eq "joe") ; 556 # fk sk fv sv 557 ok(70, checkOutput( "fred", "fred", "joe", "")) ; 558 559 # replace the filters, but remember the previous set 560 my ($old_fk) = $db->filter_fetch_key 561 (sub { $_ = uc $_ ; $fetch_key = $_ }) ; 562 my ($old_sk) = $db->filter_store_key 563 (sub { $_ = lc $_ ; $store_key = $_ }) ; 564 my ($old_fv) = $db->filter_fetch_value 565 (sub { $_ = "[$_]"; $fetch_value = $_ }) ; 566 my ($old_sv) = $db->filter_store_value 567 (sub { s/o/x/g; $store_value = $_ }) ; 568 569 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 570 $h{"Fred"} = "Joe" ; 571 # fk sk fv sv 572 ok(71, checkOutput( "", "fred", "", "Jxe")) ; 573 574 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 575 ok(72, $h{"Fred"} eq "[Jxe]"); 576 # fk sk fv sv 577 ok(73, checkOutput( "", "fred", "[Jxe]", "")) ; 578 579 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 580 $k = 'Fred'; $v =''; 581 ok(74, ! $db->seq($k, $v, R_FIRST) ) ; 582 ok(75, $k eq "FRED") or 583 print "# k [$k]\n" ; 584 ok(76, $v eq "[Jxe]") ; 585 # fk sk fv sv 586 ok(77, checkOutput( "FRED", "fred", "[Jxe]", "")) ; 587 588 # put the original filters back 589 $db->filter_fetch_key ($old_fk); 590 $db->filter_store_key ($old_sk); 591 $db->filter_fetch_value ($old_fv); 592 $db->filter_store_value ($old_sv); 593 594 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 595 $h{"fred"} = "joe" ; 596 ok(78, checkOutput( "", "fred", "", "joe")) ; 597 598 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 599 ok(79, $h{"fred"} eq "joe"); 600 ok(80, checkOutput( "", "fred", "joe", "")) ; 601 602 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 603 #ok(77, $db->FIRSTKEY() eq "fred") ; 604 $k = 'fred'; 605 ok(81, ! $db->seq($k, $v, R_FIRST) ) ; 606 ok(82, $k eq "fred") ; 607 ok(83, $v eq "joe") ; 608 # fk sk fv sv 609 ok(84, checkOutput( "fred", "fred", "joe", "")) ; 610 611 # delete the filters 612 $db->filter_fetch_key (undef); 613 $db->filter_store_key (undef); 614 $db->filter_fetch_value (undef); 615 $db->filter_store_value (undef); 616 617 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 618 $h{"fred"} = "joe" ; 619 ok(85, checkOutput( "", "", "", "")) ; 620 621 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 622 ok(86, $h{"fred"} eq "joe"); 623 ok(87, checkOutput( "", "", "", "")) ; 624 625 ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4 ; 626 $k = 'fred'; 627 ok(88, ! $db->seq($k, $v, R_FIRST) ) ; 628 ok(89, $k eq "fred") ; 629 ok(90, $v eq "joe") ; 630 ok(91, checkOutput( "", "", "", "")) ; 631 632 undef $db ; 633 untie %h; 634 unlink $Dfile; 635} 636 637{ 638 # DBM Filter with a closure 639 640 use warnings ; 641 use strict ; 642 my (%h, $db) ; 643 644 unlink $Dfile; 645 ok(92, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 646 647 my %result = () ; 648 649 sub Closure 650 { 651 my ($name) = @_ ; 652 my $count = 0 ; 653 my @kept = () ; 654 655 return sub { ++$count ; 656 push @kept, $_ ; 657 $result{$name} = "$name - $count: [@kept]" ; 658 } 659 } 660 661 $db->filter_store_key(Closure("store key")) ; 662 $db->filter_store_value(Closure("store value")) ; 663 $db->filter_fetch_key(Closure("fetch key")) ; 664 $db->filter_fetch_value(Closure("fetch value")) ; 665 666 $_ = "original" ; 667 668 $h{"fred"} = "joe" ; 669 ok(93, $result{"store key"} eq "store key - 1: [fred]"); 670 ok(94, $result{"store value"} eq "store value - 1: [joe]"); 671 ok(95, ! defined $result{"fetch key"} ); 672 ok(96, ! defined $result{"fetch value"} ); 673 ok(97, $_ eq "original") ; 674 675 ok(98, $db->FIRSTKEY() eq "fred") ; 676 ok(99, $result{"store key"} eq "store key - 1: [fred]"); 677 ok(100, $result{"store value"} eq "store value - 1: [joe]"); 678 ok(101, $result{"fetch key"} eq "fetch key - 1: [fred]"); 679 ok(102, ! defined $result{"fetch value"} ); 680 ok(103, $_ eq "original") ; 681 682 $h{"jim"} = "john" ; 683 ok(104, $result{"store key"} eq "store key - 2: [fred jim]"); 684 ok(105, $result{"store value"} eq "store value - 2: [joe john]"); 685 ok(106, $result{"fetch key"} eq "fetch key - 1: [fred]"); 686 ok(107, ! defined $result{"fetch value"} ); 687 ok(108, $_ eq "original") ; 688 689 ok(109, $h{"fred"} eq "joe"); 690 ok(110, $result{"store key"} eq "store key - 3: [fred jim fred]"); 691 ok(111, $result{"store value"} eq "store value - 2: [joe john]"); 692 ok(112, $result{"fetch key"} eq "fetch key - 1: [fred]"); 693 ok(113, $result{"fetch value"} eq "fetch value - 1: [joe]"); 694 ok(114, $_ eq "original") ; 695 696 undef $db ; 697 untie %h; 698 unlink $Dfile; 699} 700 701{ 702 # DBM Filter recursion detection 703 use warnings ; 704 use strict ; 705 my (%h, $db) ; 706 unlink $Dfile; 707 708 ok(115, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 709 710 $db->filter_store_key (sub { $_ = $h{$_} }) ; 711 712 eval '$h{1} = 1234' ; 713 ok(116, $@ =~ /^recursion detected in filter_store_key at/ ); 714 715 undef $db ; 716 untie %h; 717 unlink $Dfile; 718} 719 720 721{ 722 # Examples from the POD 723 724 my $file = "xyzt" ; 725 { 726 my $redirect = Redirect->new( $file ); 727 728 use warnings FATAL => qw(all); 729 use strict ; 730 use DB_File ; 731 our (%h, $k, $v); 732 733 unlink "fruit" ; 734 tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0640, $DB_HASH 735 or die "Cannot open file 'fruit': $!\n"; 736 737 # Add a few key/value pairs to the file 738 $h{"apple"} = "red" ; 739 $h{"orange"} = "orange" ; 740 $h{"banana"} = "yellow" ; 741 $h{"tomato"} = "red" ; 742 743 # Check for existence of a key 744 print "Banana Exists\n\n" if $h{"banana"} ; 745 746 # Delete a key/value pair. 747 delete $h{"apple"} ; 748 749 # print the contents of the file 750 while (($k, $v) = each %h) 751 { print "$k -> $v\n" } 752 753 untie %h ; 754 755 unlink "fruit" ; 756 } 757 758 ok(117, docat_del($file) eq <<'EOM') ; 759Banana Exists 760 761orange -> orange 762tomato -> red 763banana -> yellow 764EOM 765 766} 767 768{ 769 # Bug ID 20001013.009 770 # 771 # test that $hash{KEY} = undef doesn't produce the warning 772 # Use of uninitialized value in null operation 773 use warnings ; 774 use strict ; 775 use DB_File ; 776 777 unlink $Dfile; 778 my %h ; 779 my $a = ""; 780 local $SIG{__WARN__} = sub {$a = $_[0]} ; 781 782 tie %h, 'DB_File', $Dfile or die "Can't open file: $!\n" ; 783 $h{ABC} = undef; 784 ok(118, $a eq "") ; 785 untie %h ; 786 unlink $Dfile; 787} 788 789{ 790 # test that %hash = () doesn't produce the warning 791 # Argument "" isn't numeric in entersub 792 use warnings ; 793 use strict ; 794 use DB_File ; 795 796 unlink $Dfile; 797 my %h ; 798 my $a = ""; 799 local $SIG{__WARN__} = sub {$a = $_[0]} ; 800 801 tie %h, 'DB_File', $Dfile or die "Can't open file: $!\n" ; 802 %h = (); ; 803 ok(119, $a eq "") ; 804 untie %h ; 805 unlink $Dfile; 806} 807 808{ 809 # When iterating over a tied hash using "each", the key passed to FETCH 810 # will be recycled and passed to NEXTKEY. If a Source Filter modifies the 811 # key in FETCH via a filter_fetch_key method we need to check that the 812 # modified key doesn't get passed to NEXTKEY. 813 # Also Test "keys" & "values" while we are at it. 814 815 use warnings ; 816 use strict ; 817 use DB_File ; 818 819 unlink $Dfile; 820 my $bad_key = 0 ; 821 my %h = () ; 822 my $db ; 823 ok(120, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 824 $db->filter_fetch_key (sub { $_ =~ s/^Beta_/Alpha_/ if defined $_}) ; 825 $db->filter_store_key (sub { $bad_key = 1 if /^Beta_/ ; $_ =~ s/^Alpha_/Beta_/}) ; 826 827 $h{'Alpha_ABC'} = 2 ; 828 $h{'Alpha_DEF'} = 5 ; 829 830 ok(121, $h{'Alpha_ABC'} == 2); 831 ok(122, $h{'Alpha_DEF'} == 5); 832 833 my ($k, $v) = ("",""); 834 while (($k, $v) = each %h) {} 835 ok(123, $bad_key == 0); 836 837 $bad_key = 0 ; 838 foreach $k (keys %h) {} 839 ok(124, $bad_key == 0); 840 841 $bad_key = 0 ; 842 foreach $v (values %h) {} 843 ok(125, $bad_key == 0); 844 845 undef $db ; 846 untie %h ; 847 unlink $Dfile; 848} 849 850{ 851 # now an error to pass 'hash' a non-code reference 852 my $dbh = DB_File::HASHINFO->new(); 853 854 eval { $dbh->{hash} = 2 }; 855 ok(126, $@ =~ /^Key 'hash' not associated with a code reference at/); 856 857} 858 859 860#{ 861# # recursion detection in hash 862# my %hash ; 863# my $Dfile = "xxx.db"; 864# unlink $Dfile; 865# my $dbh = DB_File::HASHINFO->new(); 866# $dbh->{hash} = sub { $hash{3} = 4 ; length $_[0] } ; 867# 868# 869# ok(127, tie(%hash, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ); 870# 871# eval { $hash{1} = 2; 872# $hash{4} = 5; 873# }; 874# 875# ok(128, $@ =~ /^DB_File hash callback: recursion detected/); 876# { 877# no warnings; 878# untie %hash; 879# } 880# unlink $Dfile; 881#} 882 883#ok(127, 1); 884#ok(128, 1); 885 886{ 887 # Check that two hash's don't interact 888 my %hash1 ; 889 my %hash2 ; 890 my $h1_count = 0; 891 my $h2_count = 0; 892 unlink $Dfile, $Dfile2; 893 my $dbh1 = DB_File::HASHINFO->new(); 894 $dbh1->{hash} = sub { ++ $h1_count ; length $_[0] } ; 895 896 my $dbh2 = DB_File::HASHINFO->new(); 897 $dbh2->{hash} = sub { ++ $h2_count ; length $_[0] } ; 898 899 900 901 my (%h); 902 ok(127, tie(%hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, 0640, $dbh1 ) ); 903 ok(128, tie(%hash2, 'DB_File',$Dfile2, O_RDWR|O_CREAT, 0640, $dbh2 ) ); 904 905 $hash1{DEFG} = 5; 906 $hash1{XYZ} = 2; 907 $hash1{ABCDE} = 5; 908 909 $hash2{defg} = 5; 910 $hash2{xyz} = 2; 911 $hash2{abcde} = 5; 912 913 ok(129, $h1_count > 0); 914 ok(130, $h1_count == $h2_count); 915 916 ok(131, safeUntie \%hash1); 917 ok(132, safeUntie \%hash2); 918 unlink $Dfile, $Dfile2; 919} 920 921{ 922 # Passing undef for flags and/or mode when calling tie could cause 923 # Use of uninitialized value in subroutine entry 924 925 926 my $warn_count = 0 ; 927 #local $SIG{__WARN__} = sub { ++ $warn_count }; 928 my %hash1; 929 unlink $Dfile; 930 931 tie %hash1, 'DB_File',$Dfile, undef; 932 ok(133, $warn_count == 0); 933 $warn_count = 0; 934 untie %hash1; 935 unlink $Dfile; 936 tie %hash1, 'DB_File',$Dfile, O_RDWR|O_CREAT, undef; 937 ok(134, $warn_count == 0); 938 untie %hash1; 939 unlink $Dfile; 940 tie %hash1, 'DB_File',$Dfile, undef, undef; 941 ok(135, $warn_count == 0); 942 $warn_count = 0; 943 944 untie %hash1; 945 unlink $Dfile; 946} 947 948{ 949 # Check that DBM Filter can cope with read-only $_ 950 951 use warnings ; 952 use strict ; 953 my (%h, $db) ; 954 my $Dfile = "xxy.db"; 955 unlink $Dfile; 956 957 ok(136, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 958 959 $db->filter_fetch_key (sub { }) ; 960 $db->filter_store_key (sub { }) ; 961 $db->filter_fetch_value (sub { }) ; 962 $db->filter_store_value (sub { }) ; 963 964 $_ = "original" ; 965 966 $h{"fred"} = "joe" ; 967 ok(137, $h{"fred"} eq "joe"); 968 969 eval { my @r= grep { $h{$_} } (1, 2, 3) }; 970 ok (138, ! $@); 971 972 973 # delete the filters 974 $db->filter_fetch_key (undef); 975 $db->filter_store_key (undef); 976 $db->filter_fetch_value (undef); 977 $db->filter_store_value (undef); 978 979 $h{"fred"} = "joe" ; 980 981 ok(139, $h{"fred"} eq "joe"); 982 983 ok(140, $db->FIRSTKEY() eq "fred") ; 984 985 eval { my @r= grep { $h{$_} } (1, 2, 3) }; 986 ok (141, ! $@); 987 988 undef $db ; 989 untie %h; 990 unlink $Dfile; 991} 992 993{ 994 # Check low-level API works with filter 995 996 use warnings ; 997 use strict ; 998 my (%h, $db) ; 999 my $Dfile = "xxy.db"; 1000 unlink $Dfile; 1001 1002 ok(142, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 1003 1004 1005 $db->filter_fetch_key (sub { $_ = unpack("i", $_) } ); 1006 $db->filter_store_key (sub { $_ = pack("i", $_) } ); 1007 $db->filter_fetch_value (sub { $_ = unpack("i", $_) } ); 1008 $db->filter_store_value (sub { $_ = pack("i", $_) } ); 1009 1010 $_ = 'fred'; 1011 1012 my $key = 22 ; 1013 my $value = 34 ; 1014 1015 $db->put($key, $value) ; 1016 ok 143, $key == 22; 1017 ok 144, $value == 34 ; 1018 ok 145, $_ eq 'fred'; 1019 #print "k [$key][$value]\n" ; 1020 1021 my $val ; 1022 $db->get($key, $val) ; 1023 ok 146, $key == 22; 1024 ok 147, $val == 34 ; 1025 ok 148, $_ eq 'fred'; 1026 1027 $key = 51 ; 1028 $value = 454; 1029 $h{$key} = $value ; 1030 ok 149, $key == 51; 1031 ok 150, $value == 454 ; 1032 ok 151, $_ eq 'fred'; 1033 1034 undef $db ; 1035 untie %h; 1036 unlink $Dfile; 1037} 1038 1039 1040{ 1041 # Regression Test for bug 30237 1042 # Check that substr can be used in the key to db_put 1043 # and that db_put does not trigger the warning 1044 # 1045 # Use of uninitialized value in subroutine entry 1046 1047 1048 use warnings ; 1049 use strict ; 1050 my (%h, $db) ; 1051 my $Dfile = "xxy.db"; 1052 unlink $Dfile; 1053 1054 ok(152, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 1055 1056 my $warned = ''; 1057 local $SIG{__WARN__} = sub {$warned = $_[0]} ; 1058 1059 # db-put with substr of key 1060 my %remember = () ; 1061 for my $ix ( 1 .. 2 ) 1062 { 1063 my $key = $ix . "data" ; 1064 my $value = "value$ix" ; 1065 $remember{$key} = $value ; 1066 $db->put(substr($key,0), $value) ; 1067 } 1068 1069 ok 153, $warned eq '' 1070 or print "# Caught warning [$warned]\n" ; 1071 1072 # db-put with substr of value 1073 $warned = ''; 1074 for my $ix ( 10 .. 12 ) 1075 { 1076 my $key = $ix . "data" ; 1077 my $value = "value$ix" ; 1078 $remember{$key} = $value ; 1079 $db->put($key, substr($value,0)) ; 1080 } 1081 1082 ok 154, $warned eq '' 1083 or print "# Caught warning [$warned]\n" ; 1084 1085 # via the tied hash is not a problem, but check anyway 1086 # substr of key 1087 $warned = ''; 1088 for my $ix ( 30 .. 32 ) 1089 { 1090 my $key = $ix . "data" ; 1091 my $value = "value$ix" ; 1092 $remember{$key} = $value ; 1093 $h{substr($key,0)} = $value ; 1094 } 1095 1096 ok 155, $warned eq '' 1097 or print "# Caught warning [$warned]\n" ; 1098 1099 # via the tied hash is not a problem, but check anyway 1100 # substr of value 1101 $warned = ''; 1102 for my $ix ( 40 .. 42 ) 1103 { 1104 my $key = $ix . "data" ; 1105 my $value = "value$ix" ; 1106 $remember{$key} = $value ; 1107 $h{$key} = substr($value,0) ; 1108 } 1109 1110 ok 156, $warned eq '' 1111 or print "# Caught warning [$warned]\n" ; 1112 1113 my %bad = () ; 1114 $key = ''; 1115 for ($status = $db->seq(substr($key,0), substr($value,0), R_FIRST ) ; 1116 $status == 0 ; 1117 $status = $db->seq(substr($key,0), substr($value,0), R_NEXT ) ) { 1118 1119 #print "# key [$key] value [$value]\n" ; 1120 if (defined $remember{$key} && defined $value && 1121 $remember{$key} eq $value) { 1122 delete $remember{$key} ; 1123 } 1124 else { 1125 $bad{$key} = $value ; 1126 } 1127 } 1128 1129 ok 157, keys %bad == 0 ; 1130 ok 158, keys %remember == 0 ; 1131 1132 print "# missing -- $key=>$value\n" while ($key, $value) = each %remember; 1133 print "# bad -- $key=>$value\n" while ($key, $value) = each %bad; 1134 1135 # Make sure this fix does not break code to handle an undef key 1136 # Berkeley DB undef key is broken between versions 2.3.16 and 3.1 1137 my $value = 'fred'; 1138 $warned = ''; 1139 $db->put(undef, $value) ; 1140 ok 159, $warned eq '' 1141 or print "# Caught warning [$warned]\n" ; 1142 $warned = ''; 1143 1144 my $no_NULL = ($DB_File::db_ver >= 2.003016 && $DB_File::db_ver < 3.001) ; 1145 print "# db_ver $DB_File::db_ver\n"; 1146 $value = '' ; 1147 $db->get(undef, $value) ; 1148 ok 160, $no_NULL || $value eq 'fred' or print "# got [$value]\n" ; 1149 ok 161, $warned eq '' 1150 or print "# Caught warning [$warned]\n" ; 1151 $warned = ''; 1152 1153 undef $db ; 1154 untie %h; 1155 unlink $Dfile; 1156} 1157 1158{ 1159 # Check filter + substr 1160 1161 use warnings ; 1162 use strict ; 1163 my (%h, $db) ; 1164 my $Dfile = "xxy.db"; 1165 unlink $Dfile; 1166 1167 ok(162, $db = tie(%h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_HASH ) ); 1168 1169 1170 { 1171 $db->filter_fetch_key (sub { lc $_ } ); 1172 $db->filter_store_key (sub { uc $_ } ); 1173 $db->filter_fetch_value (sub { lc $_ } ); 1174 $db->filter_store_value (sub { uc $_ } ); 1175 } 1176 1177 $_ = 'fred'; 1178 1179 # db-put with substr of key 1180 my %remember = () ; 1181 my $status = 0 ; 1182 for my $ix ( 1 .. 2 ) 1183 { 1184 my $key = $ix . "data" ; 1185 my $value = "value$ix" ; 1186 $remember{$key} = $value ; 1187 $status += $db->put(substr($key,0), substr($value,0)) ; 1188 } 1189 1190 ok 163, $status == 0 or print "# Status $status\n" ; 1191 1192 if (1) 1193 { 1194 $db->filter_fetch_key (undef); 1195 $db->filter_store_key (undef); 1196 $db->filter_fetch_value (undef); 1197 $db->filter_store_value (undef); 1198 } 1199 1200 my %bad = () ; 1201 my $key = ''; 1202 my $value = ''; 1203 for ($status = $db->seq($key, $value, R_FIRST ) ; 1204 $status == 0 ; 1205 $status = $db->seq($key, $value, R_NEXT ) ) { 1206 1207 #print "# key [$key] value [$value]\n" ; 1208 if (defined $remember{$key} && defined $value && 1209 $remember{$key} eq $value) { 1210 delete $remember{$key} ; 1211 } 1212 else { 1213 $bad{$key} = $value ; 1214 } 1215 } 1216 1217 ok 164, $_ eq 'fred'; 1218 ok 165, keys %bad == 0 ; 1219 ok 166, keys %remember == 0 ; 1220 1221 print "# missing -- $key $value\n" while ($key, $value) = each %remember; 1222 print "# bad -- $key $value\n" while ($key, $value) = each %bad; 1223 undef $db ; 1224 untie %h; 1225 unlink $Dfile; 1226} 1227 1228exit ; 1229