xref: /freebsd/lib/libc/db/test/run.test (revision 5b31cc94b10d4bb7109c6b27940a0fc76a44a331)
1#!/bin/sh -
2
3# db regression tests
4main()
5{
6
7	PROG=./dbtest
8	TMP1=t1
9	TMP2=t2
10	TMP3=t3
11
12	if [ -f /usr/share/dict/words ]; then
13		DICT=/usr/share/dict/words
14	elif [ -f /usr/dict/words ]; then
15		DICT=/usr/dict/words
16	else
17		echo 'run.test: no dictionary'
18		exit 1
19	fi
20
21	if [ $# -eq 0 ]; then
22		for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do
23			test$t
24		done
25	else
26		while [ $# -gt 0 ]
27			do case "$1" in
28			test*)
29				$1;;
30			[0-9]*)
31				test$1;;
32			btree)
33				for t in 1 2 3 7 8 9 10 12 13; do
34					test$t
35				done;;
36			hash)
37				for t in 1 2 3 8 13 20; do
38					test$t
39				done;;
40			recno)
41				for t in 1 2 3 4 5 6 7 10 11; do
42					test$t
43				done;;
44			*)
45				echo "run.test: unknown test $1"
46				echo "usage: run.test test# | type"
47				exit 1
48			esac
49			shift
50		done
51	fi
52	rm -f $TMP1 $TMP2 $TMP3
53	exit 0
54}
55
56# Take the first hundred entries in the dictionary, and make them
57# be key/data pairs.
58test1()
59{
60	echo "Test 1: btree, hash: small key, small data pairs"
61	sed 200q $DICT > $TMP1
62	for type in btree hash; do
63		rm -f $TMP2 $TMP3
64		for i in `sed 200q $DICT`; do
65			echo p
66			echo k$i
67			echo d$i
68			echo g
69			echo k$i
70		done > $TMP2
71		$PROG -o $TMP3 $type $TMP2
72		if (cmp -s $TMP1 $TMP3) ; then :
73		else
74			echo "test1: type $type: failed"
75			exit 1
76		fi
77	done
78	echo "Test 1: recno: small key, small data pairs"
79	rm -f $TMP2 $TMP3
80	sed 200q $DICT |
81	awk '{
82		++i;
83		printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
84	}' > $TMP2
85	$PROG -o $TMP3 recno $TMP2
86	if (cmp -s $TMP1 $TMP3) ; then :
87	else
88		echo "test1: type recno: failed"
89		exit 1
90	fi
91}
92
93# Take the first 200 entries in the dictionary, and give them
94# each a medium size data entry.
95test2()
96{
97	echo "Test 2: btree, hash: small key, medium data pairs"
98	mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
99	echo $mdata |
100	awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1
101	for type in hash btree; do
102		rm -f $TMP2 $TMP3
103		for i in `sed 200q $DICT`; do
104			echo p
105			echo k$i
106			echo d$mdata
107			echo g
108			echo k$i
109		done > $TMP2
110		$PROG -o $TMP3 $type $TMP2
111		if (cmp -s $TMP1 $TMP3) ; then :
112		else
113			echo "test2: type $type: failed"
114			exit 1
115		fi
116	done
117	echo "Test 2: recno: small key, medium data pairs"
118	rm -f $TMP2 $TMP3
119	echo $mdata |
120	awk '{  for (i = 1; i < 201; ++i)
121		printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
122	}' > $TMP2
123	$PROG -o $TMP3 recno $TMP2
124	if (cmp -s $TMP1 $TMP3) ; then :
125	else
126		echo "test2: type recno: failed"
127		exit 1
128	fi
129}
130
131# Insert the programs in /bin with their paths as their keys.
132test3()
133{
134	echo "Test 3: hash: small key, big data pairs"
135	rm -f $TMP1
136	(find /bin -type f -print | xargs cat) > $TMP1
137	for type in hash; do
138		rm -f $TMP2 $TMP3
139		for i in `find /bin -type f -print`; do
140			echo p
141			echo k$i
142			echo D$i
143			echo g
144			echo k$i
145		done > $TMP2
146		$PROG -o $TMP3 $type $TMP2
147		if (cmp -s $TMP1 $TMP3) ; then :
148		else
149			echo "test3: $type: failed"
150			exit 1
151		fi
152	done
153	echo "Test 3: btree: small key, big data pairs"
154	for psize in 512 16384 65536; do
155		echo "    page size $psize"
156		for type in btree; do
157			rm -f $TMP2 $TMP3
158			for i in `find /bin -type f -print`; do
159				echo p
160				echo k$i
161				echo D$i
162				echo g
163				echo k$i
164			done > $TMP2
165			$PROG -i psize=$psize -o $TMP3 $type $TMP2
166			if (cmp -s $TMP1 $TMP3) ; then :
167			else
168				echo "test3: $type: page size $psize: failed"
169				exit 1
170			fi
171		done
172	done
173	echo "Test 3: recno: big data pairs"
174	rm -f $TMP2 $TMP3
175	find /bin -type f -print |
176	awk '{
177		++i;
178		printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
179	}' > $TMP2
180	for psize in 512 16384 65536; do
181		echo "    page size $psize"
182		$PROG -i psize=$psize -o $TMP3 recno $TMP2
183		if (cmp -s $TMP1 $TMP3) ; then :
184		else
185			echo "test3: recno: page size $psize: failed"
186			exit 1
187		fi
188	done
189}
190
191# Do random recno entries.
192test4()
193{
194	echo "Test 4: recno: random entries"
195	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
196	awk '{
197		for (i = 37; i <= 37 + 88 * 17; i += 17) {
198			if (i % 41)
199				s = substr($0, 1, i % 41);
200			else
201				s = substr($0, 1);
202			printf("input key %d: %s\n", i, s);
203		}
204		for (i = 1; i <= 15; ++i) {
205			if (i % 41)
206				s = substr($0, 1, i % 41);
207			else
208				s = substr($0, 1);
209			printf("input key %d: %s\n", i, s);
210		}
211		for (i = 19234; i <= 19234 + 61 * 27; i += 27) {
212			if (i % 41)
213				s = substr($0, 1, i % 41);
214			else
215				s = substr($0, 1);
216			printf("input key %d: %s\n", i, s);
217		}
218		exit
219	}' > $TMP1
220	rm -f $TMP2 $TMP3
221	cat $TMP1 |
222	awk 'BEGIN {
223			i = 37;
224			incr = 17;
225		}
226		{
227			printf("p\nk%d\nd%s\n", i, $0);
228			if (i == 19234 + 61 * 27)
229				exit;
230			if (i == 37 + 88 * 17) {
231				i = 1;
232				incr = 1;
233			} else if (i == 15) {
234				i = 19234;
235				incr = 27;
236			} else
237				i += incr;
238		}
239		END {
240			for (i = 37; i <= 37 + 88 * 17; i += 17)
241				printf("g\nk%d\n", i);
242			for (i = 1; i <= 15; ++i)
243				printf("g\nk%d\n", i);
244			for (i = 19234; i <= 19234 + 61 * 27; i += 27)
245				printf("g\nk%d\n", i);
246		}' > $TMP2
247	$PROG -o $TMP3 recno $TMP2
248	if (cmp -s $TMP1 $TMP3) ; then :
249	else
250		echo "test4: type recno: failed"
251		exit 1
252	fi
253}
254
255# Do reverse order recno entries.
256test5()
257{
258	echo "Test 5: recno: reverse order entries"
259	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
260	awk ' {
261		for (i = 1500; i; --i) {
262			if (i % 34)
263				s = substr($0, 1, i % 34);
264			else
265				s = substr($0, 1);
266			printf("input key %d: %s\n", i, s);
267		}
268		exit;
269	}' > $TMP1
270	rm -f $TMP2 $TMP3
271	cat $TMP1 |
272	awk 'BEGIN {
273			i = 1500;
274		}
275		{
276			printf("p\nk%d\nd%s\n", i, $0);
277			--i;
278		}
279		END {
280			for (i = 1500; i; --i)
281				printf("g\nk%d\n", i);
282		}' > $TMP2
283	$PROG -o $TMP3 recno $TMP2
284	if (cmp -s $TMP1 $TMP3) ; then :
285	else
286		echo "test5: type recno: failed"
287		exit 1
288	fi
289}
290
291# Do alternating order recno entries.
292test6()
293{
294	echo "Test 6: recno: alternating order entries"
295	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
296	awk ' {
297		for (i = 1; i < 1200; i += 2) {
298			if (i % 34)
299				s = substr($0, 1, i % 34);
300			else
301				s = substr($0, 1);
302			printf("input key %d: %s\n", i, s);
303		}
304		for (i = 2; i < 1200; i += 2) {
305			if (i % 34)
306				s = substr($0, 1, i % 34);
307			else
308				s = substr($0, 1);
309			printf("input key %d: %s\n", i, s);
310		}
311		exit;
312	}' > $TMP1
313	rm -f $TMP2 $TMP3
314	cat $TMP1 |
315	awk 'BEGIN {
316			i = 1;
317			even = 0;
318		}
319		{
320			printf("p\nk%d\nd%s\n", i, $0);
321			i += 2;
322			if (i >= 1200) {
323				if (even == 1)
324					exit;
325				even = 1;
326				i = 2;
327			}
328		}
329		END {
330			for (i = 1; i < 1200; ++i)
331				printf("g\nk%d\n", i);
332		}' > $TMP2
333	$PROG -o $TMP3 recno $TMP2
334	sort -o $TMP1 $TMP1
335	sort -o $TMP3 $TMP3
336	if (cmp -s $TMP1 $TMP3) ; then :
337	else
338		echo "test6: type recno: failed"
339		exit 1
340	fi
341}
342
343# Delete cursor record
344test7()
345{
346	echo "Test 7: btree, recno: delete cursor record"
347	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
348	awk '{
349		for (i = 1; i <= 120; ++i)
350			printf("%05d: input key %d: %s\n", i, i, $0);
351		printf("%05d: input key %d: %s\n", 120, 120, $0);
352		printf("seq failed, no such key\n");
353		printf("%05d: input key %d: %s\n", 1, 1, $0);
354		printf("%05d: input key %d: %s\n", 2, 2, $0);
355		exit;
356	}' > $TMP1
357	rm -f $TMP2 $TMP3
358
359	for type in btree recno; do
360		cat $TMP1 |
361		awk '{
362			if (i == 120)
363				exit;
364			printf("p\nk%d\nd%s\n", ++i, $0);
365		}
366		END {
367			printf("fR_NEXT\n");
368			for (i = 1; i <= 120; ++i)
369				printf("s\n");
370			printf("fR_CURSOR\ns\nk120\n");
371			printf("r\n");
372			printf("fR_NEXT\ns\n");
373			printf("fR_CURSOR\ns\nk1\n");
374			printf("r\n");
375			printf("fR_FIRST\ns\n");
376		}' > $TMP2
377		$PROG -o $TMP3 recno $TMP2
378		if (cmp -s $TMP1 $TMP3) ; then :
379		else
380			echo "test7: type $type: failed"
381			exit 1
382		fi
383	done
384}
385
386# Make sure that overflow pages are reused.
387test8()
388{
389	echo "Test 8: btree, hash: repeated small key, big data pairs"
390	rm -f $TMP1
391	echo "" |
392	awk 'BEGIN {
393		for (i = 1; i <= 10; ++i) {
394			printf("p\nkkey1\nD/bin/sh\n");
395			printf("p\nkkey2\nD/bin/csh\n");
396			if (i % 8 == 0) {
397				printf("c\nkkey2\nD/bin/csh\n");
398				printf("c\nkkey1\nD/bin/sh\n");
399				printf("e\t%d of 10 (comparison)\n", i);
400			} else
401				printf("e\t%d of 10             \n", i);
402			printf("r\nkkey1\nr\nkkey2\n");
403		}
404	}' > $TMP1
405	$PROG btree $TMP1
406#	$PROG hash $TMP1
407	# No explicit test for success.
408}
409
410# Test btree duplicate keys
411test9()
412{
413	echo "Test 9: btree: duplicate keys"
414	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
415	awk '{
416		for (i = 1; i <= 543; ++i)
417			printf("%05d: input key %d: %s\n", i, i, $0);
418		exit;
419	}' > $TMP1
420	rm -f $TMP2 $TMP3
421
422	for type in btree; do
423		cat $TMP1 |
424		awk '{
425			if (i++ % 2)
426				printf("p\nkduplicatekey\nd%s\n", $0);
427			else
428				printf("p\nkunique%dkey\nd%s\n", i, $0);
429		}
430		END {
431				printf("o\n");
432		}' > $TMP2
433		$PROG -iflags=1 -o $TMP3 $type $TMP2
434		sort -o $TMP3 $TMP3
435		if (cmp -s $TMP1 $TMP3) ; then :
436		else
437			echo "test9: type $type: failed"
438			exit 1
439		fi
440	done
441}
442
443# Test use of cursor flags without initialization
444test10()
445{
446	echo "Test 10: btree, recno: test cursor flag use"
447	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
448	awk '{
449		for (i = 1; i <= 20; ++i)
450			printf("%05d: input key %d: %s\n", i, i, $0);
451		exit;
452	}' > $TMP1
453	rm -f $TMP2 $TMP3
454
455	# Test that R_CURSOR doesn't succeed before cursor initialized
456	for type in btree recno; do
457		cat $TMP1 |
458		awk '{
459			if (i == 10)
460				exit;
461			printf("p\nk%d\nd%s\n", ++i, $0);
462		}
463		END {
464			printf("fR_CURSOR\nr\n");
465			printf("eR_CURSOR SHOULD HAVE FAILED\n");
466		}' > $TMP2
467		$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
468		if [ -s $TMP3 ] ; then
469			echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED"
470			exit 1
471		fi
472	done
473	for type in btree recno; do
474		cat $TMP1 |
475		awk '{
476			if (i == 10)
477				exit;
478			printf("p\nk%d\nd%s\n", ++i, $0);
479		}
480		END {
481			printf("fR_CURSOR\np\nk1\ndsome data\n");
482			printf("eR_CURSOR SHOULD HAVE FAILED\n");
483		}' > $TMP2
484		$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
485		if [ -s $TMP3 ] ; then
486			echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED"
487			exit 1
488		fi
489	done
490}
491
492# Test insert in reverse order.
493test11()
494{
495	echo "Test 11: recno: reverse order insert"
496	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
497	awk '{
498		for (i = 1; i <= 779; ++i)
499			printf("%05d: input key %d: %s\n", i, i, $0);
500		exit;
501	}' > $TMP1
502	rm -f $TMP2 $TMP3
503
504	for type in recno; do
505		cat $TMP1 |
506		awk '{
507			if (i == 0) {
508				i = 1;
509				printf("p\nk1\nd%s\n", $0);
510				printf("%s\n", "fR_IBEFORE");
511			} else
512				printf("p\nk1\nd%s\n", $0);
513		}
514		END {
515				printf("or\n");
516		}' > $TMP2
517		$PROG -o $TMP3 $type $TMP2
518		if (cmp -s $TMP1 $TMP3) ; then :
519		else
520			echo "test11: type $type: failed"
521			exit 1
522		fi
523	done
524}
525
526# Take the first 20000 entries in the dictionary, reverse them, and give
527# them each a small size data entry.  Use a small page size to make sure
528# the btree split code gets hammered.
529test12()
530{
531	echo "Test 12: btree: lots of keys, small page size"
532	mdata=abcdefghijklmnopqrstuvwxy
533	echo $mdata |
534	awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1
535	for type in btree; do
536		rm -f $TMP2 $TMP3
537		for i in `sed 20000q $DICT | rev`; do
538			echo p
539			echo k$i
540			echo d$mdata
541			echo g
542			echo k$i
543		done > $TMP2
544		$PROG -i psize=512 -o $TMP3 $type $TMP2
545		if (cmp -s $TMP1 $TMP3) ; then :
546		else
547			echo "test12: type $type: failed"
548			exit 1
549		fi
550	done
551}
552
553# Test different byte orders.
554test13()
555{
556	echo "Test 13: btree, hash: differing byte orders"
557	sed 50q $DICT > $TMP1
558	for order in 1234 4321; do
559		for type in btree hash; do
560			rm -f byte.file $TMP2 $TMP3
561			for i in `sed 50q $DICT`; do
562				echo p
563				echo k$i
564				echo d$i
565				echo g
566				echo k$i
567			done > $TMP2
568			$PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
569			if (cmp -s $TMP1 $TMP3) ; then :
570			else
571				echo "test13: $type/$order put failed"
572				exit 1
573			fi
574			for i in `sed 50q $DICT`; do
575				echo g
576				echo k$i
577			done > $TMP2
578			$PROG -s \
579			    -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
580			if (cmp -s $TMP1 $TMP3) ; then :
581			else
582				echo "test13: $type/$order get failed"
583				exit 1
584			fi
585		done
586	done
587	rm -f byte.file
588}
589
590# Try a variety of bucketsizes and fill factors for hashing
591test20()
592{
593	echo\
594    "Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536"
595	echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
596	awk '{
597		for (i = 1; i <= 10000; ++i) {
598			if (i % 34)
599				s = substr($0, 1, i % 34);
600			else
601				s = substr($0, 1);
602			printf("%s\n", s);
603		}
604		exit;
605	}' > $TMP1
606	sed 10000q $DICT |
607	awk 'BEGIN {
608		ds="abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg"
609	}
610	{
611		if (++i % 34)
612			s = substr(ds, 1, i % 34);
613		else
614			s = substr(ds, 1);
615		printf("p\nk%s\nd%s\n", $0, s);
616	}' > $TMP2
617	sed 10000q $DICT |
618	awk '{
619		++i;
620		printf("g\nk%s\n", $0);
621	}' >> $TMP2
622	bsize=256
623	for ffactor in 11 14 21; do
624		echo "    bucketsize $bsize, fill factor $ffactor"
625		$PROG -o$TMP3 \
626		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
627		    hash $TMP2
628		if (cmp -s $TMP1 $TMP3) ; then :
629		else
630			echo "test20: type hash:\
631bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
632			exit 1
633		fi
634	done
635	bsize=512
636	for ffactor in 21 28 43; do
637		echo "    bucketsize $bsize, fill factor $ffactor"
638		$PROG -o$TMP3 \
639		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
640		    hash $TMP2
641		if (cmp -s $TMP1 $TMP3) ; then :
642		else
643			echo "test20: type hash:\
644bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
645			exit 1
646		fi
647	done
648	bsize=1024
649	for ffactor in 43 57 85; do
650		echo "    bucketsize $bsize, fill factor $ffactor"
651		$PROG -o$TMP3 \
652		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
653		    hash $TMP2
654		if (cmp -s $TMP1 $TMP3) ; then :
655		else
656			echo "test20: type hash:\
657bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
658			exit 1
659		fi
660	done
661	bsize=2048
662	for ffactor in 85 114 171; do
663		echo "    bucketsize $bsize, fill factor $ffactor"
664		$PROG -o$TMP3 \
665		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
666		    hash $TMP2
667		if (cmp -s $TMP1 $TMP3) ; then :
668		else
669			echo "test20: type hash:\
670bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
671			exit 1
672		fi
673	done
674	bsize=4096
675	for ffactor in 171 228 341; do
676		echo "    bucketsize $bsize, fill factor $ffactor"
677		$PROG -o$TMP3 \
678		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
679		    hash $TMP2
680		if (cmp -s $TMP1 $TMP3) ; then :
681		else
682			echo "test20: type hash:\
683bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
684			exit 1
685		fi
686	done
687	bsize=8192
688	for ffactor in 341 455 683; do
689		echo "    bucketsize $bsize, fill factor $ffactor"
690		$PROG -o$TMP3 \
691		    -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
692		    hash $TMP2
693		if (cmp -s $TMP1 $TMP3) ; then :
694		else
695			echo "test20: type hash:\
696bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
697			exit 1
698		fi
699	done
700}
701
702main $*
703