1 | /*
|
---|
2 | ldb database library
|
---|
3 |
|
---|
4 | Copyright (C) Andrew Tridgell 2004
|
---|
5 |
|
---|
6 | ** NOTE! The following LGPL license applies to the ldb
|
---|
7 | ** library. This does NOT imply that all of Samba is released
|
---|
8 | ** under the LGPL
|
---|
9 |
|
---|
10 | This library is free software; you can redistribute it and/or
|
---|
11 | modify it under the terms of the GNU Lesser General Public
|
---|
12 | License as published by the Free Software Foundation; either
|
---|
13 | version 3 of the License, or (at your option) any later version.
|
---|
14 |
|
---|
15 | This library is distributed in the hope that it will be useful,
|
---|
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
18 | Lesser General Public License for more details.
|
---|
19 |
|
---|
20 | You should have received a copy of the GNU Lesser General Public
|
---|
21 | License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
---|
22 | */
|
---|
23 |
|
---|
24 | /*
|
---|
25 | * Name: ldb
|
---|
26 | *
|
---|
27 | * Component: ldbtest
|
---|
28 | *
|
---|
29 | * Description: utility to test ldb
|
---|
30 | *
|
---|
31 | * Author: Andrew Tridgell
|
---|
32 | */
|
---|
33 |
|
---|
34 | #include "includes.h"
|
---|
35 | #include "ldb/include/includes.h"
|
---|
36 | #include "ldb/tools/cmdline.h"
|
---|
37 |
|
---|
38 | static struct timeval tp1,tp2;
|
---|
39 | static struct ldb_cmdline *options;
|
---|
40 |
|
---|
41 | static void _start_timer(void)
|
---|
42 | {
|
---|
43 | gettimeofday(&tp1,NULL);
|
---|
44 | }
|
---|
45 |
|
---|
46 | static double _end_timer(void)
|
---|
47 | {
|
---|
48 | gettimeofday(&tp2,NULL);
|
---|
49 | return((tp2.tv_sec - tp1.tv_sec) +
|
---|
50 | (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
|
---|
51 | }
|
---|
52 |
|
---|
53 | static void add_records(struct ldb_context *ldb,
|
---|
54 | const struct ldb_dn *basedn,
|
---|
55 | int count)
|
---|
56 | {
|
---|
57 | struct ldb_message msg;
|
---|
58 | int i;
|
---|
59 |
|
---|
60 | #if 0
|
---|
61 | if (ldb_lock(ldb, "transaction") != 0) {
|
---|
62 | printf("transaction lock failed\n");
|
---|
63 | exit(1);
|
---|
64 | }
|
---|
65 | #endif
|
---|
66 | for (i=0;i<count;i++) {
|
---|
67 | struct ldb_message_element el[6];
|
---|
68 | struct ldb_val vals[6][1];
|
---|
69 | char *name;
|
---|
70 | TALLOC_CTX *tmp_ctx = talloc_new(ldb);
|
---|
71 |
|
---|
72 | name = talloc_asprintf(tmp_ctx, "Test%d", i);
|
---|
73 |
|
---|
74 | msg.dn = ldb_dn_build_child(tmp_ctx, "cn", name, basedn);
|
---|
75 | msg.num_elements = 6;
|
---|
76 | msg.elements = el;
|
---|
77 |
|
---|
78 | el[0].flags = 0;
|
---|
79 | el[0].name = talloc_strdup(tmp_ctx, "cn");
|
---|
80 | el[0].num_values = 1;
|
---|
81 | el[0].values = vals[0];
|
---|
82 | vals[0][0].data = (uint8_t *)name;
|
---|
83 | vals[0][0].length = strlen(name);
|
---|
84 |
|
---|
85 | el[1].flags = 0;
|
---|
86 | el[1].name = "title";
|
---|
87 | el[1].num_values = 1;
|
---|
88 | el[1].values = vals[1];
|
---|
89 | vals[1][0].data = (uint8_t *)talloc_asprintf(tmp_ctx, "The title of %s", name);
|
---|
90 | vals[1][0].length = strlen((char *)vals[1][0].data);
|
---|
91 |
|
---|
92 | el[2].flags = 0;
|
---|
93 | el[2].name = talloc_strdup(tmp_ctx, "uid");
|
---|
94 | el[2].num_values = 1;
|
---|
95 | el[2].values = vals[2];
|
---|
96 | vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name);
|
---|
97 | vals[2][0].length = strlen((char *)vals[2][0].data);
|
---|
98 |
|
---|
99 | el[3].flags = 0;
|
---|
100 | el[3].name = talloc_strdup(tmp_ctx, "mail");
|
---|
101 | el[3].num_values = 1;
|
---|
102 | el[3].values = vals[3];
|
---|
103 | vals[3][0].data = (uint8_t *)talloc_asprintf(tmp_ctx, "%s@example.com", name);
|
---|
104 | vals[3][0].length = strlen((char *)vals[3][0].data);
|
---|
105 |
|
---|
106 | el[4].flags = 0;
|
---|
107 | el[4].name = talloc_strdup(tmp_ctx, "objectClass");
|
---|
108 | el[4].num_values = 1;
|
---|
109 | el[4].values = vals[4];
|
---|
110 | vals[4][0].data = (uint8_t *)talloc_strdup(tmp_ctx, "OpenLDAPperson");
|
---|
111 | vals[4][0].length = strlen((char *)vals[4][0].data);
|
---|
112 |
|
---|
113 | el[5].flags = 0;
|
---|
114 | el[5].name = talloc_strdup(tmp_ctx, "sn");
|
---|
115 | el[5].num_values = 1;
|
---|
116 | el[5].values = vals[5];
|
---|
117 | vals[5][0].data = (uint8_t *)name;
|
---|
118 | vals[5][0].length = strlen((char *)vals[5][0].data);
|
---|
119 |
|
---|
120 | ldb_delete(ldb, msg.dn);
|
---|
121 |
|
---|
122 | if (ldb_add(ldb, &msg) != 0) {
|
---|
123 | printf("Add of %s failed - %s\n", name, ldb_errstring(ldb));
|
---|
124 | exit(1);
|
---|
125 | }
|
---|
126 |
|
---|
127 | printf("adding uid %s\r", name);
|
---|
128 | fflush(stdout);
|
---|
129 |
|
---|
130 | talloc_free(tmp_ctx);
|
---|
131 | }
|
---|
132 | #if 0
|
---|
133 | if (ldb_unlock(ldb, "transaction") != 0) {
|
---|
134 | printf("transaction unlock failed\n");
|
---|
135 | exit(1);
|
---|
136 | }
|
---|
137 | #endif
|
---|
138 | printf("\n");
|
---|
139 | }
|
---|
140 |
|
---|
141 | static void modify_records(struct ldb_context *ldb,
|
---|
142 | const struct ldb_dn *basedn,
|
---|
143 | int count)
|
---|
144 | {
|
---|
145 | struct ldb_message msg;
|
---|
146 | int i;
|
---|
147 |
|
---|
148 | for (i=0;i<count;i++) {
|
---|
149 | struct ldb_message_element el[3];
|
---|
150 | struct ldb_val vals[3];
|
---|
151 | char *name;
|
---|
152 | TALLOC_CTX *tmp_ctx = talloc_new(ldb);
|
---|
153 |
|
---|
154 | name = talloc_asprintf(tmp_ctx, "Test%d", i);
|
---|
155 | msg.dn = ldb_dn_build_child(tmp_ctx, "cn", name, basedn);
|
---|
156 |
|
---|
157 | msg.num_elements = 3;
|
---|
158 | msg.elements = el;
|
---|
159 |
|
---|
160 | el[0].flags = LDB_FLAG_MOD_DELETE;
|
---|
161 | el[0].name = talloc_strdup(tmp_ctx, "mail");
|
---|
162 | el[0].num_values = 0;
|
---|
163 |
|
---|
164 | el[1].flags = LDB_FLAG_MOD_ADD;
|
---|
165 | el[1].name = talloc_strdup(tmp_ctx, "mail");
|
---|
166 | el[1].num_values = 1;
|
---|
167 | el[1].values = &vals[1];
|
---|
168 | vals[1].data = (uint8_t *)talloc_asprintf(tmp_ctx, "%s@other.example.com", name);
|
---|
169 | vals[1].length = strlen((char *)vals[1].data);
|
---|
170 |
|
---|
171 | el[2].flags = LDB_FLAG_MOD_REPLACE;
|
---|
172 | el[2].name = talloc_strdup(tmp_ctx, "mail");
|
---|
173 | el[2].num_values = 1;
|
---|
174 | el[2].values = &vals[2];
|
---|
175 | vals[2].data = (uint8_t *)talloc_asprintf(tmp_ctx, "%s@other2.example.com", name);
|
---|
176 | vals[2].length = strlen((char *)vals[2].data);
|
---|
177 |
|
---|
178 | if (ldb_modify(ldb, &msg) != 0) {
|
---|
179 | printf("Modify of %s failed - %s\n", name, ldb_errstring(ldb));
|
---|
180 | exit(1);
|
---|
181 | }
|
---|
182 |
|
---|
183 | printf("Modifying uid %s\r", name);
|
---|
184 | fflush(stdout);
|
---|
185 |
|
---|
186 | talloc_free(tmp_ctx);
|
---|
187 | }
|
---|
188 |
|
---|
189 | printf("\n");
|
---|
190 | }
|
---|
191 |
|
---|
192 |
|
---|
193 | static void delete_records(struct ldb_context *ldb,
|
---|
194 | const struct ldb_dn *basedn,
|
---|
195 | int count)
|
---|
196 | {
|
---|
197 | int i;
|
---|
198 |
|
---|
199 | for (i=0;i<count;i++) {
|
---|
200 | struct ldb_dn *dn;
|
---|
201 | char *name = talloc_asprintf(ldb, "Test%d", i);
|
---|
202 | dn = ldb_dn_build_child(name, "cn", name, basedn);
|
---|
203 |
|
---|
204 | printf("Deleting uid Test%d\r", i);
|
---|
205 | fflush(stdout);
|
---|
206 |
|
---|
207 | if (ldb_delete(ldb, dn) != 0) {
|
---|
208 | printf("Delete of %s failed - %s\n", ldb_dn_linearize(ldb, dn), ldb_errstring(ldb));
|
---|
209 | exit(1);
|
---|
210 | }
|
---|
211 | talloc_free(name);
|
---|
212 | }
|
---|
213 |
|
---|
214 | printf("\n");
|
---|
215 | }
|
---|
216 |
|
---|
217 | static void search_uid(struct ldb_context *ldb, struct ldb_dn *basedn, int nrecords, int nsearches)
|
---|
218 | {
|
---|
219 | int i;
|
---|
220 |
|
---|
221 | for (i=0;i<nsearches;i++) {
|
---|
222 | int uid = (i * 700 + 17) % (nrecords * 2);
|
---|
223 | char *expr;
|
---|
224 | struct ldb_result *res = NULL;
|
---|
225 | int ret;
|
---|
226 |
|
---|
227 | expr = talloc_asprintf(ldb, "(uid=TEST%d)", uid);
|
---|
228 | ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, expr, NULL, &res);
|
---|
229 |
|
---|
230 | if (ret != LDB_SUCCESS || (uid < nrecords && res->count != 1)) {
|
---|
231 | printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb));
|
---|
232 | exit(1);
|
---|
233 | }
|
---|
234 |
|
---|
235 | if (uid >= nrecords && res->count > 0) {
|
---|
236 | printf("Found %s !? - %d\n", expr, ret);
|
---|
237 | exit(1);
|
---|
238 | }
|
---|
239 |
|
---|
240 | printf("testing uid %d/%d - %d \r", i, uid, res->count);
|
---|
241 | fflush(stdout);
|
---|
242 |
|
---|
243 | talloc_free(res);
|
---|
244 | talloc_free(expr);
|
---|
245 | }
|
---|
246 |
|
---|
247 | printf("\n");
|
---|
248 | }
|
---|
249 |
|
---|
250 | static void start_test(struct ldb_context *ldb, int nrecords, int nsearches)
|
---|
251 | {
|
---|
252 | struct ldb_dn *basedn;
|
---|
253 |
|
---|
254 | basedn = ldb_dn_explode(ldb, options->basedn);
|
---|
255 |
|
---|
256 | printf("Adding %d records\n", nrecords);
|
---|
257 | add_records(ldb, basedn, nrecords);
|
---|
258 |
|
---|
259 | printf("Starting search on uid\n");
|
---|
260 | _start_timer();
|
---|
261 | search_uid(ldb, basedn, nrecords, nsearches);
|
---|
262 | printf("uid search took %.2f seconds\n", _end_timer());
|
---|
263 |
|
---|
264 | printf("Modifying records\n");
|
---|
265 | modify_records(ldb, basedn, nrecords);
|
---|
266 |
|
---|
267 | printf("Deleting records\n");
|
---|
268 | delete_records(ldb, basedn, nrecords);
|
---|
269 | }
|
---|
270 |
|
---|
271 |
|
---|
272 | /*
|
---|
273 | 2) Store an @indexlist record
|
---|
274 |
|
---|
275 | 3) Store a record that contains fields that should be index according
|
---|
276 | to @index
|
---|
277 |
|
---|
278 | 4) disconnection from database
|
---|
279 |
|
---|
280 | 5) connect to same database
|
---|
281 |
|
---|
282 | 6) search for record added in step 3 using a search key that should
|
---|
283 | be indexed
|
---|
284 | */
|
---|
285 | static void start_test_index(struct ldb_context **ldb)
|
---|
286 | {
|
---|
287 | struct ldb_message *msg;
|
---|
288 | struct ldb_result *res = NULL;
|
---|
289 | struct ldb_dn *indexlist;
|
---|
290 | struct ldb_dn *basedn;
|
---|
291 | int ret;
|
---|
292 | int flags = 0;
|
---|
293 | const char *specials;
|
---|
294 |
|
---|
295 | specials = getenv("LDB_SPECIALS");
|
---|
296 | if (specials && atoi(specials) == 0) {
|
---|
297 | printf("LDB_SPECIALS disabled - skipping index test\n");
|
---|
298 | return;
|
---|
299 | }
|
---|
300 |
|
---|
301 | if (options->nosync) {
|
---|
302 | flags |= LDB_FLG_NOSYNC;
|
---|
303 | }
|
---|
304 |
|
---|
305 | printf("Starting index test\n");
|
---|
306 |
|
---|
307 | indexlist = ldb_dn_explode(NULL, "@INDEXLIST");
|
---|
308 |
|
---|
309 | ldb_delete(*ldb, indexlist);
|
---|
310 |
|
---|
311 | msg = ldb_msg_new(NULL);
|
---|
312 |
|
---|
313 | msg->dn = indexlist;
|
---|
314 | ldb_msg_add_string(msg, "@IDXATTR", strdup("uid"));
|
---|
315 |
|
---|
316 | if (ldb_add(*ldb, msg) != 0) {
|
---|
317 | printf("Add of %s failed - %s\n", ldb_dn_linearize(*ldb, msg->dn), ldb_errstring(*ldb));
|
---|
318 | exit(1);
|
---|
319 | }
|
---|
320 |
|
---|
321 | basedn = ldb_dn_explode(NULL, options->basedn);
|
---|
322 |
|
---|
323 | memset(msg, 0, sizeof(*msg));
|
---|
324 | msg->dn = ldb_dn_build_child(msg, "cn", "test", basedn);
|
---|
325 | ldb_msg_add_string(msg, "cn", strdup("test"));
|
---|
326 | ldb_msg_add_string(msg, "sn", strdup("test"));
|
---|
327 | ldb_msg_add_string(msg, "uid", strdup("test"));
|
---|
328 | ldb_msg_add_string(msg, "objectClass", strdup("OpenLDAPperson"));
|
---|
329 |
|
---|
330 | if (ldb_add(*ldb, msg) != 0) {
|
---|
331 | printf("Add of %s failed - %s\n", ldb_dn_linearize(*ldb, msg->dn), ldb_errstring(*ldb));
|
---|
332 | exit(1);
|
---|
333 | }
|
---|
334 |
|
---|
335 | if (talloc_free(*ldb) != 0) {
|
---|
336 | printf("failed to free/close ldb database");
|
---|
337 | exit(1);
|
---|
338 | }
|
---|
339 |
|
---|
340 | (*ldb) = ldb_init(options);
|
---|
341 |
|
---|
342 | ret = ldb_connect(*ldb, options->url, flags, NULL);
|
---|
343 | if (ret != 0) {
|
---|
344 | printf("failed to connect to %s\n", options->url);
|
---|
345 | exit(1);
|
---|
346 | }
|
---|
347 |
|
---|
348 | ret = ldb_search(*ldb, basedn, LDB_SCOPE_SUBTREE, "uid=test", NULL, &res);
|
---|
349 | if (ret != LDB_SUCCESS) {
|
---|
350 | printf("Search with (uid=test) filter failed!\n");
|
---|
351 | exit(1);
|
---|
352 | }
|
---|
353 | if(res->count != 1) {
|
---|
354 | printf("Should have found 1 record - found %d\n", res->count);
|
---|
355 | exit(1);
|
---|
356 | }
|
---|
357 |
|
---|
358 | if (ldb_delete(*ldb, msg->dn) != 0 ||
|
---|
359 | ldb_delete(*ldb, indexlist) != 0) {
|
---|
360 | printf("cleanup failed - %s\n", ldb_errstring(*ldb));
|
---|
361 | exit(1);
|
---|
362 | }
|
---|
363 |
|
---|
364 | printf("Finished index test\n");
|
---|
365 | }
|
---|
366 |
|
---|
367 |
|
---|
368 | static void usage(void)
|
---|
369 | {
|
---|
370 | printf("Usage: ldbtest <options>\n");
|
---|
371 | printf("Options:\n");
|
---|
372 | printf(" -H ldb_url choose the database (or $LDB_URL)\n");
|
---|
373 | printf(" --num-records nrecords database size to use\n");
|
---|
374 | printf(" --num-searches nsearches number of searches to do\n");
|
---|
375 | printf("\n");
|
---|
376 | printf("tests ldb API\n\n");
|
---|
377 | exit(1);
|
---|
378 | }
|
---|
379 |
|
---|
380 | int main(int argc, const char **argv)
|
---|
381 | {
|
---|
382 | TALLOC_CTX *mem_ctx = talloc_new(NULL);
|
---|
383 | struct ldb_context *ldb;
|
---|
384 |
|
---|
385 | ldb_global_init();
|
---|
386 |
|
---|
387 | ldb = ldb_init(mem_ctx);
|
---|
388 |
|
---|
389 | options = ldb_cmdline_process(ldb, argc, argv, usage);
|
---|
390 |
|
---|
391 | talloc_steal(mem_ctx, options);
|
---|
392 |
|
---|
393 | if (options->basedn == NULL) {
|
---|
394 | options->basedn = "ou=Ldb Test,ou=People,o=University of Michigan,c=TEST";
|
---|
395 | }
|
---|
396 |
|
---|
397 | srandom(1);
|
---|
398 |
|
---|
399 | printf("Testing with num-records=%d and num-searches=%d\n",
|
---|
400 | options->num_records, options->num_searches);
|
---|
401 |
|
---|
402 | start_test(ldb, options->num_records, options->num_searches);
|
---|
403 |
|
---|
404 | start_test_index(&ldb);
|
---|
405 |
|
---|
406 | talloc_free(mem_ctx);
|
---|
407 |
|
---|
408 | return 0;
|
---|
409 | }
|
---|