| /* 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); |
| table[i].val.dsize = APR_UUID_FORMATTED_LENGTH; |
| 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); |
| table[i].key.dsize = APR_UUID_FORMATTED_LENGTH; |
| 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, rv, APR_SUCCESS); |
| 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, rv, APR_SUCCESS); |
| 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, rv, APR_SUCCESS); |
| ABTS_INT_EQUAL(tc, (int)table[i].val.dsize, (int)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, (int)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, rv, APR_SUCCESS); |
| 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, rv, APR_SUCCESS); |
| |
| 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, table[i].deleted, 0); |
| ABTS_INT_EQUAL(tc, table[i].visited, 0); |
| table[i].visited++; |
| } |
| |
| rv = apr_dbm_nextkey(db, &key); |
| ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); |
| } while (1); |
| |
| for (i = 0; i < NUM_TABLE_ROWS; i++) { |
| if (table[i].deleted) |
| continue; |
| ABTS_INT_EQUAL(tc, table[i].visited, 1); |
| 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, rv, APR_SUCCESS); |
| |
| 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, rv, APR_SUCCESS); |
| |
| 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; |
| } |