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