4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
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.
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.
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/>.
29 * Description: utility to test ldb
31 * Author: Andrew Tridgell
35 #include "tools/cmdline.h"
37 static struct timeval tp1
,tp2
;
38 static struct ldb_cmdline
*options
;
40 static void _start_timer(void)
42 gettimeofday(&tp1
,NULL
);
45 static double _end_timer(void)
47 gettimeofday(&tp2
,NULL
);
48 return((tp2
.tv_sec
- tp1
.tv_sec
) +
49 (tp2
.tv_usec
- tp1
.tv_usec
)*1.0e-6);
52 static void add_records(struct ldb_context
*ldb
,
53 struct ldb_dn
*basedn
,
56 struct ldb_message msg
;
60 if (ldb_lock(ldb
, "transaction") != 0) {
61 printf("transaction lock failed\n");
65 for (i
=0;i
<count
;i
++) {
66 struct ldb_message_element el
[6];
67 struct ldb_val vals
[6][1];
69 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
71 name
= talloc_asprintf(tmp_ctx
, "Test%d", i
);
73 msg
.dn
= ldb_dn_copy(tmp_ctx
, basedn
);
74 ldb_dn_add_child_fmt(msg
.dn
, "cn=%s", name
);
79 el
[0].name
= talloc_strdup(tmp_ctx
, "cn");
81 el
[0].values
= vals
[0];
82 vals
[0][0].data
= (uint8_t *)name
;
83 vals
[0][0].length
= strlen(name
);
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
);
93 el
[2].name
= talloc_strdup(tmp_ctx
, "uid");
95 el
[2].values
= vals
[2];
96 vals
[2][0].data
= (uint8_t *)ldb_casefold(ldb
, tmp_ctx
, name
, strlen(name
));
97 vals
[2][0].length
= strlen((char *)vals
[2][0].data
);
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
);
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
);
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
);
120 ldb_delete(ldb
, msg
.dn
);
122 if (ldb_add(ldb
, &msg
) != 0) {
123 printf("Add of %s failed - %s\n", name
, ldb_errstring(ldb
));
127 printf("adding uid %s\r", name
);
130 talloc_free(tmp_ctx
);
133 if (ldb_unlock(ldb
, "transaction") != 0) {
134 printf("transaction unlock failed\n");
141 static void modify_records(struct ldb_context
*ldb
,
142 struct ldb_dn
*basedn
,
145 struct ldb_message msg
;
148 for (i
=0;i
<count
;i
++) {
149 struct ldb_message_element el
[3];
150 struct ldb_val vals
[3];
152 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
154 name
= talloc_asprintf(tmp_ctx
, "Test%d", i
);
155 msg
.dn
= ldb_dn_copy(tmp_ctx
, basedn
);
156 ldb_dn_add_child_fmt(msg
.dn
, "cn=%s", name
);
158 msg
.num_elements
= 3;
161 el
[0].flags
= LDB_FLAG_MOD_DELETE
;
162 el
[0].name
= talloc_strdup(tmp_ctx
, "mail");
163 el
[0].num_values
= 0;
165 el
[1].flags
= LDB_FLAG_MOD_ADD
;
166 el
[1].name
= talloc_strdup(tmp_ctx
, "mail");
167 el
[1].num_values
= 1;
168 el
[1].values
= &vals
[1];
169 vals
[1].data
= (uint8_t *)talloc_asprintf(tmp_ctx
, "%s@other.example.com", name
);
170 vals
[1].length
= strlen((char *)vals
[1].data
);
172 el
[2].flags
= LDB_FLAG_MOD_REPLACE
;
173 el
[2].name
= talloc_strdup(tmp_ctx
, "mail");
174 el
[2].num_values
= 1;
175 el
[2].values
= &vals
[2];
176 vals
[2].data
= (uint8_t *)talloc_asprintf(tmp_ctx
, "%s@other2.example.com", name
);
177 vals
[2].length
= strlen((char *)vals
[2].data
);
179 if (ldb_modify(ldb
, &msg
) != 0) {
180 printf("Modify of %s failed - %s\n", name
, ldb_errstring(ldb
));
184 printf("Modifying uid %s\r", name
);
187 talloc_free(tmp_ctx
);
194 static void delete_records(struct ldb_context
*ldb
,
195 struct ldb_dn
*basedn
,
200 for (i
=0;i
<count
;i
++) {
202 char *name
= talloc_asprintf(ldb
, "Test%d", i
);
203 dn
= ldb_dn_copy(name
, basedn
);
204 ldb_dn_add_child_fmt(dn
, "cn=%s", name
);
206 printf("Deleting uid Test%d\r", i
);
209 if (ldb_delete(ldb
, dn
) != 0) {
210 printf("Delete of %s failed - %s\n", ldb_dn_get_linearized(dn
), ldb_errstring(ldb
));
219 static void search_uid(struct ldb_context
*ldb
, struct ldb_dn
*basedn
, int nrecords
, int nsearches
)
223 for (i
=0;i
<nsearches
;i
++) {
224 int uid
= (i
* 700 + 17) % (nrecords
* 2);
226 struct ldb_result
*res
= NULL
;
229 expr
= talloc_asprintf(ldb
, "(uid=TEST%d)", uid
);
230 ret
= ldb_search(ldb
, ldb
, &res
, basedn
, LDB_SCOPE_SUBTREE
, NULL
, "%s", expr
);
232 if (ret
!= LDB_SUCCESS
|| (uid
< nrecords
&& res
->count
!= 1)) {
233 printf("Failed to find %s - %s\n", expr
, ldb_errstring(ldb
));
237 if (uid
>= nrecords
&& res
->count
> 0) {
238 printf("Found %s !? - %d\n", expr
, ret
);
242 printf("testing uid %d/%d - %d \r", i
, uid
, res
->count
);
252 static void start_test(struct ldb_context
*ldb
, int nrecords
, int nsearches
)
254 struct ldb_dn
*basedn
;
256 basedn
= ldb_dn_new(ldb
, ldb
, options
->basedn
);
257 if ( ! ldb_dn_validate(basedn
)) {
258 printf("Invalid base DN\n");
262 printf("Adding %d records\n", nrecords
);
263 add_records(ldb
, basedn
, nrecords
);
265 printf("Starting search on uid\n");
267 search_uid(ldb
, basedn
, nrecords
, nsearches
);
268 printf("uid search took %.2f seconds\n", _end_timer());
270 printf("Modifying records\n");
271 modify_records(ldb
, basedn
, nrecords
);
273 printf("Deleting records\n");
274 delete_records(ldb
, basedn
, nrecords
);
279 2) Store an @indexlist record
281 3) Store a record that contains fields that should be index according
284 4) disconnection from database
286 5) connect to same database
288 6) search for record added in step 3 using a search key that should
291 static void start_test_index(struct ldb_context
**ldb
)
293 struct ldb_message
*msg
;
294 struct ldb_result
*res
= NULL
;
295 struct ldb_dn
*indexlist
;
296 struct ldb_dn
*basedn
;
299 const char *specials
;
301 specials
= getenv("LDB_SPECIALS");
302 if (specials
&& atoi(specials
) == 0) {
303 printf("LDB_SPECIALS disabled - skipping index test\n");
307 if (options
->nosync
) {
308 flags
|= LDB_FLG_NOSYNC
;
311 printf("Starting index test\n");
313 indexlist
= ldb_dn_new(*ldb
, *ldb
, "@INDEXLIST");
315 ldb_delete(*ldb
, indexlist
);
317 msg
= ldb_msg_new(NULL
);
320 ldb_msg_add_string(msg
, "@IDXATTR", strdup("uid"));
322 if (ldb_add(*ldb
, msg
) != 0) {
323 printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg
->dn
), ldb_errstring(*ldb
));
327 basedn
= ldb_dn_new(*ldb
, *ldb
, options
->basedn
);
329 memset(msg
, 0, sizeof(*msg
));
330 msg
->dn
= ldb_dn_copy(msg
, basedn
);
331 ldb_dn_add_child_fmt(msg
->dn
, "cn=test");
332 ldb_msg_add_string(msg
, "cn", strdup("test"));
333 ldb_msg_add_string(msg
, "sn", strdup("test"));
334 ldb_msg_add_string(msg
, "uid", strdup("test"));
335 ldb_msg_add_string(msg
, "objectClass", strdup("OpenLDAPperson"));
337 if (ldb_add(*ldb
, msg
) != 0) {
338 printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg
->dn
), ldb_errstring(*ldb
));
342 if (talloc_free(*ldb
) != 0) {
343 printf("failed to free/close ldb database");
347 (*ldb
) = ldb_init(options
, NULL
);
349 ret
= ldb_connect(*ldb
, options
->url
, flags
, NULL
);
351 printf("failed to connect to %s\n", options
->url
);
355 basedn
= ldb_dn_new(*ldb
, *ldb
, options
->basedn
);
357 ret
= ldb_search(*ldb
, *ldb
, &res
, basedn
, LDB_SCOPE_SUBTREE
, NULL
, "uid=test");
358 if (ret
!= LDB_SUCCESS
) {
359 printf("Search with (uid=test) filter failed!\n");
362 if(res
->count
!= 1) {
363 printf("Should have found 1 record - found %d\n", res
->count
);
367 indexlist
= ldb_dn_new(*ldb
, *ldb
, "@INDEXLIST");
369 if (ldb_delete(*ldb
, msg
->dn
) != 0 ||
370 ldb_delete(*ldb
, indexlist
) != 0) {
371 printf("cleanup failed - %s\n", ldb_errstring(*ldb
));
375 printf("Finished index test\n");
379 static void usage(void)
381 printf("Usage: ldbtest <options>\n");
382 printf("Options:\n");
383 printf(" -H ldb_url choose the database (or $LDB_URL)\n");
384 printf(" --num-records nrecords database size to use\n");
385 printf(" --num-searches nsearches number of searches to do\n");
387 printf("tests ldb API\n\n");
391 int main(int argc
, const char **argv
)
393 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
394 struct ldb_context
*ldb
;
396 ldb
= ldb_init(mem_ctx
, NULL
);
398 options
= ldb_cmdline_process(ldb
, argc
, argv
, usage
);
400 talloc_steal(mem_ctx
, options
);
402 if (options
->basedn
== NULL
) {
403 options
->basedn
= "ou=Ldb Test,ou=People,o=University of Michigan,c=TEST";
408 printf("Testing with num-records=%d and num-searches=%d\n",
409 options
->num_records
, options
->num_searches
);
411 start_test(ldb
, options
->num_records
, options
->num_searches
);
413 start_test_index(&ldb
);
415 talloc_free(mem_ctx
);