xref: /openbsd-src/gnu/usr.bin/perl/t/lib/dbmt_common.pl (revision f2a19305cfc49ea4d1a5feb55cd6c283c6f1e031)
1898184e3Ssthen#!perl
2898184e3SsthenBEGIN {
3898184e3Ssthen}
4898184e3Ssthen
5898184e3Ssthenuse strict;
6898184e3Ssthenuse warnings;
7898184e3Ssthen
8898184e3Ssthenuse Test::More;
9898184e3Ssthenuse Config;
10898184e3Ssthen
11898184e3Ssthenour $DBM_Class;
12898184e3Ssthen
13898184e3Ssthenmy ($create, $write);
14898184e3SsthenBEGIN {
15898184e3Ssthen    plan(skip_all => "$DBM_Class was not built")
16898184e3Ssthen	unless $Config{extensions} =~ /\b$DBM_Class\b/;
17898184e3Ssthen    plan(skip_all => "$DBM_Class not compatible with C++")
18898184e3Ssthen	 if $DBM_Class eq 'ODBM_File' && $Config{d_cplusplus};
19898184e3Ssthen
20898184e3Ssthen    use_ok($DBM_Class);
21898184e3Ssthen
22898184e3Ssthen    if ($::Create_and_Write) {
23898184e3Ssthen	($create, $write) = eval $::Create_and_Write;
24898184e3Ssthen	isnt($create, undef, "(eval q{$::Create_and_Write})[0]");
25898184e3Ssthen	isnt($write, undef, "(eval q{$::Create_and_Write})[1]");
26898184e3Ssthen    } else {
27898184e3Ssthen	#If Fcntl is not available, try 0x202 or 0x102 for O_RDWR|O_CREAT
28898184e3Ssthen	use_ok('Fcntl');
29898184e3Ssthen	$create = O_RDWR()|O_CREAT();
30898184e3Ssthen	$write = O_RDWR();
31898184e3Ssthen    }
32898184e3Ssthen}
33898184e3Ssthen
34898184e3Ssthenunlink <Op_dbmx.*>;
35898184e3Ssthen
36898184e3Ssthenumask(0);
37898184e3Ssthenmy %h;
38898184e3Ssthenisa_ok(tie(%h, $DBM_Class, 'Op_dbmx', $create, 0640), $DBM_Class);
39898184e3Ssthen
40898184e3Ssthenmy $Dfile = "Op_dbmx.pag";
41898184e3Ssthenif (! -e $Dfile) {
42898184e3Ssthen	($Dfile) = <Op_dbmx*>;
43898184e3Ssthen}
44898184e3SsthenSKIP: {
45898184e3Ssthen    skip "different file permission semantics on $^O", 1
46256a93a4Safresh1	if $^O eq 'amigaos' || $^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'vos';
47898184e3Ssthen    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
48898184e3Ssthen	$blksize,$blocks) = stat($Dfile);
49898184e3Ssthen    is($mode & 0777, 0640);
50898184e3Ssthen}
51898184e3Ssthenmy $i = 0;
52898184e3Ssthenwhile (my ($key,$value) = each(%h)) {
53898184e3Ssthen    $i++;
54898184e3Ssthen}
55898184e3Ssthenis($i, 0);
56898184e3Ssthen
57898184e3Ssthen$h{'goner1'} = 'snork';
58898184e3Ssthen
59898184e3Ssthen$h{'abc'} = 'ABC';
60898184e3Ssthen$h{'def'} = 'DEF';
61898184e3Ssthen$h{'jkl','mno'} = "JKL\034MNO";
62898184e3Ssthen$h{'a',2,3,4,5} = join("\034",'A',2,3,4,5);
63898184e3Ssthen$h{'a'} = 'A';
64898184e3Ssthen$h{'b'} = 'B';
65898184e3Ssthen$h{'c'} = 'C';
66898184e3Ssthen$h{'d'} = 'D';
67898184e3Ssthen$h{'e'} = 'E';
68898184e3Ssthen$h{'f'} = 'F';
69898184e3Ssthen$h{'g'} = 'G';
70898184e3Ssthen$h{'h'} = 'H';
71898184e3Ssthen$h{'i'} = 'I';
72898184e3Ssthen
73898184e3Ssthen$h{'goner2'} = 'snork';
74898184e3Ssthendelete $h{'goner2'};
75898184e3Ssthen
76898184e3Ssthenuntie(%h);
77898184e3Ssthenisa_ok(tie(%h, $DBM_Class, 'Op_dbmx', $write, 0640), $DBM_Class);
78898184e3Ssthen
79898184e3Ssthen$h{'j'} = 'J';
80898184e3Ssthen$h{'k'} = 'K';
81898184e3Ssthen$h{'l'} = 'L';
82898184e3Ssthen$h{'m'} = 'M';
83898184e3Ssthen$h{'n'} = 'N';
84898184e3Ssthen$h{'o'} = 'O';
85898184e3Ssthen$h{'p'} = 'P';
86898184e3Ssthen$h{'q'} = 'Q';
87898184e3Ssthen$h{'r'} = 'R';
88898184e3Ssthen$h{'s'} = 'S';
89898184e3Ssthen$h{'t'} = 'T';
90898184e3Ssthen$h{'u'} = 'U';
91898184e3Ssthen$h{'v'} = 'V';
92898184e3Ssthen$h{'w'} = 'W';
93898184e3Ssthen$h{'x'} = 'X';
94898184e3Ssthen$h{'y'} = 'Y';
95898184e3Ssthen$h{'z'} = 'Z';
96898184e3Ssthen
97898184e3Ssthen$h{'goner3'} = 'snork';
98898184e3Ssthen
99898184e3Ssthendelete $h{'goner1'};
100898184e3Ssthendelete $h{'goner3'};
101898184e3Ssthen
102898184e3Ssthenmy @keys = keys(%h);
103898184e3Ssthenmy @values = values(%h);
104898184e3Ssthen
105898184e3Ssthenis($#keys, 29);
106898184e3Ssthenis($#values, 29);
107898184e3Ssthen
108898184e3Ssthenwhile (my ($key, $value) = each(%h)) {
109898184e3Ssthen    if ($key eq $keys[$i] && $value eq $values[$i] && $key eq lc($value)) {
110898184e3Ssthen	$key =~ y/a-z/A-Z/;
111898184e3Ssthen	$i++ if $key eq $value;
112898184e3Ssthen    }
113898184e3Ssthen}
114898184e3Ssthen
115898184e3Ssthenis($i, 30);
116898184e3Ssthen
117898184e3Ssthen@keys = ('blurfl', keys(%h), 'dyick');
118898184e3Ssthenis($#keys, 31);
119898184e3Ssthen
120898184e3Ssthen$h{'foo'} = '';
121898184e3Ssthen$h{''} = 'bar';
122898184e3Ssthen
123898184e3Ssthenmy $ok = 1;
124898184e3Ssthenfor ($i = 1; $i < 200; $i++) { $h{$i + 0} = $i + 0; }
125898184e3Ssthenfor ($i = 1; $i < 200; $i++) { $ok = 0 unless $h{$i} == $i; }
126898184e3Ssthenis($ok, 1, 'check cache overflow and numeric keys and contents');
127898184e3Ssthen
128898184e3Ssthenmy ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
129898184e3Ssthen   $blksize,$blocks) = stat($Dfile);
130898184e3Ssthencmp_ok($size, '>', 0);
131898184e3Ssthen
132898184e3Ssthen@h{0..200} = 200..400;
133898184e3Ssthenmy @foo = @h{0..200};
134898184e3Ssthenis(join(':',200..400), join(':',@foo));
135898184e3Ssthen
136898184e3Ssthenis($h{'foo'}, '');
137898184e3Ssthenis($h{''}, 'bar');
138898184e3Ssthen
139*f2a19305Safresh1if($DBM_Class eq 'SDBM_File' || $DBM_Class eq 'NDBM_File') {
140898184e3Ssthen    is(exists $h{goner1}, '');
141898184e3Ssthen    is(exists $h{foo}, 1);
142898184e3Ssthen}
143898184e3Ssthen
144898184e3Ssthenuntie %h;
145898184e3Ssthenunlink <Op_dbmx*>, $Dfile;
146898184e3Ssthen
147898184e3Ssthen{
148898184e3Ssthen   # sub-class test
149898184e3Ssthen
150898184e3Ssthen   package Another;
151898184e3Ssthen
152898184e3Ssthen   open my $file, '>', 'SubDB.pm' or die "Cannot open SubDB.pm: $!\n";
153898184e3Ssthen   printf $file <<'EOM', $DBM_Class, $DBM_Class, $DBM_Class;
154898184e3Ssthen
155898184e3Ssthen   package SubDB;
156898184e3Ssthen
157898184e3Ssthen   use strict;
158898184e3Ssthen   use warnings;
159898184e3Ssthen
160898184e3Ssthen   require Exporter;
161898184e3Ssthen   use %s;
1625759b3d2Safresh1   our @ISA=qw(%s);
1635759b3d2Safresh1   our @EXPORT = @%s::EXPORT;
164898184e3Ssthen
165898184e3Ssthen   sub STORE {
166898184e3Ssthen	my $self = shift;
167898184e3Ssthen        my $key = shift;
168898184e3Ssthen        my $value = shift;
169898184e3Ssthen        $self->SUPER::STORE($key, $value * 2);
170898184e3Ssthen   }
171898184e3Ssthen
172898184e3Ssthen   sub FETCH {
173898184e3Ssthen	my $self = shift;
174898184e3Ssthen        my $key = shift;
175898184e3Ssthen        $self->SUPER::FETCH($key) - 1;
176898184e3Ssthen   }
177898184e3Ssthen
178898184e3Ssthen   sub A_new_method
179898184e3Ssthen   {
180898184e3Ssthen	my $self = shift;
181898184e3Ssthen        my $key = shift;
182898184e3Ssthen        my $value = $self->FETCH($key);
183898184e3Ssthen	return "[[$value]]";
184898184e3Ssthen   }
185898184e3Ssthen
186898184e3Ssthen   1;
187898184e3SsthenEOM
188898184e3Ssthen
189898184e3Ssthen    close $file or die "Could not close: $!";
190898184e3Ssthen
191898184e3Ssthen    BEGIN { push @INC, '.'; }
192898184e3Ssthen    unlink <dbhash_tmp*>;
193898184e3Ssthen
194898184e3Ssthen    main::use_ok('SubDB');
195898184e3Ssthen    my %h;
196898184e3Ssthen    my $X;
197898184e3Ssthen    eval '
198898184e3Ssthen	$X = tie(%h, "SubDB", "dbhash_tmp", $create, 0640 );
199898184e3Ssthen	';
200898184e3Ssthen
201898184e3Ssthen    main::is($@, "");
202898184e3Ssthen
203898184e3Ssthen    my $ret = eval '$h{"fred"} = 3; return $h{"fred"} ';
204898184e3Ssthen    main::is($@, "");
205898184e3Ssthen    main::is($ret, 5);
206898184e3Ssthen
207898184e3Ssthen    $ret = eval '$X->A_new_method("fred") ';
208898184e3Ssthen    main::is($@, "");
209898184e3Ssthen    main::is($ret, "[[5]]");
210898184e3Ssthen
211898184e3Ssthen    if ($DBM_Class eq 'GDBM_File') {
212898184e3Ssthen        $ret = eval 'GDBM_WRCREAT eq main::GDBM_WRCREAT';
213898184e3Ssthen        main::is($@, "");
214898184e3Ssthen        main::is($ret, 1);
215898184e3Ssthen    }
216898184e3Ssthen
217898184e3Ssthen    undef $X;
218898184e3Ssthen    untie(%h);
219898184e3Ssthen    unlink "SubDB.pm", <dbhash_tmp*>;
220898184e3Ssthen
221898184e3Ssthen}
222898184e3Ssthen
223898184e3Ssthenuntie %h;
224898184e3Ssthenunlink <Op_dbmx*>, $Dfile;
225898184e3Ssthen
226898184e3Ssthen{
227898184e3Ssthen   # DBM Filter tests
228898184e3Ssthen   my (%h, $db);
229898184e3Ssthen   my ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
230898184e3Ssthen
231898184e3Ssthen   sub checkOutput
232898184e3Ssthen   {
233898184e3Ssthen       my($fk, $sk, $fv, $sv) = @_;
234898184e3Ssthen       local $Test::Builder::Level = $Test::Builder::Level + 1;
235898184e3Ssthen       is($fetch_key, $fk);
236898184e3Ssthen       is($store_key, $sk);
237898184e3Ssthen       is($fetch_value, $fv);
238898184e3Ssthen       is($store_value, $sv);
239898184e3Ssthen       is($_, 'original');
240898184e3Ssthen   }
241898184e3Ssthen
242898184e3Ssthen   unlink <Op_dbmx*>;
243898184e3Ssthen   $db = tie %h, $DBM_Class, 'Op_dbmx', $create, 0640;
244898184e3Ssthen   isa_ok($db, $DBM_Class);
245898184e3Ssthen
246898184e3Ssthen   $db->filter_fetch_key   (sub { $fetch_key = $_ });
247898184e3Ssthen   $db->filter_store_key   (sub { $store_key = $_ });
248898184e3Ssthen   $db->filter_fetch_value (sub { $fetch_value = $_});
249898184e3Ssthen   $db->filter_store_value (sub { $store_value = $_ });
250898184e3Ssthen
251898184e3Ssthen   $_ = "original";
252898184e3Ssthen
253898184e3Ssthen   $h{"fred"} = "joe";
254898184e3Ssthen   #                   fk   sk     fv   sv
255898184e3Ssthen   checkOutput("", "fred", "", "joe");
256898184e3Ssthen
257898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
258898184e3Ssthen   is($h{"fred"}, "joe");
259898184e3Ssthen   #                   fk    sk     fv    sv
260898184e3Ssthen   checkOutput("", "fred", "joe", "");
261898184e3Ssthen
262898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
263898184e3Ssthen   is($db->FIRSTKEY(), "fred");
264898184e3Ssthen   #                    fk     sk  fv  sv
265898184e3Ssthen   checkOutput("fred", "", "", "");
266898184e3Ssthen
267898184e3Ssthen   # replace the filters, but remember the previous set
268898184e3Ssthen   my ($old_fk) = $db->filter_fetch_key
269898184e3Ssthen   			(sub { $_ = uc $_; $fetch_key = $_ });
270898184e3Ssthen   my ($old_sk) = $db->filter_store_key
271898184e3Ssthen   			(sub { $_ = lc $_; $store_key = $_ });
272898184e3Ssthen   my ($old_fv) = $db->filter_fetch_value
273898184e3Ssthen   			(sub { $_ = "[$_]"; $fetch_value = $_ });
274898184e3Ssthen   my ($old_sv) = $db->filter_store_value
275898184e3Ssthen   			(sub { s/o/x/g; $store_value = $_ });
276898184e3Ssthen
277898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
278898184e3Ssthen   $h{"Fred"} = "Joe";
279898184e3Ssthen   #                   fk   sk     fv    sv
280898184e3Ssthen   checkOutput("", "fred", "", "Jxe");
281898184e3Ssthen
282898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
283898184e3Ssthen   is($h{"Fred"}, "[Jxe]");
284898184e3Ssthen   #                   fk   sk     fv    sv
285898184e3Ssthen   checkOutput("", "fred", "[Jxe]", "");
286898184e3Ssthen
287898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
288898184e3Ssthen   is($db->FIRSTKEY(), "FRED");
289898184e3Ssthen   #                   fk   sk     fv    sv
290898184e3Ssthen   checkOutput("FRED", "", "", "");
291898184e3Ssthen
292898184e3Ssthen   # put the original filters back
293898184e3Ssthen   $db->filter_fetch_key   ($old_fk);
294898184e3Ssthen   $db->filter_store_key   ($old_sk);
295898184e3Ssthen   $db->filter_fetch_value ($old_fv);
296898184e3Ssthen   $db->filter_store_value ($old_sv);
297898184e3Ssthen
298898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
299898184e3Ssthen   $h{"fred"} = "joe";
300898184e3Ssthen   checkOutput("", "fred", "", "joe");
301898184e3Ssthen
302898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
303898184e3Ssthen   is($h{"fred"}, "joe");
304898184e3Ssthen   checkOutput("", "fred", "joe", "");
305898184e3Ssthen
306898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
307898184e3Ssthen   is($db->FIRSTKEY(), "fred");
308898184e3Ssthen   checkOutput("fred", "", "", "");
309898184e3Ssthen
310898184e3Ssthen   # delete the filters
311898184e3Ssthen   $db->filter_fetch_key   (undef);
312898184e3Ssthen   $db->filter_store_key   (undef);
313898184e3Ssthen   $db->filter_fetch_value (undef);
314898184e3Ssthen   $db->filter_store_value (undef);
315898184e3Ssthen
316898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
317898184e3Ssthen   $h{"fred"} = "joe";
318898184e3Ssthen   checkOutput("", "", "", "");
319898184e3Ssthen
320898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
321898184e3Ssthen   is($h{"fred"}, "joe");
322898184e3Ssthen   checkOutput("", "", "", "");
323898184e3Ssthen
324898184e3Ssthen   ($fetch_key, $store_key, $fetch_value, $store_value) = ("") x 4;
325898184e3Ssthen   is($db->FIRSTKEY(), "fred");
326898184e3Ssthen   checkOutput("", "", "", "");
327898184e3Ssthen
328898184e3Ssthen   undef $db;
329898184e3Ssthen   untie %h;
330898184e3Ssthen   unlink <Op_dbmx*>;
331898184e3Ssthen}
332898184e3Ssthen
333898184e3Ssthen{
334898184e3Ssthen    # DBM Filter with a closure
335898184e3Ssthen
336898184e3Ssthen    my (%h, $db);
337898184e3Ssthen
338898184e3Ssthen    unlink <Op_dbmx*>;
339898184e3Ssthen    $db = tie %h, $DBM_Class, 'Op_dbmx', $create, 0640;
340898184e3Ssthen    isa_ok($db, $DBM_Class);
341898184e3Ssthen
342898184e3Ssthen    my %result = ();
343898184e3Ssthen
344898184e3Ssthen    sub Closure
345898184e3Ssthen    {
346898184e3Ssthen        my ($name) = @_;
347898184e3Ssthen	my $count = 0;
348898184e3Ssthen	my @kept = ();
349898184e3Ssthen
350898184e3Ssthen	return sub { ++$count;
351898184e3Ssthen		     push @kept, $_;
352898184e3Ssthen		     $result{$name} = "$name - $count: [@kept]";
353898184e3Ssthen		   }
354898184e3Ssthen    }
355898184e3Ssthen
356898184e3Ssthen    $db->filter_store_key(Closure("store key"));
357898184e3Ssthen    $db->filter_store_value(Closure("store value"));
358898184e3Ssthen    $db->filter_fetch_key(Closure("fetch key"));
359898184e3Ssthen    $db->filter_fetch_value(Closure("fetch value"));
360898184e3Ssthen
361898184e3Ssthen    $_ = "original";
362898184e3Ssthen
363898184e3Ssthen    $h{"fred"} = "joe";
364898184e3Ssthen    is($result{"store key"}, "store key - 1: [fred]");
365898184e3Ssthen    is($result{"store value"}, "store value - 1: [joe]");
366898184e3Ssthen    is($result{"fetch key"}, undef);
367898184e3Ssthen    is($result{"fetch value"}, undef);
368898184e3Ssthen    is($_, "original");
369898184e3Ssthen
370898184e3Ssthen    is($db->FIRSTKEY(), "fred");
371898184e3Ssthen    is($result{"store key"}, "store key - 1: [fred]");
372898184e3Ssthen    is($result{"store value"}, "store value - 1: [joe]");
373898184e3Ssthen    is($result{"fetch key"}, "fetch key - 1: [fred]");
374898184e3Ssthen    is($result{"fetch value"}, undef);
375898184e3Ssthen    is($_, "original");
376898184e3Ssthen
377898184e3Ssthen    $h{"jim"}  = "john";
378898184e3Ssthen    is($result{"store key"}, "store key - 2: [fred jim]");
379898184e3Ssthen    is($result{"store value"}, "store value - 2: [joe john]");
380898184e3Ssthen    is($result{"fetch key"}, "fetch key - 1: [fred]");
381898184e3Ssthen    is($result{"fetch value"}, undef);
382898184e3Ssthen    is($_, "original");
383898184e3Ssthen
384898184e3Ssthen    is($h{"fred"}, "joe");
385898184e3Ssthen    is($result{"store key"}, "store key - 3: [fred jim fred]");
386898184e3Ssthen    is($result{"store value"}, "store value - 2: [joe john]");
387898184e3Ssthen    is($result{"fetch key"}, "fetch key - 1: [fred]");
388898184e3Ssthen    is($result{"fetch value"}, "fetch value - 1: [joe]");
389898184e3Ssthen    is($_, "original");
390898184e3Ssthen
391898184e3Ssthen    undef $db;
392898184e3Ssthen    untie %h;
393898184e3Ssthen    unlink <Op_dbmx*>;
394898184e3Ssthen}
395898184e3Ssthen
396898184e3Ssthen{
397898184e3Ssthen   # DBM Filter recursion detection
398898184e3Ssthen   my (%h, $db);
399898184e3Ssthen   unlink <Op_dbmx*>;
400898184e3Ssthen
401898184e3Ssthen   $db = tie %h, $DBM_Class, 'Op_dbmx', $create, 0640;
402898184e3Ssthen   isa_ok($db, $DBM_Class);
403898184e3Ssthen
404898184e3Ssthen   $db->filter_store_key (sub { $_ = $h{$_} });
405898184e3Ssthen
406898184e3Ssthen   eval '$h{1} = 1234';
407898184e3Ssthen   like($@, qr/^recursion detected in filter_store_key at/);
408898184e3Ssthen
409898184e3Ssthen   undef $db;
410898184e3Ssthen   untie %h;
411898184e3Ssthen   unlink <Op_dbmx*>;
412898184e3Ssthen}
413898184e3Ssthen
414898184e3Ssthen{
4155759b3d2Safresh1    # Bug ID 20001013.009 (#4434)
416898184e3Ssthen    #
417898184e3Ssthen    # test that $hash{KEY} = undef doesn't produce the warning
418898184e3Ssthen    #     Use of uninitialized value in null operation
419898184e3Ssthen
420898184e3Ssthen    unlink <Op_dbmx*>;
421898184e3Ssthen    my %h;
422898184e3Ssthen    my $a = "";
423898184e3Ssthen    local $SIG{__WARN__} = sub {$a = $_[0]};
424898184e3Ssthen
425898184e3Ssthen    isa_ok(tie(%h, $DBM_Class, 'Op_dbmx', $create, 0640), $DBM_Class);
426898184e3Ssthen    $h{ABC} = undef;
427898184e3Ssthen    is($a, "");
428898184e3Ssthen    untie %h;
429898184e3Ssthen    unlink <Op_dbmx*>;
430898184e3Ssthen}
431898184e3Ssthen
432898184e3Ssthen{
433898184e3Ssthen    # When iterating over a tied hash using "each", the key passed to FETCH
434898184e3Ssthen    # will be recycled and passed to NEXTKEY. If a Source Filter modifies the
435898184e3Ssthen    # key in FETCH via a filter_fetch_key method we need to check that the
436898184e3Ssthen    # modified key doesn't get passed to NEXTKEY.
437898184e3Ssthen    # Also Test "keys" & "values" while we are at it.
438898184e3Ssthen
439898184e3Ssthen    unlink <Op_dbmx*>;
440898184e3Ssthen    my $bad_key = 0;
441898184e3Ssthen    my %h = ();
442898184e3Ssthen    my $db = tie %h, $DBM_Class, 'Op_dbmx', $create, 0640;
443898184e3Ssthen    isa_ok($db, $DBM_Class);
444898184e3Ssthen    $db->filter_fetch_key (sub { $_ =~ s/^Beta_/Alpha_/ if defined $_});
445898184e3Ssthen    $db->filter_store_key (sub { $bad_key = 1 if /^Beta_/; $_ =~ s/^Alpha_/Beta_/});
446898184e3Ssthen
447898184e3Ssthen    $h{'Alpha_ABC'} = 2;
448898184e3Ssthen    $h{'Alpha_DEF'} = 5;
449898184e3Ssthen
450898184e3Ssthen    is($h{'Alpha_ABC'}, 2);
451898184e3Ssthen    is($h{'Alpha_DEF'}, 5);
452898184e3Ssthen
453898184e3Ssthen    my ($k, $v) = ("", "");
454898184e3Ssthen    while (($k, $v) = each %h) {}
455898184e3Ssthen    is($bad_key, 0);
456898184e3Ssthen
457898184e3Ssthen    $bad_key = 0;
458898184e3Ssthen    foreach $k (keys %h) {}
459898184e3Ssthen    is($bad_key, 0);
460898184e3Ssthen
461898184e3Ssthen    $bad_key = 0;
462898184e3Ssthen    foreach $v (values %h) {}
463898184e3Ssthen    is($bad_key, 0);
464898184e3Ssthen
465898184e3Ssthen    undef $db;
466898184e3Ssthen    untie %h;
467898184e3Ssthen    unlink <Op_dbmx*>;
468898184e3Ssthen}
469898184e3Ssthen
470898184e3Ssthen{
471898184e3Ssthen   # Check that DBM Filter can cope with read-only $_
472898184e3Ssthen
473898184e3Ssthen   my %h;
474898184e3Ssthen   unlink <Op1_dbmx*>;
475898184e3Ssthen
476898184e3Ssthen   my $db = tie %h, $DBM_Class, 'Op1_dbmx', $create, 0640;
477898184e3Ssthen   isa_ok($db, $DBM_Class);
478898184e3Ssthen
479898184e3Ssthen   $db->filter_fetch_key   (sub { });
480898184e3Ssthen   $db->filter_store_key   (sub { });
481898184e3Ssthen   $db->filter_fetch_value (sub { });
482898184e3Ssthen   $db->filter_store_value (sub { });
483898184e3Ssthen
484898184e3Ssthen   $_ = "original";
485898184e3Ssthen
486898184e3Ssthen   $h{"fred"} = "joe";
487898184e3Ssthen   is($h{"fred"}, "joe");
488898184e3Ssthen
489898184e3Ssthen   is_deeply([eval { map { $h{$_} } (1, 2, 3) }], [undef, undef, undef]);
490898184e3Ssthen   is($@, '');
491898184e3Ssthen
492898184e3Ssthen
493898184e3Ssthen   # delete the filters
494898184e3Ssthen   $db->filter_fetch_key   (undef);
495898184e3Ssthen   $db->filter_store_key   (undef);
496898184e3Ssthen   $db->filter_fetch_value (undef);
497898184e3Ssthen   $db->filter_store_value (undef);
498898184e3Ssthen
499898184e3Ssthen   $h{"fred"} = "joe";
500898184e3Ssthen
501898184e3Ssthen   is($h{"fred"}, "joe");
502898184e3Ssthen
503898184e3Ssthen   is($db->FIRSTKEY(), "fred");
504898184e3Ssthen
505898184e3Ssthen   is_deeply([eval { map { $h{$_} } (1, 2, 3) }], [undef, undef, undef]);
506898184e3Ssthen   is($@, '');
507898184e3Ssthen
508898184e3Ssthen   undef $db;
509898184e3Ssthen   untie %h;
510898184e3Ssthen   unlink <Op1_dbmx*>;
511898184e3Ssthen}
512898184e3Ssthen
513898184e3Ssthendone_testing();
514898184e3Ssthen1;
515