diff options
Diffstat (limited to '')
-rw-r--r-- | test/testdbm.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/test/testdbm.c b/test/testdbm.c new file mode 100644 index 0000000..4f6becb --- /dev/null +++ b/test/testdbm.c @@ -0,0 +1,221 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_errno.h" +#include "apr_dbm.h" +#include "apr_uuid.h" +#include "apr_strings.h" +#include "abts.h" +#include "testutil.h" + +#define NUM_TABLE_ROWS 1024 + +typedef struct { + apr_datum_t key; + apr_datum_t val; + int deleted; + int visited; +} dbm_table_t; + +static dbm_table_t *generate_table(void) +{ + unsigned int i; + apr_uuid_t uuid; + dbm_table_t *table = apr_pcalloc(p, sizeof(*table) * NUM_TABLE_ROWS); + + for (i = 0; i < NUM_TABLE_ROWS/2; i++) { + apr_uuid_get(&uuid); + table[i].key.dptr = apr_pmemdup(p, uuid.data, sizeof(uuid.data)); + table[i].key.dsize = sizeof(uuid.data); + table[i].val.dptr = apr_palloc(p, APR_UUID_FORMATTED_LENGTH + 1); + table[i].val.dsize = APR_UUID_FORMATTED_LENGTH + 1; + apr_uuid_format(table[i].val.dptr, &uuid); + } + + for (; i < NUM_TABLE_ROWS; i++) { + apr_uuid_get(&uuid); + table[i].val.dptr = apr_pmemdup(p, uuid.data, sizeof(uuid.data)); + table[i].val.dsize = sizeof(uuid.data); + table[i].key.dptr = apr_palloc(p, APR_UUID_FORMATTED_LENGTH + 1); + table[i].key.dsize = APR_UUID_FORMATTED_LENGTH + 1; + apr_uuid_format(table[i].key.dptr, &uuid); + } + + return table; +} + +static void test_dbm_store(abts_case *tc, apr_dbm_t *db, dbm_table_t *table) +{ + apr_status_t rv; + unsigned int i = NUM_TABLE_ROWS - 1; + + for (; i >= NUM_TABLE_ROWS/2; i--) { + rv = apr_dbm_store(db, table[i].key, table[i].val); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + table[i].deleted = FALSE; + } + + for (i = 0; i < NUM_TABLE_ROWS/2; i++) { + rv = apr_dbm_store(db, table[i].key, table[i].val); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + table[i].deleted = FALSE; + } +} + +static void test_dbm_fetch(abts_case *tc, apr_dbm_t *db, dbm_table_t *table) +{ + apr_status_t rv; + unsigned int i; + apr_datum_t val; + + for (i = 0; i < NUM_TABLE_ROWS; i++) { + memset(&val, 0, sizeof(val)); + rv = apr_dbm_fetch(db, table[i].key, &val); + if (!table[i].deleted) { + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, table[i].val.dsize, val.dsize); + ABTS_INT_EQUAL(tc, 0, memcmp(table[i].val.dptr, val.dptr, val.dsize)); + apr_dbm_freedatum(db, val); + } else { + ABTS_INT_EQUAL(tc, 0, val.dsize); + } + } +} + +static void test_dbm_delete(abts_case *tc, apr_dbm_t *db, dbm_table_t *table) +{ + apr_status_t rv; + unsigned int i; + + for (i = 0; i < NUM_TABLE_ROWS; i++) { + /* XXX: random */ + if (i & 1) + continue; + rv = apr_dbm_delete(db, table[i].key); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + table[i].deleted = TRUE; + } +} + +static void test_dbm_exists(abts_case *tc, apr_dbm_t *db, dbm_table_t *table) +{ + unsigned int i; + int cond; + + for (i = 0; i < NUM_TABLE_ROWS; i++) { + cond = apr_dbm_exists(db, table[i].key); + if (table[i].deleted) { + ABTS_TRUE(tc, cond == 0); + } else { + ABTS_TRUE(tc, cond != 0); + } + } +} + +static void test_dbm_traversal(abts_case *tc, apr_dbm_t *db, dbm_table_t *table) +{ + apr_status_t rv; + unsigned int i; + apr_datum_t key; + + rv = apr_dbm_firstkey(db, &key); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + do { + if (key.dptr == NULL || key.dsize == 0) + break; + + for (i = 0; i < NUM_TABLE_ROWS; i++) { + if (table[i].key.dsize != key.dsize) + continue; + if (memcmp(table[i].key.dptr, key.dptr, key.dsize)) + continue; + ABTS_INT_EQUAL(tc, 0, table[i].deleted); + ABTS_INT_EQUAL(tc, 0, table[i].visited); + table[i].visited++; + } + + rv = apr_dbm_nextkey(db, &key); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + } while (1); + + for (i = 0; i < NUM_TABLE_ROWS; i++) { + if (table[i].deleted) + continue; + ABTS_INT_EQUAL(tc, 1, table[i].visited); + table[i].visited = 0; + } +} + +static void test_dbm(abts_case *tc, void *data) +{ + apr_dbm_t *db; + apr_status_t rv; + dbm_table_t *table; + const char *type = data; + const char *file = apr_pstrcat(p, "data/test-", type, NULL); + + rv = apr_dbm_open_ex(&db, type, file, APR_DBM_RWCREATE, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + if (rv != APR_SUCCESS) + return; + + table = generate_table(); + + test_dbm_store(tc, db, table); + test_dbm_fetch(tc, db, table); + test_dbm_delete(tc, db, table); + test_dbm_exists(tc, db, table); + test_dbm_traversal(tc, db, table); + + apr_dbm_close(db); + + rv = apr_dbm_open_ex(&db, type, file, APR_DBM_READONLY, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + if (rv != APR_SUCCESS) + return; + + test_dbm_exists(tc, db, table); + test_dbm_traversal(tc, db, table); + test_dbm_fetch(tc, db, table); + + apr_dbm_close(db); +} + +abts_suite *testdbm(abts_suite *suite) +{ + suite = ADD_SUITE(suite); + +#if APU_HAVE_GDBM + abts_run_test(suite, test_dbm, "gdbm"); +#endif +#if APU_HAVE_NDBM + abts_run_test(suite, test_dbm, "ndbm"); +#endif +#if APU_HAVE_SDBM + abts_run_test(suite, test_dbm, "sdbm"); +#endif +#if APU_HAVE_DB + abts_run_test(suite, test_dbm, "db"); +#endif + + return suite; +} |