[PATCH 5.004_65] Config_65-02-03.diff: SunOS and Solaris hints
[p5sagit/p5-mst-13.2.git] / t / lib / db-recno.t
1 #!./perl -w
2
3 BEGIN {
4     @INC = '../lib' if -d '../lib' ;
5     require Config; import Config;
6     if ($Config{'extensions'} !~ /\bDB_File\b/) {
7         print "1..0\n";
8         exit 0;
9     }
10 }
11
12 use DB_File; 
13 use Fcntl;
14 use strict ;
15 use vars qw($dbh $Dfile $bad_ones $FA) ;
16
17 # full tied array support started in Perl 5.004_57
18 $FA = ($] >= 5.004_57) ;
19
20 sub ok
21 {
22     my $no = shift ;
23     my $result = shift ;
24
25     print "not " unless $result ;
26     print "ok $no\n" ;
27
28     return $result ;
29 }
30
31 sub bad_one
32 {
33     print STDERR <<EOM unless $bad_ones++ ;
34 #
35 # Some older versions of Berkeley DB will fail tests 51, 53 and 55.
36 #
37 # You can safely ignore the errors if you're never going to use the
38 # broken functionality (recno databases with a modified bval). 
39 # Otherwise you'll have to upgrade your DB library.
40 #
41 # If you want to upgrade Berkeley DB, the most recent version is 1.85.
42 # Check out http://www.bostic.com/db for more details.
43 #
44 EOM
45 }
46
47 print "1..78\n";
48
49 my $Dfile = "recno.tmp";
50 unlink $Dfile ;
51
52 umask(0);
53
54 # Check the interface to RECNOINFO
55
56 my $dbh = new DB_File::RECNOINFO ;
57 ok(1, ! defined $dbh->{bval}) ;
58 ok(2, ! defined $dbh->{cachesize}) ;
59 ok(3, ! defined $dbh->{psize}) ;
60 ok(4, ! defined $dbh->{flags}) ;
61 ok(5, ! defined $dbh->{lorder}) ;
62 ok(6, ! defined $dbh->{reclen}) ;
63 ok(7, ! defined $dbh->{bfname}) ;
64
65 $dbh->{bval} = 3000 ;
66 ok(8, $dbh->{bval} == 3000 );
67
68 $dbh->{cachesize} = 9000 ;
69 ok(9, $dbh->{cachesize} == 9000 );
70
71 $dbh->{psize} = 400 ;
72 ok(10, $dbh->{psize} == 400 );
73
74 $dbh->{flags} = 65 ;
75 ok(11, $dbh->{flags} == 65 );
76
77 $dbh->{lorder} = 123 ;
78 ok(12, $dbh->{lorder} == 123 );
79
80 $dbh->{reclen} = 1234 ;
81 ok(13, $dbh->{reclen} == 1234 );
82
83 $dbh->{bfname} = 1234 ;
84 ok(14, $dbh->{bfname} == 1234 );
85
86
87 # Check that an invalid entry is caught both for store & fetch
88 eval '$dbh->{fred} = 1234' ;
89 ok(15, $@ =~ /^DB_File::RECNOINFO::STORE - Unknown element 'fred' at/ );
90 eval 'my $q = $dbh->{fred}' ;
91 ok(16, $@ =~ /^DB_File::RECNOINFO::FETCH - Unknown element 'fred' at/ );
92
93 # Now check the interface to RECNOINFO
94
95 my $X  ;
96 my @h ;
97 ok(17, $X = tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) ;
98
99 ok(18, ((stat($Dfile))[2] & 0777) == (($^O eq 'os2' || $^O eq 'MSWin32') ? 0666 : 0640)
100         || $^O eq 'amigaos') ;
101
102 #my $l = @h ;
103 my $l = $X->length ;
104 ok(19, ($FA ? @h == 0 : !$l) );
105
106 my @data = qw( a b c d ever f g h  i j k longername m n o p) ;
107
108 $h[0] = shift @data ;
109 ok(20, $h[0] eq 'a' );
110
111 my $ i;
112 foreach (@data)
113   { $h[++$i] = $_ }
114
115 unshift (@data, 'a') ;
116
117 ok(21, defined $h[1] );
118 ok(22, ! defined $h[16] );
119 ok(23, $FA ? @h == @data : $X->length == @data );
120
121
122 # Overwrite an entry & check fetch it
123 $h[3] = 'replaced' ;
124 $data[3] = 'replaced' ;
125 ok(24, $h[3] eq 'replaced' );
126
127 #PUSH
128 my @push_data = qw(added to the end) ;
129 ($FA ? push(@h, @push_data) : $X->push(@push_data)) ;
130 push (@data, @push_data) ;
131 ok(25, $h[++$i] eq 'added' );
132 ok(26, $h[++$i] eq 'to' );
133 ok(27, $h[++$i] eq 'the' );
134 ok(28, $h[++$i] eq 'end' );
135
136 # POP
137 my $popped = pop (@data) ;
138 my $value = ($FA ? pop @h : $X->pop) ;
139 ok(29, $value eq $popped) ;
140
141 # SHIFT
142 $value = ($FA ? shift @h : $X->shift) ;
143 my $shifted = shift @data ;
144 ok(30, $value eq $shifted );
145
146 # UNSHIFT
147
148 # empty list
149 ($FA ? unshift @h : $X->unshift) ;
150 ok(31, ($FA ? @h == @data : $X->length == @data ));
151
152 my @new_data = qw(add this to the start of the array) ;
153 $FA ? unshift (@h, @new_data) : $X->unshift (@new_data) ;
154 unshift (@data, @new_data) ;
155 ok(32, $FA ? @h == @data : $X->length == @data );
156 ok(33, $h[0] eq "add") ;
157 ok(34, $h[1] eq "this") ;
158 ok(35, $h[2] eq "to") ;
159 ok(36, $h[3] eq "the") ;
160 ok(37, $h[4] eq "start") ;
161 ok(38, $h[5] eq "of") ;
162 ok(39, $h[6] eq "the") ;
163 ok(40, $h[7] eq "array") ;
164 ok(41, $h[8] eq $data[8]) ;
165
166 # SPLICE
167
168 # Now both arrays should be identical
169
170 my $ok = 1 ;
171 my $j = 0 ;
172 foreach (@data)
173 {
174    $ok = 0, last if $_ ne $h[$j ++] ; 
175 }
176 ok(42, $ok );
177
178 # Neagtive subscripts
179
180 # get the last element of the array
181 ok(43, $h[-1] eq $data[-1] );
182 ok(44, $h[-1] eq $h[ ($FA ? @h : $X->length) -1] );
183
184 # get the first element using a negative subscript
185 eval '$h[ - ( $FA ? @h : $X->length)] = "abcd"' ;
186 ok(45, $@ eq "" );
187 ok(46, $h[0] eq "abcd" );
188
189 # now try to read before the start of the array
190 eval '$h[ - (1 + ($FA ? @h : $X->length))] = 1234' ;
191 ok(47, $@ =~ '^Modification of non-creatable array value attempted' );
192
193 # IMPORTANT - $X must be undefined before the untie otherwise the
194 #             underlying DB close routine will not get called.
195 undef $X ;
196 untie(@h);
197
198 unlink $Dfile;
199
200 sub docat
201 {
202     my $file = shift;
203     local $/ = undef;
204     open(CAT,$file) || die "Cannot open $file:$!";
205     my $result = <CAT>;
206     close(CAT);
207     return $result;
208 }
209
210
211 {
212     # Check bval defaults to \n
213
214     my @h = () ;
215     my $dbh = new DB_File::RECNOINFO ;
216     ok(48, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
217     $h[0] = "abc" ;
218     $h[1] = "def" ;
219     $h[3] = "ghi" ;
220     untie @h ;
221     my $x = docat($Dfile) ;
222     unlink $Dfile;
223     ok(49, $x eq "abc\ndef\n\nghi\n") ;
224 }
225
226 {
227     # Change bval
228
229     my @h = () ;
230     my $dbh = new DB_File::RECNOINFO ;
231     $dbh->{bval} = "-" ;
232     ok(50, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
233     $h[0] = "abc" ;
234     $h[1] = "def" ;
235     $h[3] = "ghi" ;
236     untie @h ;
237     my $x = docat($Dfile) ;
238     unlink $Dfile;
239     my $ok = ($x eq "abc-def--ghi-") ;
240     bad_one() unless $ok ;
241     ok(51, $ok) ;
242 }
243
244 {
245     # Check R_FIXEDLEN with default bval (space)
246
247     my @h = () ;
248     my $dbh = new DB_File::RECNOINFO ;
249     $dbh->{flags} = R_FIXEDLEN ;
250     $dbh->{reclen} = 5 ;
251     ok(52, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
252     $h[0] = "abc" ;
253     $h[1] = "def" ;
254     $h[3] = "ghi" ;
255     untie @h ;
256     my $x = docat($Dfile) ;
257     unlink $Dfile;
258     my $ok = ($x eq "abc  def       ghi  ") ;
259     bad_one() unless $ok ;
260     ok(53, $ok) ;
261 }
262
263 {
264     # Check R_FIXEDLEN with user-defined bval
265
266     my @h = () ;
267     my $dbh = new DB_File::RECNOINFO ;
268     $dbh->{flags} = R_FIXEDLEN ;
269     $dbh->{bval} = "-" ;
270     $dbh->{reclen} = 5 ;
271     ok(54, tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $dbh ) ;
272     $h[0] = "abc" ;
273     $h[1] = "def" ;
274     $h[3] = "ghi" ;
275     untie @h ;
276     my $x = docat($Dfile) ;
277     unlink $Dfile;
278     my $ok = ($x eq "abc--def-------ghi--") ;
279     bad_one() unless $ok ;
280     ok(55, $ok) ;
281 }
282
283 {
284     # check that attempting to tie an associative array to a DB_RECNO will fail
285
286     my $filename = "xyz" ;
287     my %x ;
288     eval { tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0640, $DB_RECNO ; } ;
289     ok(56, $@ =~ /^DB_File can only tie an array to a DB_RECNO database/) ;
290     unlink $filename ;
291 }
292
293 {
294    # sub-class test
295
296    package Another ;
297
298    use strict ;
299
300    open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!\n" ;
301    print FILE <<'EOM' ;
302
303    package SubDB ;
304
305    use strict ;
306    use vars qw( @ISA @EXPORT) ;
307
308    require Exporter ;
309    use DB_File;
310    @ISA=qw(DB_File);
311    @EXPORT = @DB_File::EXPORT ;
312
313    sub STORE { 
314         my $self = shift ;
315         my $key = shift ;
316         my $value = shift ;
317         $self->SUPER::STORE($key, $value * 2) ;
318    }
319
320    sub FETCH { 
321         my $self = shift ;
322         my $key = shift ;
323         $self->SUPER::FETCH($key) - 1 ;
324    }
325
326    sub put { 
327         my $self = shift ;
328         my $key = shift ;
329         my $value = shift ;
330         $self->SUPER::put($key, $value * 3) ;
331    }
332
333    sub get { 
334         my $self = shift ;
335         $self->SUPER::get($_[0], $_[1]) ;
336         $_[1] -= 2 ;
337    }
338
339    sub A_new_method
340    {
341         my $self = shift ;
342         my $key = shift ;
343         my $value = $self->FETCH($key) ;
344         return "[[$value]]" ;
345    }
346
347    1 ;
348 EOM
349
350     close FILE ;
351
352     BEGIN { push @INC, '.'; } 
353     eval 'use SubDB ; ';
354     main::ok(57, $@ eq "") ;
355     my @h ;
356     my $X ;
357     eval '
358         $X = tie(@h, "SubDB","recno.tmp", O_RDWR|O_CREAT, 0640, $DB_RECNO );
359         ' ;
360
361     main::ok(58, $@ eq "") ;
362
363     my $ret = eval '$h[3] = 3 ; return $h[3] ' ;
364     main::ok(59, $@ eq "") ;
365     main::ok(60, $ret == 5) ;
366
367     my $value = 0;
368     $ret = eval '$X->put(1, 4) ; $X->get(1, $value) ; return $value' ;
369     main::ok(61, $@ eq "") ;
370     main::ok(62, $ret == 10) ;
371
372     $ret = eval ' R_NEXT eq main::R_NEXT ' ;
373     main::ok(63, $@ eq "" ) ;
374     main::ok(64, $ret == 1) ;
375
376     $ret = eval '$X->A_new_method(1) ' ;
377     main::ok(65, $@ eq "") ;
378     main::ok(66, $ret eq "[[11]]") ;
379
380     undef $X;
381     untie(@h);
382     unlink "SubDB.pm", "recno.tmp" ;
383
384 }
385
386 {
387
388     # test $#
389     my $self ;
390     unlink $Dfile;
391     ok(67, $self = tie @h, 'DB_File', $Dfile, O_RDWR|O_CREAT, 0640, $DB_RECNO ) ;
392     $h[0] = "abc" ;
393     $h[1] = "def" ;
394     $h[2] = "ghi" ;
395     $h[3] = "jkl" ;
396     ok(68, $FA ? $#h == 3 : $self->length() == 4) ;
397     undef $self ;
398     untie @h ;
399     my $x = docat($Dfile) ;
400     ok(69, $x eq "abc\ndef\nghi\njkl\n") ;
401
402     # $# sets array to same length
403     ok(70, $self = tie @h, 'DB_File', $Dfile, O_RDWR, 0640, $DB_RECNO ) ;
404     if ($FA)
405       { $#h = 3 }
406     else 
407       { $self->STORESIZE(4) }
408     ok(71, $FA ? $#h == 3 : $self->length() == 4) ;
409     undef $self ;
410     untie @h ;
411     $x = docat($Dfile) ;
412     ok(72, $x eq "abc\ndef\nghi\njkl\n") ;
413
414     # $# sets array to bigger
415     ok(73, $self = tie @h, 'DB_File', $Dfile, O_RDWR, 0640, $DB_RECNO ) ;
416     if ($FA)
417       { $#h = 6 }
418     else 
419       { $self->STORESIZE(7) }
420     ok(74, $FA ? $#h == 6 : $self->length() == 7) ;
421     undef $self ;
422     untie @h ;
423     $x = docat($Dfile) ;
424     ok(75, $x eq "abc\ndef\nghi\njkl\n\n\n\n") ;
425
426     # $# sets array smaller
427     ok(76, $self = tie @h, 'DB_File', $Dfile, O_RDWR, 0640, $DB_RECNO ) ;
428     if ($FA)
429       { $#h = 2 }
430     else 
431       { $self->STORESIZE(3) }
432     ok(77, $FA ? $#h == 2 : $self->length() == 3) ;
433     undef $self ;
434     untie @h ;
435     $x = docat($Dfile) ;
436     ok(78, $x eq "abc\ndef\nghi\n") ;
437
438     unlink $Dfile;
439
440
441 }
442
443 exit ;