1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251876Speter * contributor license agreements.  See the NOTICE file distributed with
3251876Speter * this work for additional information regarding copyright ownership.
4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251876Speter * (the "License"); you may not use this file except in compliance with
6251876Speter * the License.  You may obtain a copy of the License at
7251876Speter *
8251876Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251876Speter *
10251876Speter * Unless required by applicable law or agreed to in writing, software
11251876Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251876Speter * See the License for the specific language governing permissions and
14251876Speter * limitations under the License.
15251876Speter */
16251876Speter
17251876Speter#include "apr.h"
18251876Speter#include "apr_general.h"
19251876Speter#include "apr_pools.h"
20251876Speter#include "apr_errno.h"
21251876Speter#include "apr_dbm.h"
22251876Speter#include "apr_uuid.h"
23251876Speter#include "apr_strings.h"
24251876Speter#include "abts.h"
25251876Speter#include "testutil.h"
26251876Speter
27251876Speter#define NUM_TABLE_ROWS  1024
28251876Speter
29251876Spetertypedef struct {
30251876Speter    apr_datum_t key;
31251876Speter    apr_datum_t val;
32251876Speter    int deleted;
33251876Speter    int visited;
34251876Speter} dbm_table_t;
35251876Speter
36251876Speterstatic dbm_table_t *generate_table(void)
37251876Speter{
38251876Speter    unsigned int i;
39251876Speter    apr_uuid_t uuid;
40251876Speter    dbm_table_t *table = apr_pcalloc(p, sizeof(*table) * NUM_TABLE_ROWS);
41251876Speter
42251876Speter    for (i = 0; i < NUM_TABLE_ROWS/2; i++) {
43251876Speter        apr_uuid_get(&uuid);
44251876Speter        table[i].key.dptr = apr_pmemdup(p, uuid.data, sizeof(uuid.data));
45251876Speter        table[i].key.dsize = sizeof(uuid.data);
46251876Speter        table[i].val.dptr = apr_palloc(p, APR_UUID_FORMATTED_LENGTH);
47251876Speter        table[i].val.dsize = APR_UUID_FORMATTED_LENGTH;
48251876Speter        apr_uuid_format(table[i].val.dptr, &uuid);
49251876Speter    }
50251876Speter
51251876Speter    for (; i < NUM_TABLE_ROWS; i++) {
52251876Speter        apr_uuid_get(&uuid);
53251876Speter        table[i].val.dptr = apr_pmemdup(p, uuid.data, sizeof(uuid.data));
54251876Speter        table[i].val.dsize = sizeof(uuid.data);
55251876Speter        table[i].key.dptr = apr_palloc(p, APR_UUID_FORMATTED_LENGTH);
56251876Speter        table[i].key.dsize = APR_UUID_FORMATTED_LENGTH;
57251876Speter        apr_uuid_format(table[i].key.dptr, &uuid);
58251876Speter    }
59251876Speter
60251876Speter    return table;
61251876Speter}
62251876Speter
63251876Speterstatic void test_dbm_store(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
64251876Speter{
65251876Speter    apr_status_t rv;
66251876Speter    unsigned int i = NUM_TABLE_ROWS - 1;
67251876Speter
68251876Speter    for (; i >= NUM_TABLE_ROWS/2; i--) {
69251876Speter        rv = apr_dbm_store(db, table[i].key, table[i].val);
70251876Speter        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
71251876Speter        table[i].deleted = FALSE;
72251876Speter    }
73251876Speter
74251876Speter    for (i = 0; i < NUM_TABLE_ROWS/2; i++) {
75251876Speter        rv = apr_dbm_store(db, table[i].key, table[i].val);
76251876Speter        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
77251876Speter        table[i].deleted = FALSE;
78251876Speter    }
79251876Speter}
80251876Speter
81251876Speterstatic void test_dbm_fetch(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
82251876Speter{
83251876Speter    apr_status_t rv;
84251876Speter    unsigned int i;
85251876Speter    apr_datum_t val;
86251876Speter
87251876Speter    for (i = 0; i < NUM_TABLE_ROWS; i++) {
88251876Speter        memset(&val, 0, sizeof(val));
89251876Speter        rv = apr_dbm_fetch(db, table[i].key, &val);
90251876Speter        if (!table[i].deleted) {
91251876Speter            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
92251876Speter            ABTS_INT_EQUAL(tc, table[i].val.dsize, val.dsize);
93251876Speter            ABTS_INT_EQUAL(tc, 0, memcmp(table[i].val.dptr, val.dptr, val.dsize));
94251876Speter            apr_dbm_freedatum(db, val);
95251876Speter        } else {
96251876Speter            ABTS_INT_EQUAL(tc, 0, val.dsize);
97251876Speter        }
98251876Speter    }
99251876Speter}
100251876Speter
101251876Speterstatic void test_dbm_delete(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
102251876Speter{
103251876Speter    apr_status_t rv;
104251876Speter    unsigned int i;
105251876Speter
106251876Speter    for (i = 0; i < NUM_TABLE_ROWS; i++) {
107251876Speter        /* XXX: random */
108251876Speter        if (i & 1)
109251876Speter            continue;
110251876Speter        rv = apr_dbm_delete(db, table[i].key);
111251876Speter        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
112251876Speter        table[i].deleted = TRUE;
113251876Speter    }
114251876Speter}
115251876Speter
116251876Speterstatic void test_dbm_exists(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
117251876Speter{
118251876Speter    unsigned int i;
119251876Speter    int cond;
120251876Speter
121251876Speter    for (i = 0; i < NUM_TABLE_ROWS; i++) {
122251876Speter        cond = apr_dbm_exists(db, table[i].key);
123251876Speter        if (table[i].deleted) {
124251876Speter            ABTS_TRUE(tc, cond == 0);
125251876Speter        } else {
126251876Speter            ABTS_TRUE(tc, cond != 0);
127251876Speter        }
128251876Speter    }
129251876Speter}
130251876Speter
131251876Speterstatic void test_dbm_traversal(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
132251876Speter{
133251876Speter    apr_status_t rv;
134251876Speter    unsigned int i;
135251876Speter    apr_datum_t key;
136251876Speter
137251876Speter    rv = apr_dbm_firstkey(db, &key);
138251876Speter    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
139251876Speter
140251876Speter    do {
141251876Speter        if (key.dptr == NULL || key.dsize == 0)
142251876Speter            break;
143251876Speter
144251876Speter        for (i = 0; i < NUM_TABLE_ROWS; i++) {
145251876Speter            if (table[i].key.dsize != key.dsize)
146251876Speter                continue;
147251876Speter            if (memcmp(table[i].key.dptr, key.dptr, key.dsize))
148251876Speter                continue;
149251876Speter            ABTS_INT_EQUAL(tc, 0, table[i].deleted);
150251876Speter            ABTS_INT_EQUAL(tc, 0, table[i].visited);
151251876Speter            table[i].visited++;
152251876Speter        }
153251876Speter
154251876Speter        rv = apr_dbm_nextkey(db, &key);
155251876Speter        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
156251876Speter    } while (1);
157251876Speter
158251876Speter    for (i = 0; i < NUM_TABLE_ROWS; i++) {
159251876Speter        if (table[i].deleted)
160251876Speter            continue;
161251876Speter        ABTS_INT_EQUAL(tc, 1, table[i].visited);
162251876Speter        table[i].visited = 0;
163251876Speter    }
164251876Speter}
165251876Speter
166251876Speterstatic void test_dbm(abts_case *tc, void *data)
167251876Speter{
168251876Speter    apr_dbm_t *db;
169251876Speter    apr_status_t rv;
170251876Speter    dbm_table_t *table;
171251876Speter    const char *type = data;
172251876Speter    const char *file = apr_pstrcat(p, "data/test-", type, NULL);
173251876Speter
174251876Speter    rv = apr_dbm_open_ex(&db, type, file, APR_DBM_RWCREATE, APR_OS_DEFAULT, p);
175251876Speter    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
176251876Speter
177251876Speter    if (rv != APR_SUCCESS)
178251876Speter        return;
179251876Speter
180251876Speter    table = generate_table();
181251876Speter
182251876Speter    test_dbm_store(tc, db, table);
183251876Speter    test_dbm_fetch(tc, db, table);
184251876Speter    test_dbm_delete(tc, db, table);
185251876Speter    test_dbm_exists(tc, db, table);
186251876Speter    test_dbm_traversal(tc, db, table);
187251876Speter
188251876Speter    apr_dbm_close(db);
189251876Speter
190251876Speter    rv = apr_dbm_open_ex(&db, type, file, APR_DBM_READONLY, APR_OS_DEFAULT, p);
191251876Speter    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
192251876Speter
193251876Speter    if (rv != APR_SUCCESS)
194251876Speter        return;
195251876Speter
196251876Speter    test_dbm_exists(tc, db, table);
197251876Speter    test_dbm_traversal(tc, db, table);
198251876Speter    test_dbm_fetch(tc, db, table);
199251876Speter
200251876Speter    apr_dbm_close(db);
201251876Speter}
202251876Speter
203251876Speterabts_suite *testdbm(abts_suite *suite)
204251876Speter{
205251876Speter    suite = ADD_SUITE(suite);
206251876Speter
207251876Speter#if APU_HAVE_GDBM
208251876Speter    abts_run_test(suite, test_dbm, "gdbm");
209251876Speter#endif
210251876Speter#if APU_HAVE_NDBM
211251876Speter    abts_run_test(suite, test_dbm, "ndbm");
212251876Speter#endif
213251876Speter#if APU_HAVE_SDBM
214251876Speter    abts_run_test(suite, test_dbm, "sdbm");
215251876Speter#endif
216251876Speter#if APU_HAVE_DB
217251876Speter    abts_run_test(suite, test_dbm, "db");
218251876Speter#endif
219251876Speter
220251876Speter    return suite;
221251876Speter}
222