1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "apr.h"
18 #include "apr_general.h"
19 #include "apr_pools.h"
20 #include "apr_errno.h"
21 #include "apr_dbm.h"
22 #include "apr_uuid.h"
23 #include "apr_strings.h"
24 #include "abts.h"
25 #include "testutil.h"
26
27 #define NUM_TABLE_ROWS 1024
28
29 typedef struct {
30 apr_datum_t key;
31 apr_datum_t val;
32 int deleted;
33 int visited;
34 } dbm_table_t;
35
generate_table(void)36 static dbm_table_t *generate_table(void)
37 {
38 unsigned int i;
39 apr_uuid_t uuid;
40 dbm_table_t *table = apr_pcalloc(p, sizeof(*table) * NUM_TABLE_ROWS);
41
42 for (i = 0; i < NUM_TABLE_ROWS/2; i++) {
43 apr_uuid_get(&uuid);
44 table[i].key.dptr = apr_pmemdup(p, uuid.data, sizeof(uuid.data));
45 table[i].key.dsize = sizeof(uuid.data);
46 table[i].val.dptr = apr_palloc(p, APR_UUID_FORMATTED_LENGTH);
47 table[i].val.dsize = APR_UUID_FORMATTED_LENGTH;
48 apr_uuid_format(table[i].val.dptr, &uuid);
49 }
50
51 for (; i < NUM_TABLE_ROWS; i++) {
52 apr_uuid_get(&uuid);
53 table[i].val.dptr = apr_pmemdup(p, uuid.data, sizeof(uuid.data));
54 table[i].val.dsize = sizeof(uuid.data);
55 table[i].key.dptr = apr_palloc(p, APR_UUID_FORMATTED_LENGTH);
56 table[i].key.dsize = APR_UUID_FORMATTED_LENGTH;
57 apr_uuid_format(table[i].key.dptr, &uuid);
58 }
59
60 return table;
61 }
62
test_dbm_store(abts_case * tc,apr_dbm_t * db,dbm_table_t * table)63 static void test_dbm_store(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
64 {
65 apr_status_t rv;
66 unsigned int i = NUM_TABLE_ROWS - 1;
67
68 for (; i >= NUM_TABLE_ROWS/2; i--) {
69 rv = apr_dbm_store(db, table[i].key, table[i].val);
70 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
71 table[i].deleted = FALSE;
72 }
73
74 for (i = 0; i < NUM_TABLE_ROWS/2; i++) {
75 rv = apr_dbm_store(db, table[i].key, table[i].val);
76 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
77 table[i].deleted = FALSE;
78 }
79 }
80
test_dbm_fetch(abts_case * tc,apr_dbm_t * db,dbm_table_t * table)81 static void test_dbm_fetch(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
82 {
83 apr_status_t rv;
84 unsigned int i;
85 apr_datum_t val;
86
87 for (i = 0; i < NUM_TABLE_ROWS; i++) {
88 memset(&val, 0, sizeof(val));
89 rv = apr_dbm_fetch(db, table[i].key, &val);
90 if (!table[i].deleted) {
91 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
92 ABTS_INT_EQUAL(tc, table[i].val.dsize, val.dsize);
93 ABTS_INT_EQUAL(tc, 0, memcmp(table[i].val.dptr, val.dptr, val.dsize));
94 apr_dbm_freedatum(db, val);
95 } else {
96 ABTS_INT_EQUAL(tc, 0, val.dsize);
97 }
98 }
99 }
100
test_dbm_delete(abts_case * tc,apr_dbm_t * db,dbm_table_t * table)101 static void test_dbm_delete(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
102 {
103 apr_status_t rv;
104 unsigned int i;
105
106 for (i = 0; i < NUM_TABLE_ROWS; i++) {
107 /* XXX: random */
108 if (i & 1)
109 continue;
110 rv = apr_dbm_delete(db, table[i].key);
111 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
112 table[i].deleted = TRUE;
113 }
114 }
115
test_dbm_exists(abts_case * tc,apr_dbm_t * db,dbm_table_t * table)116 static void test_dbm_exists(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
117 {
118 unsigned int i;
119 int cond;
120
121 for (i = 0; i < NUM_TABLE_ROWS; i++) {
122 cond = apr_dbm_exists(db, table[i].key);
123 if (table[i].deleted) {
124 ABTS_TRUE(tc, cond == 0);
125 } else {
126 ABTS_TRUE(tc, cond != 0);
127 }
128 }
129 }
130
test_dbm_traversal(abts_case * tc,apr_dbm_t * db,dbm_table_t * table)131 static void test_dbm_traversal(abts_case *tc, apr_dbm_t *db, dbm_table_t *table)
132 {
133 apr_status_t rv;
134 unsigned int i;
135 apr_datum_t key;
136
137 rv = apr_dbm_firstkey(db, &key);
138 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
139
140 do {
141 if (key.dptr == NULL || key.dsize == 0)
142 break;
143
144 for (i = 0; i < NUM_TABLE_ROWS; i++) {
145 if (table[i].key.dsize != key.dsize)
146 continue;
147 if (memcmp(table[i].key.dptr, key.dptr, key.dsize))
148 continue;
149 ABTS_INT_EQUAL(tc, 0, table[i].deleted);
150 ABTS_INT_EQUAL(tc, 0, table[i].visited);
151 table[i].visited++;
152 }
153
154 rv = apr_dbm_nextkey(db, &key);
155 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
156 } while (1);
157
158 for (i = 0; i < NUM_TABLE_ROWS; i++) {
159 if (table[i].deleted)
160 continue;
161 ABTS_INT_EQUAL(tc, 1, table[i].visited);
162 table[i].visited = 0;
163 }
164 }
165
test_dbm(abts_case * tc,void * data)166 static void test_dbm(abts_case *tc, void *data)
167 {
168 apr_dbm_t *db;
169 apr_status_t rv;
170 dbm_table_t *table;
171 const char *type = data;
172 const char *file = apr_pstrcat(p, "data/test-", type, NULL);
173
174 rv = apr_dbm_open_ex(&db, type, file, APR_DBM_RWCREATE, APR_OS_DEFAULT, p);
175 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
176
177 if (rv != APR_SUCCESS)
178 return;
179
180 table = generate_table();
181
182 test_dbm_store(tc, db, table);
183 test_dbm_fetch(tc, db, table);
184 test_dbm_delete(tc, db, table);
185 test_dbm_exists(tc, db, table);
186 test_dbm_traversal(tc, db, table);
187
188 apr_dbm_close(db);
189
190 rv = apr_dbm_open_ex(&db, type, file, APR_DBM_READONLY, APR_OS_DEFAULT, p);
191 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
192
193 if (rv != APR_SUCCESS)
194 return;
195
196 test_dbm_exists(tc, db, table);
197 test_dbm_traversal(tc, db, table);
198 test_dbm_fetch(tc, db, table);
199
200 apr_dbm_close(db);
201 }
202
testdbm(abts_suite * suite)203 abts_suite *testdbm(abts_suite *suite)
204 {
205 suite = ADD_SUITE(suite);
206
207 #if APU_HAVE_GDBM
208 abts_run_test(suite, test_dbm, "gdbm");
209 #endif
210 #if APU_HAVE_NDBM
211 abts_run_test(suite, test_dbm, "ndbm");
212 #endif
213 #if APU_HAVE_SDBM
214 abts_run_test(suite, test_dbm, "sdbm");
215 #endif
216 #if APU_HAVE_DB
217 abts_run_test(suite, test_dbm, "db");
218 #endif
219
220 return suite;
221 }
222