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