The db test has been atf-ified
This commit is contained in:
parent
27aeaab683
commit
a3eac7b0e8
|
@ -1,6 +1,6 @@
|
|||
# $NetBSD: Makefile,v 1.75 2011/01/07 02:51:38 pgoyette Exp $
|
||||
# $NetBSD: Makefile,v 1.76 2011/01/07 15:08:40 pgoyette Exp $
|
||||
|
||||
SUBDIR+= citrus db divrem getaddrinfo int_fmtio locale regex rpc
|
||||
SUBDIR+= citrus divrem getaddrinfo int_fmtio locale regex rpc
|
||||
|
||||
.include <bsd.own.mk>
|
||||
.include <bsd.sys.mk>
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
# $NetBSD: Makefile,v 1.19 2009/01/24 22:11:45 christos Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
NOMAN= # defined
|
||||
WARNS=4
|
||||
|
||||
PROG= dbtest
|
||||
.if defined(LOCALLIBC)
|
||||
SRCS= dbtest.c
|
||||
SRCS+= hash.c hash_bigkey.c hash_buf.c hash_func.c hash_log2.c
|
||||
SRCS+= hash_page.c ndbm.c ndbmdatum.c
|
||||
SRCS+= bt_close.c bt_conv.c bt_debug.c bt_delete.c bt_get.c bt_open.c
|
||||
SRCS+= bt_overflow.c bt_page.c bt_put.c bt_search.c bt_seq.c bt_split.c
|
||||
SRCS+= bt_utils.c
|
||||
SRCS+= rec_close.c rec_delete.c rec_get.c rec_open.c rec_put.c
|
||||
SRCS+= rec_search.c rec_seq.c rec_utils.c
|
||||
SRCS+= db.c
|
||||
SRCS+= mpool.c
|
||||
.PATH.c: /usr/src/lib/libc/db/hash
|
||||
.PATH.c: /usr/src/lib/libc/db/btree
|
||||
.PATH.c: /usr/src/lib/libc/db/recno
|
||||
.PATH.c: /usr/src/lib/libc/db/mpool
|
||||
.PATH.c: /usr/src/lib/libc/db/db
|
||||
|
||||
# add -DSTATISTICS to CPPFLAGS to get usage statistics. Note that
|
||||
# for this to work, libc must be compiled with -DSTATISTICS as well
|
||||
CPPFLAGS+= -g -D__DBINTERFACE_PRIVATE
|
||||
CPPFLAGS+= -I/usr/src/lib/libc/include
|
||||
CPPFLAGS+= -DDEBUG -DSTATISTICS -DHASH_STATISTICS
|
||||
CPPFLAGS+= -DDEBUG1 -DDEBUG2 -DDEBUG3 -DDEBUG4 -DDEBUG5 -DDIAGNOSTIC
|
||||
.endif
|
||||
CLEANFILES+= t1 t2 t3
|
||||
|
||||
regress: dbtest
|
||||
${HOST_SH} ${.CURDIR}/run.test
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -1,68 +0,0 @@
|
|||
# $NetBSD: README,v 1.5 1996/05/03 21:54:19 cgd Exp $
|
||||
# @(#)README 8.8 (Berkeley) 7/31/94
|
||||
|
||||
To run the tests, enter "make regress".
|
||||
|
||||
Fairly large files (the command files) are built in this directory during
|
||||
the test runs, and even larger files (the database files) are created in
|
||||
"/var/tmp". If the latter directory doesn't exist, set the environmental
|
||||
variable TMPDIR to a directory where the files can be built.
|
||||
|
||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
The script file consists of lines with an initial character which is
|
||||
the command for that line, or an initial character indicating a key
|
||||
or data entry for a previous command.
|
||||
|
||||
Legal command characters are as follows:
|
||||
|
||||
c: compare a record
|
||||
+ must be followed by [kK][dD]; the data value in the database
|
||||
associated with the specified key is compared to the specified
|
||||
data value.
|
||||
e: echo a string
|
||||
+ writes out the rest of the line into the output file; if the
|
||||
last character is not a carriage-return, a newline is appended.
|
||||
f: set the flags for the next command
|
||||
+ no value zero's the flags
|
||||
g: do a get command
|
||||
+ must be followed by [kK]
|
||||
+ writes out the retrieved data DBT.
|
||||
o [r]: dump [reverse]
|
||||
+ dump the database out, if 'r' is set, in reverse order.
|
||||
p: do a put command
|
||||
+ must be followed by [kK][dD]
|
||||
r: do a del command
|
||||
+ must be followed by [kK] unless R_CURSOR flag set.
|
||||
S: sync the database
|
||||
s: do a seq command
|
||||
+ must be followed by [kK] if R_CURSOR flag set.
|
||||
+ writes out the retrieved data DBT.
|
||||
|
||||
Legal key/data characters are as follows:
|
||||
|
||||
D [file]: data file
|
||||
+ set the current data value to the contents of the file
|
||||
d [data]:
|
||||
+ set the current key value to the contents of the line.
|
||||
K [file]: key file
|
||||
+ set the current key value to the contents of the file
|
||||
k [data]:
|
||||
+ set the current key value to the contents of the line.
|
||||
|
||||
Blank lines, lines with leading white space, and lines with leading
|
||||
hash marks (#) are ignored.
|
||||
|
||||
Options to dbtest are as follows:
|
||||
|
||||
-d: Set the DB_LOCK flag.
|
||||
-f: Use the file argument as the database file.
|
||||
-i: Use the rest of the argument to set elements in the info
|
||||
structure. If the type is btree, then "-i cachesize=10240"
|
||||
will set BTREEINFO.cachesize to 10240.
|
||||
-o: The rest of the argument is the output file instead of
|
||||
using stdout.
|
||||
-s: Don't delete the database file before opening it, i.e.
|
||||
use the database file from a previous run.
|
||||
|
||||
Dbtest requires two arguments, the type of access "hash", "recno"
|
||||
or "btree", and the script name or "-" to indicate stdin.
|
|
@ -1,731 +0,0 @@
|
|||
/* $NetBSD: dbtest.c,v 1.18 2009/01/25 17:00:09 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)dbtest.c 8.17 (Berkeley) 9/1/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: dbtest.c,v 1.18 2009/01/25 17:00:09 nonaka Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <db.h>
|
||||
|
||||
enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
|
||||
|
||||
static void compare(DBT *, DBT *);
|
||||
static DBTYPE dbtype(const char *);
|
||||
static void dump(DB *, int);
|
||||
static void get(DB *, DBT *);
|
||||
static void getdata(DB *, DBT *, DBT *);
|
||||
static void put(DB *, DBT *, DBT *);
|
||||
static void rem(DB *, DBT *);
|
||||
static const char *sflags(int);
|
||||
static void synk(DB *);
|
||||
static void *rfile(char *, size_t *);
|
||||
static void seq(DB *, DBT *);
|
||||
static u_int setflags(char *);
|
||||
static void *setinfo(DBTYPE, char *);
|
||||
static void usage(void) __attribute__((__noreturn__));
|
||||
static void *xcopy(void *, size_t);
|
||||
static void chkcmd(enum S);
|
||||
static void chkdata(enum S);
|
||||
static void chkkey(enum S);
|
||||
|
||||
#ifdef STATISTICS
|
||||
extern void __bt_stat(DB *);
|
||||
#endif
|
||||
|
||||
static DBTYPE type; /* Database type. */
|
||||
static void *infop; /* Iflags. */
|
||||
static size_t lineno; /* Current line in test script. */
|
||||
static u_int flags; /* Current DB flags. */
|
||||
static int ofd = STDOUT_FILENO; /* Standard output fd. */
|
||||
|
||||
static DB *XXdbp; /* Global for gdb. */
|
||||
static size_t XXlineno; /* Fast breakpoint for gdb. */
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
enum S command = COMMAND, state;
|
||||
DB *dbp;
|
||||
DBT data, key, keydata;
|
||||
size_t len;
|
||||
int ch, oflags, sflag;
|
||||
char *fname, *infoarg, *p, *t, buf[8 * 1024];
|
||||
bool unlink_dbfile;
|
||||
|
||||
infoarg = NULL;
|
||||
fname = NULL;
|
||||
unlink_dbfile = false;
|
||||
oflags = O_CREAT | O_RDWR;
|
||||
sflag = 0;
|
||||
while ((ch = getopt(argc, argv, "f:i:lo:s")) != -1)
|
||||
switch (ch) {
|
||||
case 'f':
|
||||
fname = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
infoarg = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
oflags |= DB_LOCK;
|
||||
break;
|
||||
case 'o':
|
||||
if ((ofd = open(optarg,
|
||||
O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
|
||||
err(1, "Cannot create `%s'", optarg);
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 2)
|
||||
usage();
|
||||
|
||||
/* Set the type. */
|
||||
type = dbtype(*argv++);
|
||||
|
||||
/* Open the descriptor file. */
|
||||
if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL)
|
||||
err(1, "Cannot reopen `%s'", *argv);
|
||||
|
||||
/* Set up the db structure as necessary. */
|
||||
if (infoarg == NULL)
|
||||
infop = NULL;
|
||||
else
|
||||
for (p = strtok(infoarg, ",\t "); p != NULL;
|
||||
p = strtok(0, ",\t "))
|
||||
if (*p != '\0')
|
||||
infop = setinfo(type, p);
|
||||
|
||||
/*
|
||||
* Open the DB. Delete any preexisting copy, you almost never
|
||||
* want it around, and it often screws up tests.
|
||||
*/
|
||||
if (fname == NULL) {
|
||||
const char *q = getenv("TMPDIR");
|
||||
if (q == NULL)
|
||||
q = "/var/tmp";
|
||||
(void)snprintf(buf, sizeof(buf), "%s/__dbtest", q);
|
||||
fname = buf;
|
||||
(void)unlink(buf);
|
||||
unlink_dbfile = true;
|
||||
} else if (!sflag)
|
||||
(void)unlink(fname);
|
||||
|
||||
if ((dbp = dbopen(fname,
|
||||
oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL)
|
||||
err(1, "Cannot dbopen `%s'", fname);
|
||||
XXdbp = dbp;
|
||||
if (unlink_dbfile)
|
||||
(void)unlink(fname);
|
||||
|
||||
state = COMMAND;
|
||||
for (lineno = 1;
|
||||
(p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
|
||||
/* Delete the newline, displaying the key/data is easier. */
|
||||
if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL)
|
||||
*t = '\0';
|
||||
if ((len = strlen(buf)) == 0 || isspace((unsigned char)*p) ||
|
||||
*p == '#')
|
||||
continue;
|
||||
|
||||
/* Convenient gdb break point. */
|
||||
if (XXlineno == lineno)
|
||||
XXlineno = 1;
|
||||
switch (*p) {
|
||||
case 'c': /* compare */
|
||||
chkcmd(state);
|
||||
state = KEY;
|
||||
command = COMPARE;
|
||||
break;
|
||||
case 'e': /* echo */
|
||||
chkcmd(state);
|
||||
/* Don't display the newline, if CR at EOL. */
|
||||
if (p[len - 2] == '\r')
|
||||
--len;
|
||||
if ((size_t)write(ofd, p + 1, len - 1) != (len - 1) ||
|
||||
write(ofd, "\n", 1) != 1)
|
||||
err(1, "write failed");
|
||||
break;
|
||||
case 'g': /* get */
|
||||
chkcmd(state);
|
||||
state = KEY;
|
||||
command = GET;
|
||||
break;
|
||||
case 'p': /* put */
|
||||
chkcmd(state);
|
||||
state = KEY;
|
||||
command = PUT;
|
||||
break;
|
||||
case 'r': /* remove */
|
||||
chkcmd(state);
|
||||
if (flags == R_CURSOR) {
|
||||
rem(dbp, &key);
|
||||
state = COMMAND;
|
||||
} else {
|
||||
state = KEY;
|
||||
command = REMOVE;
|
||||
}
|
||||
break;
|
||||
case 'S': /* sync */
|
||||
chkcmd(state);
|
||||
synk(dbp);
|
||||
state = COMMAND;
|
||||
break;
|
||||
case 's': /* seq */
|
||||
chkcmd(state);
|
||||
if (flags == R_CURSOR) {
|
||||
state = KEY;
|
||||
command = SEQ;
|
||||
} else
|
||||
seq(dbp, &key);
|
||||
break;
|
||||
case 'f':
|
||||
flags = setflags(p + 1);
|
||||
break;
|
||||
case 'D': /* data file */
|
||||
chkdata(state);
|
||||
data.data = rfile(p + 1, &data.size);
|
||||
goto ldata;
|
||||
case 'd': /* data */
|
||||
chkdata(state);
|
||||
data.data = xcopy(p + 1, len - 1);
|
||||
data.size = len - 1;
|
||||
ldata: switch (command) {
|
||||
case COMPARE:
|
||||
compare(&keydata, &data);
|
||||
break;
|
||||
case PUT:
|
||||
put(dbp, &key, &data);
|
||||
break;
|
||||
default:
|
||||
errx(1, "line %zu: command doesn't take data",
|
||||
lineno);
|
||||
}
|
||||
if (type != DB_RECNO)
|
||||
free(key.data);
|
||||
free(data.data);
|
||||
state = COMMAND;
|
||||
break;
|
||||
case 'K': /* key file */
|
||||
chkkey(state);
|
||||
if (type == DB_RECNO)
|
||||
errx(1, "line %zu: 'K' not available for recno",
|
||||
lineno);
|
||||
key.data = rfile(p + 1, &key.size);
|
||||
goto lkey;
|
||||
case 'k': /* key */
|
||||
chkkey(state);
|
||||
if (type == DB_RECNO) {
|
||||
static recno_t recno;
|
||||
recno = atoi(p + 1);
|
||||
key.data = &recno;
|
||||
key.size = sizeof(recno);
|
||||
} else {
|
||||
key.data = xcopy(p + 1, len - 1);
|
||||
key.size = len - 1;
|
||||
}
|
||||
lkey: switch (command) {
|
||||
case COMPARE:
|
||||
getdata(dbp, &key, &keydata);
|
||||
state = DATA;
|
||||
break;
|
||||
case GET:
|
||||
get(dbp, &key);
|
||||
if (type != DB_RECNO)
|
||||
free(key.data);
|
||||
state = COMMAND;
|
||||
break;
|
||||
case PUT:
|
||||
state = DATA;
|
||||
break;
|
||||
case REMOVE:
|
||||
rem(dbp, &key);
|
||||
if ((type != DB_RECNO) && (flags != R_CURSOR))
|
||||
free(key.data);
|
||||
state = COMMAND;
|
||||
break;
|
||||
case SEQ:
|
||||
seq(dbp, &key);
|
||||
if ((type != DB_RECNO) && (flags != R_CURSOR))
|
||||
free(key.data);
|
||||
state = COMMAND;
|
||||
break;
|
||||
default:
|
||||
errx(1, "line %zu: command doesn't take a key",
|
||||
lineno);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
dump(dbp, p[1] == 'r');
|
||||
break;
|
||||
default:
|
||||
errx(1, "line %zu: %s: unknown command character",
|
||||
lineno, p);
|
||||
}
|
||||
}
|
||||
#ifdef STATISTICS
|
||||
/*
|
||||
* -l must be used (DB_LOCK must be set) for this to be
|
||||
* used, otherwise a page will be locked and it will fail.
|
||||
*/
|
||||
if (type == DB_BTREE && oflags & DB_LOCK)
|
||||
__bt_stat(dbp);
|
||||
#endif
|
||||
if ((*dbp->close)(dbp))
|
||||
err(1, "db->close failed");
|
||||
(void)close(ofd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NOOVERWRITE "put failed, would overwrite key\n"
|
||||
|
||||
static void
|
||||
compare(DBT *db1, DBT *db2)
|
||||
{
|
||||
size_t len;
|
||||
u_char *p1, *p2;
|
||||
|
||||
if (db1->size != db2->size)
|
||||
printf("compare failed: key->data len %zu != data len %zu\n",
|
||||
db1->size, db2->size);
|
||||
|
||||
len = MIN(db1->size, db2->size);
|
||||
for (p1 = db1->data, p2 = db2->data; len--;)
|
||||
if (*p1++ != *p2++) {
|
||||
printf("compare failed at offset %lu\n",
|
||||
(unsigned long)(p1 - (u_char *)db1->data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get(DB *dbp, DBT *kp)
|
||||
{
|
||||
DBT data;
|
||||
|
||||
switch ((*dbp->get)(dbp, kp, &data, flags)) {
|
||||
case 0:
|
||||
(void)write(ofd, data.data, data.size);
|
||||
if (ofd == STDOUT_FILENO)
|
||||
(void)write(ofd, "\n", 1);
|
||||
break;
|
||||
case -1:
|
||||
err(1, "line %zu: get failed", lineno);
|
||||
/* NOTREACHED */
|
||||
case 1:
|
||||
#define NOSUCHKEY "get failed, no such key\n"
|
||||
if (ofd != STDOUT_FILENO)
|
||||
(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
|
||||
else
|
||||
(void)fprintf(stderr, "%zu: %.*s: %s",
|
||||
lineno, (int)MIN(kp->size, 20),
|
||||
(const char *)kp->data,
|
||||
NOSUCHKEY);
|
||||
#undef NOSUCHKEY
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
getdata(DB *dbp, DBT *kp, DBT *dp)
|
||||
{
|
||||
switch ((*dbp->get)(dbp, kp, dp, flags)) {
|
||||
case 0:
|
||||
return;
|
||||
case -1:
|
||||
err(1, "line %zu: getdata failed", lineno);
|
||||
/* NOTREACHED */
|
||||
case 1:
|
||||
errx(1, "line %zu: getdata failed, no such key", lineno);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
put(DB *dbp, DBT *kp, DBT *dp)
|
||||
{
|
||||
switch ((*dbp->put)(dbp, kp, dp, flags)) {
|
||||
case 0:
|
||||
break;
|
||||
case -1:
|
||||
err(1, "line %zu: put failed", lineno);
|
||||
/* NOTREACHED */
|
||||
case 1:
|
||||
(void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rem(DB *dbp, DBT *kp)
|
||||
{
|
||||
switch ((*dbp->del)(dbp, kp, flags)) {
|
||||
case 0:
|
||||
break;
|
||||
case -1:
|
||||
err(1, "line %zu: rem failed", lineno);
|
||||
/* NOTREACHED */
|
||||
case 1:
|
||||
#define NOSUCHKEY "rem failed, no such key\n"
|
||||
if (ofd != STDOUT_FILENO)
|
||||
(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
|
||||
else if (flags != R_CURSOR)
|
||||
(void)fprintf(stderr, "%zu: %.*s: %s",
|
||||
lineno, (int)MIN(kp->size, 20),
|
||||
(const char *)kp->data, NOSUCHKEY);
|
||||
else
|
||||
(void)fprintf(stderr,
|
||||
"%zu: rem of cursor failed\n", lineno);
|
||||
#undef NOSUCHKEY
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
synk(DB *dbp)
|
||||
{
|
||||
switch ((*dbp->sync)(dbp, flags)) {
|
||||
case 0:
|
||||
break;
|
||||
case -1:
|
||||
err(1, "line %zu: synk failed", lineno);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
seq(DB *dbp, DBT *kp)
|
||||
{
|
||||
DBT data;
|
||||
|
||||
switch (dbp->seq(dbp, kp, &data, flags)) {
|
||||
case 0:
|
||||
(void)write(ofd, data.data, data.size);
|
||||
if (ofd == STDOUT_FILENO)
|
||||
(void)write(ofd, "\n", 1);
|
||||
break;
|
||||
case -1:
|
||||
err(1, "line %zu: seq failed", lineno);
|
||||
/* NOTREACHED */
|
||||
case 1:
|
||||
#define NOSUCHKEY "seq failed, no such key\n"
|
||||
if (ofd != STDOUT_FILENO)
|
||||
(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
|
||||
else if (flags == R_CURSOR)
|
||||
(void)fprintf(stderr, "%zu: %.*s: %s",
|
||||
lineno, (int)MIN(kp->size, 20),
|
||||
(const char *)kp->data, NOSUCHKEY);
|
||||
else
|
||||
(void)fprintf(stderr,
|
||||
"%zu: seq (%s) failed\n", lineno, sflags(flags));
|
||||
#undef NOSUCHKEY
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump(DB *dbp, int rev)
|
||||
{
|
||||
DBT key, data;
|
||||
int xflags, nflags;
|
||||
|
||||
if (rev) {
|
||||
xflags = R_LAST;
|
||||
nflags = R_PREV;
|
||||
} else {
|
||||
xflags = R_FIRST;
|
||||
nflags = R_NEXT;
|
||||
}
|
||||
for (;; xflags = nflags)
|
||||
switch (dbp->seq(dbp, &key, &data, xflags)) {
|
||||
case 0:
|
||||
(void)write(ofd, data.data, data.size);
|
||||
if (ofd == STDOUT_FILENO)
|
||||
(void)write(ofd, "\n", 1);
|
||||
break;
|
||||
case 1:
|
||||
goto done;
|
||||
case -1:
|
||||
err(1, "line %zu: (dump) seq failed", lineno);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
done: return;
|
||||
}
|
||||
|
||||
static u_int
|
||||
setflags(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (; isspace((unsigned char)*s); ++s);
|
||||
if (*s == '\n' || *s == '\0')
|
||||
return 0;
|
||||
if ((p = strchr(s, '\n')) != NULL)
|
||||
*p = '\0';
|
||||
if (!strcmp(s, "R_CURSOR")) return R_CURSOR;
|
||||
if (!strcmp(s, "R_FIRST")) return R_FIRST;
|
||||
if (!strcmp(s, "R_IAFTER")) return R_IAFTER;
|
||||
if (!strcmp(s, "R_IBEFORE")) return R_IBEFORE;
|
||||
if (!strcmp(s, "R_LAST")) return R_LAST;
|
||||
if (!strcmp(s, "R_NEXT")) return R_NEXT;
|
||||
if (!strcmp(s, "R_NOOVERWRITE")) return R_NOOVERWRITE;
|
||||
if (!strcmp(s, "R_PREV")) return R_PREV;
|
||||
if (!strcmp(s, "R_SETCURSOR")) return R_SETCURSOR;
|
||||
|
||||
errx(1, "line %zu: %s: unknown flag", lineno, s);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static const char *
|
||||
sflags(int xflags)
|
||||
{
|
||||
switch (xflags) {
|
||||
case R_CURSOR: return "R_CURSOR";
|
||||
case R_FIRST: return "R_FIRST";
|
||||
case R_IAFTER: return "R_IAFTER";
|
||||
case R_IBEFORE: return "R_IBEFORE";
|
||||
case R_LAST: return "R_LAST";
|
||||
case R_NEXT: return "R_NEXT";
|
||||
case R_NOOVERWRITE: return "R_NOOVERWRITE";
|
||||
case R_PREV: return "R_PREV";
|
||||
case R_SETCURSOR: return "R_SETCURSOR";
|
||||
}
|
||||
|
||||
return "UNKNOWN!";
|
||||
}
|
||||
|
||||
static DBTYPE
|
||||
dbtype(const char *s)
|
||||
{
|
||||
if (!strcmp(s, "btree"))
|
||||
return DB_BTREE;
|
||||
if (!strcmp(s, "hash"))
|
||||
return DB_HASH;
|
||||
if (!strcmp(s, "recno"))
|
||||
return DB_RECNO;
|
||||
errx(1, "%s: unknown type (use btree, hash or recno)", s);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static void *
|
||||
setinfo(DBTYPE dtype, char *s)
|
||||
{
|
||||
static BTREEINFO ib;
|
||||
static HASHINFO ih;
|
||||
static RECNOINFO rh;
|
||||
char *eq;
|
||||
|
||||
if ((eq = strchr(s, '=')) == NULL)
|
||||
errx(1, "%s: illegal structure set statement", s);
|
||||
*eq++ = '\0';
|
||||
if (!isdigit((unsigned char)*eq))
|
||||
errx(1, "%s: structure set statement must be a number", s);
|
||||
|
||||
switch (dtype) {
|
||||
case DB_BTREE:
|
||||
if (!strcmp("flags", s)) {
|
||||
ib.flags = atoi(eq);
|
||||
return &ib;
|
||||
}
|
||||
if (!strcmp("cachesize", s)) {
|
||||
ib.cachesize = atoi(eq);
|
||||
return &ib;
|
||||
}
|
||||
if (!strcmp("maxkeypage", s)) {
|
||||
ib.maxkeypage = atoi(eq);
|
||||
return &ib;
|
||||
}
|
||||
if (!strcmp("minkeypage", s)) {
|
||||
ib.minkeypage = atoi(eq);
|
||||
return &ib;
|
||||
}
|
||||
if (!strcmp("lorder", s)) {
|
||||
ib.lorder = atoi(eq);
|
||||
return &ib;
|
||||
}
|
||||
if (!strcmp("psize", s)) {
|
||||
ib.psize = atoi(eq);
|
||||
return &ib;
|
||||
}
|
||||
break;
|
||||
case DB_HASH:
|
||||
if (!strcmp("bsize", s)) {
|
||||
ih.bsize = atoi(eq);
|
||||
return &ih;
|
||||
}
|
||||
if (!strcmp("ffactor", s)) {
|
||||
ih.ffactor = atoi(eq);
|
||||
return &ih;
|
||||
}
|
||||
if (!strcmp("nelem", s)) {
|
||||
ih.nelem = atoi(eq);
|
||||
return &ih;
|
||||
}
|
||||
if (!strcmp("cachesize", s)) {
|
||||
ih.cachesize = atoi(eq);
|
||||
return &ih;
|
||||
}
|
||||
if (!strcmp("lorder", s)) {
|
||||
ih.lorder = atoi(eq);
|
||||
return &ih;
|
||||
}
|
||||
break;
|
||||
case DB_RECNO:
|
||||
if (!strcmp("flags", s)) {
|
||||
rh.flags = atoi(eq);
|
||||
return &rh;
|
||||
}
|
||||
if (!strcmp("cachesize", s)) {
|
||||
rh.cachesize = atoi(eq);
|
||||
return &rh;
|
||||
}
|
||||
if (!strcmp("lorder", s)) {
|
||||
rh.lorder = atoi(eq);
|
||||
return &rh;
|
||||
}
|
||||
if (!strcmp("reclen", s)) {
|
||||
rh.reclen = atoi(eq);
|
||||
return &rh;
|
||||
}
|
||||
if (!strcmp("bval", s)) {
|
||||
rh.bval = atoi(eq);
|
||||
return &rh;
|
||||
}
|
||||
if (!strcmp("psize", s)) {
|
||||
rh.psize = atoi(eq);
|
||||
return &rh;
|
||||
}
|
||||
break;
|
||||
}
|
||||
errx(1, "%s: unknown structure value", s);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static void *
|
||||
rfile(char *name, size_t *lenp)
|
||||
{
|
||||
struct stat sb;
|
||||
void *p;
|
||||
int fd;
|
||||
char *np;
|
||||
|
||||
for (; isspace((unsigned char)*name); ++name)
|
||||
continue;
|
||||
if ((np = strchr(name, '\n')) != NULL)
|
||||
*np = '\0';
|
||||
if ((fd = open(name, O_RDONLY, 0)) == -1 || fstat(fd, &sb) == -1)
|
||||
err(1, "Cannot open `%s'", name);
|
||||
#ifdef NOT_PORTABLE
|
||||
if (sb.st_size > (off_t)SIZE_T_MAX) {
|
||||
errno = E2BIG;
|
||||
err("Cannot process `%s'", name);
|
||||
}
|
||||
#endif
|
||||
if ((p = malloc((size_t)sb.st_size)) == NULL)
|
||||
err(1, "Cannot allocate %zu bytes", (size_t)sb.st_size);
|
||||
if (read(fd, p, (ssize_t)sb.st_size) != (ssize_t)sb.st_size)
|
||||
err(1, "read failed");
|
||||
*lenp = (size_t)sb.st_size;
|
||||
(void)close(fd);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void *
|
||||
xcopy(void *text, size_t len)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if ((p = malloc(len)) == NULL)
|
||||
err(1, "Cannot allocate %zu bytes", len);
|
||||
(void)memmove(p, text, len);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
chkcmd(enum S state)
|
||||
{
|
||||
if (state != COMMAND)
|
||||
errx(1, "line %zu: not expecting command", lineno);
|
||||
}
|
||||
|
||||
static void
|
||||
chkdata(enum S state)
|
||||
{
|
||||
if (state != DATA)
|
||||
errx(1, "line %zu: not expecting data", lineno);
|
||||
}
|
||||
|
||||
static void
|
||||
chkkey(enum S state)
|
||||
{
|
||||
if (state != KEY)
|
||||
errx(1, "line %zu: not expecting a key", lineno);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"Usage: %s [-l] [-f file] [-i info] [-o file] type script\n",
|
||||
getprogname());
|
||||
exit(1);
|
||||
}
|
|
@ -1,709 +0,0 @@
|
|||
#!/bin/sh -
|
||||
#
|
||||
# $NetBSD: run.test,v 1.11 2007/02/03 20:59:34 christos Exp $
|
||||
# @(#)run.test 8.10 (Berkeley) 7/26/94
|
||||
#
|
||||
|
||||
# db regression tests
|
||||
|
||||
PNAME="$(basename "$0")"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $PNAME [-p <binary>] test# ... | [hash|btree|recno]" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
PROG=./dbtest
|
||||
while getopts p: f; do
|
||||
case $f in
|
||||
p) PROG="$OPTARG";;
|
||||
*) usage;;
|
||||
esac
|
||||
done
|
||||
shift $(expr $OPTIND - 1)
|
||||
TMP1=t1
|
||||
TMP2=t2
|
||||
TMP3=t3
|
||||
SEVEN_SEVEN="abcdefg|abcdefg|abcdefg|abcdefg|abcdefg|abcdefg|abcdefg"
|
||||
|
||||
trap "rm -f $TMP1 $TMP2 $TMP3" 0 1 2 3 15
|
||||
|
||||
if [ -f /usr/share/dict/words ]; then
|
||||
DICT=/usr/share/dict/words
|
||||
elif [ -f /usr/dict/words ]; then
|
||||
DICT=/usr/dict/words
|
||||
else
|
||||
echo "$PNAME: no dictionary" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20 21; do
|
||||
test$t
|
||||
done
|
||||
else
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
test*)
|
||||
$1;;
|
||||
[0-9]*)
|
||||
test$1;;
|
||||
btree)
|
||||
for t in 1 2 3 7 8 9 10 12 13; do
|
||||
test$t
|
||||
done;;
|
||||
hash)
|
||||
for t in 1 2 3 8 13 20; do
|
||||
test$t
|
||||
done;;
|
||||
recno)
|
||||
for t in 1 2 3 4 5 6 7 10 11; do
|
||||
test$t
|
||||
done;;
|
||||
*)
|
||||
echo "$PNAME: unknown test $1" 1>&2
|
||||
usage
|
||||
esac
|
||||
shift
|
||||
done
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Take the first hundred entries in the dictionary, and make them
|
||||
# be key/data pairs.
|
||||
test1()
|
||||
{
|
||||
echo "Test 1: btree, hash: small key, small data pairs"
|
||||
sed 200q $DICT > $TMP1
|
||||
for type in btree hash; do
|
||||
rm -f $TMP2 $TMP3
|
||||
for i in `sed 200q $DICT`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$i
|
||||
echo g
|
||||
echo k$i
|
||||
done > $TMP2
|
||||
$PROG -o $TMP3 $type $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test1: type $type: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Test 1: recno: small key, small data pairs"
|
||||
rm -f $TMP2 $TMP3
|
||||
sed 200q $DICT |
|
||||
awk '{
|
||||
++i;
|
||||
printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
|
||||
}' > $TMP2
|
||||
$PROG -o $TMP3 recno $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test1: type recno: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Take the first 200 entries in the dictionary, and give them
|
||||
# each a medium size data entry.
|
||||
test2()
|
||||
{
|
||||
echo "Test 2: btree, hash: small key, medium data pairs"
|
||||
mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
|
||||
echo $mdata |
|
||||
awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1
|
||||
for type in hash btree; do
|
||||
rm -f $TMP2 $TMP3
|
||||
for i in $(sed 200q $DICT); do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$mdata
|
||||
echo g
|
||||
echo k$i
|
||||
done > $TMP2
|
||||
$PROG -o $TMP3 $type $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test2: type $type: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Test 2: recno: small key, medium data pairs"
|
||||
rm -f $TMP2 $TMP3
|
||||
echo $mdata |
|
||||
awk '{ for (i = 1; i < 201; ++i)
|
||||
printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
|
||||
}' > $TMP2
|
||||
$PROG -o $TMP3 recno $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test2: type recno: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Insert the programs in /bin with their paths as their keys.
|
||||
test3()
|
||||
{
|
||||
echo "Test 3: hash: small key, big data pairs"
|
||||
rm -f $TMP1
|
||||
(find /bin -type f -print | xargs cat) > $TMP1
|
||||
for type in hash; do
|
||||
rm -f $TMP2 $TMP3
|
||||
for i in `find /bin -type f -print`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo D$i
|
||||
echo g
|
||||
echo k$i
|
||||
done > $TMP2
|
||||
$PROG -o $TMP3 $type $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test3: $type: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Test 3: btree: small key, big data pairs"
|
||||
for psize in 512 16384 65536; do
|
||||
echo " page size $psize"
|
||||
for type in btree; do
|
||||
rm -f $TMP2 $TMP3
|
||||
for i in `find /bin -type f -print`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo D$i
|
||||
echo g
|
||||
echo k$i
|
||||
done > $TMP2
|
||||
$PROG -i psize=$psize -o $TMP3 $type $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test3: $type: page size $psize: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
echo "Test 3: recno: big data pairs"
|
||||
rm -f $TMP2 $TMP3
|
||||
find /bin -type f -print |
|
||||
awk '{
|
||||
++i;
|
||||
printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
|
||||
}' > $TMP2
|
||||
for psize in 512 16384 65536; do
|
||||
echo " page size $psize"
|
||||
$PROG -i psize=$psize -o $TMP3 recno $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test3: recno: page size $psize: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Do random recno entries.
|
||||
test4()
|
||||
{
|
||||
echo "Test 4: recno: random entries"
|
||||
echo $SEVEN_SEVEN |
|
||||
awk '{
|
||||
for (i = 37; i <= 37 + 88 * 17; i += 17) {
|
||||
if (i % 41)
|
||||
s = substr($0, 1, i % 41);
|
||||
else
|
||||
s = substr($0, 1);
|
||||
printf("input key %d: %s\n", i, s);
|
||||
}
|
||||
for (i = 1; i <= 15; ++i) {
|
||||
if (i % 41)
|
||||
s = substr($0, 1, i % 41);
|
||||
else
|
||||
s = substr($0, 1);
|
||||
printf("input key %d: %s\n", i, s);
|
||||
}
|
||||
for (i = 19234; i <= 19234 + 61 * 27; i += 27) {
|
||||
if (i % 41)
|
||||
s = substr($0, 1, i % 41);
|
||||
else
|
||||
s = substr($0, 1);
|
||||
printf("input key %d: %s\n", i, s);
|
||||
}
|
||||
exit
|
||||
}' > $TMP1
|
||||
rm -f $TMP2 $TMP3
|
||||
cat $TMP1 |
|
||||
awk 'BEGIN {
|
||||
i = 37;
|
||||
incr = 17;
|
||||
}
|
||||
{
|
||||
printf("p\nk%d\nd%s\n", i, $0);
|
||||
if (i == 19234 + 61 * 27)
|
||||
exit;
|
||||
if (i == 37 + 88 * 17) {
|
||||
i = 1;
|
||||
incr = 1;
|
||||
} else if (i == 15) {
|
||||
i = 19234;
|
||||
incr = 27;
|
||||
} else
|
||||
i += incr;
|
||||
}
|
||||
END {
|
||||
for (i = 37; i <= 37 + 88 * 17; i += 17)
|
||||
printf("g\nk%d\n", i);
|
||||
for (i = 1; i <= 15; ++i)
|
||||
printf("g\nk%d\n", i);
|
||||
for (i = 19234; i <= 19234 + 61 * 27; i += 27)
|
||||
printf("g\nk%d\n", i);
|
||||
}' > $TMP2
|
||||
$PROG -o $TMP3 recno $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test4: type recno: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Do reverse order recno entries.
|
||||
test5()
|
||||
{
|
||||
echo "Test 5: recno: reverse order entries"
|
||||
echo $SEVEN_SEVEN |
|
||||
awk ' {
|
||||
for (i = 1500; i; --i) {
|
||||
if (i % 34)
|
||||
s = substr($0, 1, i % 34);
|
||||
else
|
||||
s = substr($0, 1);
|
||||
printf("input key %d: %s\n", i, s);
|
||||
}
|
||||
exit;
|
||||
}' > $TMP1
|
||||
rm -f $TMP2 $TMP3
|
||||
cat $TMP1 |
|
||||
awk 'BEGIN {
|
||||
i = 1500;
|
||||
}
|
||||
{
|
||||
printf("p\nk%d\nd%s\n", i, $0);
|
||||
--i;
|
||||
}
|
||||
END {
|
||||
for (i = 1500; i; --i)
|
||||
printf("g\nk%d\n", i);
|
||||
}' > $TMP2
|
||||
$PROG -o $TMP3 recno $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test5: type recno: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Do alternating order recno entries.
|
||||
test6()
|
||||
{
|
||||
echo "Test 6: recno: alternating order entries"
|
||||
echo $SEVEN_SEVEN |
|
||||
awk ' {
|
||||
for (i = 1; i < 1200; i += 2) {
|
||||
if (i % 34)
|
||||
s = substr($0, 1, i % 34);
|
||||
else
|
||||
s = substr($0, 1);
|
||||
printf("input key %d: %s\n", i, s);
|
||||
}
|
||||
for (i = 2; i < 1200; i += 2) {
|
||||
if (i % 34)
|
||||
s = substr($0, 1, i % 34);
|
||||
else
|
||||
s = substr($0, 1);
|
||||
printf("input key %d: %s\n", i, s);
|
||||
}
|
||||
exit;
|
||||
}' > $TMP1
|
||||
rm -f $TMP2 $TMP3
|
||||
cat $TMP1 |
|
||||
awk 'BEGIN {
|
||||
i = 1;
|
||||
even = 0;
|
||||
}
|
||||
{
|
||||
printf("p\nk%d\nd%s\n", i, $0);
|
||||
i += 2;
|
||||
if (i >= 1200) {
|
||||
if (even == 1)
|
||||
exit;
|
||||
even = 1;
|
||||
i = 2;
|
||||
}
|
||||
}
|
||||
END {
|
||||
for (i = 1; i < 1200; ++i)
|
||||
printf("g\nk%d\n", i);
|
||||
}' > $TMP2
|
||||
$PROG -o $TMP3 recno $TMP2
|
||||
sort -o $TMP1 $TMP1
|
||||
sort -o $TMP3 $TMP3
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test6: type recno: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Delete cursor record
|
||||
test7()
|
||||
{
|
||||
echo "Test 7: btree, recno: delete cursor record"
|
||||
echo $SEVEN_SEVEN |
|
||||
awk '{
|
||||
for (i = 1; i <= 120; ++i)
|
||||
printf("%05d: input key %d: %s\n", i, i, $0);
|
||||
printf("%05d: input key %d: %s\n", 120, 120, $0);
|
||||
printf("seq failed, no such key\n");
|
||||
printf("%05d: input key %d: %s\n", 1, 1, $0);
|
||||
printf("%05d: input key %d: %s\n", 2, 2, $0);
|
||||
exit;
|
||||
}' > $TMP1
|
||||
rm -f $TMP2 $TMP3
|
||||
|
||||
for type in btree recno; do
|
||||
cat $TMP1 |
|
||||
awk '{
|
||||
if (i == 120)
|
||||
exit;
|
||||
printf("p\nk%d\nd%s\n", ++i, $0);
|
||||
}
|
||||
END {
|
||||
printf("fR_NEXT\n");
|
||||
for (i = 1; i <= 120; ++i)
|
||||
printf("s\n");
|
||||
printf("fR_CURSOR\ns\nk120\n");
|
||||
printf("r\n");
|
||||
printf("fR_NEXT\ns\n");
|
||||
printf("fR_CURSOR\ns\nk1\n");
|
||||
printf("r\n");
|
||||
printf("fR_FIRST\ns\n");
|
||||
}' > $TMP2
|
||||
$PROG -o $TMP3 recno $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test7: type $type: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Make sure that overflow pages are reused.
|
||||
test8()
|
||||
{
|
||||
echo "Test 8: btree, hash: repeated small key, big data pairs"
|
||||
rm -f $TMP1
|
||||
echo "" |
|
||||
awk 'BEGIN {
|
||||
for (i = 1; i <= 10; ++i) {
|
||||
printf("p\nkkey1\nD/bin/sh\n");
|
||||
printf("p\nkkey2\nD/bin/csh\n");
|
||||
if (i % 8 == 0) {
|
||||
printf("c\nkkey2\nD/bin/csh\n");
|
||||
printf("c\nkkey1\nD/bin/sh\n");
|
||||
printf("e\t%d of 10 (comparison)\n", i);
|
||||
} else
|
||||
printf("e\t%d of 10 \n", i);
|
||||
printf("r\nkkey1\nr\nkkey2\n");
|
||||
}
|
||||
}' > $TMP1
|
||||
$PROG btree $TMP1
|
||||
# $PROG hash $TMP1
|
||||
# No explicit test for success.
|
||||
}
|
||||
|
||||
# Test btree duplicate keys
|
||||
test9()
|
||||
{
|
||||
echo "Test 9: btree: duplicate keys"
|
||||
echo $SEVEN_SEVEN |
|
||||
awk '{
|
||||
for (i = 1; i <= 543; ++i)
|
||||
printf("%05d: input key %d: %s\n", i, i, $0);
|
||||
exit;
|
||||
}' > $TMP1
|
||||
rm -f $TMP2 $TMP3
|
||||
|
||||
for type in btree; do
|
||||
cat $TMP1 |
|
||||
awk '{
|
||||
if (i++ % 2)
|
||||
printf("p\nkduplicatekey\nd%s\n", $0);
|
||||
else
|
||||
printf("p\nkunique%dkey\nd%s\n", i, $0);
|
||||
}
|
||||
END {
|
||||
printf("o\n");
|
||||
}' > $TMP2
|
||||
$PROG -iflags=1 -o $TMP3 $type $TMP2
|
||||
sort -o $TMP3 $TMP3
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test9: type $type: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Test use of cursor flags without initialization
|
||||
test10()
|
||||
{
|
||||
echo "Test 10: btree, recno: test cursor flag use"
|
||||
echo $SEVEN_SEVEN |
|
||||
awk '{
|
||||
for (i = 1; i <= 20; ++i)
|
||||
printf("%05d: input key %d: %s\n", i, i, $0);
|
||||
exit;
|
||||
}' > $TMP1
|
||||
rm -f $TMP2 $TMP3
|
||||
|
||||
# Test that R_CURSOR doesn't succeed before cursor initialized
|
||||
for type in btree recno; do
|
||||
cat $TMP1 |
|
||||
awk '{
|
||||
if (i == 10)
|
||||
exit;
|
||||
printf("p\nk%d\nd%s\n", ++i, $0);
|
||||
}
|
||||
END {
|
||||
printf("fR_CURSOR\nr\n");
|
||||
printf("eR_CURSOR SHOULD HAVE FAILED\n");
|
||||
}' > $TMP2
|
||||
$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
|
||||
if [ -s $TMP3 ] ; then
|
||||
echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
for type in btree recno; do
|
||||
cat $TMP1 |
|
||||
awk '{
|
||||
if (i == 10)
|
||||
exit;
|
||||
printf("p\nk%d\nd%s\n", ++i, $0);
|
||||
}
|
||||
END {
|
||||
printf("fR_CURSOR\np\nk1\ndsome data\n");
|
||||
printf("eR_CURSOR SHOULD HAVE FAILED\n");
|
||||
}' > $TMP2
|
||||
$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
|
||||
if [ -s $TMP3 ] ; then
|
||||
echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Test insert in reverse order.
|
||||
test11()
|
||||
{
|
||||
echo "Test 11: recno: reverse order insert"
|
||||
echo $SEVEN_SEVEN |
|
||||
awk '{
|
||||
for (i = 1; i <= 779; ++i)
|
||||
printf("%05d: input key %d: %s\n", i, i, $0);
|
||||
exit;
|
||||
}' > $TMP1
|
||||
rm -f $TMP2 $TMP3
|
||||
|
||||
for type in recno; do
|
||||
cat $TMP1 |
|
||||
awk '{
|
||||
if (i == 0) {
|
||||
i = 1;
|
||||
printf("p\nk1\nd%s\n", $0);
|
||||
printf("%s\n", "fR_IBEFORE");
|
||||
} else
|
||||
printf("p\nk1\nd%s\n", $0);
|
||||
}
|
||||
END {
|
||||
printf("or\n");
|
||||
}' > $TMP2
|
||||
$PROG -o $TMP3 $type $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test11: type $type: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Take the first 20000 entries in the dictionary, reverse them, and give
|
||||
# them each a small size data entry. Use a small page size to make sure
|
||||
# the btree split code gets hammered.
|
||||
test12()
|
||||
{
|
||||
echo "Test 12: btree: lots of keys, small page size"
|
||||
mdata=abcdefghijklmnopqrstuvwxy
|
||||
echo $mdata |
|
||||
awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1
|
||||
for type in btree; do
|
||||
rm -f $TMP2 $TMP3
|
||||
for i in `sed 20000q $DICT | rev`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$mdata
|
||||
echo g
|
||||
echo k$i
|
||||
done > $TMP2
|
||||
$PROG -i psize=512 -o $TMP3 $type $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test12: type $type: failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Test different byte orders.
|
||||
test13()
|
||||
{
|
||||
echo "Test 13: btree, hash: differing byte orders"
|
||||
sed 50q $DICT > $TMP1
|
||||
for order in 1234 4321; do
|
||||
for type in btree hash; do
|
||||
rm -f byte.file $TMP2 $TMP3
|
||||
for i in `sed 50q $DICT`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$i
|
||||
echo g
|
||||
echo k$i
|
||||
done > $TMP2
|
||||
$PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test13: $type/$order put failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
for i in `sed 50q $DICT`; do
|
||||
echo g
|
||||
echo k$i
|
||||
done > $TMP2
|
||||
$PROG -s \
|
||||
-ilorder=$order -f byte.file -o $TMP3 $type $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test13: $type/$order get failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
rm -f byte.file
|
||||
}
|
||||
|
||||
# Try a variety of bucketsizes and fill factors for hashing
|
||||
test20()
|
||||
{
|
||||
echo\
|
||||
"Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536"
|
||||
echo $SEVEN_SEVEN |
|
||||
awk '{
|
||||
for (i = 1; i <= 10000; ++i) {
|
||||
if (i % 34)
|
||||
s = substr($0, 1, i % 34);
|
||||
else
|
||||
s = substr($0, 1);
|
||||
printf("%s\n", s);
|
||||
}
|
||||
exit;
|
||||
}' > $TMP1
|
||||
sed 10000q $DICT |
|
||||
awk 'BEGIN {
|
||||
ds="'$SEVEN_SEVEN'"
|
||||
}
|
||||
{
|
||||
if (++i % 34)
|
||||
s = substr(ds, 1, i % 34);
|
||||
else
|
||||
s = substr(ds, 1);
|
||||
printf("p\nk%s\nd%s\n", $0, s);
|
||||
}' > $TMP2
|
||||
sed 10000q $DICT |
|
||||
awk '{
|
||||
++i;
|
||||
printf("g\nk%s\n", $0);
|
||||
}' >> $TMP2
|
||||
bsize=256
|
||||
for ffactor in 11 14 21; do
|
||||
echo " bucketsize $bsize, fill factor $ffactor"
|
||||
$PROG -o$TMP3 \
|
||||
-ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
|
||||
hash $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test20: type hash:\
|
||||
bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
bsize=512
|
||||
for ffactor in 21 28 43; do
|
||||
echo " bucketsize $bsize, fill factor $ffactor"
|
||||
$PROG -o$TMP3 \
|
||||
-ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
|
||||
hash $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test20: type hash:\
|
||||
bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
bsize=1024
|
||||
for ffactor in 43 57 85; do
|
||||
echo " bucketsize $bsize, fill factor $ffactor"
|
||||
$PROG -o$TMP3 \
|
||||
-ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
|
||||
hash $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test20: type hash:\
|
||||
bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
bsize=2048
|
||||
for ffactor in 85 114 171; do
|
||||
echo " bucketsize $bsize, fill factor $ffactor"
|
||||
$PROG -o$TMP3 \
|
||||
-ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
|
||||
hash $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test20: type hash:\
|
||||
bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
bsize=4096
|
||||
for ffactor in 171 228 341; do
|
||||
echo " bucketsize $bsize, fill factor $ffactor"
|
||||
$PROG -o$TMP3 \
|
||||
-ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
|
||||
hash $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test20: type hash:\
|
||||
bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
bsize=8192
|
||||
for ffactor in 341 455 683; do
|
||||
echo " bucketsize $bsize, fill factor $ffactor"
|
||||
$PROG -o$TMP3 \
|
||||
-ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
|
||||
hash $TMP2
|
||||
if ! cmp -s $TMP1 $TMP3; then
|
||||
echo "$PNAME: test20: type hash:\
|
||||
bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
test21() {
|
||||
cat << _EOF | $PROG -i bsize=65536 hash /dev/stdin
|
||||
p
|
||||
k1234
|
||||
d1234
|
||||
r
|
||||
k1234
|
||||
_EOF
|
||||
}
|
||||
|
||||
main "$@"
|
Loading…
Reference in New Issue