summaryrefslogtreecommitdiffstats
path: root/test/testdbm.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--test/testdbm.c221
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;
+}