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 "ldb/include/includes.h"
36 #include "ldb/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 const 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_build_child(tmp_ctx
, "cn", name
, basedn
);
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
);
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 const 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_build_child(tmp_ctx
, "cn", name
, basedn
);
157 msg
.num_elements
= 3;
160 el
[0].flags
= LDB_FLAG_MOD_DELETE
;
161 el
[0].name
= talloc_strdup(tmp_ctx
, "mail");
162 el
[0].num_values
= 0;
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
);
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
);
178 if (ldb_modify(ldb
, &msg
) != 0) {
179 printf("Modify of %s failed - %s\n", name
, ldb_errstring(ldb
));
183 printf("Modifying uid %s\r", name
);
186 talloc_free(tmp_ctx
);
193 static void delete_records(struct ldb_context
*ldb
,
194 const struct ldb_dn
*basedn
,
199 for (i
=0;i
<count
;i
++) {
201 char *name
= talloc_asprintf(ldb
, "Test%d", i
);
202 dn
= ldb_dn_build_child(name
, "cn", name
, basedn
);
204 printf("Deleting uid Test%d\r", i
);
207 if (ldb_delete(ldb
, dn
) != 0) {
208 printf("Delete of %s failed - %s\n", ldb_dn_linearize(ldb
, dn
), ldb_errstring(ldb
));
217 static void search_uid(struct ldb_context
*ldb
, struct ldb_dn
*basedn
, int nrecords
, int nsearches
)
221 for (i
=0;i
<nsearches
;i
++) {
222 int uid
= (i
* 700 + 17) % (nrecords
* 2);
224 struct ldb_result
*res
= NULL
;
227 expr
= talloc_asprintf(ldb
, "(uid=TEST%d)", uid
);
228 ret
= ldb_search(ldb
, basedn
, LDB_SCOPE_SUBTREE
, expr
, NULL
, &res
);
230 if (ret
!= LDB_SUCCESS
|| (uid
< nrecords
&& res
->count
!= 1)) {
231 printf("Failed to find %s - %s\n", expr
, ldb_errstring(ldb
));
235 if (uid
>= nrecords
&& res
->count
> 0) {
236 printf("Found %s !? - %d\n", expr
, ret
);
240 printf("testing uid %d/%d - %d \r", i
, uid
, res
->count
);
250 static void start_test(struct ldb_context
*ldb
, int nrecords
, int nsearches
)
252 struct ldb_dn
*basedn
;
254 basedn
= ldb_dn_explode(ldb
, options
->basedn
);
256 printf("Adding %d records\n", nrecords
);
257 add_records(ldb
, basedn
, nrecords
);
259 printf("Starting search on uid\n");
261 search_uid(ldb
, basedn
, nrecords
, nsearches
);
262 printf("uid search took %.2f seconds\n", _end_timer());
264 printf("Modifying records\n");
265 modify_records(ldb
, basedn
, nrecords
);
267 printf("Deleting records\n");
268 delete_records(ldb
, basedn
, nrecords
);
273 2) Store an @indexlist record
275 3) Store a record that contains fields that should be index according
278 4) disconnection from database
280 5) connect to same database
282 6) search for record added in step 3 using a search key that should
285 static void start_test_index(struct ldb_context
**ldb
)
287 struct ldb_message
*msg
;
288 struct ldb_result
*res
= NULL
;
289 struct ldb_dn
*indexlist
;
290 struct ldb_dn
*basedn
;
293 const char *specials
;
295 specials
= getenv("LDB_SPECIALS");
296 if (specials
&& atoi(specials
) == 0) {
297 printf("LDB_SPECIALS disabled - skipping index test\n");
301 if (options
->nosync
) {
302 flags
|= LDB_FLG_NOSYNC
;
305 printf("Starting index test\n");
307 indexlist
= ldb_dn_explode(NULL
, "@INDEXLIST");
309 ldb_delete(*ldb
, indexlist
);
311 msg
= ldb_msg_new(NULL
);
314 ldb_msg_add_string(msg
, "@IDXATTR", strdup("uid"));
316 if (ldb_add(*ldb
, msg
) != 0) {
317 printf("Add of %s failed - %s\n", ldb_dn_linearize(*ldb
, msg
->dn
), ldb_errstring(*ldb
));
321 basedn
= ldb_dn_explode(NULL
, options
->basedn
);
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"));
330 if (ldb_add(*ldb
, msg
) != 0) {
331 printf("Add of %s failed - %s\n", ldb_dn_linearize(*ldb
, msg
->dn
), ldb_errstring(*ldb
));
335 if (talloc_free(*ldb
) != 0) {
336 printf("failed to free/close ldb database");
340 (*ldb
) = ldb_init(options
);
342 ret
= ldb_connect(*ldb
, options
->url
, flags
, NULL
);
344 printf("failed to connect to %s\n", options
->url
);
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");
353 if(res
->count
!= 1) {
354 printf("Should have found 1 record - found %d\n", res
->count
);
358 if (ldb_delete(*ldb
, msg
->dn
) != 0 ||
359 ldb_delete(*ldb
, indexlist
) != 0) {
360 printf("cleanup failed - %s\n", ldb_errstring(*ldb
));
364 printf("Finished index test\n");
368 static void usage(void)
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");
376 printf("tests ldb API\n\n");
380 int main(int argc
, const char **argv
)
382 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
383 struct ldb_context
*ldb
;
387 ldb
= ldb_init(mem_ctx
);
389 options
= ldb_cmdline_process(ldb
, argc
, argv
, usage
);
391 talloc_steal(mem_ctx
, options
);
393 if (options
->basedn
== NULL
) {
394 options
->basedn
= "ou=Ldb Test,ou=People,o=University of Michigan,c=TEST";
399 printf("Testing with num-records=%d and num-searches=%d\n",
400 options
->num_records
, options
->num_searches
);
402 start_test(ldb
, options
->num_records
, options
->num_searches
);
404 start_test_index(&ldb
);
406 talloc_free(mem_ctx
);