~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/lib/ldb/tools/ldbtest.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "ldb_includes.h"
 
35
#include "ldb.h"
 
36
#include "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
                        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_copy(tmp_ctx, basedn);
 
75
                ldb_dn_add_child_fmt(msg.dn, "cn=%s", name);
 
76
                msg.num_elements = 6;
 
77
                msg.elements = el;
 
78
 
 
79
                el[0].flags = 0;
 
80
                el[0].name = talloc_strdup(tmp_ctx, "cn");
 
81
                el[0].num_values = 1;
 
82
                el[0].values = vals[0];
 
83
                vals[0][0].data = (uint8_t *)name;
 
84
                vals[0][0].length = strlen(name);
 
85
 
 
86
                el[1].flags = 0;
 
87
                el[1].name = "title";
 
88
                el[1].num_values = 1;
 
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);
 
92
 
 
93
                el[2].flags = 0;
 
94
                el[2].name = talloc_strdup(tmp_ctx, "uid");
 
95
                el[2].num_values = 1;
 
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);
 
99
 
 
100
                el[3].flags = 0;
 
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);
 
106
 
 
107
                el[4].flags = 0;
 
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);
 
113
 
 
114
                el[5].flags = 0;
 
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);
 
120
 
 
121
                ldb_delete(ldb, msg.dn);
 
122
 
 
123
                if (ldb_add(ldb, &msg) != 0) {
 
124
                        printf("Add of %s failed - %s\n", name, ldb_errstring(ldb));
 
125
                        exit(1);
 
126
                }
 
127
 
 
128
                printf("adding uid %s\r", name);
 
129
                fflush(stdout);
 
130
 
 
131
                talloc_free(tmp_ctx);
 
132
        }
 
133
#if 0
 
134
        if (ldb_unlock(ldb, "transaction") != 0) {
 
135
                printf("transaction unlock failed\n");
 
136
                exit(1);
 
137
        }
 
138
#endif
 
139
        printf("\n");
 
140
}
 
141
 
 
142
static void modify_records(struct ldb_context *ldb,
 
143
                           struct ldb_dn *basedn,
 
144
                           int count)
 
145
{
 
146
        struct ldb_message msg;
 
147
        int i;
 
148
 
 
149
        for (i=0;i<count;i++) {
 
150
                struct ldb_message_element el[3];
 
151
                struct ldb_val vals[3];
 
152
                char *name;
 
153
                TALLOC_CTX *tmp_ctx = talloc_new(ldb);
 
154
                
 
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);
 
158
 
 
159
                msg.num_elements = 3;
 
160
                msg.elements = el;
 
161
 
 
162
                el[0].flags = LDB_FLAG_MOD_DELETE;
 
163
                el[0].name = talloc_strdup(tmp_ctx, "mail");
 
164
                el[0].num_values = 0;
 
165
 
 
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);
 
172
 
 
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);
 
179
 
 
180
                if (ldb_modify(ldb, &msg) != 0) {
 
181
                        printf("Modify of %s failed - %s\n", name, ldb_errstring(ldb));
 
182
                        exit(1);
 
183
                }
 
184
 
 
185
                printf("Modifying uid %s\r", name);
 
186
                fflush(stdout);
 
187
 
 
188
                talloc_free(tmp_ctx);
 
189
        }
 
190
 
 
191
        printf("\n");
 
192
}
 
193
 
 
194
 
 
195
static void delete_records(struct ldb_context *ldb,
 
196
                           struct ldb_dn *basedn,
 
197
                           int count)
 
198
{
 
199
        int i;
 
200
 
 
201
        for (i=0;i<count;i++) {
 
202
                struct ldb_dn *dn;
 
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);
 
206
 
 
207
                printf("Deleting uid Test%d\r", i);
 
208
                fflush(stdout);
 
209
 
 
210
                if (ldb_delete(ldb, dn) != 0) {
 
211
                        printf("Delete of %s failed - %s\n", ldb_dn_get_linearized(dn), ldb_errstring(ldb));
 
212
                        exit(1);
 
213
                }
 
214
                talloc_free(name);
 
215
        }
 
216
 
 
217
        printf("\n");
 
218
}
 
219
 
 
220
static void search_uid(struct ldb_context *ldb, struct ldb_dn *basedn, int nrecords, int nsearches)
 
221
{
 
222
        int i;
 
223
 
 
224
        for (i=0;i<nsearches;i++) {
 
225
                int uid = (i * 700 + 17) % (nrecords * 2);
 
226
                char *expr;
 
227
                struct ldb_result *res = NULL;
 
228
                int ret;
 
229
 
 
230
                expr = talloc_asprintf(ldb, "(uid=TEST%d)", uid);
 
231
                ret = ldb_search(ldb, ldb, &res, basedn, LDB_SCOPE_SUBTREE, NULL, "%s", expr);
 
232
 
 
233
                if (ret != LDB_SUCCESS || (uid < nrecords && res->count != 1)) {
 
234
                        printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb));
 
235
                        exit(1);
 
236
                }
 
237
 
 
238
                if (uid >= nrecords && res->count > 0) {
 
239
                        printf("Found %s !? - %d\n", expr, ret);
 
240
                        exit(1);
 
241
                }
 
242
 
 
243
                printf("testing uid %d/%d - %d  \r", i, uid, res->count);
 
244
                fflush(stdout);
 
245
 
 
246
                talloc_free(res);
 
247
                talloc_free(expr);
 
248
        }
 
249
 
 
250
        printf("\n");
 
251
}
 
252
 
 
253
static void start_test(struct ldb_context *ldb, int nrecords, int nsearches)
 
254
{
 
255
        struct ldb_dn *basedn;
 
256
 
 
257
        basedn = ldb_dn_new(ldb, ldb, options->basedn);
 
258
        if ( ! ldb_dn_validate(basedn)) {
 
259
                printf("Invalid base DN\n");
 
260
                exit(1);
 
261
        }
 
262
 
 
263
        printf("Adding %d records\n", nrecords);
 
264
        add_records(ldb, basedn, nrecords);
 
265
 
 
266
        printf("Starting search on uid\n");
 
267
        _start_timer();
 
268
        search_uid(ldb, basedn, nrecords, nsearches);
 
269
        printf("uid search took %.2f seconds\n", _end_timer());
 
270
 
 
271
        printf("Modifying records\n");
 
272
        modify_records(ldb, basedn, nrecords);
 
273
 
 
274
        printf("Deleting records\n");
 
275
        delete_records(ldb, basedn, nrecords);
 
276
}
 
277
 
 
278
 
 
279
/*
 
280
      2) Store an @indexlist record
 
281
 
 
282
      3) Store a record that contains fields that should be index according
 
283
to @index
 
284
 
 
285
      4) disconnection from database
 
286
 
 
287
      5) connect to same database
 
288
 
 
289
      6) search for record added in step 3 using a search key that should
 
290
be indexed
 
291
*/
 
292
static void start_test_index(struct ldb_context **ldb)
 
293
{
 
294
        struct ldb_message *msg;
 
295
        struct ldb_result *res = NULL;
 
296
        struct ldb_dn *indexlist;
 
297
        struct ldb_dn *basedn;
 
298
        int ret;
 
299
        int flags = 0;
 
300
        const char *specials;
 
301
 
 
302
        specials = getenv("LDB_SPECIALS");
 
303
        if (specials && atoi(specials) == 0) {
 
304
                printf("LDB_SPECIALS disabled - skipping index test\n");
 
305
                return;
 
306
        }
 
307
 
 
308
        if (options->nosync) {
 
309
                flags |= LDB_FLG_NOSYNC;
 
310
        }
 
311
 
 
312
        printf("Starting index test\n");
 
313
 
 
314
        indexlist = ldb_dn_new(*ldb, *ldb, "@INDEXLIST");
 
315
 
 
316
        ldb_delete(*ldb, indexlist);
 
317
 
 
318
        msg = ldb_msg_new(NULL);
 
319
 
 
320
        msg->dn = indexlist;
 
321
        ldb_msg_add_string(msg, "@IDXATTR", strdup("uid"));
 
322
 
 
323
        if (ldb_add(*ldb, msg) != 0) {
 
324
                printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb));
 
325
                exit(1);
 
326
        }
 
327
 
 
328
        basedn = ldb_dn_new(*ldb, *ldb, options->basedn);
 
329
 
 
330
        memset(msg, 0, sizeof(*msg));
 
331
        msg->dn = ldb_dn_copy(msg, basedn);
 
332
        ldb_dn_add_child_fmt(msg->dn, "cn=test");
 
333
        ldb_msg_add_string(msg, "cn", strdup("test"));
 
334
        ldb_msg_add_string(msg, "sn", strdup("test"));
 
335
        ldb_msg_add_string(msg, "uid", strdup("test"));
 
336
        ldb_msg_add_string(msg, "objectClass", strdup("OpenLDAPperson"));
 
337
 
 
338
        if (ldb_add(*ldb, msg) != 0) {
 
339
                printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb));
 
340
                exit(1);
 
341
        }
 
342
 
 
343
        if (talloc_free(*ldb) != 0) {
 
344
                printf("failed to free/close ldb database");
 
345
                exit(1);
 
346
        }
 
347
 
 
348
        (*ldb) = ldb_init(options, NULL);
 
349
 
 
350
        ret = ldb_connect(*ldb, options->url, flags, NULL);
 
351
        if (ret != 0) {
 
352
                printf("failed to connect to %s\n", options->url);
 
353
                exit(1);
 
354
        }
 
355
 
 
356
        basedn = ldb_dn_new(*ldb, *ldb, options->basedn);
 
357
 
 
358
        ret = ldb_search(*ldb, *ldb, &res, basedn, LDB_SCOPE_SUBTREE, NULL, "uid=test");
 
359
        if (ret != LDB_SUCCESS) { 
 
360
                printf("Search with (uid=test) filter failed!\n");
 
361
                exit(1);
 
362
        }
 
363
        if(res->count != 1) {
 
364
                printf("Should have found 1 record - found %d\n", res->count);
 
365
                exit(1);
 
366
        }
 
367
 
 
368
        indexlist = ldb_dn_new(*ldb, *ldb, "@INDEXLIST");
 
369
 
 
370
        if (ldb_delete(*ldb, msg->dn) != 0 ||
 
371
            ldb_delete(*ldb, indexlist) != 0) {
 
372
                printf("cleanup failed - %s\n", ldb_errstring(*ldb));
 
373
                exit(1);
 
374
        }
 
375
 
 
376
        printf("Finished index test\n");
 
377
}
 
378
 
 
379
 
 
380
static void usage(void)
 
381
{
 
382
        printf("Usage: ldbtest <options>\n");
 
383
        printf("Options:\n");
 
384
        printf("  -H ldb_url       choose the database (or $LDB_URL)\n");
 
385
        printf("  --num-records  nrecords      database size to use\n");
 
386
        printf("  --num-searches nsearches     number of searches to do\n");
 
387
        printf("\n");
 
388
        printf("tests ldb API\n\n");
 
389
        exit(1);
 
390
}
 
391
 
 
392
int main(int argc, const char **argv)
 
393
{
 
394
        TALLOC_CTX *mem_ctx = talloc_new(NULL);
 
395
        struct ldb_context *ldb;
 
396
 
 
397
        ldb = ldb_init(mem_ctx, NULL);
 
398
 
 
399
        options = ldb_cmdline_process(ldb, argc, argv, usage);
 
400
 
 
401
        talloc_steal(mem_ctx, options);
 
402
 
 
403
        if (options->basedn == NULL) {
 
404
                options->basedn = "ou=Ldb Test,ou=People,o=University of Michigan,c=TEST";
 
405
        }
 
406
 
 
407
        srandom(1);
 
408
 
 
409
        printf("Testing with num-records=%d and num-searches=%d\n", 
 
410
               options->num_records, options->num_searches);
 
411
 
 
412
        start_test(ldb, options->num_records, options->num_searches);
 
413
 
 
414
        start_test_index(&ldb);
 
415
 
 
416
        talloc_free(mem_ctx);
 
417
 
 
418
        return 0;
 
419
}