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