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
34 #include "ldb_includes.h"
36 #include "tools/cmdline.h"
38 static struct timeval tp1
,tp2
;
39 static struct ldb_cmdline
*options
;
41 static void _start_timer(void)
43 gettimeofday(&tp1
,NULL
);
46 static double _end_timer(void)
48 gettimeofday(&tp2
,NULL
);
49 return((tp2
.tv_sec
- tp1
.tv_sec
) +
50 (tp2
.tv_usec
- tp1
.tv_usec
)*1.0e-6);
53 static void add_records(struct ldb_context
*ldb
,
54 struct ldb_dn
*basedn
,
57 struct ldb_message msg
;
61 if (ldb_lock(ldb
, "transaction") != 0) {
62 printf("transaction lock failed\n");
66 for (i
=0;i
<count
;i
++) {
67 struct ldb_message_element el
[6];
68 struct ldb_val vals
[6][1];
70 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
72 name
= talloc_asprintf(tmp_ctx
, "Test%d", i
);
74 msg
.dn
= ldb_dn_copy(tmp_ctx
, basedn
);
75 ldb_dn_add_child_fmt(msg
.dn
, "cn=%s", name
);
80 el
[0].name
= talloc_strdup(tmp_ctx
, "cn");
82 el
[0].values
= vals
[0];
83 vals
[0][0].data
= (uint8_t *)name
;
84 vals
[0][0].length
= strlen(name
);
89 el
[1].values
= vals
[1];
90 vals
[1][0].data
= (uint8_t *)talloc_asprintf(tmp_ctx
, "The title of %s", name
);
91 vals
[1][0].length
= strlen((char *)vals
[1][0].data
);
94 el
[2].name
= talloc_strdup(tmp_ctx
, "uid");
96 el
[2].values
= vals
[2];
97 vals
[2][0].data
= (uint8_t *)ldb_casefold(ldb
, tmp_ctx
, name
, strlen(name
));
98 vals
[2][0].length
= strlen((char *)vals
[2][0].data
);
101 el
[3].name
= talloc_strdup(tmp_ctx
, "mail");
102 el
[3].num_values
= 1;
103 el
[3].values
= vals
[3];
104 vals
[3][0].data
= (uint8_t *)talloc_asprintf(tmp_ctx
, "%s@example.com", name
);
105 vals
[3][0].length
= strlen((char *)vals
[3][0].data
);
108 el
[4].name
= talloc_strdup(tmp_ctx
, "objectClass");
109 el
[4].num_values
= 1;
110 el
[4].values
= vals
[4];
111 vals
[4][0].data
= (uint8_t *)talloc_strdup(tmp_ctx
, "OpenLDAPperson");
112 vals
[4][0].length
= strlen((char *)vals
[4][0].data
);
115 el
[5].name
= talloc_strdup(tmp_ctx
, "sn");
116 el
[5].num_values
= 1;
117 el
[5].values
= vals
[5];
118 vals
[5][0].data
= (uint8_t *)name
;
119 vals
[5][0].length
= strlen((char *)vals
[5][0].data
);
121 ldb_delete(ldb
, msg
.dn
);
123 if (ldb_add(ldb
, &msg
) != 0) {
124 printf("Add of %s failed - %s\n", name
, ldb_errstring(ldb
));
128 printf("adding uid %s\r", name
);
131 talloc_free(tmp_ctx
);
134 if (ldb_unlock(ldb
, "transaction") != 0) {
135 printf("transaction unlock failed\n");
142 static void modify_records(struct ldb_context
*ldb
,
143 struct ldb_dn
*basedn
,
146 struct ldb_message msg
;
149 for (i
=0;i
<count
;i
++) {
150 struct ldb_message_element el
[3];
151 struct ldb_val vals
[3];
153 TALLOC_CTX
*tmp_ctx
= talloc_new(ldb
);
155 name
= talloc_asprintf(tmp_ctx
, "Test%d", i
);
156 msg
.dn
= ldb_dn_copy(tmp_ctx
, basedn
);
157 ldb_dn_add_child_fmt(msg
.dn
, "cn=%s", name
);
159 msg
.num_elements
= 3;
162 el
[0].flags
= LDB_FLAG_MOD_DELETE
;
163 el
[0].name
= talloc_strdup(tmp_ctx
, "mail");
164 el
[0].num_values
= 0;
166 el
[1].flags
= LDB_FLAG_MOD_ADD
;
167 el
[1].name
= talloc_strdup(tmp_ctx
, "mail");
168 el
[1].num_values
= 1;
169 el
[1].values
= &vals
[1];
170 vals
[1].data
= (uint8_t *)talloc_asprintf(tmp_ctx
, "%s@other.example.com", name
);
171 vals
[1].length
= strlen((char *)vals
[1].data
);
173 el
[2].flags
= LDB_FLAG_MOD_REPLACE
;
174 el
[2].name
= talloc_strdup(tmp_ctx
, "mail");
175 el
[2].num_values
= 1;
176 el
[2].values
= &vals
[2];
177 vals
[2].data
= (uint8_t *)talloc_asprintf(tmp_ctx
, "%s@other2.example.com", name
);
178 vals
[2].length
= strlen((char *)vals
[2].data
);
180 if (ldb_modify(ldb
, &msg
) != 0) {
181 printf("Modify of %s failed - %s\n", name
, ldb_errstring(ldb
));
185 printf("Modifying uid %s\r", name
);
188 talloc_free(tmp_ctx
);
195 static void delete_records(struct ldb_context
*ldb
,
196 struct ldb_dn
*basedn
,
201 for (i
=0;i
<count
;i
++) {
203 char *name
= talloc_asprintf(ldb
, "Test%d", i
);
204 dn
= ldb_dn_copy(name
, basedn
);
205 ldb_dn_add_child_fmt(dn
, "cn=%s", name
);
207 printf("Deleting uid Test%d\r", i
);
210 if (ldb_delete(ldb
, dn
) != 0) {
211 printf("Delete of %s failed - %s\n", ldb_dn_get_linearized(dn
), ldb_errstring(ldb
));
220 static void search_uid(struct ldb_context
*ldb
, struct ldb_dn
*basedn
,
221 unsigned int nrecords
, unsigned int nsearches
)
225 for (i
=0;i
<nsearches
;i
++) {
226 int uid
= (i
* 700 + 17) % (nrecords
* 2);
228 struct ldb_result
*res
= NULL
;
231 expr
= talloc_asprintf(ldb
, "(uid=TEST%d)", uid
);
232 ret
= ldb_search(ldb
, ldb
, &res
, basedn
, LDB_SCOPE_SUBTREE
, NULL
, "%s", expr
);
234 if (ret
!= LDB_SUCCESS
|| (uid
< nrecords
&& res
->count
!= 1)) {
235 printf("Failed to find %s - %s\n", expr
, ldb_errstring(ldb
));
239 if (uid
>= nrecords
&& res
->count
> 0) {
240 printf("Found %s !? - %d\n", expr
, ret
);
244 printf("testing uid %d/%d - %d \r", i
, uid
, res
->count
);
254 static void start_test(struct ldb_context
*ldb
, unsigned int nrecords
,
255 unsigned int nsearches
)
257 struct ldb_dn
*basedn
;
259 basedn
= ldb_dn_new(ldb
, ldb
, options
->basedn
);
260 if ( ! ldb_dn_validate(basedn
)) {
261 printf("Invalid base DN\n");
265 printf("Adding %d records\n", nrecords
);
266 add_records(ldb
, basedn
, nrecords
);
268 printf("Starting search on uid\n");
270 search_uid(ldb
, basedn
, nrecords
, nsearches
);
271 printf("uid search took %.2f seconds\n", _end_timer());
273 printf("Modifying records\n");
274 modify_records(ldb
, basedn
, nrecords
);
276 printf("Deleting records\n");
277 delete_records(ldb
, basedn
, nrecords
);
282 2) Store an @indexlist record
284 3) Store a record that contains fields that should be index according
287 4) disconnection from database
289 5) connect to same database
291 6) search for record added in step 3 using a search key that should
294 static void start_test_index(struct ldb_context
**ldb
)
296 struct ldb_message
*msg
;
297 struct ldb_result
*res
= NULL
;
298 struct ldb_dn
*indexlist
;
299 struct ldb_dn
*basedn
;
302 const char *specials
;
304 specials
= getenv("LDB_SPECIALS");
305 if (specials
&& atoi(specials
) == 0) {
306 printf("LDB_SPECIALS disabled - skipping index test\n");
310 if (options
->nosync
) {
311 flags
|= LDB_FLG_NOSYNC
;
314 printf("Starting index test\n");
316 indexlist
= ldb_dn_new(*ldb
, *ldb
, "@INDEXLIST");
318 ldb_delete(*ldb
, indexlist
);
320 msg
= ldb_msg_new(NULL
);
323 ldb_msg_add_string(msg
, "@IDXATTR", strdup("uid"));
325 if (ldb_add(*ldb
, msg
) != 0) {
326 printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg
->dn
), ldb_errstring(*ldb
));
330 basedn
= ldb_dn_new(*ldb
, *ldb
, options
->basedn
);
332 memset(msg
, 0, sizeof(*msg
));
333 msg
->dn
= ldb_dn_copy(msg
, basedn
);
334 ldb_dn_add_child_fmt(msg
->dn
, "cn=test");
335 ldb_msg_add_string(msg
, "cn", strdup("test"));
336 ldb_msg_add_string(msg
, "sn", strdup("test"));
337 ldb_msg_add_string(msg
, "uid", strdup("test"));
338 ldb_msg_add_string(msg
, "objectClass", strdup("OpenLDAPperson"));
340 if (ldb_add(*ldb
, msg
) != 0) {
341 printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg
->dn
), ldb_errstring(*ldb
));
345 if (talloc_free(*ldb
) != 0) {
346 printf("failed to free/close ldb database");
350 (*ldb
) = ldb_init(options
, NULL
);
352 ret
= ldb_connect(*ldb
, options
->url
, flags
, NULL
);
354 printf("failed to connect to %s\n", options
->url
);
358 basedn
= ldb_dn_new(*ldb
, *ldb
, options
->basedn
);
360 ldb_dn_add_child_fmt(msg
->dn
, "cn=test");
362 ret
= ldb_search(*ldb
, *ldb
, &res
, basedn
, LDB_SCOPE_SUBTREE
, NULL
, "uid=test");
363 if (ret
!= LDB_SUCCESS
) {
364 printf("Search with (uid=test) filter failed!\n");
367 if(res
->count
!= 1) {
368 printf("Should have found 1 record - found %d\n", res
->count
);
372 indexlist
= ldb_dn_new(*ldb
, *ldb
, "@INDEXLIST");
374 if (ldb_delete(*ldb
, msg
->dn
) != 0 ||
375 ldb_delete(*ldb
, indexlist
) != 0) {
376 printf("cleanup failed - %s\n", ldb_errstring(*ldb
));
380 printf("Finished index test\n");
384 static void usage(void)
386 printf("Usage: ldbtest <options>\n");
387 printf("Options:\n");
388 printf(" -H ldb_url choose the database (or $LDB_URL)\n");
389 printf(" --num-records nrecords database size to use\n");
390 printf(" --num-searches nsearches number of searches to do\n");
392 printf("tests ldb API\n\n");
396 int main(int argc
, const char **argv
)
398 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
399 struct ldb_context
*ldb
;
401 ldb
= ldb_init(mem_ctx
, NULL
);
403 options
= ldb_cmdline_process(ldb
, argc
, argv
, usage
);
405 talloc_steal(mem_ctx
, options
);
407 if (options
->basedn
== NULL
) {
408 options
->basedn
= "ou=Ldb Test,ou=People,o=University of Michigan,c=TEST";
413 printf("Testing with num-records=%d and num-searches=%d\n",
414 options
->num_records
, options
->num_searches
);
417 (unsigned int) options
->num_records
,
418 (unsigned int) options
->num_searches
);
420 start_test_index(&ldb
);
422 talloc_free(mem_ctx
);