Atf-ify the db tests.
XXX Note that the original regress version of this test did not run the XXX btree_delete test; that test is broken, and is disabled for now.
This commit is contained in:
parent
38b3ed96cc
commit
0308b37ff4
@ -1,9 +1,9 @@
|
||||
# $NetBSD: Makefile,v 1.23 2011/01/07 02:47:40 pgoyette Exp $
|
||||
# $NetBSD: Makefile,v 1.24 2011/01/07 15:05:57 pgoyette Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
.include <bsd.sys.mk>
|
||||
|
||||
TESTS_SUBDIRS+= gen hash ieeefp setjmp stdlib stdio string ttyio
|
||||
TESTS_SUBDIRS+= db gen hash ieeefp setjmp stdlib stdio string ttyio
|
||||
|
||||
.if ${HAS_SSP} == "yes"
|
||||
TESTS_SUBDIRS+= ssp
|
||||
|
18
tests/lib/libc/db/Makefile
Normal file
18
tests/lib/libc/db/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
# $NetBSD: Makefile,v 1.1 2011/01/07 15:05:58 pgoyette Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/lib/libc/db
|
||||
|
||||
TESTS_SH+= t_db
|
||||
|
||||
BINDIR= ${TESTSDIR}
|
||||
MKMAN= no
|
||||
|
||||
PROGS+= h_db
|
||||
|
||||
FILESDIR= ${TESTSDIR}
|
||||
|
||||
FILES+= README
|
||||
|
||||
.include <bsd.test.mk>
|
66
tests/lib/libc/db/README
Normal file
66
tests/lib/libc/db/README
Normal file
@ -0,0 +1,66 @@
|
||||
# $NetBSD: README,v 1.1 2011/01/07 15:05:58 pgoyette Exp $
|
||||
# @(#)README 8.8 (Berkeley) 7/31/94
|
||||
|
||||
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.
|
731
tests/lib/libc/db/h_db.c
Normal file
731
tests/lib/libc/db/h_db.c
Normal file
@ -0,0 +1,731 @@
|
||||
/* $NetBSD: h_db.c,v 1.1 2011/01/07 15:05:58 pgoyette 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: h_db.c,v 1.1 2011/01/07 15:05:58 pgoyette 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 (write(ofd, p + 1, len - 1) != (ssize_t)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);
|
||||
}
|
903
tests/lib/libc/db/t_db.sh
Normal file
903
tests/lib/libc/db/t_db.sh
Normal file
@ -0,0 +1,903 @@
|
||||
# $NetBSD: t_db.sh,v 1.1 2011/01/07 15:05:58 pgoyette Exp $
|
||||
#
|
||||
# Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
# 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.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
#
|
||||
|
||||
prog()
|
||||
{
|
||||
echo $(atf_get_srcdir)/h_db
|
||||
}
|
||||
|
||||
dict()
|
||||
{
|
||||
if [ -f /usr/share/dict/words ]; then
|
||||
echo /usr/share/dict/words
|
||||
elif [ -f /usr/dict/words ]; then
|
||||
echo /usr/dict/words
|
||||
else
|
||||
atf_fail "no dictionary found"
|
||||
fi
|
||||
}
|
||||
|
||||
SEVEN_SEVEN="abcdefg|abcdefg|abcdefg|abcdefg|abcdefg|abcdefg|abcdefg"
|
||||
|
||||
atf_test_case small_btree
|
||||
small_btree_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks btree database using small keys and small data" \
|
||||
"pairs: takes the first hundred entries in the dictionary," \
|
||||
"and makes them be key/data pairs."
|
||||
}
|
||||
small_btree_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
sed 200q $(dict) >exp
|
||||
|
||||
for i in `sed 200q $(dict)`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$i
|
||||
echo g
|
||||
echo k$i
|
||||
done >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" btree in
|
||||
}
|
||||
|
||||
atf_test_case small_hash
|
||||
small_hash_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks hash database using small keys and small data" \
|
||||
"pairs: takes the first hundred entries in the dictionary," \
|
||||
"and makes them be key/data pairs."
|
||||
}
|
||||
small_hash_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
sed 200q $(dict) >exp
|
||||
|
||||
for i in `sed 200q $(dict)`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$i
|
||||
echo g
|
||||
echo k$i
|
||||
done >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" hash in
|
||||
}
|
||||
|
||||
atf_test_case small_recno
|
||||
small_recno_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks recno database using small keys and small data" \
|
||||
"pairs: takes the first hundred entries in the dictionary," \
|
||||
"and makes them be key/data pairs."
|
||||
}
|
||||
small_recno_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
sed 200q $(dict) >exp
|
||||
|
||||
sed 200q $(dict) |
|
||||
awk '{
|
||||
++i;
|
||||
printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
|
||||
}' >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" recno in
|
||||
}
|
||||
|
||||
atf_test_case medium_btree
|
||||
medium_btree_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks btree database using small keys and medium" \
|
||||
"data pairs: takes the first 200 entries in the" \
|
||||
"dictionary, and gives them each a medium size data entry."
|
||||
}
|
||||
medium_btree_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
|
||||
echo $mdata |
|
||||
awk '{ for (i = 1; i < 201; ++i) print $0 }' >exp
|
||||
|
||||
for i in $(sed 200q $(dict)); do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$mdata
|
||||
echo g
|
||||
echo k$i
|
||||
done >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" btree in
|
||||
}
|
||||
|
||||
atf_test_case medium_hash
|
||||
medium_hash_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks hash database using small keys and medium" \
|
||||
"data pairs: takes the first 200 entries in the" \
|
||||
"dictionary, and gives them each a medium size data entry."
|
||||
}
|
||||
medium_hash_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
|
||||
echo $mdata |
|
||||
awk '{ for (i = 1; i < 201; ++i) print $0 }' >exp
|
||||
|
||||
for i in $(sed 200q $(dict)); do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$mdata
|
||||
echo g
|
||||
echo k$i
|
||||
done >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" hash in
|
||||
}
|
||||
|
||||
atf_test_case medium_recno
|
||||
medium_recno_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks recno database using small keys and medium" \
|
||||
"data pairs: takes the first 200 entries in the" \
|
||||
"dictionary, and gives them each a medium size data entry."
|
||||
}
|
||||
medium_recno_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
|
||||
echo $mdata |
|
||||
awk '{ for (i = 1; i < 201; ++i) print $0 }' >exp
|
||||
|
||||
echo $mdata |
|
||||
awk '{ for (i = 1; i < 201; ++i)
|
||||
printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
|
||||
}' >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" recno in
|
||||
}
|
||||
|
||||
atf_test_case big_btree
|
||||
big_btree_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks btree database using small keys and big data" \
|
||||
"pairs: inserts the programs in /bin with their paths" \
|
||||
"as their keys."
|
||||
}
|
||||
big_btree_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
(find /bin -type f -print | xargs cat) >exp
|
||||
|
||||
for psize in 512 16384 65536; do
|
||||
echo "checking page size: $psize"
|
||||
|
||||
for i in `find /bin -type f -print`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo D$i
|
||||
echo g
|
||||
echo k$i
|
||||
done >in
|
||||
|
||||
atf_check "$(prog)" -o out btree in
|
||||
cmp -s exp out || atf_fail "test failed for page size: $psize"
|
||||
done
|
||||
}
|
||||
|
||||
atf_test_case big_hash
|
||||
big_hash_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks hash database using small keys and big data" \
|
||||
"pairs: inserts the programs in /bin with their paths" \
|
||||
"as their keys."
|
||||
}
|
||||
big_hash_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
(find /bin -type f -print | xargs cat) >exp
|
||||
|
||||
for i in `find /bin -type f -print`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo D$i
|
||||
echo g
|
||||
echo k$i
|
||||
done >in
|
||||
|
||||
atf_check "$(prog)" -o out hash in
|
||||
cmp -s exp out || atf_fail "test failed"
|
||||
}
|
||||
|
||||
atf_test_case big_recno
|
||||
big_recno_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks recno database using small keys and big data" \
|
||||
"pairs: inserts the programs in /bin with their paths" \
|
||||
"as their keys."
|
||||
}
|
||||
big_recno_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
(find /bin -type f -print | xargs cat) >exp
|
||||
|
||||
find /bin -type f -print |
|
||||
awk '{
|
||||
++i;
|
||||
printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
|
||||
}' >in
|
||||
|
||||
for psize in 512 16384 65536; do
|
||||
echo "checking page size: $psize"
|
||||
|
||||
atf_check "$(prog)" -o out recno in
|
||||
cmp -s exp out || atf_fail "test failed for page size: $psize"
|
||||
done
|
||||
}
|
||||
|
||||
atf_test_case random_recno
|
||||
random_recno_head()
|
||||
{
|
||||
atf_set "descr" "Checks recno database using random entries"
|
||||
}
|
||||
random_recno_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
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
|
||||
}' >exp
|
||||
|
||||
cat exp |
|
||||
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);
|
||||
}' >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" recno in
|
||||
}
|
||||
|
||||
atf_test_case reverse_recno
|
||||
reverse_recno_head()
|
||||
{
|
||||
atf_set "descr" "Checks recno database using reverse order entries"
|
||||
}
|
||||
reverse_recno_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
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;
|
||||
}' >exp
|
||||
|
||||
cat exp |
|
||||
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);
|
||||
}' >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" recno in
|
||||
}
|
||||
|
||||
atf_test_case alternate_recno
|
||||
alternate_recno_head()
|
||||
{
|
||||
atf_set "descr" "Checks recno database using alternating order entries"
|
||||
}
|
||||
alternate_recno_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
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;
|
||||
}' >exp
|
||||
|
||||
cat exp |
|
||||
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);
|
||||
}' >in
|
||||
|
||||
atf_check "$(prog)" -o out recno in
|
||||
|
||||
sort -o exp exp
|
||||
sort -o out out
|
||||
|
||||
cmp -s exp out || atf_fail "test failed"
|
||||
}
|
||||
|
||||
h_delete()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
type=$1
|
||||
|
||||
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;
|
||||
}' >exp
|
||||
|
||||
cat exp |
|
||||
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");
|
||||
}' >in
|
||||
|
||||
atf_check "$(prog)" -o out $type in
|
||||
atf_check -o file:exp cat out
|
||||
}
|
||||
|
||||
# FIXME: should it actually work? the original test apparently
|
||||
# was supposed to run such test, but didn't
|
||||
atf_test_case delete_btree
|
||||
delete_btree_head()
|
||||
{
|
||||
atf_set "descr" "Checks removing records in btree database"
|
||||
}
|
||||
delete_btree_body()
|
||||
{
|
||||
#
|
||||
# The delete_btree test was skipped in the original ..../regress test
|
||||
# structure, so noone ever noticed that it didn't work! Disable it for
|
||||
# now, until we correct the generation of in/out files to reflect the
|
||||
# actual collating sequence of key values ("19" comes before "2")
|
||||
#
|
||||
atf_skip "delete_btreee test case is broken"
|
||||
h_delete btree
|
||||
}
|
||||
|
||||
atf_test_case delete_recno
|
||||
delete_recno_head()
|
||||
{
|
||||
atf_set "descr" "Checks removing records in recno database"
|
||||
}
|
||||
delete_recno_body()
|
||||
{
|
||||
h_delete recno
|
||||
}
|
||||
|
||||
h_repeated()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
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");
|
||||
}
|
||||
}' >in
|
||||
|
||||
$(prog) btree in
|
||||
}
|
||||
|
||||
atf_test_case repeated_btree
|
||||
repeated_btree_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks btree database with repeated small keys and" \
|
||||
"big data pairs. Makes sure that overflow pages are reused"
|
||||
}
|
||||
repeated_btree_body()
|
||||
{
|
||||
h_repeated btree
|
||||
}
|
||||
|
||||
atf_test_case repeated_hash
|
||||
repeated_hash_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks hash database with repeated small keys and" \
|
||||
"big data pairs. Makes sure that overflow pages are reused"
|
||||
}
|
||||
repeated_hash_body()
|
||||
{
|
||||
h_repeated hash
|
||||
}
|
||||
|
||||
atf_test_case duplicate_btree
|
||||
duplicate_btree_head()
|
||||
{
|
||||
atf_set "descr" "Checks btree database with duplicate keys"
|
||||
}
|
||||
duplicate_btree_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
echo $SEVEN_SEVEN |
|
||||
awk '{
|
||||
for (i = 1; i <= 543; ++i)
|
||||
printf("%05d: input key %d: %s\n", i, i, $0);
|
||||
exit;
|
||||
}' >exp
|
||||
|
||||
cat exp |
|
||||
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");
|
||||
}' >in
|
||||
|
||||
atf_check -o file:exp -x "$(prog) -iflags=1 btree in | sort"
|
||||
}
|
||||
|
||||
h_cursor_flags()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
type=$1
|
||||
|
||||
echo $SEVEN_SEVEN |
|
||||
awk '{
|
||||
for (i = 1; i <= 20; ++i)
|
||||
printf("%05d: input key %d: %s\n", i, i, $0);
|
||||
exit;
|
||||
}' >exp
|
||||
|
||||
# Test that R_CURSOR doesn't succeed before cursor initialized
|
||||
cat exp |
|
||||
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");
|
||||
}' >in
|
||||
|
||||
atf_check -o ignore -e ignore -s ne:0 "$(prog)" -o out $type in
|
||||
atf_check -s ne:0 test -s out
|
||||
|
||||
cat exp |
|
||||
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");
|
||||
}' >in
|
||||
|
||||
atf_check -o ignore -e ignore -s ne:0 "$(prog)" -o out $type in
|
||||
atf_check -s ne:0 test -s out
|
||||
}
|
||||
|
||||
atf_test_case cursor_flags_btree
|
||||
cursor_flags_btree_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks use of cursor flags without initialization in btree database"
|
||||
}
|
||||
cursor_flags_btree_body()
|
||||
{
|
||||
h_cursor_flags btree
|
||||
}
|
||||
|
||||
atf_test_case cursor_flags_recno
|
||||
cursor_flags_recno_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks use of cursor flags without initialization in recno database"
|
||||
}
|
||||
cursor_flags_recno_body()
|
||||
{
|
||||
h_cursor_flags recno
|
||||
}
|
||||
|
||||
atf_test_case reverse_order_recno
|
||||
reverse_order_recno_head()
|
||||
{
|
||||
atf_set "descr" "Checks reverse order inserts in recno database"
|
||||
}
|
||||
reverse_order_recno_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
echo $SEVEN_SEVEN |
|
||||
awk '{
|
||||
for (i = 1; i <= 779; ++i)
|
||||
printf("%05d: input key %d: %s\n", i, i, $0);
|
||||
exit;
|
||||
}' >exp
|
||||
|
||||
cat exp |
|
||||
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");
|
||||
}' >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" recno in
|
||||
}
|
||||
|
||||
atf_test_case small_page_btree
|
||||
small_page_btree_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks btree database with lots of keys and small page" \
|
||||
"size: takes the first 20000 entries in the dictionary," \
|
||||
"reverses them, and gives them each a small size data" \
|
||||
"entry. Uses a small page size to make sure the btree" \
|
||||
"split code gets hammered."
|
||||
}
|
||||
small_page_btree_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
mdata=abcdefghijklmnopqrstuvwxy
|
||||
echo $mdata |
|
||||
awk '{ for (i = 1; i < 20001; ++i) print $0 }' >exp
|
||||
|
||||
for i in `sed 20000q $(dict) | rev`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$mdata
|
||||
echo g
|
||||
echo k$i
|
||||
done >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" -i psize=512 btree in
|
||||
}
|
||||
|
||||
h_byte_orders()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
type=$1
|
||||
|
||||
sed 50q $(dict) >exp
|
||||
for order in 1234 4321; do
|
||||
for i in `sed 50q $(dict)`; do
|
||||
echo p
|
||||
echo k$i
|
||||
echo d$i
|
||||
echo g
|
||||
echo k$i
|
||||
done >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" -ilorder=$order -f byte.file $type in
|
||||
|
||||
for i in `sed 50q $(dict)`; do
|
||||
echo g
|
||||
echo k$i
|
||||
done >in
|
||||
|
||||
atf_check -o file:exp "$(prog)" -s -ilorder=$order -f byte.file $type in
|
||||
done
|
||||
}
|
||||
|
||||
atf_test_case byte_orders_btree
|
||||
byte_orders_btree_head()
|
||||
{
|
||||
atf_set "descr" "Checks btree database using differing byte orders"
|
||||
}
|
||||
byte_orders_btree_body()
|
||||
{
|
||||
h_byte_orders btree
|
||||
}
|
||||
|
||||
atf_test_case byte_orders_hash
|
||||
byte_orders_hash_head()
|
||||
{
|
||||
atf_set "descr" "Checks hash database using differing byte orders"
|
||||
}
|
||||
byte_orders_hash_body()
|
||||
{
|
||||
h_byte_orders hash
|
||||
}
|
||||
|
||||
h_bsize_ffactor()
|
||||
{
|
||||
bsize=$1
|
||||
ffactor=$2
|
||||
|
||||
echo "bucketsize $bsize, fill factor $ffactor"
|
||||
atf_check -o file:exp "$(prog)" "-ibsize=$bsize,\
|
||||
ffactor=$ffactor,nelem=25000,cachesize=65536" hash in
|
||||
}
|
||||
|
||||
atf_test_case bsize_ffactor
|
||||
bsize_ffactor_head()
|
||||
{
|
||||
atf_set "descr" "Checks hash database with various" \
|
||||
"bucketsizes and fill factors"
|
||||
}
|
||||
bsize_ffactor_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
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;
|
||||
|
||||
}' >exp
|
||||
|
||||
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);
|
||||
}' >in
|
||||
|
||||
sed 10000q $(dict) |
|
||||
awk '{
|
||||
++i;
|
||||
printf("g\nk%s\n", $0);
|
||||
}' >>in
|
||||
|
||||
h_bsize_ffactor 256 11
|
||||
h_bsize_ffactor 256 14
|
||||
h_bsize_ffactor 256 21
|
||||
|
||||
h_bsize_ffactor 512 21
|
||||
h_bsize_ffactor 512 28
|
||||
h_bsize_ffactor 512 43
|
||||
|
||||
h_bsize_ffactor 1024 43
|
||||
h_bsize_ffactor 1024 57
|
||||
h_bsize_ffactor 1024 85
|
||||
|
||||
h_bsize_ffactor 2048 85
|
||||
h_bsize_ffactor 2048 114
|
||||
h_bsize_ffactor 2048 171
|
||||
|
||||
h_bsize_ffactor 4096 171
|
||||
h_bsize_ffactor 4096 228
|
||||
h_bsize_ffactor 4096 341
|
||||
|
||||
h_bsize_ffactor 8192 341
|
||||
h_bsize_ffactor 8192 455
|
||||
h_bsize_ffactor 8192 683
|
||||
}
|
||||
|
||||
# FIXME: what does it test?
|
||||
atf_test_case four_char_hash
|
||||
four_char_hash_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"Checks hash database with 4 char key and" \
|
||||
"value insert on a 65536 bucket size"
|
||||
}
|
||||
four_char_hash_body()
|
||||
{
|
||||
TMPDIR="$(pwd)/db_dir"; export TMPDIR
|
||||
mkdir ${TMPDIR}
|
||||
|
||||
cat >in <<EOF
|
||||
p
|
||||
k1234
|
||||
d1234
|
||||
r
|
||||
k1234
|
||||
EOF
|
||||
|
||||
atf_check "$(prog)" -i bsize=65536 hash in
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case small_btree
|
||||
atf_add_test_case small_hash
|
||||
atf_add_test_case small_recno
|
||||
atf_add_test_case medium_btree
|
||||
atf_add_test_case medium_hash
|
||||
atf_add_test_case medium_recno
|
||||
atf_add_test_case big_btree
|
||||
atf_add_test_case big_hash
|
||||
atf_add_test_case big_recno
|
||||
atf_add_test_case random_recno
|
||||
atf_add_test_case reverse_recno
|
||||
atf_add_test_case alternate_recno
|
||||
atf_add_test_case delete_btree
|
||||
atf_add_test_case delete_recno
|
||||
atf_add_test_case repeated_btree
|
||||
atf_add_test_case repeated_hash
|
||||
atf_add_test_case duplicate_btree
|
||||
atf_add_test_case cursor_flags_btree
|
||||
atf_add_test_case cursor_flags_recno
|
||||
atf_add_test_case reverse_order_recno
|
||||
atf_add_test_case small_page_btree
|
||||
atf_add_test_case byte_orders_btree
|
||||
atf_add_test_case byte_orders_hash
|
||||
atf_add_test_case bsize_ffactor
|
||||
atf_add_test_case four_char_hash
|
||||
}
|
Loading…
Reference in New Issue
Block a user