]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/netbsd-tests/lib/libc/db/t_db.sh
MFC r314450,r313439:
[FreeBSD/stable/10.git] / contrib / netbsd-tests / lib / libc / db / t_db.sh
1 # $NetBSD: t_db.sh,v 1.7 2016/09/24 20:12:33 christos Exp $
2 #
3 # Copyright (c) 2008 The NetBSD Foundation, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 # POSSIBILITY OF SUCH DAMAGE.
26 #
27
28 prog_db()
29 {
30         echo $(atf_get_srcdir)/h_db
31 }
32
33 prog_lfsr()
34 {
35         echo $(atf_get_srcdir)/h_lfsr
36 }
37
38 dict()
39 {
40         if [ -f /usr/share/dict/words ]; then
41                 echo /usr/share/dict/words
42         elif [ -f /usr/dict/words ]; then
43                 echo /usr/dict/words
44         else
45                 atf_fail "no dictionary found"
46         fi
47 }
48
49 SEVEN_SEVEN="abcdefg|abcdefg|abcdefg|abcdefg|abcdefg|abcdefg|abcdefg"
50
51 atf_test_case small_btree
52 small_btree_head()
53 {
54         atf_set "descr" \
55                 "Checks btree database using small keys and small data" \
56                 "pairs: takes the first hundred entries in the dictionary," \
57                 "and makes them be key/data pairs."
58         # Begin FreeBSD
59         atf_set "require.files" /usr/share/dict/words
60         # End FreeBSD
61 }
62 small_btree_body()
63 {
64         TMPDIR="$(pwd)/db_dir"; export TMPDIR
65         mkdir ${TMPDIR}
66
67         sed 200q $(dict) >exp
68
69         for i in `sed 200q $(dict)`; do
70                 echo p
71                 echo k$i
72                 echo d$i
73                 echo g
74                 echo k$i
75         done >in
76
77         atf_check -o file:exp "$(prog_db)" btree in
78 }
79
80 atf_test_case small_hash
81 small_hash_head()
82 {
83         atf_set "descr" \
84                 "Checks hash database using small keys and small data" \
85                 "pairs: takes the first hundred entries in the dictionary," \
86                 "and makes them be key/data pairs."
87         # Begin FreeBSD
88         atf_set "require.files" /usr/share/dict/words
89         # End FreeBSD
90 }
91 small_hash_body()
92 {
93         TMPDIR="$(pwd)/db_dir"; export TMPDIR
94         mkdir ${TMPDIR}
95
96         sed 200q $(dict) >exp
97
98         for i in `sed 200q $(dict)`; do
99                 echo p
100                 echo k$i
101                 echo d$i
102                 echo g
103                 echo k$i
104         done >in
105
106         atf_check -o file:exp "$(prog_db)" hash in
107 }
108
109 atf_test_case small_recno
110 small_recno_head()
111 {
112         atf_set "descr" \
113                 "Checks recno database using small keys and small data" \
114                 "pairs: takes the first hundred entries in the dictionary," \
115                 "and makes them be key/data pairs."
116         # Begin FreeBSD
117         atf_set "require.files" /usr/share/dict/words
118         # End FreeBSD
119 }
120 small_recno_body()
121 {
122         TMPDIR="$(pwd)/db_dir"; export TMPDIR
123         mkdir ${TMPDIR}
124
125         sed 200q $(dict) >exp
126
127         sed 200q $(dict) |
128         awk '{ 
129                 ++i;
130                 printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
131         }' >in
132
133         atf_check -o file:exp "$(prog_db)" recno in
134 }
135
136 atf_test_case medium_btree
137 medium_btree_head()
138 {
139         atf_set "descr" \
140                 "Checks btree database using small keys and medium" \
141                 "data pairs: takes the first 200 entries in the" \
142                 "dictionary, and gives them each a medium size data entry."
143         # Begin FreeBSD
144         atf_set "require.files" /usr/share/dict/words
145         # End FreeBSD
146 }
147 medium_btree_body()
148 {
149         TMPDIR="$(pwd)/db_dir"; export TMPDIR
150         mkdir ${TMPDIR}
151
152         mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
153         echo $mdata |
154         awk '{ for (i = 1; i < 201; ++i) print $0 }' >exp
155
156         for i in $(sed 200q $(dict)); do
157                 echo p
158                 echo k$i
159                 echo d$mdata
160                 echo g
161                 echo k$i
162         done >in
163
164         atf_check -o file:exp "$(prog_db)" btree in
165 }
166
167 atf_test_case medium_hash
168 medium_hash_head()
169 {
170         atf_set "descr" \
171                 "Checks hash database using small keys and medium" \
172                 "data pairs: takes the first 200 entries in the" \
173                 "dictionary, and gives them each a medium size data entry."
174         # Begin FreeBSD
175         atf_set "require.files" /usr/share/dict/words
176         # End FreeBSD
177 }
178 medium_hash_body()
179 {
180         TMPDIR="$(pwd)/db_dir"; export TMPDIR
181         mkdir ${TMPDIR}
182
183         mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
184         echo $mdata |
185         awk '{ for (i = 1; i < 201; ++i) print $0 }' >exp
186
187         for i in $(sed 200q $(dict)); do
188                 echo p
189                 echo k$i
190                 echo d$mdata
191                 echo g
192                 echo k$i
193         done >in
194
195         atf_check -o file:exp "$(prog_db)" hash in
196 }
197
198 atf_test_case medium_recno
199 medium_recno_head()
200 {
201         atf_set "descr" \
202                 "Checks recno database using small keys and medium" \
203                 "data pairs: takes the first 200 entries in the" \
204                 "dictionary, and gives them each a medium size data entry."
205 }
206 medium_recno_body()
207 {
208         TMPDIR="$(pwd)/db_dir"; export TMPDIR
209         mkdir ${TMPDIR}
210
211         mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
212         echo $mdata |
213         awk '{ for (i = 1; i < 201; ++i) print $0 }' >exp
214
215         echo $mdata | 
216         awk '{  for (i = 1; i < 201; ++i)
217                 printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
218         }' >in
219
220         atf_check -o file:exp "$(prog_db)" recno in
221 }
222
223 atf_test_case big_btree
224 big_btree_head()
225 {
226         atf_set "descr" \
227                 "Checks btree database using small keys and big data" \
228                 "pairs: inserts the programs in /bin with their paths" \
229                 "as their keys."
230 }
231 big_btree_body()
232 {
233         TMPDIR="$(pwd)/db_dir"; export TMPDIR
234         mkdir ${TMPDIR}
235
236         (find /bin -type f -print | xargs cat) >exp
237
238         for psize in 512 16384 65536; do
239                 echo "checking page size: $psize"
240
241                 for i in `find /bin -type f -print`; do
242                         echo p
243                         echo k$i
244                         echo D$i
245                         echo g
246                         echo k$i
247                 done >in
248
249                 atf_check "$(prog_db)" -o out btree in
250                 cmp -s exp out || atf_fail "test failed for page size: $psize"
251         done
252 }
253
254 atf_test_case big_hash
255 big_hash_head()
256 {
257         atf_set "descr" \
258                 "Checks hash database using small keys and big data" \
259                 "pairs: inserts the programs in /bin with their paths" \
260                 "as their keys."
261 }
262 big_hash_body()
263 {
264         TMPDIR="$(pwd)/db_dir"; export TMPDIR
265         mkdir ${TMPDIR}
266
267         (find /bin -type f -print | xargs cat) >exp
268
269         for i in `find /bin -type f -print`; do
270                 echo p
271                 echo k$i
272                 echo D$i
273                 echo g
274                 echo k$i
275         done >in
276
277         atf_check "$(prog_db)" -o out hash in
278         cmp -s exp out || atf_fail "test failed"
279 }
280
281 atf_test_case big_recno
282 big_recno_head()
283 {
284         atf_set "descr" \
285                 "Checks recno database using small keys and big data" \
286                 "pairs: inserts the programs in /bin with their paths" \
287                 "as their keys."
288 }
289 big_recno_body()
290 {
291         TMPDIR="$(pwd)/db_dir"; export TMPDIR
292         mkdir ${TMPDIR}
293
294         (find /bin -type f -print | xargs cat) >exp
295
296         find /bin -type f -print | 
297         awk '{
298                 ++i;
299                 printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
300         }' >in
301
302         for psize in 512 16384 65536; do
303                 echo "checking page size: $psize"
304
305                 atf_check "$(prog_db)" -o out recno in
306                 cmp -s exp out || atf_fail "test failed for page size: $psize"
307         done
308 }
309
310 atf_test_case random_recno
311 random_recno_head()
312 {
313         atf_set "descr" "Checks recno database using random entries"
314 }
315 random_recno_body()
316 {
317         TMPDIR="$(pwd)/db_dir"; export TMPDIR
318         mkdir ${TMPDIR}
319
320         echo $SEVEN_SEVEN |
321         awk '{
322                 for (i = 37; i <= 37 + 88 * 17; i += 17) {
323                         if (i % 41)
324                                 s = substr($0, 1, i % 41);
325                         else
326                                 s = substr($0, 1);
327                         printf("input key %d: %s\n", i, s);
328                 }
329                 for (i = 1; i <= 15; ++i) {
330                         if (i % 41)
331                                 s = substr($0, 1, i % 41);
332                         else
333                                 s = substr($0, 1);
334                         printf("input key %d: %s\n", i, s);
335                 }
336                 for (i = 19234; i <= 19234 + 61 * 27; i += 27) {
337                         if (i % 41)
338                                 s = substr($0, 1, i % 41);
339                         else
340                                 s = substr($0, 1);
341                         printf("input key %d: %s\n", i, s);
342                 }
343                 exit
344         }' >exp
345
346         cat exp |
347         awk 'BEGIN {
348                         i = 37;
349                         incr = 17;
350                 }
351                 {
352                         printf("p\nk%d\nd%s\n", i, $0);
353                         if (i == 19234 + 61 * 27)
354                                 exit;
355                         if (i == 37 + 88 * 17) {
356                                 i = 1;
357                                 incr = 1;
358                         } else if (i == 15) {
359                                 i = 19234;
360                                 incr = 27;
361                         } else
362                                 i += incr;
363                 }
364                 END {
365                         for (i = 37; i <= 37 + 88 * 17; i += 17)
366                                 printf("g\nk%d\n", i);
367                         for (i = 1; i <= 15; ++i)
368                                 printf("g\nk%d\n", i);
369                         for (i = 19234; i <= 19234 + 61 * 27; i += 27)
370                                 printf("g\nk%d\n", i);
371                 }' >in
372
373         atf_check -o file:exp "$(prog_db)" recno in
374 }
375
376 atf_test_case reverse_recno
377 reverse_recno_head()
378 {
379         atf_set "descr" "Checks recno database using reverse order entries"
380 }
381 reverse_recno_body()
382 {
383         TMPDIR="$(pwd)/db_dir"; export TMPDIR
384         mkdir ${TMPDIR}
385
386         echo $SEVEN_SEVEN |
387         awk ' {
388                 for (i = 1500; i; --i) {
389                         if (i % 34)
390                                 s = substr($0, 1, i % 34);
391                         else
392                                 s = substr($0, 1);
393                         printf("input key %d: %s\n", i, s);
394                 }
395                 exit;
396         }' >exp
397
398         cat exp |
399         awk 'BEGIN {
400                         i = 1500;
401                 }
402                 {
403                         printf("p\nk%d\nd%s\n", i, $0);
404                         --i;
405                 }
406                 END {
407                         for (i = 1500; i; --i) 
408                                 printf("g\nk%d\n", i);
409                 }' >in
410
411         atf_check -o file:exp "$(prog_db)" recno in
412 }
413                 
414 atf_test_case alternate_recno
415 alternate_recno_head()
416 {
417         atf_set "descr" "Checks recno database using alternating order entries"
418 }
419 alternate_recno_body()
420 {
421         TMPDIR="$(pwd)/db_dir"; export TMPDIR
422         mkdir ${TMPDIR}
423
424         echo $SEVEN_SEVEN |
425         awk ' {
426                 for (i = 1; i < 1200; i += 2) {
427                         if (i % 34)
428                                 s = substr($0, 1, i % 34);
429                         else
430                                 s = substr($0, 1);
431                         printf("input key %d: %s\n", i, s);
432                 }
433                 for (i = 2; i < 1200; i += 2) {
434                         if (i % 34)
435                                 s = substr($0, 1, i % 34);
436                         else
437                                 s = substr($0, 1);
438                         printf("input key %d: %s\n", i, s);
439                 }
440                 exit;
441         }' >exp
442
443         cat exp |
444         awk 'BEGIN {
445                         i = 1;
446                         even = 0;
447                 }
448                 {
449                         printf("p\nk%d\nd%s\n", i, $0);
450                         i += 2;
451                         if (i >= 1200) {
452                                 if (even == 1)
453                                         exit;
454                                 even = 1;
455                                 i = 2;
456                         }
457                 }
458                 END {
459                         for (i = 1; i < 1200; ++i) 
460                                 printf("g\nk%d\n", i);
461                 }' >in
462
463         atf_check "$(prog_db)" -o out recno in
464         
465         sort -o exp exp
466         sort -o out out
467
468         cmp -s exp out || atf_fail "test failed"
469 }
470
471 h_delete()
472 {
473         TMPDIR="$(pwd)/db_dir"; export TMPDIR
474         mkdir ${TMPDIR}
475
476         type=$1
477
478         echo $SEVEN_SEVEN |
479         awk '{
480                 for (i = 1; i <= 120; ++i)
481                         printf("%05d: input key %d: %s\n", i, i, $0);
482         }' >exp
483
484         cat exp |
485         awk '{
486                 printf("p\nk%d\nd%s\n", ++i, $0);
487         }
488         END {
489                 printf("fR_NEXT\n");
490                 for (i = 1; i <= 120; ++i)
491                         printf("s\n");
492                 printf("fR_CURSOR\ns\nkXX\n");
493                 printf("r\n");
494                 printf("fR_NEXT\ns\n");
495                 printf("fR_CURSOR\ns\nk1\n");
496                 printf("r\n");
497                 printf("fR_FIRST\ns\n");
498         }' >in
499
500         # For btree, the records are ordered by the string representation
501         # of the key value.  So sort the expected output file accordingly,
502         # and set the seek_last key to the last expected key value.
503
504         if [ "$type" = "btree" ] ; then
505                 sed -e 's/kXX/k99/' < in > tmp
506                 mv tmp in
507                 sort -d -k4 < exp > tmp
508                 mv tmp exp
509                 echo $SEVEN_SEVEN |
510                 awk '{
511                         printf("%05d: input key %d: %s\n", 99, 99, $0);
512                         printf("seq failed, no such key\n");
513                         printf("%05d: input key %d: %s\n", 1, 1, $0);
514                         printf("%05d: input key %d: %s\n", 10, 10, $0);
515                         exit;
516                 }' >> exp
517         else
518         # For recno, records are ordered by numerical key value.  No sort
519         # is needed, but still need to set proper seek_last key value.
520                 sed -e 's/kXX/k120/' < in > tmp
521                 mv tmp in
522                 echo $SEVEN_SEVEN |
523                 awk '{
524                         printf("%05d: input key %d: %s\n", 120, 120, $0);
525                         printf("seq failed, no such key\n");
526                         printf("%05d: input key %d: %s\n", 1, 1, $0);
527                         printf("%05d: input key %d: %s\n", 2, 2, $0);
528                         exit;
529                 }' >> exp
530         fi
531
532         atf_check "$(prog_db)" -o out $type in
533         atf_check -o file:exp cat out
534 }
535
536 atf_test_case delete_btree
537 delete_btree_head()
538 {
539         atf_set "descr" "Checks removing records in btree database"
540 }
541 delete_btree_body()
542 {
543         h_delete btree
544 }
545
546 atf_test_case delete_recno
547 delete_recno_head()
548 {
549         atf_set "descr" "Checks removing records in recno database"
550 }
551 delete_recno_body()
552 {
553         h_delete recno
554 }
555
556 h_repeated()
557 {
558         local type="$1"
559         TMPDIR="$(pwd)/db_dir"; export TMPDIR
560         mkdir ${TMPDIR}
561
562         echo "" | 
563         awk 'BEGIN {
564                 for (i = 1; i <= 10; ++i) {
565                         printf("p\nkkey1\nD/bin/sh\n");
566                         printf("p\nkkey2\nD/bin/csh\n");
567                         if (i % 8 == 0) {
568                                 printf("c\nkkey2\nD/bin/csh\n");
569                                 printf("c\nkkey1\nD/bin/sh\n");
570                                 printf("e\t%d of 10 (comparison)\n", i);
571                         } else
572                                 printf("e\t%d of 10             \n", i);
573                         printf("r\nkkey1\nr\nkkey2\n");
574                 }
575         }' >in
576
577         $(prog_db) $type in
578 }
579
580 atf_test_case repeated_btree
581 repeated_btree_head()
582 {
583         atf_set "descr" \
584                 "Checks btree database with repeated small keys and" \
585                 "big data pairs. Makes sure that overflow pages are reused"
586 }
587 repeated_btree_body()
588 {
589         h_repeated btree
590 }
591
592 atf_test_case repeated_hash
593 repeated_hash_head()
594 {
595         atf_set "descr" \
596                 "Checks hash database with repeated small keys and" \
597                 "big data pairs. Makes sure that overflow pages are reused"
598 }
599 repeated_hash_body()
600 {
601         h_repeated hash
602 }
603
604 atf_test_case duplicate_btree
605 duplicate_btree_head()
606 {
607         atf_set "descr" "Checks btree database with duplicate keys"
608 }
609 duplicate_btree_body()
610 {
611         TMPDIR="$(pwd)/db_dir"; export TMPDIR
612         mkdir ${TMPDIR}
613
614         echo $SEVEN_SEVEN |
615         awk '{
616                 for (i = 1; i <= 543; ++i)
617                         printf("%05d: input key %d: %s\n", i, i, $0);
618                 exit;
619         }' >exp
620
621         cat exp | 
622         awk '{
623                 if (i++ % 2)
624                         printf("p\nkduplicatekey\nd%s\n", $0);
625                 else
626                         printf("p\nkunique%dkey\nd%s\n", i, $0);
627         }
628         END {
629                         printf("o\n");
630         }' >in
631
632         atf_check -o file:exp -x "$(prog_db) -iflags=1 btree in | sort"
633 }
634
635 h_cursor_flags()
636 {
637         local type=$1
638         TMPDIR="$(pwd)/db_dir"; export TMPDIR
639         mkdir ${TMPDIR}
640
641         echo $SEVEN_SEVEN |
642         awk '{
643                 for (i = 1; i <= 20; ++i)
644                         printf("%05d: input key %d: %s\n", i, i, $0);
645                 exit;
646         }' >exp
647
648         # Test that R_CURSOR doesn't succeed before cursor initialized
649         cat exp |
650         awk '{
651                 if (i == 10)
652                         exit;
653                 printf("p\nk%d\nd%s\n", ++i, $0);
654         }
655         END {
656                 printf("fR_CURSOR\nr\n");
657                 printf("eR_CURSOR SHOULD HAVE FAILED\n");
658         }' >in
659
660         atf_check -o ignore -e ignore -s ne:0 "$(prog_db)" -o out $type in
661         atf_check -s ne:0 test -s out
662
663         cat exp |
664         awk '{
665                 if (i == 10)
666                         exit;
667                 printf("p\nk%d\nd%s\n", ++i, $0);
668         }
669         END {
670                 printf("fR_CURSOR\np\nk1\ndsome data\n");
671                 printf("eR_CURSOR SHOULD HAVE FAILED\n");
672         }' >in
673
674         atf_check -o ignore -e ignore -s ne:0 "$(prog_db)" -o out $type in
675         atf_check -s ne:0 test -s out
676 }
677
678 atf_test_case cursor_flags_btree
679 cursor_flags_btree_head()
680 {
681         atf_set "descr" \
682                 "Checks use of cursor flags without initialization in btree database"
683 }
684 cursor_flags_btree_body()
685 {
686         h_cursor_flags btree
687 }
688
689 atf_test_case cursor_flags_recno
690 cursor_flags_recno_head()
691 {
692         atf_set "descr" \
693                 "Checks use of cursor flags without initialization in recno database"
694 }
695 cursor_flags_recno_body()
696 {
697         h_cursor_flags recno
698 }
699
700 atf_test_case reverse_order_recno
701 reverse_order_recno_head()
702 {
703         atf_set "descr" "Checks reverse order inserts in recno database"
704 }
705 reverse_order_recno_body()
706 {
707         TMPDIR="$(pwd)/db_dir"; export TMPDIR
708         mkdir ${TMPDIR}
709
710         echo $SEVEN_SEVEN |
711         awk '{
712                 for (i = 1; i <= 779; ++i)
713                         printf("%05d: input key %d: %s\n", i, i, $0);
714                 exit;
715         }' >exp
716
717         cat exp |
718         awk '{
719                 if (i == 0) {
720                         i = 1;
721                         printf("p\nk1\nd%s\n", $0);
722                         printf("%s\n", "fR_IBEFORE");
723                 } else
724                         printf("p\nk1\nd%s\n", $0);
725         }
726         END {
727                         printf("or\n");
728         }' >in
729
730         atf_check -o file:exp "$(prog_db)" recno in
731 }
732
733 atf_test_case small_page_btree
734 small_page_btree_head()
735 {
736         atf_set "descr" \
737                 "Checks btree database with lots of keys and small page" \
738                 "size: takes the first 20000 entries in the dictionary," \
739                 "reverses them, and gives them each a small size data" \
740                 "entry. Uses a small page size to make sure the btree" \
741                 "split code gets hammered."
742         # Begin FreeBSD
743         atf_set "require.files" /usr/share/dict/words
744         # End FreeBSD
745 }
746 small_page_btree_body()
747 {
748         TMPDIR="$(pwd)/db_dir"; export TMPDIR
749         mkdir ${TMPDIR}
750
751         mdata=abcdefghijklmnopqrstuvwxy
752         echo $mdata |
753         awk '{ for (i = 1; i < 20001; ++i) print $0 }' >exp
754
755         for i in `sed 20000q $(dict) | rev`; do
756                 echo p
757                 echo k$i
758                 echo d$mdata
759                 echo g
760                 echo k$i
761         done >in
762
763         atf_check -o file:exp "$(prog_db)" -i psize=512 btree in
764 }
765
766 h_byte_orders()
767 {
768         TMPDIR="$(pwd)/db_dir"; export TMPDIR
769         mkdir ${TMPDIR}
770
771         type=$1
772
773         sed 50q $(dict) >exp
774         for order in 1234 4321; do
775                 for i in `sed 50q $(dict)`; do
776                         echo p
777                         echo k$i
778                         echo d$i
779                         echo S
780                         echo g
781                         echo k$i
782                 done >in
783
784                 atf_check -o file:exp "$(prog_db)" -ilorder=$order -f byte.file $type in
785
786                 for i in `sed 50q $(dict)`; do
787                         echo g
788                         echo k$i
789                 done >in
790
791                 atf_check -o file:exp "$(prog_db)" -s -ilorder=$order -f byte.file $type in
792         done
793 }
794
795 atf_test_case byte_orders_btree
796 byte_orders_btree_head()
797 {
798         atf_set "descr" "Checks btree database using differing byte orders"
799         # Begin FreeBSD
800         atf_set "require.files" /usr/share/dict/words
801         # End FreeBSD
802 }
803 byte_orders_btree_body()
804 {
805         h_byte_orders btree
806 }
807
808 atf_test_case byte_orders_hash
809 byte_orders_hash_head()
810 {
811         atf_set "descr" "Checks hash database using differing byte orders"
812 }
813 byte_orders_hash_body()
814 {
815         h_byte_orders hash
816 }
817
818 h_bsize_ffactor()
819 {
820         bsize=$1
821         ffactor=$2
822
823         echo "bucketsize $bsize, fill factor $ffactor"
824         atf_check -o file:exp "$(prog_db)" "-ibsize=$bsize,\
825 ffactor=$ffactor,nelem=25000,cachesize=65536" hash in
826 }
827
828 atf_test_case bsize_ffactor
829 bsize_ffactor_head()
830 {
831         atf_set "timeout" "1800"
832         atf_set "descr" "Checks hash database with various" \
833                                         "bucketsizes and fill factors"
834         # Begin FreeBSD
835         atf_set "require.files" /usr/share/dict/words
836         # End FreeBSD
837 }
838 bsize_ffactor_body()
839 {
840         TMPDIR="$(pwd)/db_dir"; export TMPDIR
841         mkdir ${TMPDIR}
842
843         echo $SEVEN_SEVEN |
844         awk '{
845                 for (i = 1; i <= 10000; ++i) {
846                         if (i % 34)
847                                 s = substr($0, 1, i % 34);
848                         else
849                                 s = substr($0, 1);
850                         printf("%s\n", s);
851                 }
852                 exit;
853
854         }' >exp
855
856         sed 10000q $(dict) |
857         awk 'BEGIN {
858                 ds="'$SEVEN_SEVEN'"
859         }
860         {
861                 if (++i % 34)
862                         s = substr(ds, 1, i % 34);
863                 else
864                         s = substr(ds, 1);
865                 printf("p\nk%s\nd%s\n", $0, s);
866         }' >in
867
868         sed 10000q $(dict) |
869         awk '{
870                 ++i;
871                 printf("g\nk%s\n", $0);
872         }' >>in
873
874         h_bsize_ffactor 256 11
875         h_bsize_ffactor 256 14
876         h_bsize_ffactor 256 21
877
878         h_bsize_ffactor 512 21
879         h_bsize_ffactor 512 28
880         h_bsize_ffactor 512 43
881
882         h_bsize_ffactor 1024 43
883         h_bsize_ffactor 1024 57
884         h_bsize_ffactor 1024 85
885
886         h_bsize_ffactor 2048 85
887         h_bsize_ffactor 2048 114
888         h_bsize_ffactor 2048 171
889
890         h_bsize_ffactor 4096 171
891         h_bsize_ffactor 4096 228
892         h_bsize_ffactor 4096 341
893
894         h_bsize_ffactor 8192 341
895         h_bsize_ffactor 8192 455
896         h_bsize_ffactor 8192 683
897
898         h_bsize_ffactor 16384 341
899         h_bsize_ffactor 16384 455
900         h_bsize_ffactor 16384 683
901
902         h_bsize_ffactor 32768 341
903         h_bsize_ffactor 32768 455
904         h_bsize_ffactor 32768 683
905
906         # Begin FreeBSD
907         if false; then
908         # End FreeBSD
909         h_bsize_ffactor 65536 341
910         h_bsize_ffactor 65536 455
911         h_bsize_ffactor 65536 683
912         # Begin FreeBSD
913         fi
914         # End FreeBSD
915 }
916
917 # This tests 64K block size addition/removal
918 atf_test_case four_char_hash
919 four_char_hash_head()
920 {
921         atf_set "descr" \
922                 "Checks hash database with 4 char key and" \
923                 "value insert on a 65536 bucket size"
924 }
925 four_char_hash_body()
926 {
927         TMPDIR="$(pwd)/db_dir"; export TMPDIR
928         mkdir ${TMPDIR}
929
930         cat >in <<EOF
931 p
932 k1234
933 d1234
934 r
935 k1234
936 EOF
937
938         # Begin FreeBSD
939         if true; then
940                 atf_check "$(prog_db)" -i bsize=32768 hash in
941         else
942         # End FreeBSD
943         atf_check "$(prog_db)" -i bsize=65536 hash in
944         # Begin FreeBSD
945         fi
946         # End FreeBSD
947 }
948
949
950 atf_test_case bsize_torture
951 bsize_torture_head()
952 {
953         atf_set "timeout" "36000"
954         atf_set "descr" "Checks hash database with various bucket sizes"
955 }
956 bsize_torture_body()
957 {
958         TMPDIR="$(pwd)/db_dir"; export TMPDIR
959         mkdir ${TMPDIR}
960         # Begin FreeBSD
961         #
962         # db(3) doesn't support 64kB bucket sizes
963         for i in 2048 4096 8192 16384 32768 # 65536
964         # End FreeBSD
965         do
966                 atf_check "$(prog_lfsr)" $i
967         done
968 }
969
970 atf_test_case btree_weird_page_split
971 btree_weird_page_split_head()
972 {
973         atf_set "descr"  \
974             "Test for a weird page split condition where an insertion " \
975             "into index 0 of a page that would cause the new item to " \
976             "be the only item on the left page results in index 0 of " \
977             "the right page being erroneously skipped; this only " \
978             "happens with one particular key+data length for each page size."
979 }
980 btree_weird_page_split_body()
981 {
982         for psize in 512 1024 2048 4096 8192; do
983                 echo "    page size $psize"
984                 kdsizes=`awk 'BEGIN {
985                         psize = '$psize'; hsize = int(psize/2);
986                         for (kdsize = hsize-40; kdsize <= hsize; kdsize++) {
987                                 print kdsize;
988                         }
989                 }' /dev/null`
990
991                 # Use a series of keylen+datalen values in the right
992                 # neighborhood to find the one that triggers the bug.
993                 # We could compute the exact size that triggers the
994                 # bug but this additional fuzz may be useful.
995
996                 # Insert keys in reverse order to maximize the chances
997                 # for a split on index 0.
998
999                 for kdsize in $kdsizes; do
1000                         awk 'BEGIN {
1001                                 kdsize = '$kdsize';
1002                                 for (i = 8; i-- > 0; ) {
1003                                         s = sprintf("a%03d:%09d", i, kdsize);
1004                                         for (j = 0; j < kdsize-20; j++) {
1005                                                 s = s "x";
1006                                         }
1007                                         printf("p\nka%03d\nd%s\n", i, s);
1008                                 }
1009                                 print "o";
1010                         }' /dev/null > in
1011                         sed -n 's/^d//p' in | sort > exp
1012                         atf_check -o file:exp \
1013                             "$(prog_db)" -i psize=$psize btree in
1014                 done
1015         done
1016 }
1017
1018 # Extremely tricky test attempting to replicate some unusual database
1019 # corruption seen in the field: pieces of the database becoming
1020 # inaccessible to random access, sequential access, or both.  The
1021 # hypothesis is that at least some of these are triggered by the bug
1022 # in page splits on index 0 with a particular exact keylen+datalen.
1023 # (See Test 40.)  For psize=4096, this size is exactly 2024.
1024
1025 # The order of operations here relies on very specific knowledge of
1026 # the internals of the btree access method in order to place records
1027 # at specific offsets in a page and to create certain keys on internal
1028 # pages.  The to-be-split page immediately prior to the bug-triggering
1029 # split has the following properties:
1030 #
1031 # * is not the leftmost leaf page
1032 # * key on the parent page is compares less than the key of the item
1033 #   on index 0
1034 # * triggering record's key also compares greater than the key on the
1035 #   parent page
1036
1037 # Additionally, we prime the mpool LRU chain so that the head page on
1038 # the chain has the following properties:
1039 #
1040 # * record at index 0 is located where it will not get overwritten by
1041 #   items written to the right-hand page during the split
1042 # * key of the record at index 0 compares less than the key of the
1043 #   bug-triggering record
1044
1045 # If the page-split bug exists, this test appears to create a database
1046 # where some records are inaccessible to a search, but still remain in
1047 # the file and are accessible by sequential traversal.  At least one
1048 # record gets duplicated out of sequence.
1049
1050 atf_test_case btree_tricky_page_split
1051 btree_tricky_page_split_head()
1052 {
1053         atf_set "descr"  \
1054             "btree: no unsearchables due to page split on index 0"
1055 }
1056 btree_tricky_page_split_body()
1057 {
1058         list=`(for i in a b c d; do
1059                         for j in 990 998 999; do
1060                                 echo g ${i}${j} 1024
1061                         done
1062                 done;
1063                 echo g y997 2014
1064                 for i in y z; do
1065                         for j in 998 999; do
1066                                 echo g ${i}${j} 1024
1067                         done
1068                 done)`
1069         # Exact number for trigger condition accounts for newlines
1070         # retained by dbtest with -ofile but not without; we use
1071         # -ofile, so count newlines.  keylen=5,datalen=5+2014 for
1072         # psize=4096 here.
1073         (cat - <<EOF
1074 p z999 1024
1075 p z998 1024
1076 p y999 1024
1077 p y990 1024
1078 p d999 1024
1079 p d990 1024
1080 p c999 1024
1081 p c990 1024
1082 p b999 1024
1083 p b990 1024
1084 p a999 1024
1085 p a990 1024
1086 p y998 1024
1087 r y990
1088 p d998 1024
1089 p d990 1024
1090 p c998 1024
1091 p c990 1024
1092 p b998 1024
1093 p b990 1024
1094 p a998 1024
1095 p a990 1024
1096 p y997 2014
1097 S
1098 o
1099 EOF
1100         echo "$list") |
1101         # awk script input:
1102         # {p|g|r} key [datasize]
1103         awk '/^[pgr]/{
1104                 printf("%s\nk%s\n", $1, $2);
1105         }
1106         /^p/{
1107                 s = $2;
1108                 for (i = 0; i < $3; i++) {
1109                         s = s "x";
1110                 }
1111                 printf("d%s\n", s);
1112         }
1113         !/^[pgr]/{
1114                 print $0;
1115         }' > in
1116         (echo "$list"; echo "$list") | awk '{
1117                 s = $2;
1118                 for (i = 0; i < $3; i++) {
1119                         s = s "x";
1120                 }
1121                 print s;
1122         }' > exp 
1123         atf_check -o file:exp \
1124             "$(prog_db)" -i psize=4096 btree in
1125 }
1126
1127 # Begin FreeBSD
1128 if false; then
1129 # End FreeBSD
1130 atf_test_case btree_recursive_traversal
1131 btree_recursive_traversal_head()
1132 {
1133         atf_set "descr"  \
1134             "btree: Test for recursive traversal successfully " \
1135             "retrieving records that are inaccessible to normal " \
1136             "sequential 'sibling-link' traversal. This works by " \
1137             "unlinking a few leaf pages but leaving their parent " \
1138             "links intact. To verify that the unlink actually makes " \
1139             "records inaccessible, the test first uses 'o' to do a " \
1140             "normal sequential traversal, followed by 'O' to do a " \
1141             "recursive traversal."
1142 }
1143 btree_recursive_traversal_body()
1144 {
1145         fill="abcdefghijklmnopqrstuvwxyzy"
1146         script='{
1147                 for (i = 0; i < 20000; i++) {
1148                         printf("p\nkAA%05d\nd%05d%s\n", i, i, $0);
1149                 }
1150                 print "u";
1151                 print "u";
1152                 print "u";
1153                 print "u";
1154         }'
1155         (echo $fill | awk "$script"; echo o) > in1
1156         echo $fill |
1157         awk '{
1158                 for (i = 0; i < 20000; i++) {
1159                         if (i >= 5 && i <= 40)
1160                                 continue;
1161                         printf("%05d%s\n", i, $0);
1162                 }
1163         }' > exp1
1164         atf_check -o file:exp1 \
1165             "$(prog_db)" -i psize=512 btree in1
1166         echo $fill |
1167         awk '{
1168                 for (i = 0; i < 20000; i++) {
1169                         printf("%05d%s\n", i, $0);
1170                 }
1171         }' > exp2
1172         (echo $fill | awk "$script"; echo O) > in2
1173         atf_check -o file:exp2 \
1174             "$(prog_db)" -i psize=512 btree in2
1175 }
1176 # Begin FreeBSD
1177 fi
1178 # End FreeBSD
1179
1180 atf_test_case btree_byteswap_unaligned_access_bksd
1181 btree_byteswap_unaligned_access_bksd_head()
1182 {
1183         atf_set "descr"  \
1184             "btree: big key, small data, byteswap unaligned access"
1185 }
1186 btree_byteswap_unaligned_access_bksd_body()
1187 {
1188         (echo foo; echo bar) |
1189         awk '{
1190                 s = $0
1191                 for (i = 0; i < 488; i++) {
1192                         s = s "x";
1193                 }
1194                 printf("p\nk%s\ndx\n", s);
1195         }' > in
1196         for order in 1234 4321; do
1197                 atf_check \
1198                     "$(prog_db)" -o out -i psize=512,lorder=$order btree in
1199         done
1200 }
1201
1202 atf_test_case btree_byteswap_unaligned_access_skbd
1203 btree_byteswap_unaligned_access_skbd_head()
1204 {
1205         atf_set "descr"  \
1206             "btree: small key, big data, byteswap unaligned access"
1207 }
1208 btree_byteswap_unaligned_access_skbd_body()
1209 {
1210         # 484 = 512 - 20 (header) - 7 ("foo1234") - 1 (newline)
1211         (echo foo1234; echo bar1234) |
1212         awk '{
1213                 s = $0
1214                 for (i = 0; i < 484; i++) {
1215                         s = s "x";
1216                 }
1217                 printf("p\nk%s\nd%s\n", $0, s);
1218         }' > in
1219         for order in 1234 4321; do
1220                 atf_check \
1221                     "$(prog_db)" -o out -i psize=512,lorder=$order btree in
1222         done
1223 }
1224
1225 atf_test_case btree_known_byte_order
1226 btree_known_byte_order_head()
1227 {
1228         atf_set "descr"  \
1229             "btree: small key, big data, known byte order"
1230 }
1231 btree_known_byte_order_body()
1232 {
1233         local a="-i psize=512,lorder="
1234
1235         (echo foo1234; echo bar1234) |
1236         awk '{
1237                 s = $0
1238                 for (i = 0; i < 484; i++) {
1239                         s = s "x";
1240                 }
1241                 printf("%s\n", s);
1242         }' > exp
1243         (echo foo1234; echo bar1234) |
1244         awk '{
1245                 s = $0
1246                 for (i = 0; i < 484; i++) {
1247                         s = s "x";
1248                 }
1249                 printf("p\nk%s\nd%s\n", $0, s);
1250         }' > in1
1251         for order in 1234 4321; do
1252                 atf_check \
1253                     "$(prog_db)" -f out.$order $a$order btree in1
1254         done
1255         (echo g; echo kfoo1234; echo g; echo kbar1234) > in2
1256         for order in 1234 4321; do
1257                 atf_check -o file:exp \
1258                     "$(prog_db)" -s -f out.$order $a$order btree in2
1259         done
1260 }
1261
1262 atf_init_test_cases()
1263 {
1264         atf_add_test_case small_btree
1265         atf_add_test_case small_hash
1266         atf_add_test_case small_recno
1267         atf_add_test_case medium_btree
1268         atf_add_test_case medium_hash
1269         atf_add_test_case medium_recno
1270         atf_add_test_case big_btree
1271         atf_add_test_case big_hash
1272         atf_add_test_case big_recno
1273         atf_add_test_case random_recno
1274         atf_add_test_case reverse_recno
1275         atf_add_test_case alternate_recno
1276         atf_add_test_case delete_btree
1277         atf_add_test_case delete_recno
1278         atf_add_test_case repeated_btree
1279         atf_add_test_case repeated_hash
1280         atf_add_test_case duplicate_btree
1281         atf_add_test_case cursor_flags_btree
1282         atf_add_test_case cursor_flags_recno
1283         atf_add_test_case reverse_order_recno
1284         atf_add_test_case small_page_btree
1285         atf_add_test_case byte_orders_btree
1286         atf_add_test_case byte_orders_hash
1287         atf_add_test_case bsize_ffactor
1288         atf_add_test_case four_char_hash
1289         atf_add_test_case bsize_torture
1290         atf_add_test_case btree_weird_page_split
1291         atf_add_test_case btree_tricky_page_split
1292         # Begin FreeBSD
1293         if false; then
1294         # End FreeBSD
1295         atf_add_test_case btree_recursive_traversal
1296         # Begin FreeBSD
1297         fi
1298         # End FreeBSD
1299         atf_add_test_case btree_byteswap_unaligned_access_bksd
1300         atf_add_test_case btree_byteswap_unaligned_access_skbd
1301         atf_add_test_case btree_known_byte_order
1302 }