Line data Source code
1 : /*
2 : * from cmocka.c:
3 : * These headers or their equivalents should be included prior to
4 : * including
5 : * this header file.
6 : *
7 : * #include <stdarg.h>
8 : * #include <stddef.h>
9 : * #include <setjmp.h>
10 : *
11 : * This allows test applications to use custom definitions of C standard
12 : * library functions and types.
13 : */
14 : #include <stdarg.h>
15 : #include <stddef.h>
16 : #include <stdint.h>
17 : #include <setjmp.h>
18 : #include <cmocka.h>
19 :
20 : #include <errno.h>
21 : #include <unistd.h>
22 : #include <talloc.h>
23 :
24 : #define TEVENT_DEPRECATED 1
25 : #include <tevent.h>
26 :
27 : #include <ldb.h>
28 : #include <ldb_module.h>
29 : #include <ldb_private.h>
30 : #include <string.h>
31 : #include <ctype.h>
32 :
33 : #include <sys/wait.h>
34 :
35 :
36 : #define DEFAULT_BE "tdb"
37 :
38 : #ifndef TEST_BE
39 : #define TEST_BE DEFAULT_BE
40 : #endif /* TEST_BE */
41 :
42 : #ifdef TEST_LMDB
43 : #include "lmdb.h"
44 : #include "../ldb_tdb/ldb_tdb.h"
45 : #include "../ldb_mdb/ldb_mdb.h"
46 : #endif
47 :
48 : struct ldbtest_ctx {
49 : struct tevent_context *ev;
50 : struct ldb_context *ldb;
51 :
52 : const char *dbfile;
53 : const char *lockfile; /* lockfile is separate */
54 :
55 : const char *dbpath;
56 : char *debug_string;
57 : };
58 :
59 356 : static void unlink_old_db(struct ldbtest_ctx *test_ctx)
60 : {
61 356 : int ret;
62 :
63 356 : errno = 0;
64 356 : ret = unlink(test_ctx->lockfile);
65 356 : if (ret == -1 && errno != ENOENT) {
66 0 : fail();
67 : }
68 :
69 356 : errno = 0;
70 356 : ret = unlink(test_ctx->dbfile);
71 356 : if (ret == -1 && errno != ENOENT) {
72 0 : fail();
73 : }
74 356 : }
75 :
76 178 : static int ldbtest_noconn_setup(void **state)
77 : {
78 178 : struct ldbtest_ctx *test_ctx;
79 :
80 178 : test_ctx = talloc_zero(NULL, struct ldbtest_ctx);
81 178 : assert_non_null(test_ctx);
82 :
83 178 : test_ctx->ev = tevent_context_init(test_ctx);
84 178 : assert_non_null(test_ctx->ev);
85 :
86 178 : test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
87 178 : assert_non_null(test_ctx->ldb);
88 :
89 178 : test_ctx->dbfile = talloc_strdup(test_ctx, "apitest.ldb");
90 178 : assert_non_null(test_ctx->dbfile);
91 :
92 178 : test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
93 : test_ctx->dbfile);
94 178 : assert_non_null(test_ctx->lockfile);
95 :
96 178 : test_ctx->dbpath = talloc_asprintf(test_ctx,
97 : TEST_BE"://%s", test_ctx->dbfile);
98 178 : assert_non_null(test_ctx->dbpath);
99 :
100 178 : unlink_old_db(test_ctx);
101 178 : *state = test_ctx;
102 178 : return 0;
103 : }
104 :
105 178 : static int ldbtest_noconn_teardown(void **state)
106 : {
107 178 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
108 : struct ldbtest_ctx);
109 :
110 178 : unlink_old_db(test_ctx);
111 178 : talloc_free(test_ctx);
112 178 : return 0;
113 : }
114 :
115 3 : static void test_connect(void **state)
116 : {
117 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
118 : struct ldbtest_ctx);
119 3 : int ret;
120 :
121 3 : ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
122 3 : assert_int_equal(ret, 0);
123 3 : }
124 :
125 3 : static struct ldb_message *get_test_ldb_message(TALLOC_CTX *mem_ctx,
126 : struct ldb_context *ldb)
127 : {
128 3 : struct ldb_message *msg = ldb_msg_new(mem_ctx);
129 3 : int ret;
130 3 : assert_non_null(msg);
131 :
132 3 : msg->dn = ldb_dn_new(msg, ldb, "dc=samba,dc=org");
133 3 : assert_non_null(msg->dn);
134 3 : ret = ldb_msg_add_string(msg, "public", "key");
135 3 : assert_int_equal(ret, LDB_SUCCESS);
136 3 : ret = ldb_msg_add_string(msg, "supersecret", "password");
137 3 : assert_int_equal(ret, LDB_SUCCESS);
138 3 : ret = ldb_msg_add_string(msg, "binary", "\xff\xff\0");
139 3 : assert_int_equal(ret, LDB_SUCCESS);
140 3 : return msg;
141 : }
142 :
143 3 : static void test_ldif_message(void **state)
144 : {
145 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
146 : struct ldbtest_ctx);
147 3 : char *got_ldif;
148 3 : const char *expected_ldif =
149 : "dn: dc=samba,dc=org\n"
150 : "changetype: add\n"
151 : "public: key\n"
152 : "supersecret: password\n"
153 : "binary:: //8=\n"
154 : "\n";
155 :
156 3 : struct ldb_message *msg = get_test_ldb_message(test_ctx,
157 : test_ctx->ldb);
158 :
159 3 : got_ldif = ldb_ldif_message_string(test_ctx->ldb,
160 : test_ctx,
161 : LDB_CHANGETYPE_ADD,
162 : msg);
163 3 : assert_string_equal(got_ldif, expected_ldif);
164 3 : TALLOC_FREE(got_ldif);
165 3 : }
166 :
167 3 : static void test_ldif_message_redacted(void **state)
168 : {
169 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
170 : struct ldbtest_ctx);
171 3 : int ret;
172 3 : char *got_ldif;
173 3 : const char *expected_ldif =
174 : "dn: dc=samba,dc=org\n"
175 : "changetype: add\n"
176 : "public: key\n"
177 : "# supersecret::: REDACTED SECRET ATTRIBUTE\n"
178 : "binary:: //8=\n"
179 : "\n";
180 :
181 3 : const char *secret_attrs[] = {
182 : "supersecret",
183 : NULL
184 : };
185 :
186 3 : struct ldb_message *msg = ldb_msg_new(test_ctx);
187 :
188 3 : ldb_set_opaque(test_ctx->ldb,
189 : LDB_SECRET_ATTRIBUTE_LIST_OPAQUE,
190 : secret_attrs);
191 :
192 3 : assert_non_null(msg);
193 :
194 3 : msg->dn = ldb_dn_new(msg, test_ctx->ldb, "dc=samba,dc=org");
195 3 : ret = ldb_msg_add_string(msg, "public", "key");
196 3 : assert_int_equal(ret, LDB_SUCCESS);
197 3 : ret = ldb_msg_add_string(msg, "supersecret", "password");
198 3 : assert_int_equal(ret, LDB_SUCCESS);
199 3 : ret = ldb_msg_add_string(msg, "binary", "\xff\xff\0");
200 3 : assert_int_equal(ret, LDB_SUCCESS);
201 3 : got_ldif = ldb_ldif_message_redacted_string(test_ctx->ldb,
202 : test_ctx,
203 : LDB_CHANGETYPE_ADD,
204 : msg);
205 3 : assert_string_equal(got_ldif, expected_ldif);
206 3 : TALLOC_FREE(got_ldif);
207 3 : assert_int_equal(ret, 0);
208 3 : }
209 :
210 145 : static int ldbtest_setup(void **state)
211 : {
212 145 : struct ldbtest_ctx *test_ctx;
213 145 : struct ldb_ldif *ldif;
214 : #ifdef GUID_IDX
215 97 : const char *index_ldif = \
216 : "dn: @INDEXLIST\n"
217 : "@IDXGUID: objectUUID\n"
218 : "@IDX_DN_GUID: GUID\n"
219 : "\n";
220 : #else
221 48 : const char *index_ldif = "\n";
222 : #endif
223 145 : int ret;
224 :
225 145 : ldbtest_noconn_setup((void **) &test_ctx);
226 :
227 145 : ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
228 145 : assert_int_equal(ret, 0);
229 :
230 242 : while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) {
231 97 : ret = ldb_add(test_ctx->ldb, ldif->msg);
232 97 : assert_int_equal(ret, LDB_SUCCESS);
233 : }
234 145 : *state = test_ctx;
235 145 : return 0;
236 : }
237 :
238 169 : static int ldbtest_teardown(void **state)
239 : {
240 169 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
241 : struct ldbtest_ctx);
242 169 : ldbtest_noconn_teardown((void **) &test_ctx);
243 169 : return 0;
244 : }
245 :
246 3 : static void test_ldb_add(void **state)
247 : {
248 3 : int ret;
249 3 : struct ldb_message *msg;
250 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
251 : struct ldbtest_ctx);
252 3 : TALLOC_CTX *tmp_ctx;
253 :
254 3 : tmp_ctx = talloc_new(test_ctx);
255 3 : assert_non_null(tmp_ctx);
256 :
257 3 : msg = ldb_msg_new(tmp_ctx);
258 3 : assert_non_null(msg);
259 :
260 3 : msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=test");
261 3 : assert_non_null(msg->dn);
262 :
263 3 : ret = ldb_msg_add_string(msg, "cn", "test_cn_val");
264 3 : assert_int_equal(ret, 0);
265 :
266 3 : ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcdef");
267 3 : assert_int_equal(ret, 0);
268 :
269 3 : ret = ldb_add(test_ctx->ldb, msg);
270 3 : assert_int_equal(ret, 0);
271 :
272 3 : talloc_free(tmp_ctx);
273 3 : }
274 :
275 3 : static void test_ldb_search(void **state)
276 : {
277 3 : int ret;
278 3 : struct ldb_message *msg;
279 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
280 : struct ldbtest_ctx);
281 3 : TALLOC_CTX *tmp_ctx;
282 3 : struct ldb_dn *basedn;
283 3 : struct ldb_dn *basedn2;
284 3 : struct ldb_result *result = NULL;
285 :
286 3 : tmp_ctx = talloc_new(test_ctx);
287 3 : assert_non_null(tmp_ctx);
288 :
289 3 : basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test");
290 3 : assert_non_null(basedn);
291 :
292 3 : ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn,
293 : LDB_SCOPE_BASE, NULL, NULL);
294 3 : assert_int_equal(ret, 0);
295 3 : assert_non_null(result);
296 3 : assert_int_equal(result->count, 0);
297 :
298 3 : msg = ldb_msg_new(tmp_ctx);
299 3 : assert_non_null(msg);
300 :
301 3 : msg->dn = basedn;
302 3 : assert_non_null(msg->dn);
303 :
304 3 : ret = ldb_msg_add_string(msg, "cn", "test_cn_val1");
305 3 : assert_int_equal(ret, 0);
306 :
307 3 : ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcde1");
308 3 : assert_int_equal(ret, 0);
309 :
310 3 : ret = ldb_add(test_ctx->ldb, msg);
311 3 : assert_int_equal(ret, 0);
312 :
313 3 : basedn2 = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test2");
314 3 : assert_non_null(basedn2);
315 :
316 3 : msg = ldb_msg_new(tmp_ctx);
317 3 : assert_non_null(msg);
318 :
319 3 : msg->dn = basedn2;
320 3 : assert_non_null(msg->dn);
321 :
322 3 : ret = ldb_msg_add_string(msg, "cn", "test_cn_val2");
323 3 : assert_int_equal(ret, 0);
324 :
325 3 : ret = ldb_msg_add_string(msg, "objectUUID", "0123456789abcde2");
326 3 : assert_int_equal(ret, 0);
327 :
328 3 : ret = ldb_add(test_ctx->ldb, msg);
329 3 : assert_int_equal(ret, 0);
330 :
331 3 : ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn,
332 : LDB_SCOPE_BASE, NULL, NULL);
333 3 : assert_int_equal(ret, 0);
334 3 : assert_non_null(result);
335 3 : assert_int_equal(result->count, 1);
336 3 : assert_string_equal(ldb_dn_get_linearized(result->msgs[0]->dn),
337 : ldb_dn_get_linearized(basedn));
338 :
339 3 : ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn2,
340 : LDB_SCOPE_BASE, NULL, NULL);
341 3 : assert_int_equal(ret, 0);
342 3 : assert_non_null(result);
343 3 : assert_int_equal(result->count, 1);
344 3 : assert_string_equal(ldb_dn_get_linearized(result->msgs[0]->dn),
345 : ldb_dn_get_linearized(basedn2));
346 :
347 3 : talloc_free(tmp_ctx);
348 3 : }
349 :
350 403 : static int base_search_count(struct ldbtest_ctx *test_ctx, const char *entry_dn)
351 : {
352 403 : TALLOC_CTX *tmp_ctx;
353 403 : struct ldb_dn *basedn;
354 403 : struct ldb_result *result = NULL;
355 403 : int ret;
356 403 : int count;
357 :
358 403 : tmp_ctx = talloc_new(test_ctx);
359 403 : assert_non_null(tmp_ctx);
360 :
361 403 : basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "%s", entry_dn);
362 403 : assert_non_null(basedn);
363 :
364 403 : ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn,
365 : LDB_SCOPE_BASE, NULL, NULL);
366 403 : assert_int_equal(ret, LDB_SUCCESS);
367 403 : assert_non_null(result);
368 :
369 403 : count = result->count;
370 403 : talloc_free(tmp_ctx);
371 403 : return count;
372 : }
373 :
374 33 : static int sub_search_count(struct ldbtest_ctx *test_ctx,
375 : const char *base_dn,
376 : const char *filter)
377 : {
378 33 : TALLOC_CTX *tmp_ctx;
379 33 : struct ldb_dn *basedn;
380 33 : struct ldb_result *result = NULL;
381 33 : int ret;
382 33 : int count;
383 :
384 33 : tmp_ctx = talloc_new(test_ctx);
385 33 : assert_non_null(tmp_ctx);
386 :
387 33 : basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "%s", base_dn);
388 33 : assert_non_null(basedn);
389 :
390 33 : ret = ldb_search(test_ctx->ldb, tmp_ctx, &result, basedn,
391 : LDB_SCOPE_SUBTREE, NULL, "%s", filter);
392 33 : assert_int_equal(ret, LDB_SUCCESS);
393 33 : assert_non_null(result);
394 :
395 33 : count = result->count;
396 33 : talloc_free(tmp_ctx);
397 33 : return count;
398 : }
399 :
400 : /* In general it would be better if utility test functions didn't assert
401 : * but only returned a value, then assert in the test shows correct
402 : * line
403 : */
404 39 : static void assert_dn_exists(struct ldbtest_ctx *test_ctx,
405 : const char *entry_dn)
406 : {
407 39 : int count;
408 :
409 39 : count = base_search_count(test_ctx, entry_dn);
410 39 : assert_int_equal(count, 1);
411 39 : }
412 :
413 102 : static void assert_dn_doesnt_exist(struct ldbtest_ctx *test_ctx,
414 : const char *entry_dn)
415 : {
416 102 : int count;
417 :
418 102 : count = base_search_count(test_ctx, entry_dn);
419 102 : assert_int_equal(count, 0);
420 102 : }
421 :
422 21 : static void add_dn_with_cn(struct ldbtest_ctx *test_ctx,
423 : struct ldb_dn *dn,
424 : const char *cn_value,
425 : const char *uuid_value)
426 : {
427 21 : int ret;
428 21 : TALLOC_CTX *tmp_ctx;
429 21 : struct ldb_message *msg;
430 :
431 21 : tmp_ctx = talloc_new(test_ctx);
432 21 : assert_non_null(tmp_ctx);
433 :
434 21 : assert_dn_doesnt_exist(test_ctx,
435 : ldb_dn_get_linearized(dn));
436 :
437 21 : msg = ldb_msg_new(tmp_ctx);
438 21 : assert_non_null(msg);
439 21 : msg->dn = dn;
440 :
441 21 : ret = ldb_msg_add_string(msg, "cn", cn_value);
442 21 : assert_int_equal(ret, LDB_SUCCESS);
443 :
444 21 : ret = ldb_msg_add_string(msg, "objectUUID", uuid_value);
445 21 : assert_int_equal(ret, 0);
446 :
447 21 : ret = ldb_add(test_ctx->ldb, msg);
448 21 : assert_int_equal(ret, LDB_SUCCESS);
449 :
450 21 : assert_dn_exists(test_ctx,
451 : ldb_dn_get_linearized(dn));
452 21 : talloc_free(tmp_ctx);
453 21 : }
454 :
455 3 : static void test_ldb_del(void **state)
456 : {
457 3 : int ret;
458 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
459 : struct ldbtest_ctx);
460 3 : const char *basedn = "dc=ldb_del_test";
461 3 : struct ldb_dn *dn;
462 :
463 3 : dn = ldb_dn_new_fmt(test_ctx, test_ctx->ldb, "%s", basedn);
464 3 : assert_non_null(dn);
465 :
466 3 : add_dn_with_cn(test_ctx, dn,
467 : "test_del_cn_val",
468 : "0123456789abcdef");
469 :
470 3 : ret = ldb_delete(test_ctx->ldb, dn);
471 3 : assert_int_equal(ret, LDB_SUCCESS);
472 :
473 3 : assert_dn_doesnt_exist(test_ctx, basedn);
474 3 : }
475 :
476 3 : static void test_ldb_del_noexist(void **state)
477 : {
478 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
479 : struct ldbtest_ctx);
480 3 : struct ldb_dn *basedn;
481 3 : int ret;
482 :
483 3 : basedn = ldb_dn_new(test_ctx, test_ctx->ldb, "dc=nosuchplace");
484 3 : assert_non_null(basedn);
485 :
486 3 : ret = ldb_delete(test_ctx->ldb, basedn);
487 3 : assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
488 3 : }
489 :
490 3 : static void test_ldb_handle(void **state)
491 : {
492 3 : int ret;
493 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
494 : struct ldbtest_ctx);
495 3 : TALLOC_CTX *tmp_ctx;
496 3 : struct ldb_dn *basedn;
497 3 : struct ldb_request *request = NULL;
498 3 : struct ldb_request *request2 = NULL;
499 3 : struct ldb_result *res = NULL;
500 3 : const char *attrs[] = { "cn", NULL };
501 :
502 3 : tmp_ctx = talloc_new(test_ctx);
503 3 : assert_non_null(tmp_ctx);
504 :
505 3 : basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test");
506 3 : assert_non_null(basedn);
507 :
508 3 : res = talloc_zero(tmp_ctx, struct ldb_result);
509 3 : assert_non_null(res);
510 :
511 3 : ret = ldb_build_search_req(&request, test_ctx->ldb, tmp_ctx,
512 : basedn, LDB_SCOPE_BASE,
513 : NULL, attrs, NULL, res,
514 : ldb_search_default_callback,
515 : NULL);
516 3 : assert_int_equal(ret, 0);
517 :
518 : /* We are against ldb_tdb, so expect private event contexts */
519 3 : assert_ptr_not_equal(ldb_handle_get_event_context(request->handle),
520 : ldb_get_event_context(test_ctx->ldb));
521 :
522 3 : ret = ldb_build_search_req(&request2, test_ctx->ldb, tmp_ctx,
523 : basedn, LDB_SCOPE_BASE,
524 : NULL, attrs, NULL, res,
525 : ldb_search_default_callback,
526 : request);
527 3 : assert_int_equal(ret, 0);
528 :
529 : /* Expect that same event context will be chained */
530 3 : assert_ptr_equal(ldb_handle_get_event_context(request->handle),
531 : ldb_handle_get_event_context(request2->handle));
532 :
533 : /* Now force this to use the global context */
534 3 : ldb_handle_use_global_event_context(request2->handle);
535 3 : assert_ptr_equal(ldb_handle_get_event_context(request2->handle),
536 : ldb_get_event_context(test_ctx->ldb));
537 :
538 3 : talloc_free(tmp_ctx);
539 3 : }
540 :
541 3 : static void test_ldb_build_search_req(void **state)
542 : {
543 3 : int ret;
544 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
545 : struct ldbtest_ctx);
546 3 : TALLOC_CTX *tmp_ctx;
547 3 : struct ldb_dn *basedn;
548 3 : struct ldb_request *request = NULL;
549 3 : struct ldb_request *request2 = NULL;
550 3 : struct ldb_result *res = NULL;
551 3 : const char *attrs[] = { "cn", NULL };
552 :
553 3 : tmp_ctx = talloc_new(test_ctx);
554 3 : assert_non_null(tmp_ctx);
555 :
556 3 : basedn = ldb_dn_new_fmt(tmp_ctx, test_ctx->ldb, "dc=test");
557 3 : assert_non_null(basedn);
558 :
559 3 : res = talloc_zero(tmp_ctx, struct ldb_result);
560 3 : assert_non_null(res);
561 :
562 3 : ret = ldb_build_search_req(&request, test_ctx->ldb, tmp_ctx,
563 : basedn, LDB_SCOPE_BASE,
564 : NULL, attrs, NULL, res,
565 : ldb_search_default_callback,
566 : NULL);
567 3 : assert_int_equal(ret, 0);
568 :
569 3 : assert_int_equal(request->operation, LDB_SEARCH);
570 3 : assert_ptr_equal(request->op.search.base, basedn);
571 3 : assert_int_equal(request->op.search.scope, LDB_SCOPE_BASE);
572 3 : assert_non_null(request->op.search.tree);
573 3 : assert_ptr_equal(request->op.search.attrs, attrs);
574 3 : assert_ptr_equal(request->context, res);
575 3 : assert_ptr_equal(request->callback, ldb_search_default_callback);
576 :
577 3 : ret = ldb_build_search_req(&request2, test_ctx->ldb, tmp_ctx,
578 : basedn, LDB_SCOPE_BASE,
579 : NULL, attrs, NULL, res,
580 : ldb_search_default_callback,
581 : request);
582 3 : assert_int_equal(ret, 0);
583 3 : assert_ptr_equal(request, request2->handle->parent);
584 3 : assert_int_equal(request->starttime, request2->starttime);
585 3 : assert_int_equal(request->timeout, request2->timeout);
586 :
587 3 : talloc_free(tmp_ctx);
588 3 : }
589 :
590 12 : static void add_keyval(struct ldbtest_ctx *test_ctx,
591 : const char *key,
592 : const char *val,
593 : const char *uuid)
594 : {
595 12 : int ret;
596 12 : struct ldb_message *msg;
597 :
598 12 : msg = ldb_msg_new(test_ctx);
599 12 : assert_non_null(msg);
600 :
601 12 : msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "%s=%s", key, val);
602 12 : assert_non_null(msg->dn);
603 :
604 12 : ret = ldb_msg_add_string(msg, key, val);
605 12 : assert_int_equal(ret, 0);
606 :
607 12 : ret = ldb_msg_add_string(msg, "objectUUID", uuid);
608 12 : assert_int_equal(ret, 0);
609 :
610 12 : ret = ldb_add(test_ctx->ldb, msg);
611 12 : assert_int_equal(ret, 0);
612 :
613 12 : talloc_free(msg);
614 12 : }
615 :
616 12 : static struct ldb_result *get_keyval(struct ldbtest_ctx *test_ctx,
617 : const char *key,
618 : const char *val)
619 : {
620 12 : int ret;
621 12 : struct ldb_result *result;
622 12 : struct ldb_dn *basedn;
623 :
624 12 : basedn = ldb_dn_new_fmt(test_ctx, test_ctx->ldb, "%s=%s", key, val);
625 12 : assert_non_null(basedn);
626 :
627 12 : ret = ldb_search(test_ctx->ldb, test_ctx, &result, basedn,
628 : LDB_SCOPE_BASE, NULL, NULL);
629 12 : assert_int_equal(ret, 0);
630 :
631 12 : return result;
632 : }
633 :
634 3 : static void test_transactions(void **state)
635 : {
636 3 : int ret;
637 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
638 : struct ldbtest_ctx);
639 3 : struct ldb_result *res;
640 :
641 : /* start lev-0 transaction */
642 3 : ret = ldb_transaction_start(test_ctx->ldb);
643 3 : assert_int_equal(ret, 0);
644 :
645 3 : add_keyval(test_ctx, "vegetable", "carrot",
646 : "0123456789abcde0");
647 :
648 : /* commit lev-0 transaction */
649 3 : ret = ldb_transaction_commit(test_ctx->ldb);
650 3 : assert_int_equal(ret, 0);
651 :
652 : /* start another lev-1 nested transaction */
653 3 : ret = ldb_transaction_start(test_ctx->ldb);
654 3 : assert_int_equal(ret, 0);
655 :
656 3 : add_keyval(test_ctx, "fruit", "apple",
657 : "0123456789abcde1");
658 :
659 : /* abort lev-1 nested transaction */
660 3 : ret = ldb_transaction_cancel(test_ctx->ldb);
661 3 : assert_int_equal(ret, 0);
662 :
663 3 : res = get_keyval(test_ctx, "vegetable", "carrot");
664 3 : assert_non_null(res);
665 3 : assert_int_equal(res->count, 1);
666 :
667 3 : res = get_keyval(test_ctx, "fruit", "apple");
668 3 : assert_non_null(res);
669 3 : assert_int_equal(res->count, 0);
670 3 : }
671 :
672 3 : static void test_nested_transactions(void **state)
673 : {
674 3 : int ret;
675 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
676 : struct ldbtest_ctx);
677 3 : struct ldb_result *res;
678 :
679 : /* start lev-0 transaction */
680 3 : ret = ldb_transaction_start(test_ctx->ldb);
681 3 : assert_int_equal(ret, 0);
682 :
683 3 : add_keyval(test_ctx, "vegetable", "carrot",
684 : "0123456789abcde0");
685 :
686 :
687 : /* start another lev-1 nested transaction */
688 3 : ret = ldb_transaction_start(test_ctx->ldb);
689 3 : assert_int_equal(ret, 0);
690 :
691 3 : add_keyval(test_ctx, "fruit", "apple",
692 : "0123456789abcde1");
693 :
694 : /* abort lev-1 nested transaction */
695 3 : ret = ldb_transaction_cancel(test_ctx->ldb);
696 3 : assert_int_equal(ret, 0);
697 :
698 : /* commit lev-0 transaction */
699 3 : ret = ldb_transaction_commit(test_ctx->ldb);
700 3 : assert_int_equal(ret, 0);
701 :
702 3 : res = get_keyval(test_ctx, "vegetable", "carrot");
703 3 : assert_non_null(res);
704 3 : assert_int_equal(res->count, 1);
705 :
706 : /* This documents the current ldb behaviour, i.e. nested
707 : * transactions are not supported. And the cancellation of the nested
708 : * transaction has no effect.
709 : */
710 3 : res = get_keyval(test_ctx, "fruit", "apple");
711 3 : assert_non_null(res);
712 3 : assert_int_equal(res->count, 1);
713 3 : }
714 : struct ldb_mod_test_ctx {
715 : struct ldbtest_ctx *ldb_test_ctx;
716 : const char *entry_dn;
717 : };
718 :
719 : struct keyval {
720 : const char *key;
721 : const char *val;
722 : };
723 :
724 158 : static struct ldb_message *build_mod_msg(TALLOC_CTX *mem_ctx,
725 : struct ldbtest_ctx *test_ctx,
726 : const char *dn,
727 : int modify_flags,
728 : struct keyval *kvs)
729 : {
730 158 : struct ldb_message *msg;
731 158 : int ret;
732 158 : int i;
733 :
734 158 : msg = ldb_msg_new(mem_ctx);
735 158 : assert_non_null(msg);
736 :
737 158 : msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "%s", dn);
738 158 : assert_non_null(msg->dn);
739 :
740 911 : for (i = 0; kvs[i].key != NULL; i++) {
741 595 : if (modify_flags) {
742 24 : ret = ldb_msg_add_empty(msg, kvs[i].key,
743 : modify_flags, NULL);
744 24 : assert_int_equal(ret, 0);
745 : }
746 :
747 595 : if (kvs[i].val) {
748 586 : ret = ldb_msg_add_string(msg, kvs[i].key, kvs[i].val);
749 586 : assert_int_equal(ret, LDB_SUCCESS);
750 : }
751 : }
752 :
753 158 : return msg;
754 : }
755 :
756 134 : static void ldb_test_add_data(TALLOC_CTX *mem_ctx,
757 : struct ldbtest_ctx *ldb_test_ctx,
758 : const char *basedn,
759 : struct keyval *kvs)
760 : {
761 134 : TALLOC_CTX *tmp_ctx;
762 134 : struct ldb_message *msg;
763 134 : struct ldb_result *result = NULL;
764 134 : int ret;
765 :
766 134 : tmp_ctx = talloc_new(mem_ctx);
767 134 : assert_non_null(tmp_ctx);
768 :
769 134 : msg = build_mod_msg(tmp_ctx, ldb_test_ctx,
770 : basedn, 0, kvs);
771 134 : assert_non_null(msg);
772 :
773 134 : ret = ldb_add(ldb_test_ctx->ldb, msg);
774 134 : assert_int_equal(ret, LDB_SUCCESS);
775 :
776 134 : ret = ldb_search(ldb_test_ctx->ldb, tmp_ctx, &result, msg->dn,
777 : LDB_SCOPE_BASE, NULL, NULL);
778 134 : assert_int_equal(ret, LDB_SUCCESS);
779 134 : assert_non_null(result);
780 134 : assert_int_equal(result->count, 1);
781 134 : assert_string_equal(ldb_dn_get_linearized(result->msgs[0]->dn),
782 : ldb_dn_get_linearized(msg->dn));
783 :
784 134 : talloc_free(tmp_ctx);
785 134 : }
786 :
787 259 : static void ldb_test_remove_data(TALLOC_CTX *mem_ctx,
788 : struct ldbtest_ctx *ldb_test_ctx,
789 : const char *strdn)
790 : {
791 259 : TALLOC_CTX *tmp_ctx;
792 259 : struct ldb_dn *basedn;
793 259 : int ret;
794 259 : size_t count;
795 :
796 259 : tmp_ctx = talloc_new(mem_ctx);
797 259 : assert_non_null(tmp_ctx);
798 :
799 259 : basedn = ldb_dn_new_fmt(tmp_ctx, ldb_test_ctx->ldb,
800 : "%s", strdn);
801 259 : assert_non_null(basedn);
802 :
803 259 : ret = ldb_delete(ldb_test_ctx->ldb, basedn);
804 259 : assert_true(ret == LDB_SUCCESS || ret == LDB_ERR_NO_SUCH_OBJECT);
805 :
806 259 : count = base_search_count(ldb_test_ctx, ldb_dn_get_linearized(basedn));
807 259 : assert_int_equal(count, 0);
808 :
809 259 : talloc_free(tmp_ctx);
810 259 : }
811 :
812 27 : static void mod_test_add_data(struct ldb_mod_test_ctx *mod_test_ctx,
813 : struct keyval *kvs)
814 : {
815 27 : ldb_test_add_data(mod_test_ctx,
816 : mod_test_ctx->ldb_test_ctx,
817 : mod_test_ctx->entry_dn,
818 : kvs);
819 : }
820 :
821 54 : static void mod_test_remove_data(struct ldb_mod_test_ctx *mod_test_ctx)
822 : {
823 54 : ldb_test_remove_data(mod_test_ctx,
824 : mod_test_ctx->ldb_test_ctx,
825 : mod_test_ctx->entry_dn);
826 : }
827 :
828 24 : static struct ldb_result *run_mod_test(struct ldb_mod_test_ctx *mod_test_ctx,
829 : int modify_flags,
830 : struct keyval *kvs)
831 : {
832 24 : TALLOC_CTX *tmp_ctx;
833 24 : struct ldb_result *res;
834 24 : struct ldb_message *mod_msg;
835 24 : struct ldb_dn *basedn;
836 24 : struct ldbtest_ctx *ldb_test_ctx;
837 24 : int ret;
838 :
839 24 : ldb_test_ctx = mod_test_ctx->ldb_test_ctx;
840 :
841 24 : tmp_ctx = talloc_new(mod_test_ctx);
842 24 : assert_non_null(tmp_ctx);
843 :
844 24 : mod_msg = build_mod_msg(tmp_ctx, ldb_test_ctx, mod_test_ctx->entry_dn,
845 : modify_flags, kvs);
846 24 : assert_non_null(mod_msg);
847 :
848 24 : ret = ldb_modify(ldb_test_ctx->ldb, mod_msg);
849 24 : assert_int_equal(ret, LDB_SUCCESS);
850 :
851 24 : basedn = ldb_dn_new_fmt(tmp_ctx, ldb_test_ctx->ldb,
852 : "%s", mod_test_ctx->entry_dn);
853 24 : assert_non_null(basedn);
854 :
855 24 : ret = ldb_search(ldb_test_ctx->ldb, mod_test_ctx, &res, basedn,
856 : LDB_SCOPE_BASE, NULL, NULL);
857 24 : assert_int_equal(ret, LDB_SUCCESS);
858 24 : assert_non_null(res);
859 24 : assert_int_equal(res->count, 1);
860 24 : assert_string_equal(ldb_dn_get_linearized(res->msgs[0]->dn),
861 : ldb_dn_get_linearized(mod_msg->dn));
862 :
863 24 : talloc_free(tmp_ctx);
864 24 : return res;
865 : }
866 :
867 27 : static int ldb_modify_test_setup(void **state)
868 : {
869 27 : struct ldbtest_ctx *ldb_test_ctx;
870 27 : struct ldb_mod_test_ctx *mod_test_ctx;
871 27 : struct keyval kvs[] = {
872 : { "cn", "test_mod_cn" },
873 : { "objectUUID", "0123456789abcdef"},
874 : { NULL, NULL },
875 : };
876 :
877 27 : ldbtest_setup((void **) &ldb_test_ctx);
878 :
879 27 : mod_test_ctx = talloc(ldb_test_ctx, struct ldb_mod_test_ctx);
880 27 : assert_non_null(mod_test_ctx);
881 :
882 27 : mod_test_ctx->entry_dn = "dc=mod_test_entry";
883 27 : mod_test_ctx->ldb_test_ctx = ldb_test_ctx;
884 :
885 27 : mod_test_remove_data(mod_test_ctx);
886 27 : mod_test_add_data(mod_test_ctx, kvs);
887 27 : *state = mod_test_ctx;
888 27 : return 0;
889 : }
890 :
891 27 : static int ldb_modify_test_teardown(void **state)
892 : {
893 27 : struct ldb_mod_test_ctx *mod_test_ctx = \
894 27 : talloc_get_type_abort(*state,
895 : struct ldb_mod_test_ctx);
896 27 : struct ldbtest_ctx *ldb_test_ctx;
897 :
898 27 : ldb_test_ctx = mod_test_ctx->ldb_test_ctx;
899 :
900 27 : mod_test_remove_data(mod_test_ctx);
901 27 : talloc_free(mod_test_ctx);
902 :
903 27 : ldbtest_teardown((void **) &ldb_test_ctx);
904 27 : return 0;
905 : }
906 :
907 3 : static void test_ldb_modify_add_key(void **state)
908 : {
909 3 : struct ldb_mod_test_ctx *mod_test_ctx = \
910 3 : talloc_get_type_abort(*state,
911 : struct ldb_mod_test_ctx);
912 3 : struct keyval mod_kvs[] = {
913 : { "name", "test_mod_name" },
914 : { NULL, NULL },
915 : };
916 3 : struct ldb_result *res;
917 3 : struct ldb_message_element *el;
918 :
919 3 : res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_ADD, mod_kvs);
920 3 : assert_non_null(res);
921 :
922 : /* Check cn is intact and name was added */
923 3 : assert_int_equal(res->count, 1);
924 3 : el = ldb_msg_find_element(res->msgs[0], "cn");
925 3 : assert_non_null(el);
926 3 : assert_int_equal(el->num_values, 1);
927 3 : assert_string_equal((const char *)el->values[0].data, "test_mod_cn");
928 :
929 3 : el = ldb_msg_find_element(res->msgs[0], "name");
930 3 : assert_non_null(el);
931 3 : assert_int_equal(el->num_values, 1);
932 3 : assert_string_equal((const char *)el->values[0].data, "test_mod_name");
933 3 : }
934 :
935 3 : static void test_ldb_modify_extend_key(void **state)
936 : {
937 3 : struct ldb_mod_test_ctx *mod_test_ctx = \
938 3 : talloc_get_type_abort(*state,
939 : struct ldb_mod_test_ctx);
940 3 : struct keyval mod_kvs[] = {
941 : { "cn", "test_mod_cn2" },
942 : { NULL, NULL },
943 : };
944 3 : struct ldb_result *res;
945 3 : struct ldb_message_element *el;
946 :
947 3 : res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_ADD, mod_kvs);
948 3 : assert_non_null(res);
949 :
950 : /* Check cn was extended with another value */
951 3 : assert_int_equal(res->count, 1);
952 3 : el = ldb_msg_find_element(res->msgs[0], "cn");
953 3 : assert_non_null(el);
954 3 : assert_int_equal(el->num_values, 2);
955 3 : assert_string_equal((const char *)el->values[0].data, "test_mod_cn");
956 3 : assert_string_equal((const char *)el->values[1].data, "test_mod_cn2");
957 3 : }
958 :
959 3 : static void test_ldb_modify_add_key_noval(void **state)
960 : {
961 3 : struct ldb_mod_test_ctx *mod_test_ctx = \
962 3 : talloc_get_type_abort(*state,
963 : struct ldb_mod_test_ctx);
964 3 : struct ldb_message *mod_msg;
965 3 : struct ldbtest_ctx *ldb_test_ctx;
966 3 : struct ldb_message_element *el;
967 3 : int ret;
968 :
969 3 : ldb_test_ctx = mod_test_ctx->ldb_test_ctx;
970 :
971 3 : mod_msg = ldb_msg_new(mod_test_ctx);
972 3 : assert_non_null(mod_msg);
973 :
974 3 : mod_msg->dn = ldb_dn_new_fmt(mod_msg, ldb_test_ctx->ldb,
975 : "%s", mod_test_ctx->entry_dn);
976 3 : assert_non_null(mod_msg->dn);
977 :
978 3 : el = talloc_zero(mod_msg, struct ldb_message_element);
979 3 : el->flags = LDB_FLAG_MOD_ADD;
980 3 : assert_non_null(el);
981 3 : el->name = talloc_strdup(el, "cn");
982 3 : assert_non_null(el->name);
983 :
984 3 : mod_msg->elements = el;
985 3 : mod_msg->num_elements = 1;
986 :
987 3 : ret = ldb_modify(ldb_test_ctx->ldb, mod_msg);
988 3 : assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION);
989 3 : }
990 :
991 3 : static void test_ldb_modify_replace_key(void **state)
992 : {
993 3 : struct ldb_mod_test_ctx *mod_test_ctx = \
994 3 : talloc_get_type_abort(*state,
995 : struct ldb_mod_test_ctx);
996 3 : const char *new_cn = "new_cn";
997 3 : struct keyval mod_kvs[] = {
998 : { "cn", new_cn },
999 : { NULL, NULL },
1000 : };
1001 3 : struct ldb_result *res;
1002 3 : struct ldb_message_element *el;
1003 :
1004 3 : res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_REPLACE, mod_kvs);
1005 3 : assert_non_null(res);
1006 :
1007 : /* Check cn was replaced */
1008 3 : assert_int_equal(res->count, 1);
1009 3 : el = ldb_msg_find_element(res->msgs[0], "cn");
1010 3 : assert_non_null(el);
1011 3 : assert_int_equal(el->num_values, 1);
1012 3 : assert_string_equal((const char *)el->values[0].data, new_cn);
1013 3 : }
1014 :
1015 3 : static void test_ldb_modify_replace_noexist_key(void **state)
1016 : {
1017 3 : struct ldb_mod_test_ctx *mod_test_ctx = \
1018 3 : talloc_get_type_abort(*state,
1019 : struct ldb_mod_test_ctx);
1020 3 : struct keyval mod_kvs[] = {
1021 : { "name", "name_val" },
1022 : { NULL, NULL },
1023 : };
1024 3 : struct ldb_result *res;
1025 3 : struct ldb_message_element *el;
1026 :
1027 3 : res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_REPLACE, mod_kvs);
1028 3 : assert_non_null(res);
1029 :
1030 : /* Check cn is intact and name was added */
1031 3 : assert_int_equal(res->count, 1);
1032 3 : el = ldb_msg_find_element(res->msgs[0], "cn");
1033 3 : assert_non_null(el);
1034 3 : assert_int_equal(el->num_values, 1);
1035 3 : assert_string_equal((const char *)el->values[0].data, "test_mod_cn");
1036 :
1037 3 : el = ldb_msg_find_element(res->msgs[0], mod_kvs[0].key);
1038 3 : assert_non_null(el);
1039 3 : assert_int_equal(el->num_values, 1);
1040 3 : assert_string_equal((const char *)el->values[0].data, mod_kvs[0].val);
1041 3 : }
1042 :
1043 3 : static void test_ldb_modify_replace_zero_vals(void **state)
1044 : {
1045 3 : struct ldb_mod_test_ctx *mod_test_ctx = \
1046 3 : talloc_get_type_abort(*state,
1047 : struct ldb_mod_test_ctx);
1048 3 : struct ldb_message_element *el;
1049 3 : struct ldb_result *res;
1050 3 : struct keyval kvs[] = {
1051 : { "cn", NULL },
1052 : { NULL, NULL },
1053 : };
1054 :
1055 : /* cn must be gone */
1056 3 : res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_REPLACE, kvs);
1057 3 : assert_non_null(res);
1058 3 : el = ldb_msg_find_element(res->msgs[0], "cn");
1059 3 : assert_null(el);
1060 3 : }
1061 :
1062 3 : static void test_ldb_modify_replace_noexist_key_zero_vals(void **state)
1063 : {
1064 3 : struct ldb_mod_test_ctx *mod_test_ctx = \
1065 3 : talloc_get_type_abort(*state,
1066 : struct ldb_mod_test_ctx);
1067 3 : struct ldb_message_element *el;
1068 3 : struct ldb_result *res;
1069 3 : struct keyval kvs[] = {
1070 : { "noexist_key", NULL },
1071 : { NULL, NULL },
1072 : };
1073 :
1074 : /* cn must be gone */
1075 3 : res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_REPLACE, kvs);
1076 3 : assert_non_null(res);
1077 :
1078 : /* cn should be intact */
1079 3 : el = ldb_msg_find_element(res->msgs[0], "cn");
1080 3 : assert_non_null(el);
1081 3 : }
1082 :
1083 3 : static void test_ldb_modify_del_key(void **state)
1084 : {
1085 3 : struct ldb_mod_test_ctx *mod_test_ctx = \
1086 3 : talloc_get_type_abort(*state,
1087 : struct ldb_mod_test_ctx);
1088 3 : struct ldb_message_element *el;
1089 3 : struct ldb_result *res;
1090 3 : struct keyval kvs[] = {
1091 : { "cn", NULL },
1092 : { NULL, NULL },
1093 : };
1094 :
1095 : /* cn must be gone */
1096 3 : res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_DELETE, kvs);
1097 3 : assert_non_null(res);
1098 :
1099 3 : el = ldb_msg_find_element(res->msgs[0], "cn");
1100 3 : assert_null(el);
1101 3 : }
1102 :
1103 3 : static void test_ldb_modify_del_keyval(void **state)
1104 : {
1105 3 : struct ldb_mod_test_ctx *mod_test_ctx = \
1106 3 : talloc_get_type_abort(*state,
1107 : struct ldb_mod_test_ctx);
1108 3 : struct ldb_message_element *el;
1109 3 : struct ldb_result *res;
1110 3 : struct keyval kvs[] = {
1111 : { "cn", "test_mod_cn" },
1112 : { NULL, NULL },
1113 : };
1114 :
1115 : /* cn must be gone */
1116 3 : res = run_mod_test(mod_test_ctx, LDB_FLAG_MOD_DELETE, kvs);
1117 3 : assert_non_null(res);
1118 :
1119 3 : el = ldb_msg_find_element(res->msgs[0], "cn");
1120 3 : assert_null(el);
1121 3 : }
1122 :
1123 : struct search_test_ctx {
1124 : struct ldbtest_ctx *ldb_test_ctx;
1125 : const char *base_dn;
1126 : };
1127 :
1128 110 : static char *get_full_dn(TALLOC_CTX *mem_ctx,
1129 : struct search_test_ctx *search_test_ctx,
1130 : const char *rdn)
1131 : {
1132 110 : char *full_dn;
1133 :
1134 110 : full_dn = talloc_asprintf(mem_ctx,
1135 : "%s,%s", rdn, search_test_ctx->base_dn);
1136 110 : assert_non_null(full_dn);
1137 :
1138 110 : return full_dn;
1139 : }
1140 :
1141 98 : static void search_test_add_data(struct search_test_ctx *search_test_ctx,
1142 : const char *rdn,
1143 : struct keyval *kvs)
1144 : {
1145 98 : char *full_dn;
1146 :
1147 98 : full_dn = get_full_dn(search_test_ctx, search_test_ctx, rdn);
1148 :
1149 98 : ldb_test_add_data(search_test_ctx,
1150 : search_test_ctx->ldb_test_ctx,
1151 : full_dn,
1152 : kvs);
1153 98 : }
1154 :
1155 196 : static void search_test_remove_data(struct search_test_ctx *search_test_ctx,
1156 : const char *rdn)
1157 : {
1158 196 : char *full_dn;
1159 :
1160 196 : full_dn = talloc_asprintf(search_test_ctx,
1161 : "%s,%s", rdn, search_test_ctx->base_dn);
1162 196 : assert_non_null(full_dn);
1163 :
1164 196 : ldb_test_remove_data(search_test_ctx,
1165 : search_test_ctx->ldb_test_ctx,
1166 : full_dn);
1167 196 : }
1168 :
1169 49 : static int ldb_search_test_setup(void **state)
1170 : {
1171 49 : struct ldbtest_ctx *ldb_test_ctx;
1172 49 : struct search_test_ctx *search_test_ctx;
1173 49 : struct keyval kvs[] = {
1174 : { "cn", "test_search_cn" },
1175 : { "cn", "test_search_cn2" },
1176 : { "uid", "test_search_uid" },
1177 : { "uid", "test_search_uid2" },
1178 : { "objectUUID", "0123456789abcde0"},
1179 : { NULL, NULL },
1180 : };
1181 49 : struct keyval kvs2[] = {
1182 : { "cn", "test_search_2_cn" },
1183 : { "cn", "test_search_2_cn2" },
1184 : { "uid", "test_search_2_uid" },
1185 : { "uid", "test_search_2_uid2" },
1186 : { "objectUUID", "0123456789abcde1"},
1187 : { NULL, NULL },
1188 : };
1189 :
1190 49 : ldbtest_setup((void **) &ldb_test_ctx);
1191 :
1192 49 : search_test_ctx = talloc(ldb_test_ctx, struct search_test_ctx);
1193 49 : assert_non_null(search_test_ctx);
1194 :
1195 49 : search_test_ctx->base_dn = "dc=search_test_entry";
1196 49 : search_test_ctx->ldb_test_ctx = ldb_test_ctx;
1197 :
1198 49 : search_test_remove_data(search_test_ctx, "cn=test_search_cn");
1199 49 : search_test_add_data(search_test_ctx, "cn=test_search_cn", kvs);
1200 :
1201 49 : search_test_remove_data(search_test_ctx, "cn=test_search_2_cn");
1202 49 : search_test_add_data(search_test_ctx, "cn=test_search_2_cn", kvs2);
1203 :
1204 49 : *state = search_test_ctx;
1205 49 : return 0;
1206 : }
1207 :
1208 49 : static int ldb_search_test_teardown(void **state)
1209 : {
1210 49 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
1211 : struct search_test_ctx);
1212 49 : struct ldbtest_ctx *ldb_test_ctx;
1213 :
1214 49 : ldb_test_ctx = search_test_ctx->ldb_test_ctx;
1215 :
1216 49 : search_test_remove_data(search_test_ctx, "cn=test_search_cn");
1217 49 : search_test_remove_data(search_test_ctx, "cn=test_search_2_cn");
1218 49 : ldbtest_teardown((void **) &ldb_test_ctx);
1219 49 : return 0;
1220 : }
1221 :
1222 21 : static void assert_attr_has_vals(struct ldb_message *msg,
1223 : const char *attr,
1224 : const char *vals[],
1225 : const size_t nvals)
1226 : {
1227 21 : struct ldb_message_element *el;
1228 21 : size_t i;
1229 :
1230 21 : el = ldb_msg_find_element(msg, attr);
1231 21 : assert_non_null(el);
1232 :
1233 21 : assert_int_equal(el->num_values, nvals);
1234 84 : for (i = 0; i < nvals; i++) {
1235 42 : assert_string_equal((const char *)el->values[i].data,
1236 : vals[i]);
1237 : }
1238 21 : }
1239 :
1240 3 : static void assert_has_no_attr(struct ldb_message *msg,
1241 : const char *attr)
1242 : {
1243 3 : struct ldb_message_element *el;
1244 :
1245 3 : el = ldb_msg_find_element(msg, attr);
1246 3 : assert_null(el);
1247 3 : }
1248 :
1249 9 : static bool has_dn(struct ldb_message *msg, const char *dn)
1250 : {
1251 9 : const char *msgdn;
1252 :
1253 9 : msgdn = ldb_dn_get_linearized(msg->dn);
1254 9 : if (strcmp(dn, msgdn) == 0) {
1255 6 : return true;
1256 : }
1257 :
1258 : return false;
1259 : }
1260 :
1261 3 : static void test_search_match_none(void **state)
1262 : {
1263 3 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
1264 : struct search_test_ctx);
1265 3 : size_t count;
1266 :
1267 3 : count = base_search_count(search_test_ctx->ldb_test_ctx,
1268 : "dc=no_such_entry");
1269 3 : assert_int_equal(count, 0);
1270 3 : }
1271 :
1272 3 : static void test_search_match_one(void **state)
1273 : {
1274 3 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
1275 : struct search_test_ctx);
1276 3 : int ret;
1277 3 : struct ldb_dn *basedn;
1278 3 : struct ldb_result *result = NULL;
1279 3 : const char *cn_vals[] = { "test_search_cn",
1280 : "test_search_cn2" };
1281 3 : const char *uid_vals[] = { "test_search_uid",
1282 : "test_search_uid2" };
1283 :
1284 6 : basedn = ldb_dn_new_fmt(search_test_ctx,
1285 3 : search_test_ctx->ldb_test_ctx->ldb,
1286 : "%s",
1287 : search_test_ctx->base_dn);
1288 3 : assert_non_null(basedn);
1289 :
1290 3 : ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb,
1291 : search_test_ctx,
1292 : &result,
1293 : basedn,
1294 : LDB_SCOPE_SUBTREE, NULL,
1295 : "cn=test_search_cn");
1296 3 : assert_int_equal(ret, 0);
1297 3 : assert_non_null(result);
1298 3 : assert_int_equal(result->count, 1);
1299 :
1300 3 : assert_attr_has_vals(result->msgs[0], "cn", cn_vals, 2);
1301 3 : assert_attr_has_vals(result->msgs[0], "uid", uid_vals, 2);
1302 3 : }
1303 :
1304 3 : static void test_search_match_filter(void **state)
1305 : {
1306 3 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
1307 : struct search_test_ctx);
1308 3 : int ret;
1309 3 : struct ldb_dn *basedn;
1310 3 : struct ldb_result *result = NULL;
1311 3 : const char *cn_vals[] = { "test_search_cn",
1312 : "test_search_cn2" };
1313 3 : const char *attrs[] = { "cn", NULL };
1314 :
1315 6 : basedn = ldb_dn_new_fmt(search_test_ctx,
1316 3 : search_test_ctx->ldb_test_ctx->ldb,
1317 : "%s",
1318 : search_test_ctx->base_dn);
1319 3 : assert_non_null(basedn);
1320 :
1321 3 : ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb,
1322 : search_test_ctx,
1323 : &result,
1324 : basedn,
1325 : LDB_SCOPE_SUBTREE,
1326 : attrs,
1327 : "cn=test_search_cn");
1328 3 : assert_int_equal(ret, 0);
1329 3 : assert_non_null(result);
1330 3 : assert_int_equal(result->count, 1);
1331 :
1332 3 : assert_attr_has_vals(result->msgs[0], "cn", cn_vals, 2);
1333 3 : assert_has_no_attr(result->msgs[0], "uid");
1334 3 : }
1335 :
1336 6 : static void assert_expected(struct search_test_ctx *search_test_ctx,
1337 : struct ldb_message *msg)
1338 : {
1339 6 : char *full_dn1;
1340 6 : char *full_dn2;
1341 6 : const char *cn_vals[] = { "test_search_cn",
1342 : "test_search_cn2" };
1343 6 : const char *uid_vals[] = { "test_search_uid",
1344 : "test_search_uid2" };
1345 6 : const char *cn2_vals[] = { "test_search_2_cn",
1346 : "test_search_2_cn2" };
1347 6 : const char *uid2_vals[] = { "test_search_2_uid",
1348 : "test_search_2_uid2" };
1349 :
1350 6 : full_dn1 = get_full_dn(search_test_ctx,
1351 : search_test_ctx,
1352 : "cn=test_search_cn");
1353 :
1354 6 : full_dn2 = get_full_dn(search_test_ctx,
1355 : search_test_ctx,
1356 : "cn=test_search_2_cn");
1357 :
1358 6 : if (has_dn(msg, full_dn1) == true) {
1359 3 : assert_attr_has_vals(msg, "cn", cn_vals, 2);
1360 3 : assert_attr_has_vals(msg, "uid", uid_vals, 2);
1361 3 : } else if (has_dn(msg, full_dn2) == true) {
1362 3 : assert_attr_has_vals(msg, "cn", cn2_vals, 2);
1363 3 : assert_attr_has_vals(msg, "uid", uid2_vals, 2);
1364 : } else {
1365 0 : fail();
1366 : }
1367 6 : }
1368 :
1369 3 : static void test_search_match_both(void **state)
1370 : {
1371 3 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
1372 : struct search_test_ctx);
1373 3 : int ret;
1374 3 : struct ldb_dn *basedn;
1375 3 : struct ldb_result *result = NULL;
1376 :
1377 6 : basedn = ldb_dn_new_fmt(search_test_ctx,
1378 3 : search_test_ctx->ldb_test_ctx->ldb,
1379 : "%s",
1380 : search_test_ctx->base_dn);
1381 3 : assert_non_null(basedn);
1382 :
1383 3 : ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb,
1384 : search_test_ctx,
1385 : &result,
1386 : basedn,
1387 : LDB_SCOPE_SUBTREE, NULL,
1388 : "cn=test_search_*");
1389 3 : assert_int_equal(ret, 0);
1390 3 : assert_non_null(result);
1391 3 : assert_int_equal(result->count, 2);
1392 :
1393 3 : assert_expected(search_test_ctx, result->msgs[0]);
1394 3 : assert_expected(search_test_ctx, result->msgs[1]);
1395 3 : }
1396 :
1397 3 : static void test_search_match_basedn(void **state)
1398 : {
1399 3 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
1400 : struct search_test_ctx);
1401 3 : int ret;
1402 3 : struct ldb_dn *basedn;
1403 3 : struct ldb_result *result = NULL;
1404 3 : struct ldb_message *msg;
1405 :
1406 6 : basedn = ldb_dn_new_fmt(search_test_ctx,
1407 3 : search_test_ctx->ldb_test_ctx->ldb,
1408 : "dc=nosuchdn");
1409 3 : assert_non_null(basedn);
1410 :
1411 3 : ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb,
1412 : search_test_ctx,
1413 : &result,
1414 : basedn,
1415 : LDB_SCOPE_SUBTREE, NULL,
1416 : "cn=*");
1417 3 : assert_int_equal(ret, 0);
1418 :
1419 : /* Add 'checkBaseOnSearch' to @OPTIONS */
1420 3 : msg = ldb_msg_new(search_test_ctx);
1421 3 : assert_non_null(msg);
1422 :
1423 6 : msg->dn = ldb_dn_new_fmt(msg,
1424 3 : search_test_ctx->ldb_test_ctx->ldb,
1425 : "@OPTIONS");
1426 3 : assert_non_null(msg->dn);
1427 :
1428 3 : ret = ldb_msg_add_string(msg, "checkBaseOnSearch", "TRUE");
1429 3 : assert_int_equal(ret, 0);
1430 :
1431 3 : ret = ldb_add(search_test_ctx->ldb_test_ctx->ldb, msg);
1432 3 : assert_int_equal(ret, 0);
1433 :
1434 : /* Search again */
1435 : /* The search should return LDB_ERR_NO_SUCH_OBJECT */
1436 3 : ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb,
1437 : search_test_ctx,
1438 : &result,
1439 : basedn,
1440 : LDB_SCOPE_SUBTREE, NULL,
1441 : "cn=*");
1442 3 : assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
1443 :
1444 3 : ret = ldb_delete(search_test_ctx->ldb_test_ctx->ldb, msg->dn);
1445 3 : assert_int_equal(ret, 0);
1446 3 : }
1447 :
1448 :
1449 : /*
1450 : * This test is complex.
1451 : * The purpose is to test for a deadlock detected between ldb_search()
1452 : * and ldb_transaction_commit(). The deadlock happens if in process
1453 : * (1) and (2):
1454 : * - (1) the all-record lock is taken in ltdb_search()
1455 : * - (2) the ldb_transaction_start() call is made
1456 : * - (1) an un-indexed search starts (forced here by doing it in
1457 : * the callback
1458 : * - (2) the ldb_transaction_commit() is called.
1459 : * This returns LDB_ERR_BUSY if the deadlock is detected
1460 : *
1461 : * With ldb 1.1.31 and tdb 1.3.12 we avoid this only due to a missing
1462 : * lock call in ltdb_search() due to a refcounting bug in
1463 : * ltdb_lock_read()
1464 : */
1465 :
1466 : struct search_against_transaction_ctx {
1467 : struct ldbtest_ctx *test_ctx;
1468 : int res_count;
1469 : pid_t child_pid;
1470 : struct ldb_dn *basedn;
1471 : };
1472 :
1473 9 : static int test_ldb_search_against_transaction_callback2(struct ldb_request *req,
1474 : struct ldb_reply *ares)
1475 : {
1476 9 : struct search_against_transaction_ctx *ctx = req->context;
1477 9 : switch (ares->type) {
1478 6 : case LDB_REPLY_ENTRY:
1479 6 : ctx->res_count++;
1480 6 : if (ctx->res_count != 1) {
1481 : return LDB_SUCCESS;
1482 : }
1483 :
1484 : break;
1485 :
1486 : case LDB_REPLY_REFERRAL:
1487 : break;
1488 :
1489 3 : case LDB_REPLY_DONE:
1490 3 : return ldb_request_done(req, LDB_SUCCESS);
1491 : }
1492 :
1493 : return 0;
1494 :
1495 : }
1496 :
1497 : /*
1498 : * This purpose of this callback is to trigger a transaction in
1499 : * the child process while the all-record lock is held, but before
1500 : * we take any locks in the tdb_traverse_read() handler.
1501 : *
1502 : * In tdb 1.3.12 tdb_traverse_read() take the read transaction lock
1503 : * however in ldb 1.1.31 ltdb_search() forgets to take the all-record
1504 : * lock (except the very first time) due to a ref-counting bug.
1505 : *
1506 : */
1507 :
1508 6 : static int test_ldb_search_against_transaction_callback1(struct ldb_request *req,
1509 : struct ldb_reply *ares)
1510 : {
1511 6 : int ret, ret2;
1512 6 : int pipes[2];
1513 6 : char buf[2];
1514 6 : struct search_against_transaction_ctx *ctx = req->context;
1515 6 : switch (ares->type) {
1516 : case LDB_REPLY_ENTRY:
1517 : break;
1518 :
1519 : case LDB_REPLY_REFERRAL:
1520 : return LDB_SUCCESS;
1521 :
1522 3 : case LDB_REPLY_DONE:
1523 3 : return ldb_request_done(req, LDB_SUCCESS);
1524 : }
1525 :
1526 3 : ret = pipe(pipes);
1527 3 : assert_int_equal(ret, 0);
1528 :
1529 3 : ctx->child_pid = fork();
1530 6 : if (ctx->child_pid == 0) {
1531 3 : TALLOC_CTX *tmp_ctx = NULL;
1532 3 : struct ldb_message *msg;
1533 3 : TALLOC_FREE(ctx->test_ctx->ldb);
1534 3 : TALLOC_FREE(ctx->test_ctx->ev);
1535 3 : close(pipes[0]);
1536 3 : ctx->test_ctx->ev = tevent_context_init(ctx->test_ctx);
1537 3 : if (ctx->test_ctx->ev == NULL) {
1538 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1539 : }
1540 :
1541 3 : ctx->test_ctx->ldb = ldb_init(ctx->test_ctx,
1542 : ctx->test_ctx->ev);
1543 3 : if (ctx->test_ctx->ldb == NULL) {
1544 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1545 : }
1546 :
1547 3 : ret = ldb_connect(ctx->test_ctx->ldb,
1548 : ctx->test_ctx->dbpath, 0, NULL);
1549 3 : if (ret != LDB_SUCCESS) {
1550 0 : exit(ret);
1551 : }
1552 :
1553 3 : tmp_ctx = talloc_new(ctx->test_ctx);
1554 3 : if (tmp_ctx == NULL) {
1555 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1556 : }
1557 :
1558 3 : msg = ldb_msg_new(tmp_ctx);
1559 3 : if (msg == NULL) {
1560 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1561 : }
1562 :
1563 3 : msg->dn = ldb_dn_new_fmt(msg, ctx->test_ctx->ldb,
1564 : "dc=test");
1565 3 : if (msg->dn == NULL) {
1566 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1567 : }
1568 :
1569 3 : ret = ldb_msg_add_string(msg, "cn", "test_cn_val");
1570 3 : if (ret != 0) {
1571 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1572 : }
1573 :
1574 3 : ret = ldb_transaction_start(ctx->test_ctx->ldb);
1575 3 : if (ret != 0) {
1576 0 : exit(ret);
1577 : }
1578 :
1579 3 : ret = write(pipes[1], "GO", 2);
1580 3 : if (ret != 2) {
1581 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1582 : }
1583 :
1584 3 : ret = ldb_msg_add_string(msg, "objectUUID",
1585 : "0123456789abcdef");
1586 3 : if (ret != 0) {
1587 0 : exit(ret);
1588 : }
1589 :
1590 3 : ret = ldb_add(ctx->test_ctx->ldb, msg);
1591 3 : if (ret != 0) {
1592 0 : exit(ret);
1593 : }
1594 :
1595 3 : ret = ldb_transaction_commit(ctx->test_ctx->ldb);
1596 3 : exit(ret);
1597 : }
1598 3 : close(pipes[1]);
1599 3 : ret = read(pipes[0], buf, 2);
1600 3 : assert_int_equal(ret, 2);
1601 :
1602 : /* This search must be unindexed (ie traverse in tdb) */
1603 6 : ret = ldb_build_search_req(&req,
1604 : ctx->test_ctx->ldb,
1605 3 : ctx->test_ctx,
1606 : ctx->basedn,
1607 : LDB_SCOPE_SUBTREE,
1608 : "cn=*", NULL,
1609 : NULL,
1610 : ctx,
1611 : test_ldb_search_against_transaction_callback2,
1612 : NULL);
1613 : /*
1614 : * we don't assert on these return codes until after the search is
1615 : * finished, or the clean up will fail because we hold locks.
1616 : */
1617 :
1618 3 : ret2 = ldb_request(ctx->test_ctx->ldb, req);
1619 :
1620 3 : if (ret2 == LDB_SUCCESS) {
1621 3 : ret2 = ldb_wait(req->handle, LDB_WAIT_ALL);
1622 : }
1623 3 : assert_int_equal(ret, 0);
1624 3 : assert_int_equal(ret2, 0);
1625 3 : assert_int_equal(ctx->res_count, 2);
1626 :
1627 3 : return LDB_SUCCESS;
1628 : }
1629 :
1630 3 : static void test_ldb_search_against_transaction(void **state)
1631 : {
1632 3 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
1633 : struct search_test_ctx);
1634 3 : struct search_against_transaction_ctx
1635 3 : ctx =
1636 : { .res_count = 0,
1637 3 : .test_ctx = search_test_ctx->ldb_test_ctx
1638 : };
1639 :
1640 3 : int ret;
1641 3 : struct ldb_request *req;
1642 3 : pid_t pid;
1643 3 : int wstatus;
1644 3 : struct ldb_dn *base_search_dn;
1645 :
1646 3 : tevent_loop_allow_nesting(search_test_ctx->ldb_test_ctx->ev);
1647 :
1648 3 : base_search_dn
1649 6 : = ldb_dn_new_fmt(search_test_ctx,
1650 3 : search_test_ctx->ldb_test_ctx->ldb,
1651 : "cn=test_search_cn,%s",
1652 : search_test_ctx->base_dn);
1653 3 : assert_non_null(base_search_dn);
1654 :
1655 3 : ctx.basedn
1656 6 : = ldb_dn_new_fmt(search_test_ctx,
1657 3 : search_test_ctx->ldb_test_ctx->ldb,
1658 : "%s",
1659 : search_test_ctx->base_dn);
1660 3 : assert_non_null(ctx.basedn);
1661 :
1662 :
1663 : /* This search must be indexed (ie no traverse in tdb) */
1664 6 : ret = ldb_build_search_req(&req,
1665 3 : search_test_ctx->ldb_test_ctx->ldb,
1666 : search_test_ctx,
1667 : base_search_dn,
1668 : LDB_SCOPE_BASE,
1669 : "cn=*", NULL,
1670 : NULL,
1671 : &ctx,
1672 : test_ldb_search_against_transaction_callback1,
1673 : NULL);
1674 3 : assert_int_equal(ret, 0);
1675 3 : ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req);
1676 :
1677 3 : if (ret == LDB_SUCCESS) {
1678 3 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1679 : }
1680 3 : assert_int_equal(ret, 0);
1681 3 : assert_int_equal(ctx.res_count, 2);
1682 :
1683 3 : pid = waitpid(ctx.child_pid, &wstatus, 0);
1684 3 : assert_int_equal(pid, ctx.child_pid);
1685 :
1686 3 : assert_true(WIFEXITED(wstatus));
1687 :
1688 3 : assert_int_equal(WEXITSTATUS(wstatus), 0);
1689 :
1690 :
1691 3 : }
1692 :
1693 : /*
1694 : * This test is also complex.
1695 : * The purpose is to test if a modify can occur during an ldb_search()
1696 : * This would be a failure if if in process
1697 : * (1) and (2):
1698 : * - (1) ltdb_search() starts and calls back for one entry
1699 : * - (2) one of the entries to be matched is modified
1700 : * - (1) the indexed search tries to return the modified entry, but
1701 : * it is no longer found, either:
1702 : * - despite it still matching (dn changed)
1703 : * - it no longer matching (attrs changed)
1704 : *
1705 : * We also try un-indexed to show that the behaviour differs on this
1706 : * point, which it should not (an index should only impact search
1707 : * speed).
1708 : */
1709 :
1710 : struct modify_during_search_test_ctx {
1711 : struct ldbtest_ctx *test_ctx;
1712 : int res_count;
1713 : pid_t child_pid;
1714 : struct ldb_dn *basedn;
1715 : bool got_cn;
1716 : bool got_2_cn;
1717 : bool rename;
1718 : };
1719 :
1720 : /*
1721 : * This purpose of this callback is to trigger a write in
1722 : * the child process while a search is in progress.
1723 : *
1724 : * In tdb 1.3.12 tdb_traverse_read() take the read transaction lock
1725 : * however in ldb 1.1.31 ltdb_search() forgets to take the all-record
1726 : * lock (except the very first time) due to a ref-counting bug.
1727 : *
1728 : * We assume that if the write will proceed, it will proceed in a 3
1729 : * second window after the function is called.
1730 : */
1731 :
1732 36 : static int test_ldb_modify_during_search_callback1(struct ldb_request *req,
1733 : struct ldb_reply *ares)
1734 : {
1735 36 : int ret;
1736 36 : int pipes[2];
1737 36 : char buf[2];
1738 36 : struct modify_during_search_test_ctx *ctx = req->context;
1739 36 : switch (ares->type) {
1740 24 : case LDB_REPLY_ENTRY:
1741 : {
1742 24 : const struct ldb_val *cn_val
1743 24 : = ldb_dn_get_component_val(ares->message->dn, 0);
1744 24 : const char *cn = (char *)cn_val->data;
1745 24 : ctx->res_count++;
1746 24 : if (strcmp(cn, "test_search_cn") == 0) {
1747 12 : ctx->got_cn = true;
1748 12 : } else if (strcmp(cn, "test_search_2_cn") == 0) {
1749 12 : ctx->got_2_cn = true;
1750 : }
1751 24 : if (ctx->res_count == 2) {
1752 : return LDB_SUCCESS;
1753 : }
1754 : break;
1755 : }
1756 : case LDB_REPLY_REFERRAL:
1757 : return LDB_SUCCESS;
1758 :
1759 12 : case LDB_REPLY_DONE:
1760 12 : return ldb_request_done(req, LDB_SUCCESS);
1761 : }
1762 :
1763 12 : ret = pipe(pipes);
1764 12 : assert_int_equal(ret, 0);
1765 :
1766 12 : ctx->child_pid = fork();
1767 24 : if (ctx->child_pid == 0 && ctx->rename) {
1768 6 : TALLOC_CTX *tmp_ctx = NULL;
1769 6 : struct ldb_dn *dn, *new_dn;
1770 6 : TALLOC_FREE(ctx->test_ctx->ldb);
1771 6 : TALLOC_FREE(ctx->test_ctx->ev);
1772 6 : close(pipes[0]);
1773 6 : ctx->test_ctx->ev = tevent_context_init(ctx->test_ctx);
1774 6 : if (ctx->test_ctx->ev == NULL) {
1775 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1776 : }
1777 :
1778 6 : ctx->test_ctx->ldb = ldb_init(ctx->test_ctx,
1779 : ctx->test_ctx->ev);
1780 6 : if (ctx->test_ctx->ldb == NULL) {
1781 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1782 : }
1783 :
1784 6 : ret = ldb_connect(ctx->test_ctx->ldb,
1785 : ctx->test_ctx->dbpath, 0, NULL);
1786 6 : if (ret != LDB_SUCCESS) {
1787 0 : exit(ret);
1788 : }
1789 :
1790 6 : tmp_ctx = talloc_new(ctx->test_ctx);
1791 6 : if (tmp_ctx == NULL) {
1792 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1793 : }
1794 :
1795 6 : if (ctx->got_cn) {
1796 : /* Modify the other one */
1797 5 : dn = ldb_dn_new_fmt(tmp_ctx, ctx->test_ctx->ldb,
1798 : "cn=test_search_2_cn,"
1799 : "dc=search_test_entry");
1800 : } else {
1801 1 : dn = ldb_dn_new_fmt(tmp_ctx, ctx->test_ctx->ldb,
1802 : "cn=test_search_cn,"
1803 : "dc=search_test_entry");
1804 : }
1805 6 : if (dn == NULL) {
1806 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1807 : }
1808 :
1809 6 : new_dn = ldb_dn_new_fmt(tmp_ctx, ctx->test_ctx->ldb,
1810 : "cn=test_search_cn_renamed,"
1811 : "dc=search_test_entry");
1812 6 : if (new_dn == NULL) {
1813 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1814 : }
1815 :
1816 6 : ret = ldb_transaction_start(ctx->test_ctx->ldb);
1817 6 : if (ret != 0) {
1818 0 : exit(ret);
1819 : }
1820 :
1821 6 : if (write(pipes[1], "GO", 2) != 2) {
1822 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1823 : }
1824 :
1825 6 : ret = ldb_rename(ctx->test_ctx->ldb, dn, new_dn);
1826 6 : if (ret != 0) {
1827 0 : exit(ret);
1828 : }
1829 :
1830 6 : ret = ldb_transaction_commit(ctx->test_ctx->ldb);
1831 6 : exit(ret);
1832 :
1833 18 : } else if (ctx->child_pid == 0) {
1834 6 : TALLOC_CTX *tmp_ctx = NULL;
1835 6 : struct ldb_message *msg;
1836 6 : struct ldb_message_element *el;
1837 6 : TALLOC_FREE(ctx->test_ctx->ldb);
1838 6 : TALLOC_FREE(ctx->test_ctx->ev);
1839 6 : close(pipes[0]);
1840 6 : ctx->test_ctx->ev = tevent_context_init(ctx->test_ctx);
1841 6 : if (ctx->test_ctx->ev == NULL) {
1842 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1843 : }
1844 :
1845 6 : ctx->test_ctx->ldb = ldb_init(ctx->test_ctx,
1846 : ctx->test_ctx->ev);
1847 6 : if (ctx->test_ctx->ldb == NULL) {
1848 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1849 : }
1850 :
1851 6 : ret = ldb_connect(ctx->test_ctx->ldb,
1852 : ctx->test_ctx->dbpath, 0, NULL);
1853 6 : if (ret != LDB_SUCCESS) {
1854 0 : exit(ret);
1855 : }
1856 :
1857 6 : tmp_ctx = talloc_new(ctx->test_ctx);
1858 6 : if (tmp_ctx == NULL) {
1859 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1860 : }
1861 :
1862 6 : msg = ldb_msg_new(tmp_ctx);
1863 6 : if (msg == NULL) {
1864 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1865 : }
1866 :
1867 6 : if (ctx->got_cn) {
1868 : /* Modify the other one */
1869 5 : msg->dn = ldb_dn_new_fmt(msg, ctx->test_ctx->ldb,
1870 : "cn=test_search_2_cn,"
1871 : "dc=search_test_entry");
1872 : } else {
1873 1 : msg->dn = ldb_dn_new_fmt(msg, ctx->test_ctx->ldb,
1874 : "cn=test_search_cn,"
1875 : "dc=search_test_entry");
1876 : }
1877 6 : if (msg->dn == NULL) {
1878 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1879 : }
1880 :
1881 6 : ret = ldb_msg_add_string(msg, "filterAttr", "TRUE");
1882 6 : if (ret != 0) {
1883 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1884 : }
1885 6 : el = ldb_msg_find_element(msg, "filterAttr");
1886 6 : if (el == NULL) {
1887 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1888 : }
1889 6 : el->flags = LDB_FLAG_MOD_REPLACE;
1890 :
1891 6 : ret = ldb_transaction_start(ctx->test_ctx->ldb);
1892 6 : if (ret != 0) {
1893 0 : exit(ret);
1894 : }
1895 :
1896 6 : if (write(pipes[1], "GO", 2) != 2) {
1897 0 : exit(LDB_ERR_OPERATIONS_ERROR);
1898 : }
1899 :
1900 6 : ret = ldb_modify(ctx->test_ctx->ldb, msg);
1901 6 : if (ret != 0) {
1902 0 : exit(ret);
1903 : }
1904 :
1905 6 : ret = ldb_transaction_commit(ctx->test_ctx->ldb);
1906 6 : exit(ret);
1907 : }
1908 :
1909 : /*
1910 : * With TDB 1.3.13 and before "tdb: Remove locking from tdb_traverse_read()"
1911 : * we will hang here because the child process can not proceed to
1912 : * sending the "GO" as it is blocked at ldb_transaction_start().
1913 : */
1914 :
1915 12 : close(pipes[1]);
1916 12 : ret = read(pipes[0], buf, 2);
1917 12 : assert_int_equal(ret, 2);
1918 :
1919 12 : sleep(3);
1920 :
1921 12 : return LDB_SUCCESS;
1922 : }
1923 :
1924 12 : static void test_ldb_modify_during_search(void **state, bool add_index,
1925 : bool rename)
1926 : {
1927 12 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
1928 : struct search_test_ctx);
1929 12 : struct modify_during_search_test_ctx
1930 12 : ctx =
1931 : { .res_count = 0,
1932 12 : .test_ctx = search_test_ctx->ldb_test_ctx,
1933 : .rename = rename
1934 : };
1935 :
1936 12 : int ret;
1937 12 : struct ldb_request *req;
1938 12 : pid_t pid;
1939 12 : int wstatus;
1940 :
1941 12 : if (add_index) {
1942 6 : struct ldb_message *msg;
1943 6 : struct ldb_dn *indexlist = ldb_dn_new(search_test_ctx,
1944 : search_test_ctx->ldb_test_ctx->ldb,
1945 : "@INDEXLIST");
1946 6 : assert_non_null(indexlist);
1947 :
1948 6 : msg = ldb_msg_new(search_test_ctx);
1949 6 : assert_non_null(msg);
1950 :
1951 6 : msg->dn = indexlist;
1952 :
1953 6 : ret = ldb_msg_add_string(msg, "@IDXATTR", "cn");
1954 6 : assert_int_equal(ret, LDB_SUCCESS);
1955 6 : ret = ldb_add(search_test_ctx->ldb_test_ctx->ldb,
1956 : msg);
1957 6 : if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
1958 4 : msg->elements[0].flags = LDB_FLAG_MOD_ADD;
1959 4 : ret = ldb_modify(search_test_ctx->ldb_test_ctx->ldb,
1960 : msg);
1961 : }
1962 6 : assert_int_equal(ret, LDB_SUCCESS);
1963 : }
1964 :
1965 12 : tevent_loop_allow_nesting(search_test_ctx->ldb_test_ctx->ev);
1966 :
1967 12 : ctx.basedn
1968 24 : = ldb_dn_new_fmt(search_test_ctx,
1969 12 : search_test_ctx->ldb_test_ctx->ldb,
1970 : "%s",
1971 : search_test_ctx->base_dn);
1972 12 : assert_non_null(ctx.basedn);
1973 :
1974 :
1975 : /*
1976 : * This search must be over multiple items, and should include
1977 : * the new name after a rename, to show that it would match
1978 : * both before and after that modify
1979 : */
1980 24 : ret = ldb_build_search_req(&req,
1981 12 : search_test_ctx->ldb_test_ctx->ldb,
1982 : search_test_ctx,
1983 : ctx.basedn,
1984 : LDB_SCOPE_SUBTREE,
1985 : "(&(!(filterAttr=*))"
1986 : "(|(cn=test_search_cn_renamed)"
1987 : "(cn=test_search_cn)"
1988 : "(cn=test_search_2_cn)"
1989 : "))",
1990 : NULL,
1991 : NULL,
1992 : &ctx,
1993 : test_ldb_modify_during_search_callback1,
1994 : NULL);
1995 12 : assert_int_equal(ret, 0);
1996 12 : ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req);
1997 :
1998 12 : if (ret == LDB_SUCCESS) {
1999 12 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
2000 : }
2001 12 : assert_int_equal(ret, 0);
2002 12 : assert_int_equal(ctx.res_count, 2);
2003 12 : assert_int_equal(ctx.got_cn, true);
2004 12 : assert_int_equal(ctx.got_2_cn, true);
2005 :
2006 12 : pid = waitpid(ctx.child_pid, &wstatus, 0);
2007 12 : assert_int_equal(pid, ctx.child_pid);
2008 :
2009 12 : assert_true(WIFEXITED(wstatus));
2010 :
2011 12 : assert_int_equal(WEXITSTATUS(wstatus), 0);
2012 :
2013 :
2014 12 : }
2015 :
2016 3 : static void test_ldb_modify_during_indexed_search(void **state)
2017 : {
2018 3 : test_ldb_modify_during_search(state, true, false);
2019 3 : }
2020 :
2021 3 : static void test_ldb_modify_during_unindexed_search(void **state)
2022 : {
2023 3 : test_ldb_modify_during_search(state, false, false);
2024 3 : }
2025 :
2026 3 : static void test_ldb_rename_during_indexed_search(void **state)
2027 : {
2028 3 : test_ldb_modify_during_search(state, true, true);
2029 3 : }
2030 :
2031 3 : static void test_ldb_rename_during_unindexed_search(void **state)
2032 : {
2033 3 : test_ldb_modify_during_search(state, false, true);
2034 3 : }
2035 :
2036 : /*
2037 : * This test is also complex.
2038 : *
2039 : * The purpose is to test if a modify can occur during an ldb_search()
2040 : * before the end of the callback
2041 : *
2042 : * This would be a failure if if in process
2043 : * (1) and (2):
2044 : * - (1) ldb_search() starts and calls back for a number of entries
2045 : * - (2) an entry in the DB is allowed to change before the callback returns
2046 : * - (1) the callback can see the modification
2047 : *
2048 : */
2049 :
2050 : /*
2051 : * This purpose of this callback is to trigger a write in
2052 : * the child process while a search DONE callback is in progress.
2053 : *
2054 : * In ldb 1.1.31 ldb_search() omitted to take a all-record
2055 : * lock for the full duration of the search and callbacks
2056 : *
2057 : * We assume that if the write will proceed, it will proceed in a 3
2058 : * second window after the function is called.
2059 : */
2060 :
2061 6 : static int test_ldb_modify_during_whole_search_callback1(struct ldb_request *req,
2062 : struct ldb_reply *ares)
2063 : {
2064 6 : int ret;
2065 6 : int pipes[2];
2066 6 : char buf[2];
2067 6 : struct modify_during_search_test_ctx *ctx = req->context;
2068 6 : struct ldb_dn *search_dn;
2069 6 : struct ldb_result *res2;
2070 6 : unsigned res_count;
2071 6 : switch (ares->type) {
2072 : case LDB_REPLY_ENTRY:
2073 : case LDB_REPLY_REFERRAL:
2074 : return LDB_SUCCESS;
2075 :
2076 : case LDB_REPLY_DONE:
2077 : break;
2078 : }
2079 :
2080 3 : ret = pipe(pipes);
2081 3 : assert_int_equal(ret, 0);
2082 :
2083 3 : ctx->child_pid = fork();
2084 6 : if (ctx->child_pid == 0) {
2085 3 : TALLOC_CTX *tmp_ctx = NULL;
2086 3 : struct ldb_message *msg;
2087 3 : struct ldb_message_element *el;
2088 3 : TALLOC_FREE(ctx->test_ctx->ldb);
2089 3 : TALLOC_FREE(ctx->test_ctx->ev);
2090 3 : close(pipes[0]);
2091 3 : ctx->test_ctx->ev = tevent_context_init(ctx->test_ctx);
2092 3 : if (ctx->test_ctx->ev == NULL) {
2093 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2094 : }
2095 :
2096 3 : ctx->test_ctx->ldb = ldb_init(ctx->test_ctx,
2097 : ctx->test_ctx->ev);
2098 3 : if (ctx->test_ctx->ldb == NULL) {
2099 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2100 : }
2101 :
2102 3 : ret = ldb_connect(ctx->test_ctx->ldb,
2103 : ctx->test_ctx->dbpath, 0, NULL);
2104 3 : if (ret != LDB_SUCCESS) {
2105 0 : exit(ret);
2106 : }
2107 :
2108 3 : tmp_ctx = talloc_new(ctx->test_ctx);
2109 3 : if (tmp_ctx == NULL) {
2110 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2111 : }
2112 :
2113 3 : msg = ldb_msg_new(tmp_ctx);
2114 3 : if (msg == NULL) {
2115 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2116 : }
2117 :
2118 3 : msg->dn = ldb_dn_new_fmt(msg, ctx->test_ctx->ldb,
2119 : "cn=test_search_cn,"
2120 : "dc=search_test_entry");
2121 3 : if (msg->dn == NULL) {
2122 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2123 : }
2124 :
2125 3 : ret = ldb_msg_add_string(msg, "filterAttr", "TRUE");
2126 3 : if (ret != 0) {
2127 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2128 : }
2129 3 : el = ldb_msg_find_element(msg, "filterAttr");
2130 3 : if (el == NULL) {
2131 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2132 : }
2133 3 : el->flags = LDB_FLAG_MOD_REPLACE;
2134 :
2135 3 : ret = ldb_transaction_start(ctx->test_ctx->ldb);
2136 3 : if (ret != 0) {
2137 0 : exit(ret);
2138 : }
2139 :
2140 3 : if (write(pipes[1], "GO", 2) != 2) {
2141 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2142 : }
2143 :
2144 3 : ret = ldb_modify(ctx->test_ctx->ldb, msg);
2145 3 : if (ret != 0) {
2146 0 : exit(ret);
2147 : }
2148 :
2149 3 : ret = ldb_transaction_commit(ctx->test_ctx->ldb);
2150 3 : exit(ret);
2151 : }
2152 :
2153 3 : close(pipes[1]);
2154 3 : ret = read(pipes[0], buf, 2);
2155 3 : assert_int_equal(ret, 2);
2156 :
2157 3 : sleep(3);
2158 :
2159 : /*
2160 : * If writes are not blocked until after this function, we
2161 : * will be able to successfully search for this modification
2162 : * here
2163 : */
2164 :
2165 3 : search_dn = ldb_dn_new_fmt(ares, ctx->test_ctx->ldb,
2166 : "cn=test_search_cn,"
2167 : "dc=search_test_entry");
2168 :
2169 3 : ret = ldb_search(ctx->test_ctx->ldb, ares,
2170 : &res2, search_dn, LDB_SCOPE_BASE, NULL,
2171 : "filterAttr=TRUE");
2172 :
2173 : /*
2174 : * We do this in an unusual order, because if we fail an assert before
2175 : * ldb_request_done(), we will also fail to clean up as we hold locks.
2176 : */
2177 :
2178 3 : res_count = res2->count;
2179 3 : ldb_request_done(req, LDB_SUCCESS);
2180 3 : assert_int_equal(ret, 0);
2181 :
2182 : /* We should not have got the result */
2183 3 : assert_int_equal(res_count, 0);
2184 :
2185 3 : return ret;
2186 : }
2187 :
2188 3 : static void test_ldb_modify_during_whole_search(void **state)
2189 : {
2190 3 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
2191 : struct search_test_ctx);
2192 3 : struct modify_during_search_test_ctx
2193 3 : ctx =
2194 : {
2195 3 : .test_ctx = search_test_ctx->ldb_test_ctx,
2196 : };
2197 :
2198 3 : int ret;
2199 3 : struct ldb_request *req;
2200 3 : pid_t pid;
2201 3 : int wstatus;
2202 3 : struct ldb_dn *search_dn;
2203 3 : struct ldb_result *res2;
2204 :
2205 3 : tevent_loop_allow_nesting(search_test_ctx->ldb_test_ctx->ev);
2206 :
2207 3 : ctx.basedn
2208 6 : = ldb_dn_new_fmt(search_test_ctx,
2209 3 : search_test_ctx->ldb_test_ctx->ldb,
2210 : "%s",
2211 : search_test_ctx->base_dn);
2212 3 : assert_non_null(ctx.basedn);
2213 :
2214 :
2215 : /*
2216 : * The search just needs to call DONE, we don't care about the
2217 : * contents of the search for this test
2218 : */
2219 6 : ret = ldb_build_search_req(&req,
2220 3 : search_test_ctx->ldb_test_ctx->ldb,
2221 : search_test_ctx,
2222 : ctx.basedn,
2223 : LDB_SCOPE_SUBTREE,
2224 : "(&(!(filterAttr=*))"
2225 : "(cn=test_search_cn))",
2226 : NULL,
2227 : NULL,
2228 : &ctx,
2229 : test_ldb_modify_during_whole_search_callback1,
2230 : NULL);
2231 3 : assert_int_equal(ret, 0);
2232 3 : ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req);
2233 :
2234 3 : if (ret == LDB_SUCCESS) {
2235 3 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
2236 : }
2237 3 : assert_int_equal(ret, 0);
2238 :
2239 3 : pid = waitpid(ctx.child_pid, &wstatus, 0);
2240 3 : assert_int_equal(pid, ctx.child_pid);
2241 :
2242 3 : assert_true(WIFEXITED(wstatus));
2243 :
2244 3 : assert_int_equal(WEXITSTATUS(wstatus), 0);
2245 :
2246 : /*
2247 : * If writes are blocked until after the search function, we
2248 : * will be able to successfully search for this modification
2249 : * now
2250 : */
2251 :
2252 6 : search_dn = ldb_dn_new_fmt(search_test_ctx,
2253 3 : search_test_ctx->ldb_test_ctx->ldb,
2254 : "cn=test_search_cn,"
2255 : "dc=search_test_entry");
2256 :
2257 3 : ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb,
2258 : search_test_ctx,
2259 : &res2, search_dn, LDB_SCOPE_BASE, NULL,
2260 : "filterAttr=TRUE");
2261 3 : assert_int_equal(ret, 0);
2262 :
2263 : /* We got the result */
2264 3 : assert_int_equal(res2->count, 1);
2265 3 : }
2266 :
2267 : /*
2268 : * This test is also complex.
2269 : *
2270 : * The purpose is to test if a modify can occur during an ldb_search()
2271 : * before the request is destroyed with TALLOC_FREE()
2272 : *
2273 : * This would be a failure if in process
2274 : * (1) and (2):
2275 : * - (1) ldb_search() starts and waits
2276 : * - (2) an entry in the DB is allowed to change before the ldb_wait() is called
2277 : * - (1) the original process can see the modification before the TALLOC_FREE()
2278 : * also we check that
2279 : * - (1) the original process can see the modification after the TALLOC_FREE()
2280 : *
2281 : */
2282 :
2283 : /*
2284 : * This purpose of this callback is to trigger a write in
2285 : * the child process before the ldb_wait() is called
2286 : *
2287 : * In ldb 1.1.31 ldb_search() omitted to take a all-record
2288 : * lock for the full duration of the search and callbacks
2289 : *
2290 : * We assume that if the write will proceed, it will proceed in a 3
2291 : * second window after the function is called.
2292 : */
2293 :
2294 0 : static int test_ldb_modify_before_ldb_wait_callback1(struct ldb_request *req,
2295 : struct ldb_reply *ares)
2296 : {
2297 0 : switch (ares->type) {
2298 : case LDB_REPLY_ENTRY:
2299 : case LDB_REPLY_REFERRAL:
2300 : return LDB_SUCCESS;
2301 :
2302 : case LDB_REPLY_DONE:
2303 : break;
2304 : }
2305 :
2306 0 : return ldb_request_done(req, LDB_SUCCESS);
2307 : }
2308 :
2309 3 : static void test_ldb_modify_before_ldb_wait(void **state)
2310 : {
2311 3 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
2312 : struct search_test_ctx);
2313 3 : int ret;
2314 3 : struct ldb_request *req;
2315 3 : pid_t pid;
2316 3 : int wstatus;
2317 3 : struct ldb_dn *search_dn;
2318 3 : struct ldb_dn *basedn;
2319 3 : struct ldb_result *res2;
2320 3 : int pipes[2];
2321 3 : char buf[2];
2322 3 : pid_t child_pid;
2323 3 : unsigned res_count;
2324 :
2325 6 : search_dn = ldb_dn_new_fmt(search_test_ctx,
2326 3 : search_test_ctx->ldb_test_ctx->ldb,
2327 : "cn=test_search_cn,"
2328 : "dc=search_test_entry");
2329 3 : assert_non_null(search_dn);
2330 :
2331 6 : basedn = ldb_dn_new_fmt(search_test_ctx,
2332 3 : search_test_ctx->ldb_test_ctx->ldb,
2333 : "%s",
2334 : search_test_ctx->base_dn);
2335 3 : assert_non_null(basedn);
2336 :
2337 : /*
2338 : * The search just needs to call DONE, we don't care about the
2339 : * contents of the search for this test
2340 : */
2341 6 : ret = ldb_build_search_req(&req,
2342 3 : search_test_ctx->ldb_test_ctx->ldb,
2343 : search_test_ctx,
2344 : basedn,
2345 : LDB_SCOPE_SUBTREE,
2346 : "(&(!(filterAttr=*))"
2347 : "(cn=test_search_cn))",
2348 : NULL,
2349 : NULL,
2350 : NULL,
2351 : test_ldb_modify_before_ldb_wait_callback1,
2352 : NULL);
2353 3 : assert_int_equal(ret, 0);
2354 3 : ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req);
2355 :
2356 3 : ret = pipe(pipes);
2357 3 : assert_int_equal(ret, 0);
2358 :
2359 3 : child_pid = fork();
2360 6 : if (child_pid == 0) {
2361 3 : TALLOC_CTX *tmp_ctx = NULL;
2362 3 : struct ldb_message *msg;
2363 3 : struct ldb_message_element *el;
2364 3 : TALLOC_FREE(search_test_ctx->ldb_test_ctx->ldb);
2365 3 : TALLOC_FREE(search_test_ctx->ldb_test_ctx->ev);
2366 3 : close(pipes[0]);
2367 3 : search_test_ctx->ldb_test_ctx->ev = tevent_context_init(search_test_ctx->ldb_test_ctx);
2368 3 : if (search_test_ctx->ldb_test_ctx->ev == NULL) {
2369 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2370 : }
2371 :
2372 3 : search_test_ctx->ldb_test_ctx->ldb = ldb_init(search_test_ctx->ldb_test_ctx,
2373 : search_test_ctx->ldb_test_ctx->ev);
2374 3 : if (search_test_ctx->ldb_test_ctx->ldb == NULL) {
2375 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2376 : }
2377 :
2378 3 : ret = ldb_connect(search_test_ctx->ldb_test_ctx->ldb,
2379 : search_test_ctx->ldb_test_ctx->dbpath, 0, NULL);
2380 3 : if (ret != LDB_SUCCESS) {
2381 0 : exit(ret);
2382 : }
2383 :
2384 3 : tmp_ctx = talloc_new(search_test_ctx->ldb_test_ctx);
2385 3 : if (tmp_ctx == NULL) {
2386 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2387 : }
2388 :
2389 3 : msg = ldb_msg_new(tmp_ctx);
2390 3 : if (msg == NULL) {
2391 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2392 : }
2393 :
2394 : /*
2395 : * We must re-create this DN from a string to ensure
2396 : * it does not reference the now-gone LDB context of
2397 : * the parent
2398 : */
2399 6 : msg->dn = ldb_dn_new_fmt(search_test_ctx,
2400 3 : search_test_ctx->ldb_test_ctx->ldb,
2401 : "cn=test_search_cn,"
2402 : "dc=search_test_entry");
2403 :
2404 3 : if (msg->dn == NULL) {
2405 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2406 : }
2407 :
2408 3 : ret = ldb_msg_add_string(msg, "filterAttr", "TRUE");
2409 3 : if (ret != 0) {
2410 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2411 : }
2412 3 : el = ldb_msg_find_element(msg, "filterAttr");
2413 3 : if (el == NULL) {
2414 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2415 : }
2416 3 : el->flags = LDB_FLAG_MOD_REPLACE;
2417 :
2418 3 : ret = ldb_transaction_start(search_test_ctx->ldb_test_ctx->ldb);
2419 3 : if (ret != 0) {
2420 0 : exit(ret);
2421 : }
2422 :
2423 3 : if (write(pipes[1], "GO", 2) != 2) {
2424 0 : exit(LDB_ERR_OPERATIONS_ERROR);
2425 : }
2426 :
2427 3 : ret = ldb_modify(search_test_ctx->ldb_test_ctx->ldb, msg);
2428 3 : if (ret != 0) {
2429 0 : exit(ret);
2430 : }
2431 :
2432 3 : ret = ldb_transaction_commit(search_test_ctx->ldb_test_ctx->ldb);
2433 3 : exit(ret);
2434 : }
2435 3 : close(pipes[1]);
2436 :
2437 3 : ret = read(pipes[0], buf, 2);
2438 3 : assert_int_equal(ret, 2);
2439 :
2440 3 : sleep(3);
2441 :
2442 : /*
2443 : * If writes are not blocked until after the (never called) ldb_wait(), we
2444 : * will be able to successfully search for this modification
2445 : * here
2446 : */
2447 :
2448 3 : ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb, search_test_ctx,
2449 : &res2, search_dn, LDB_SCOPE_BASE, NULL,
2450 : "filterAttr=TRUE");
2451 :
2452 : /*
2453 : * We avoid making assertions before TALLOC_FREE()ing the request,
2454 : * lest the assert fail and mess with the clean-up because we still
2455 : * have locks.
2456 : */
2457 3 : res_count = res2->count;
2458 3 : TALLOC_FREE(req);
2459 :
2460 : /* We should not have got the result */
2461 3 : assert_int_equal(res_count, 0);
2462 3 : assert_int_equal(ret, 0);
2463 :
2464 3 : pid = waitpid(child_pid, &wstatus, 0);
2465 3 : assert_int_equal(pid, child_pid);
2466 :
2467 3 : assert_true(WIFEXITED(wstatus));
2468 :
2469 3 : assert_int_equal(WEXITSTATUS(wstatus), 0);
2470 :
2471 : /*
2472 : * If writes are blocked until after the search request was freed, we
2473 : * will be able to successfully search for this modification
2474 : * now
2475 : */
2476 :
2477 6 : search_dn = ldb_dn_new_fmt(search_test_ctx,
2478 3 : search_test_ctx->ldb_test_ctx->ldb,
2479 : "cn=test_search_cn,"
2480 : "dc=search_test_entry");
2481 :
2482 3 : ret = ldb_search(search_test_ctx->ldb_test_ctx->ldb,
2483 : search_test_ctx,
2484 : &res2, search_dn, LDB_SCOPE_BASE, NULL,
2485 : "filterAttr=TRUE");
2486 3 : assert_int_equal(ret, 0);
2487 :
2488 : /* We got the result */
2489 3 : assert_int_equal(res2->count, 1);
2490 3 : }
2491 :
2492 : /*
2493 : * This test is also complex.
2494 : * The purpose is to test if a modify can occur during an ldb_search()
2495 : * This would be a failure if if in process
2496 : * (1) and (2):
2497 : * - (1) ltdb_search() starts and calls back for one entry
2498 : * - (2) one of the entries to be matched is modified
2499 : * - (1) the indexed search tries to return the modified entry, but
2500 : * it is no longer found, either:
2501 : * - despite it still matching (dn changed)
2502 : * - it no longer matching (attrs changed)
2503 : *
2504 : * We also try un-indexed to show that the behaviour differs on this
2505 : * point, which it should not (an index should only impact search
2506 : * speed).
2507 : */
2508 :
2509 : /*
2510 : * This purpose of this callback is to trigger a write in the callback
2511 : * so as to change in in-memory index code while looping over the
2512 : * index result.
2513 : */
2514 :
2515 36 : static int test_ldb_callback_modify_during_search_callback1(struct ldb_request *req,
2516 : struct ldb_reply *ares)
2517 : {
2518 36 : int ret;
2519 36 : struct modify_during_search_test_ctx *ctx = req->context;
2520 36 : struct ldb_dn *dn = NULL, *new_dn = NULL;
2521 36 : TALLOC_CTX *tmp_ctx = talloc_new(ctx->test_ctx);
2522 36 : struct ldb_message *msg = NULL;
2523 :
2524 36 : assert_non_null(tmp_ctx);
2525 :
2526 36 : switch (ares->type) {
2527 24 : case LDB_REPLY_ENTRY:
2528 : {
2529 24 : const struct ldb_val *cn_val
2530 24 : = ldb_dn_get_component_val(ares->message->dn, 0);
2531 24 : const char *cn = (char *)cn_val->data;
2532 24 : ctx->res_count++;
2533 24 : if (strcmp(cn, "test_search_cn") == 0) {
2534 12 : ctx->got_cn = true;
2535 12 : } else if (strcmp(cn, "test_search_2_cn") == 0) {
2536 12 : ctx->got_2_cn = true;
2537 : }
2538 24 : if (ctx->res_count == 2) {
2539 : return LDB_SUCCESS;
2540 : }
2541 : break;
2542 : }
2543 : case LDB_REPLY_REFERRAL:
2544 : return LDB_SUCCESS;
2545 :
2546 12 : case LDB_REPLY_DONE:
2547 12 : return ldb_request_done(req, LDB_SUCCESS);
2548 : }
2549 :
2550 12 : if (ctx->rename) {
2551 6 : if (ctx->got_2_cn) {
2552 : /* Modify this one */
2553 0 : dn = ldb_dn_new_fmt(tmp_ctx,
2554 0 : ctx->test_ctx->ldb,
2555 : "cn=test_search_2_cn,%s",
2556 : ldb_dn_get_linearized(ctx->basedn));
2557 : } else {
2558 6 : dn = ldb_dn_new_fmt(tmp_ctx,
2559 6 : ctx->test_ctx->ldb,
2560 : "cn=test_search_cn,%s",
2561 : ldb_dn_get_linearized(ctx->basedn));
2562 : }
2563 6 : assert_non_null(dn);
2564 :
2565 12 : new_dn = ldb_dn_new_fmt(tmp_ctx,
2566 6 : ctx->test_ctx->ldb,
2567 : "cn=test_search_cn_renamed,"
2568 : "dc=not_search_test_entry");
2569 6 : assert_non_null(new_dn);
2570 :
2571 6 : ret = ldb_rename(ctx->test_ctx->ldb, dn, new_dn);
2572 6 : assert_int_equal(ret, 0);
2573 :
2574 : } else {
2575 6 : if (ctx->got_2_cn) {
2576 : /* Delete this one */
2577 0 : dn = ldb_dn_new_fmt(tmp_ctx,
2578 0 : ctx->test_ctx->ldb,
2579 : "cn=test_search_2_cn,%s",
2580 : ldb_dn_get_linearized(ctx->basedn));
2581 : } else {
2582 6 : dn = ldb_dn_new_fmt(tmp_ctx,
2583 6 : ctx->test_ctx->ldb,
2584 : "cn=test_search_cn,%s",
2585 : ldb_dn_get_linearized(ctx->basedn));
2586 : }
2587 6 : assert_non_null(dn);
2588 :
2589 6 : ret = ldb_delete(ctx->test_ctx->ldb, dn);
2590 6 : assert_int_equal(ret, 0);
2591 : }
2592 :
2593 : /*
2594 : * Now fill in the position we just removed from the
2595 : * index to ensure we fail the test (otherwise we just read
2596 : * past the end of the array and find the value we wanted to
2597 : * skip)
2598 : */
2599 12 : msg = ldb_msg_new(tmp_ctx);
2600 12 : assert_non_null(msg);
2601 :
2602 : /* We deliberately use ou= not cn= here */
2603 12 : msg->dn = ldb_dn_new_fmt(msg,
2604 12 : ctx->test_ctx->ldb,
2605 : "ou=test_search_cn_extra,%s",
2606 : ldb_dn_get_linearized(ctx->basedn));
2607 :
2608 12 : ret = ldb_msg_add_string(msg,
2609 : "objectUUID",
2610 : "0123456789abcde3");
2611 :
2612 12 : ret = ldb_add(ctx->test_ctx->ldb,
2613 : msg);
2614 12 : assert_int_equal(ret, LDB_SUCCESS);
2615 :
2616 12 : TALLOC_FREE(tmp_ctx);
2617 : return LDB_SUCCESS;
2618 : }
2619 :
2620 12 : static void test_ldb_callback_modify_during_search(void **state, bool add_index,
2621 : bool rename)
2622 : {
2623 12 : struct search_test_ctx *search_test_ctx = talloc_get_type_abort(*state,
2624 : struct search_test_ctx);
2625 12 : struct modify_during_search_test_ctx
2626 12 : ctx =
2627 : { .res_count = 0,
2628 12 : .test_ctx = search_test_ctx->ldb_test_ctx,
2629 : .rename = rename
2630 : };
2631 :
2632 12 : int ret;
2633 12 : struct ldb_request *req;
2634 :
2635 12 : ret = ldb_transaction_start(search_test_ctx->ldb_test_ctx->ldb);
2636 12 : assert_int_equal(ret, 0);
2637 :
2638 12 : if (add_index) {
2639 6 : struct ldb_message *msg;
2640 12 : struct ldb_dn *indexlist = ldb_dn_new(search_test_ctx,
2641 6 : search_test_ctx->ldb_test_ctx->ldb,
2642 : "@INDEXLIST");
2643 6 : assert_non_null(indexlist);
2644 :
2645 6 : msg = ldb_msg_new(search_test_ctx);
2646 6 : assert_non_null(msg);
2647 :
2648 6 : msg->dn = indexlist;
2649 :
2650 6 : ret = ldb_msg_add_string(msg, "@IDXONE", "1");
2651 6 : assert_int_equal(ret, LDB_SUCCESS);
2652 6 : ret = ldb_msg_add_string(msg, "@IDXATTR", "cn");
2653 6 : assert_int_equal(ret, LDB_SUCCESS);
2654 6 : ret = ldb_add(search_test_ctx->ldb_test_ctx->ldb,
2655 : msg);
2656 6 : if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
2657 4 : msg->elements[0].flags = LDB_FLAG_MOD_ADD;
2658 4 : msg->elements[1].flags = LDB_FLAG_MOD_ADD;
2659 4 : ret = ldb_modify(search_test_ctx->ldb_test_ctx->ldb,
2660 : msg);
2661 : }
2662 6 : assert_int_equal(ret, LDB_SUCCESS);
2663 :
2664 : /*
2665 : * Now bring the IDXONE index into memory by modifying
2666 : * it. This exposes an issue in ldb_tdb
2667 : */
2668 6 : msg = ldb_msg_new(search_test_ctx);
2669 6 : assert_non_null(msg);
2670 :
2671 12 : msg->dn = ldb_dn_new_fmt(search_test_ctx,
2672 6 : search_test_ctx->ldb_test_ctx->ldb,
2673 : "cn=test_search_cn_extra,%s",
2674 : search_test_ctx->base_dn);
2675 :
2676 6 : ret = ldb_msg_add_string(msg,
2677 : "objectUUID",
2678 : "0123456789abcde2");
2679 :
2680 6 : ret = ldb_add(search_test_ctx->ldb_test_ctx->ldb,
2681 : msg);
2682 6 : assert_int_equal(ret, LDB_SUCCESS);
2683 :
2684 6 : ret = ldb_delete(search_test_ctx->ldb_test_ctx->ldb,
2685 : msg->dn);
2686 6 : assert_int_equal(ret, LDB_SUCCESS);
2687 : }
2688 :
2689 12 : tevent_loop_allow_nesting(search_test_ctx->ldb_test_ctx->ev);
2690 :
2691 12 : ctx.basedn
2692 24 : = ldb_dn_new_fmt(search_test_ctx,
2693 12 : search_test_ctx->ldb_test_ctx->ldb,
2694 : "%s",
2695 : search_test_ctx->base_dn);
2696 12 : assert_non_null(ctx.basedn);
2697 :
2698 :
2699 : /*
2700 : * This search must be over multiple items, and should include
2701 : * the new name after a rename, to show that it would match
2702 : * both before and after that modify
2703 : *
2704 : * This needs to be a search that isn't matched by an index so
2705 : * that we just use the one-level index.
2706 : */
2707 24 : ret = ldb_build_search_req(&req,
2708 12 : search_test_ctx->ldb_test_ctx->ldb,
2709 : search_test_ctx,
2710 : ctx.basedn,
2711 : LDB_SCOPE_ONELEVEL,
2712 : "(cn=*)",
2713 : NULL,
2714 : NULL,
2715 : &ctx,
2716 : test_ldb_callback_modify_during_search_callback1,
2717 : NULL);
2718 12 : assert_int_equal(ret, 0);
2719 :
2720 12 : ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req);
2721 :
2722 12 : if (ret == LDB_SUCCESS) {
2723 12 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
2724 : }
2725 12 : assert_int_equal(ret, 0);
2726 :
2727 12 : ret = ldb_transaction_commit(search_test_ctx->ldb_test_ctx->ldb);
2728 12 : assert_int_equal(ret, 0);
2729 :
2730 12 : assert_int_equal(ctx.res_count, 2);
2731 12 : assert_int_equal(ctx.got_cn, true);
2732 12 : assert_int_equal(ctx.got_2_cn, true);
2733 12 : }
2734 :
2735 3 : static void test_ldb_callback_delete_during_indexed_search(void **state)
2736 : {
2737 3 : test_ldb_callback_modify_during_search(state, true, false);
2738 3 : }
2739 :
2740 3 : static void test_ldb_callback_delete_during_unindexed_search(void **state)
2741 : {
2742 3 : test_ldb_callback_modify_during_search(state, false, false);
2743 3 : }
2744 :
2745 3 : static void test_ldb_callback_rename_during_indexed_search(void **state)
2746 : {
2747 3 : test_ldb_callback_modify_during_search(state, true, true);
2748 3 : }
2749 :
2750 3 : static void test_ldb_callback_rename_during_unindexed_search(void **state)
2751 : {
2752 3 : test_ldb_callback_modify_during_search(state, false, true);
2753 3 : }
2754 :
2755 9 : static int ldb_case_test_setup(void **state)
2756 : {
2757 9 : int ret;
2758 9 : struct ldb_ldif *ldif;
2759 9 : struct ldbtest_ctx *ldb_test_ctx;
2760 9 : const char *attrs_ldif = \
2761 : "dn: @ATTRIBUTES\n"
2762 : "cn: CASE_INSENSITIVE\n"
2763 : "\n";
2764 9 : struct keyval kvs[] = {
2765 : { "cn", "CaseInsensitiveValue" },
2766 : { "uid", "CaseSensitiveValue" },
2767 : { "objectUUID", "0123456789abcdef" },
2768 : { NULL, NULL },
2769 : };
2770 :
2771 :
2772 9 : ldbtest_setup((void **) &ldb_test_ctx);
2773 :
2774 18 : while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &attrs_ldif))) {
2775 9 : ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
2776 9 : assert_int_equal(ret, LDB_SUCCESS);
2777 : }
2778 :
2779 9 : ldb_test_add_data(ldb_test_ctx,
2780 : ldb_test_ctx,
2781 : "cn=CaseInsensitiveValue",
2782 : kvs);
2783 :
2784 9 : *state = ldb_test_ctx;
2785 9 : return 0;
2786 : }
2787 :
2788 9 : static int ldb_case_test_teardown(void **state)
2789 : {
2790 9 : int ret;
2791 9 : struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
2792 : struct ldbtest_ctx);
2793 :
2794 9 : struct ldb_dn *del_dn;
2795 :
2796 9 : del_dn = ldb_dn_new_fmt(ldb_test_ctx,
2797 : ldb_test_ctx->ldb,
2798 : "@ATTRIBUTES");
2799 9 : assert_non_null(del_dn);
2800 :
2801 9 : ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
2802 9 : assert_int_equal(ret, LDB_SUCCESS);
2803 :
2804 9 : assert_dn_doesnt_exist(ldb_test_ctx,
2805 : "@ATTRIBUTES");
2806 :
2807 9 : ldb_test_remove_data(ldb_test_ctx, ldb_test_ctx,
2808 : "cn=CaseInsensitiveValue");
2809 :
2810 9 : ldbtest_teardown((void **) &ldb_test_ctx);
2811 9 : return 0;
2812 : }
2813 :
2814 3 : static void test_ldb_attrs_case_insensitive(void **state)
2815 : {
2816 3 : int cnt;
2817 3 : struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
2818 : struct ldbtest_ctx);
2819 :
2820 : /* cn matches exact case */
2821 3 : cnt = sub_search_count(ldb_test_ctx, "", "cn=CaseInsensitiveValue");
2822 3 : assert_int_equal(cnt, 1);
2823 :
2824 : /* cn matches lower case */
2825 3 : cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
2826 3 : assert_int_equal(cnt, 1);
2827 :
2828 : /* uid matches exact case */
2829 3 : cnt = sub_search_count(ldb_test_ctx, "", "uid=CaseSensitiveValue");
2830 3 : assert_int_equal(cnt, 1);
2831 :
2832 : /* uid does not match lower case */
2833 3 : cnt = sub_search_count(ldb_test_ctx, "", "uid=casesensitivevalue");
2834 3 : assert_int_equal(cnt, 0);
2835 3 : }
2836 :
2837 : static struct ldb_schema_attribute cn_attr_1;
2838 : static struct ldb_schema_attribute cn_attr_2;
2839 : static struct ldb_schema_attribute default_attr;
2840 :
2841 : /*
2842 : override the name to attribute handler function
2843 : */
2844 145 : static const struct ldb_schema_attribute *ldb_test_attribute_handler_override(struct ldb_context *ldb,
2845 : void *private_data,
2846 : const char *name)
2847 : {
2848 145 : if (private_data != NULL && ldb_attr_cmp(name, "cn") == 0) {
2849 : return &cn_attr_1;
2850 109 : } else if (private_data == NULL && ldb_attr_cmp(name, "cn") == 0) {
2851 : return &cn_attr_2;
2852 75 : } else if (ldb_attr_cmp(name, "uid") == 0) {
2853 18 : return &cn_attr_2;
2854 : }
2855 : return &default_attr;
2856 : }
2857 :
2858 3 : static void test_ldb_attrs_case_handler(void **state)
2859 : {
2860 3 : int cnt;
2861 3 : int ret;
2862 3 : const struct ldb_schema_syntax *syntax;
2863 :
2864 3 : struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
2865 : struct ldbtest_ctx);
2866 3 : struct ldb_context *ldb = ldb_test_ctx->ldb;
2867 :
2868 : /* cn matches lower case */
2869 3 : cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
2870 3 : assert_int_equal(cnt, 1);
2871 :
2872 3 : syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING);
2873 3 : assert_non_null(syntax);
2874 :
2875 3 : ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
2876 : "*", 0,
2877 : syntax, &default_attr);
2878 3 : assert_int_equal(ret, LDB_SUCCESS);
2879 :
2880 3 : syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING);
2881 3 : assert_non_null(syntax);
2882 :
2883 3 : ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
2884 : "cn", 0,
2885 : syntax, &cn_attr_1);
2886 3 : assert_int_equal(ret, LDB_SUCCESS);
2887 :
2888 : /*
2889 : * Set an attribute handler, which will fail to match as we
2890 : * force case sensitive
2891 : */
2892 3 : ldb_schema_attribute_set_override_handler(ldb,
2893 : ldb_test_attribute_handler_override,
2894 : (void *)1);
2895 :
2896 : /* cn does not matche lower case */
2897 3 : cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
2898 3 : assert_int_equal(cnt, 0);
2899 :
2900 3 : syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_DIRECTORY_STRING);
2901 3 : assert_non_null(syntax);
2902 :
2903 3 : ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
2904 : "cn", 0,
2905 : syntax, &cn_attr_2);
2906 3 : assert_int_equal(ret, LDB_SUCCESS);
2907 :
2908 : /*
2909 : * Set an attribute handler, which will match as we
2910 : * force case insensitive
2911 : */
2912 3 : ldb_schema_attribute_set_override_handler(ldb,
2913 : ldb_test_attribute_handler_override,
2914 : NULL);
2915 :
2916 : /* cn matches lower case */
2917 3 : cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
2918 3 : assert_int_equal(cnt, 1);
2919 :
2920 3 : }
2921 :
2922 :
2923 3 : static void test_ldb_attrs_index_handler(void **state)
2924 : {
2925 3 : int cnt;
2926 3 : int ret;
2927 3 : const struct ldb_schema_syntax *syntax;
2928 3 : struct ldb_ldif *ldif;
2929 :
2930 3 : const char *index_ldif = \
2931 : "dn: @INDEXLIST\n"
2932 : "@IDXATTR: cn\n"
2933 : "\n";
2934 :
2935 3 : struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
2936 : struct ldbtest_ctx);
2937 3 : struct ldb_context *ldb = ldb_test_ctx->ldb;
2938 :
2939 : /* cn matches lower case */
2940 3 : cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
2941 3 : assert_int_equal(cnt, 1);
2942 :
2943 3 : syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING);
2944 3 : assert_non_null(syntax);
2945 :
2946 3 : ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
2947 : "cn", 0,
2948 : syntax, &cn_attr_1);
2949 3 : assert_int_equal(ret, LDB_SUCCESS);
2950 :
2951 3 : syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_DIRECTORY_STRING);
2952 3 : assert_non_null(syntax);
2953 :
2954 3 : ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
2955 : "cn", LDB_ATTR_FLAG_INDEXED,
2956 : syntax, &cn_attr_2);
2957 3 : assert_int_equal(ret, LDB_SUCCESS);
2958 :
2959 3 : syntax = ldb_standard_syntax_by_name(ldb, LDB_SYNTAX_OCTET_STRING);
2960 3 : assert_non_null(syntax);
2961 :
2962 3 : ret = ldb_schema_attribute_fill_with_syntax(ldb, ldb,
2963 : "", 0,
2964 : syntax, &default_attr);
2965 3 : assert_int_equal(ret, LDB_SUCCESS);
2966 :
2967 : /*
2968 : * Set an attribute handler
2969 : */
2970 3 : ldb_schema_attribute_set_override_handler(ldb,
2971 : ldb_test_attribute_handler_override,
2972 : NULL);
2973 :
2974 : /* cn matches lower case */
2975 3 : cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
2976 3 : assert_int_equal(cnt, 1);
2977 :
2978 : /* Add the index (actually any modify will do) */
2979 6 : while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) {
2980 3 : ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
2981 3 : if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
2982 2 : ldif->msg->elements[0].flags = LDB_FLAG_MOD_ADD;
2983 2 : ret = ldb_modify(ldb_test_ctx->ldb,
2984 : ldif->msg);
2985 : }
2986 3 : assert_int_equal(ret, LDB_SUCCESS);
2987 : }
2988 :
2989 3 : ldb_schema_set_override_indexlist(ldb, false);
2990 :
2991 : /* cn does match as there is an index now */
2992 3 : cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
2993 3 : assert_int_equal(cnt, 1);
2994 :
2995 : /*
2996 : * Set an attribute handler, which will later fail to match as we
2997 : * didn't re-index the DB
2998 : */
2999 3 : ldb_schema_attribute_set_override_handler(ldb,
3000 : ldb_test_attribute_handler_override,
3001 : (void *)1);
3002 :
3003 : /*
3004 : * cn does not match as we changed the case sensitivity, but
3005 : * didn't re-index
3006 : *
3007 : * This shows that the override is in control
3008 : */
3009 3 : cnt = sub_search_count(ldb_test_ctx, "", "cn=caseinsensitivevalue");
3010 3 : assert_int_equal(cnt, 0);
3011 :
3012 3 : }
3013 :
3014 3 : static int ldb_case_attrs_index_test_teardown(void **state)
3015 : {
3016 3 : int ret;
3017 3 : struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
3018 : struct ldbtest_ctx);
3019 3 : struct ldb_dn *del_dn;
3020 :
3021 3 : del_dn = ldb_dn_new_fmt(ldb_test_ctx,
3022 : ldb_test_ctx->ldb,
3023 : "@INDEXLIST");
3024 3 : assert_non_null(del_dn);
3025 :
3026 3 : ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
3027 3 : if (ret != LDB_ERR_NO_SUCH_OBJECT) {
3028 3 : assert_int_equal(ret, LDB_SUCCESS);
3029 : }
3030 :
3031 3 : assert_dn_doesnt_exist(ldb_test_ctx,
3032 : "@INDEXLIST");
3033 :
3034 3 : ldb_case_test_teardown(state);
3035 3 : return 0;
3036 : }
3037 :
3038 :
3039 : struct rename_test_ctx {
3040 : struct ldbtest_ctx *ldb_test_ctx;
3041 :
3042 : struct ldb_dn *basedn;
3043 : const char *str_basedn;
3044 :
3045 : const char *teardown_dn;
3046 : };
3047 :
3048 15 : static int ldb_rename_test_setup(void **state)
3049 : {
3050 15 : struct ldbtest_ctx *ldb_test_ctx;
3051 15 : struct rename_test_ctx *rename_test_ctx;
3052 15 : const char *strdn = "dc=rename_test_entry_from";
3053 :
3054 15 : ldbtest_setup((void **) &ldb_test_ctx);
3055 :
3056 15 : rename_test_ctx = talloc(ldb_test_ctx, struct rename_test_ctx);
3057 15 : assert_non_null(rename_test_ctx);
3058 15 : rename_test_ctx->ldb_test_ctx = ldb_test_ctx;
3059 15 : assert_non_null(rename_test_ctx->ldb_test_ctx);
3060 :
3061 30 : rename_test_ctx->basedn = ldb_dn_new_fmt(rename_test_ctx,
3062 15 : rename_test_ctx->ldb_test_ctx->ldb,
3063 : "%s", strdn);
3064 15 : assert_non_null(rename_test_ctx->basedn);
3065 :
3066 15 : rename_test_ctx->str_basedn = strdn;
3067 15 : rename_test_ctx->teardown_dn = strdn;
3068 :
3069 15 : add_dn_with_cn(ldb_test_ctx,
3070 : rename_test_ctx->basedn,
3071 : "test_rename_cn_val",
3072 : "0123456789abcde0");
3073 :
3074 15 : *state = rename_test_ctx;
3075 15 : return 0;
3076 : }
3077 :
3078 15 : static int ldb_rename_test_teardown(void **state)
3079 : {
3080 15 : int ret;
3081 15 : struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort(*state,
3082 : struct rename_test_ctx);
3083 15 : struct ldbtest_ctx *ldb_test_ctx;
3084 15 : struct ldb_dn *del_dn;
3085 :
3086 15 : ldb_test_ctx = rename_test_ctx->ldb_test_ctx;
3087 :
3088 15 : del_dn = ldb_dn_new_fmt(rename_test_ctx,
3089 : rename_test_ctx->ldb_test_ctx->ldb,
3090 : "%s", rename_test_ctx->teardown_dn);
3091 15 : assert_non_null(del_dn);
3092 :
3093 15 : ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
3094 15 : assert_int_equal(ret, LDB_SUCCESS);
3095 :
3096 15 : assert_dn_doesnt_exist(ldb_test_ctx,
3097 : rename_test_ctx->teardown_dn);
3098 :
3099 15 : ldbtest_teardown((void **) &ldb_test_ctx);
3100 15 : return 0;
3101 : }
3102 :
3103 3 : static void test_ldb_rename(void **state)
3104 : {
3105 3 : struct rename_test_ctx *rename_test_ctx =
3106 3 : talloc_get_type_abort(*state, struct rename_test_ctx);
3107 3 : int ret;
3108 3 : const char *str_new_dn = "dc=rename_test_entry_to";
3109 3 : struct ldb_dn *new_dn;
3110 :
3111 6 : new_dn = ldb_dn_new_fmt(rename_test_ctx,
3112 3 : rename_test_ctx->ldb_test_ctx->ldb,
3113 : "%s", str_new_dn);
3114 3 : assert_non_null(new_dn);
3115 :
3116 3 : ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb,
3117 : rename_test_ctx->basedn,
3118 : new_dn);
3119 3 : assert_int_equal(ret, LDB_SUCCESS);
3120 :
3121 3 : assert_dn_exists(rename_test_ctx->ldb_test_ctx, str_new_dn);
3122 3 : assert_dn_doesnt_exist(rename_test_ctx->ldb_test_ctx,
3123 : rename_test_ctx->str_basedn);
3124 3 : rename_test_ctx->teardown_dn = str_new_dn;
3125 :
3126 : /* FIXME - test the values which didn't change */
3127 3 : }
3128 :
3129 3 : static void test_ldb_rename_from_doesnt_exist(void **state)
3130 : {
3131 3 : struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort(
3132 : *state,
3133 : struct rename_test_ctx);
3134 3 : int ret;
3135 3 : const char *str_new_dn = "dc=rename_test_entry_to";
3136 3 : const char *str_bad_old_dn = "dc=rename_test_no_such_entry";
3137 3 : struct ldb_dn *new_dn;
3138 3 : struct ldb_dn *bad_old_dn;
3139 :
3140 6 : new_dn = ldb_dn_new_fmt(rename_test_ctx,
3141 3 : rename_test_ctx->ldb_test_ctx->ldb,
3142 : "%s", str_new_dn);
3143 3 : assert_non_null(new_dn);
3144 :
3145 6 : bad_old_dn = ldb_dn_new_fmt(rename_test_ctx,
3146 3 : rename_test_ctx->ldb_test_ctx->ldb,
3147 : "%s", str_bad_old_dn);
3148 3 : assert_non_null(bad_old_dn);
3149 :
3150 3 : assert_dn_doesnt_exist(rename_test_ctx->ldb_test_ctx,
3151 : str_bad_old_dn);
3152 :
3153 3 : ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb,
3154 : bad_old_dn, new_dn);
3155 3 : assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
3156 :
3157 3 : assert_dn_doesnt_exist(rename_test_ctx->ldb_test_ctx,
3158 : str_new_dn);
3159 3 : }
3160 :
3161 3 : static void test_ldb_rename_to_exists(void **state)
3162 : {
3163 3 : struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort(
3164 : *state,
3165 : struct rename_test_ctx);
3166 3 : int ret;
3167 3 : const char *str_new_dn = "dc=rename_test_already_exists";
3168 3 : struct ldb_dn *new_dn;
3169 :
3170 6 : new_dn = ldb_dn_new_fmt(rename_test_ctx,
3171 3 : rename_test_ctx->ldb_test_ctx->ldb,
3172 : "%s", str_new_dn);
3173 3 : assert_non_null(new_dn);
3174 :
3175 3 : add_dn_with_cn(rename_test_ctx->ldb_test_ctx,
3176 : new_dn,
3177 : "test_rename_cn_val",
3178 : "0123456789abcde1");
3179 :
3180 3 : ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb,
3181 : rename_test_ctx->basedn,
3182 : new_dn);
3183 3 : assert_int_equal(ret, LDB_ERR_ENTRY_ALREADY_EXISTS);
3184 :
3185 : /* Old object must still exist */
3186 3 : assert_dn_exists(rename_test_ctx->ldb_test_ctx,
3187 : rename_test_ctx->str_basedn);
3188 :
3189 3 : ret = ldb_delete(rename_test_ctx->ldb_test_ctx->ldb,
3190 : new_dn);
3191 3 : assert_int_equal(ret, LDB_SUCCESS);
3192 :
3193 3 : assert_dn_exists(rename_test_ctx->ldb_test_ctx,
3194 : rename_test_ctx->teardown_dn);
3195 3 : }
3196 :
3197 3 : static void test_ldb_rename_self(void **state)
3198 : {
3199 3 : struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort(
3200 : *state,
3201 : struct rename_test_ctx);
3202 3 : int ret;
3203 :
3204 : /* Oddly enough, this is a success in ldb.. */
3205 3 : ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb,
3206 : rename_test_ctx->basedn,
3207 : rename_test_ctx->basedn);
3208 3 : assert_int_equal(ret, LDB_SUCCESS);
3209 :
3210 : /* Old object must still exist */
3211 3 : assert_dn_exists(rename_test_ctx->ldb_test_ctx,
3212 : rename_test_ctx->str_basedn);
3213 3 : }
3214 :
3215 3 : static void test_ldb_rename_dn_case_change(void **state)
3216 : {
3217 3 : struct rename_test_ctx *rename_test_ctx = talloc_get_type_abort(
3218 : *state,
3219 : struct rename_test_ctx);
3220 3 : int ret;
3221 3 : char *str_new_dn;
3222 3 : struct ldb_dn *new_dn;
3223 3 : unsigned i;
3224 :
3225 3 : str_new_dn = talloc_strdup(rename_test_ctx, rename_test_ctx->str_basedn);
3226 3 : assert_non_null(str_new_dn);
3227 81 : for (i = 0; str_new_dn[i]; i++) {
3228 75 : str_new_dn[i] = toupper(str_new_dn[i]);
3229 : }
3230 :
3231 6 : new_dn = ldb_dn_new_fmt(rename_test_ctx,
3232 3 : rename_test_ctx->ldb_test_ctx->ldb,
3233 : "%s", str_new_dn);
3234 3 : assert_non_null(new_dn);
3235 :
3236 3 : ret = ldb_rename(rename_test_ctx->ldb_test_ctx->ldb,
3237 : rename_test_ctx->basedn,
3238 : new_dn);
3239 3 : assert_int_equal(ret, LDB_SUCCESS);
3240 :
3241 : /* DNs are case insensitive, so both searches will match */
3242 3 : assert_dn_exists(rename_test_ctx->ldb_test_ctx, str_new_dn);
3243 3 : assert_dn_exists(rename_test_ctx->ldb_test_ctx,
3244 : rename_test_ctx->str_basedn);
3245 : /* FIXME - test the values didn't change */
3246 3 : }
3247 :
3248 3 : static int ldb_read_only_setup(void **state)
3249 : {
3250 3 : struct ldbtest_ctx *test_ctx;
3251 :
3252 3 : ldbtest_setup((void **) &test_ctx);
3253 :
3254 3 : *state = test_ctx;
3255 3 : return 0;
3256 : }
3257 :
3258 3 : static int ldb_read_only_teardown(void **state)
3259 : {
3260 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
3261 : struct ldbtest_ctx);
3262 3 : ldbtest_teardown((void **) &test_ctx);
3263 3 : return 0;
3264 : }
3265 :
3266 3 : static void test_read_only(void **state)
3267 : {
3268 3 : struct ldb_context *ro_ldb = NULL;
3269 3 : struct ldb_context *rw_ldb = NULL;
3270 3 : int ret;
3271 3 : TALLOC_CTX *tmp_ctx = NULL;
3272 :
3273 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
3274 : struct ldbtest_ctx);
3275 : /*
3276 : * Close the ldb context freeing it this will ensure it exists on
3277 : * disk and can be opened in read only mode
3278 : */
3279 3 : TALLOC_FREE(test_ctx->ldb);
3280 :
3281 : /*
3282 : * Open the database in read only and read write mode,
3283 : * ensure it's opened in read only mode first
3284 : */
3285 3 : ro_ldb = ldb_init(test_ctx, test_ctx->ev);
3286 3 : ret = ldb_connect(ro_ldb, test_ctx->dbpath, LDB_FLG_RDONLY, NULL);
3287 3 : assert_int_equal(ret, 0);
3288 :
3289 3 : rw_ldb = ldb_init(test_ctx, test_ctx->ev);
3290 3 : ret = ldb_connect(rw_ldb, test_ctx->dbpath, 0, NULL);
3291 3 : assert_int_equal(ret, 0);
3292 :
3293 :
3294 : /*
3295 : * Set up a context for the temporary variables
3296 : */
3297 3 : tmp_ctx = talloc_new(test_ctx);
3298 3 : assert_non_null(tmp_ctx);
3299 :
3300 : /*
3301 : * Ensure that we can search the read write database
3302 : */
3303 : {
3304 3 : struct ldb_result *result = NULL;
3305 3 : struct ldb_dn *dn = ldb_dn_new_fmt(tmp_ctx, rw_ldb,
3306 : "dc=test");
3307 3 : assert_non_null(dn);
3308 :
3309 3 : ret = ldb_search(rw_ldb, tmp_ctx, &result, dn,
3310 : LDB_SCOPE_BASE, NULL, NULL);
3311 3 : assert_int_equal(ret, LDB_SUCCESS);
3312 3 : TALLOC_FREE(result);
3313 3 : TALLOC_FREE(dn);
3314 : }
3315 :
3316 : /*
3317 : * Ensure that we can search the read only database
3318 : */
3319 : {
3320 3 : struct ldb_result *result = NULL;
3321 3 : struct ldb_dn *dn = ldb_dn_new_fmt(tmp_ctx, ro_ldb,
3322 : "dc=test");
3323 3 : assert_non_null(dn);
3324 :
3325 3 : ret = ldb_search(ro_ldb, tmp_ctx, &result, dn,
3326 : LDB_SCOPE_BASE, NULL, NULL);
3327 3 : assert_int_equal(ret, LDB_SUCCESS);
3328 3 : TALLOC_FREE(result);
3329 3 : TALLOC_FREE(dn);
3330 : }
3331 : /*
3332 : * Ensure that a write to the read only database fails
3333 : */
3334 : {
3335 3 : struct ldb_message *msg = NULL;
3336 3 : msg = ldb_msg_new(tmp_ctx);
3337 3 : assert_non_null(msg);
3338 :
3339 3 : msg->dn = ldb_dn_new_fmt(msg, ro_ldb, "dc=test");
3340 3 : assert_non_null(msg->dn);
3341 :
3342 3 : ret = ldb_msg_add_string(msg, "cn", "test_cn_val");
3343 3 : assert_int_equal(ret, 0);
3344 :
3345 3 : ret = ldb_msg_add_string(msg, "objectUUID",
3346 : "0123456789abcde1");
3347 3 : assert_int_equal(ret, LDB_SUCCESS);
3348 :
3349 3 : ret = ldb_add(ro_ldb, msg);
3350 3 : assert_int_equal(ret, LDB_ERR_UNWILLING_TO_PERFORM);
3351 3 : TALLOC_FREE(msg);
3352 : }
3353 :
3354 : /*
3355 : * Ensure that a write to the read write database succeeds
3356 : */
3357 : {
3358 3 : struct ldb_message *msg = NULL;
3359 3 : msg = ldb_msg_new(tmp_ctx);
3360 3 : assert_non_null(msg);
3361 :
3362 3 : msg->dn = ldb_dn_new_fmt(msg, rw_ldb, "dc=test");
3363 3 : assert_non_null(msg->dn);
3364 :
3365 3 : ret = ldb_msg_add_string(msg, "cn", "test_cn_val");
3366 3 : assert_int_equal(ret, 0);
3367 :
3368 3 : ret = ldb_msg_add_string(msg, "objectUUID",
3369 : "0123456789abcde2");
3370 3 : assert_int_equal(ret, LDB_SUCCESS);
3371 :
3372 3 : ret = ldb_add(rw_ldb, msg);
3373 3 : assert_int_equal(ret, LDB_SUCCESS);
3374 3 : TALLOC_FREE(msg);
3375 : }
3376 :
3377 : /*
3378 : * Ensure that a delete from a read only database fails
3379 : */
3380 : {
3381 3 : struct ldb_dn *dn = ldb_dn_new_fmt(tmp_ctx, ro_ldb, "dc=test");
3382 3 : assert_non_null(dn);
3383 :
3384 3 : ret = ldb_delete(ro_ldb, dn);
3385 3 : assert_int_equal(ret, LDB_ERR_UNWILLING_TO_PERFORM);
3386 3 : TALLOC_FREE(dn);
3387 : }
3388 :
3389 :
3390 : /*
3391 : * Ensure that a delete from a read write succeeds
3392 : */
3393 : {
3394 3 : struct ldb_dn *dn = ldb_dn_new_fmt(tmp_ctx, rw_ldb, "dc=test");
3395 3 : assert_non_null(dn);
3396 :
3397 3 : ret = ldb_delete(rw_ldb, dn);
3398 3 : assert_int_equal(ret, LDB_SUCCESS);
3399 3 : TALLOC_FREE(dn);
3400 : }
3401 3 : TALLOC_FREE(tmp_ctx);
3402 3 : }
3403 :
3404 : static bool unique_values = false;
3405 :
3406 55 : static int unique_index_test_module_add(
3407 : struct ldb_module *module,
3408 : struct ldb_request *req)
3409 : {
3410 55 : if (unique_values) {
3411 40 : struct ldb_message *msg = discard_const(req->op.add.message);
3412 40 : struct ldb_message_element *el = NULL;
3413 40 : el = ldb_msg_find_element(msg, "cn");
3414 40 : if (el != NULL) {
3415 28 : el->flags |= LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX;
3416 : }
3417 : }
3418 :
3419 55 : return ldb_next_request(module, req);
3420 : }
3421 :
3422 18 : static int unique_index_test_module_init(struct ldb_module *module)
3423 : {
3424 18 : return ldb_next_init(module);
3425 : }
3426 :
3427 : static const struct ldb_module_ops ldb_unique_index_test_module_ops = {
3428 : .name = "unique_index_test",
3429 : .init_context = unique_index_test_module_init,
3430 : .add = unique_index_test_module_add,
3431 : };
3432 :
3433 12 : static int ldb_unique_index_test_setup(void **state)
3434 : {
3435 12 : int ret;
3436 12 : struct ldb_ldif *ldif;
3437 12 : struct ldbtest_ctx *ldb_test_ctx;
3438 12 : const char *attrs_ldif = \
3439 : "dn: @ATTRIBUTES\n"
3440 : "cn: UNIQUE_INDEX\n"
3441 : "\n";
3442 12 : const char *index_ldif = \
3443 : "dn: @INDEXLIST\n"
3444 : "@IDXATTR: cn\n"
3445 : #ifdef GUID_IDX
3446 : "@IDXGUID: objectUUID\n"
3447 : "@IDX_DN_GUID: GUID\n"
3448 : #endif
3449 : "\n";
3450 12 : const char *options[] = {"modules:unique_index_test", NULL};
3451 :
3452 :
3453 12 : ret = ldb_register_module(&ldb_unique_index_test_module_ops);
3454 12 : assert_true(ret == LDB_SUCCESS || ret == LDB_ERR_ENTRY_ALREADY_EXISTS);
3455 12 : ldbtest_noconn_setup((void **) &ldb_test_ctx);
3456 :
3457 :
3458 12 : ret = ldb_connect(ldb_test_ctx->ldb, ldb_test_ctx->dbpath, 0, options);
3459 12 : assert_int_equal(ret, 0);
3460 :
3461 24 : while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &attrs_ldif))) {
3462 12 : ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
3463 12 : assert_int_equal(ret, LDB_SUCCESS);
3464 : }
3465 :
3466 24 : while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) {
3467 12 : ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
3468 12 : assert_int_equal(ret, LDB_SUCCESS);
3469 : }
3470 :
3471 12 : unique_values = true;
3472 :
3473 12 : *state = ldb_test_ctx;
3474 12 : return 0;
3475 : }
3476 :
3477 12 : static int ldb_unique_index_test_teardown(void **state)
3478 : {
3479 12 : int ret;
3480 12 : struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
3481 : struct ldbtest_ctx);
3482 12 : struct ldb_dn *del_dn;
3483 :
3484 12 : del_dn = ldb_dn_new_fmt(ldb_test_ctx,
3485 : ldb_test_ctx->ldb,
3486 : "@INDEXLIST");
3487 12 : assert_non_null(del_dn);
3488 :
3489 12 : ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
3490 12 : if (ret != LDB_ERR_NO_SUCH_OBJECT) {
3491 12 : assert_int_equal(ret, LDB_SUCCESS);
3492 : }
3493 :
3494 12 : assert_dn_doesnt_exist(ldb_test_ctx,
3495 : "@INDEXLIST");
3496 :
3497 12 : TALLOC_FREE(del_dn);
3498 :
3499 12 : del_dn = ldb_dn_new_fmt(ldb_test_ctx,
3500 : ldb_test_ctx->ldb,
3501 : "@ATTRIBUTES");
3502 12 : assert_non_null(del_dn);
3503 :
3504 12 : ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
3505 12 : if (ret != LDB_ERR_NO_SUCH_OBJECT) {
3506 12 : assert_int_equal(ret, LDB_SUCCESS);
3507 : }
3508 :
3509 12 : assert_dn_doesnt_exist(ldb_test_ctx,
3510 : "@ATTRIBUTES");
3511 :
3512 12 : ldbtest_teardown((void **) &ldb_test_ctx);
3513 12 : return 0;
3514 : }
3515 :
3516 :
3517 3 : static void test_ldb_add_unique_value_to_unique_index(void **state)
3518 : {
3519 3 : int ret;
3520 3 : struct ldb_message *msg;
3521 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
3522 : struct ldbtest_ctx);
3523 3 : TALLOC_CTX *tmp_ctx;
3524 :
3525 3 : tmp_ctx = talloc_new(test_ctx);
3526 3 : assert_non_null(tmp_ctx);
3527 :
3528 3 : msg = ldb_msg_new(tmp_ctx);
3529 3 : assert_non_null(msg);
3530 :
3531 3 : msg->dn = ldb_dn_new_fmt(msg, test_ctx->ldb, "dc=test");
3532 3 : assert_non_null(msg->dn);
3533 :
3534 3 : ret = ldb_msg_add_string(msg, "cn", "test_unique_index");
3535 3 : assert_int_equal(ret, LDB_SUCCESS);
3536 :
3537 3 : ret = ldb_msg_add_string(msg, "objectUUID",
3538 : "0123456789abcde1");
3539 3 : assert_int_equal(ret, LDB_SUCCESS);
3540 :
3541 3 : ret = ldb_add(test_ctx->ldb, msg);
3542 3 : assert_int_equal(ret, LDB_SUCCESS);
3543 :
3544 3 : talloc_free(tmp_ctx);
3545 3 : }
3546 :
3547 6 : static int ldb_non_unique_index_test_setup(void **state)
3548 : {
3549 6 : int ret;
3550 6 : struct ldb_ldif *ldif;
3551 6 : struct ldbtest_ctx *ldb_test_ctx;
3552 6 : const char *index_ldif = \
3553 : "dn: @INDEXLIST\n"
3554 : "@IDXATTR: cn\n"
3555 : #ifdef GUID_IDX
3556 : "@IDXGUID: objectUUID\n"
3557 : "@IDX_DN_GUID: GUID\n"
3558 : #endif
3559 : "\n";
3560 6 : const char *options[] = {"modules:unique_index_test", NULL};
3561 :
3562 :
3563 6 : ret = ldb_register_module(&ldb_unique_index_test_module_ops);
3564 6 : assert_true(ret == LDB_SUCCESS || ret == LDB_ERR_ENTRY_ALREADY_EXISTS);
3565 6 : ldbtest_noconn_setup((void **) &ldb_test_ctx);
3566 :
3567 :
3568 6 : ret = ldb_connect(ldb_test_ctx->ldb, ldb_test_ctx->dbpath, 0, options);
3569 6 : assert_int_equal(ret, 0);
3570 :
3571 12 : while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) {
3572 6 : ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
3573 6 : assert_int_equal(ret, LDB_SUCCESS);
3574 : }
3575 :
3576 6 : unique_values = true;
3577 :
3578 6 : *state = ldb_test_ctx;
3579 6 : return 0;
3580 : }
3581 :
3582 6 : static int ldb_non_unique_index_test_teardown(void **state)
3583 : {
3584 6 : int ret;
3585 6 : struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
3586 : struct ldbtest_ctx);
3587 6 : struct ldb_dn *del_dn;
3588 :
3589 6 : del_dn = ldb_dn_new_fmt(ldb_test_ctx,
3590 : ldb_test_ctx->ldb,
3591 : "@INDEXLIST");
3592 6 : assert_non_null(del_dn);
3593 :
3594 6 : ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
3595 6 : if (ret != LDB_ERR_NO_SUCH_OBJECT) {
3596 6 : assert_int_equal(ret, LDB_SUCCESS);
3597 : }
3598 :
3599 6 : assert_dn_doesnt_exist(ldb_test_ctx,
3600 : "@INDEXLIST");
3601 :
3602 6 : TALLOC_FREE(del_dn);
3603 :
3604 6 : ldbtest_teardown((void **) &ldb_test_ctx);
3605 6 : return 0;
3606 : }
3607 :
3608 3 : static void test_ldb_add_duplicate_value_to_unique_index(void **state)
3609 : {
3610 3 : int ret;
3611 3 : struct ldb_message *msg01;
3612 3 : struct ldb_message *msg02;
3613 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
3614 : struct ldbtest_ctx);
3615 3 : TALLOC_CTX *tmp_ctx;
3616 :
3617 3 : tmp_ctx = talloc_new(test_ctx);
3618 3 : assert_non_null(tmp_ctx);
3619 :
3620 3 : msg01 = ldb_msg_new(tmp_ctx);
3621 3 : assert_non_null(msg01);
3622 :
3623 3 : msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
3624 3 : assert_non_null(msg01->dn);
3625 :
3626 3 : ret = ldb_msg_add_string(msg01, "cn", "test_unique_index");
3627 3 : assert_int_equal(ret, LDB_SUCCESS);
3628 :
3629 3 : ret = ldb_msg_add_string(msg01, "objectUUID",
3630 : "0123456789abcde1");
3631 3 : assert_int_equal(ret, LDB_SUCCESS);
3632 :
3633 3 : ret = ldb_add(test_ctx->ldb, msg01);
3634 3 : assert_int_equal(ret, LDB_SUCCESS);
3635 :
3636 3 : msg02 = ldb_msg_new(tmp_ctx);
3637 3 : assert_non_null(msg02);
3638 :
3639 3 : msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02");
3640 3 : assert_non_null(msg02->dn);
3641 :
3642 3 : ret = ldb_msg_add_string(msg02, "cn", "test_unique_index");
3643 3 : assert_int_equal(ret, LDB_SUCCESS);
3644 :
3645 3 : ret = ldb_msg_add_string(msg02, "objectUUID",
3646 : "0123456789abcde2");
3647 3 : assert_int_equal(ret, LDB_SUCCESS);
3648 :
3649 3 : ret = ldb_add(test_ctx->ldb, msg02);
3650 3 : assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION);
3651 3 : talloc_free(tmp_ctx);
3652 3 : }
3653 :
3654 3 : static void test_ldb_add_to_index_duplicates_allowed(void **state)
3655 : {
3656 3 : int ret;
3657 3 : struct ldb_message *msg01;
3658 3 : struct ldb_message *msg02;
3659 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
3660 : struct ldbtest_ctx);
3661 3 : TALLOC_CTX *tmp_ctx;
3662 :
3663 3 : unique_values = false;
3664 :
3665 3 : tmp_ctx = talloc_new(test_ctx);
3666 3 : assert_non_null(tmp_ctx);
3667 :
3668 :
3669 3 : msg01 = ldb_msg_new(tmp_ctx);
3670 3 : assert_non_null(msg01);
3671 :
3672 3 : msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
3673 3 : assert_non_null(msg01->dn);
3674 :
3675 3 : ret = ldb_msg_add_string(msg01, "cn", "test_unique_index");
3676 3 : assert_int_equal(ret, LDB_SUCCESS);
3677 :
3678 3 : ret = ldb_msg_add_string(msg01, "objectUUID",
3679 : "0123456789abcde1");
3680 :
3681 3 : ret = ldb_add(test_ctx->ldb, msg01);
3682 3 : assert_int_equal(ret, LDB_SUCCESS);
3683 :
3684 3 : msg02 = ldb_msg_new(tmp_ctx);
3685 3 : assert_non_null(msg02);
3686 :
3687 3 : msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02");
3688 3 : assert_non_null(msg02->dn);
3689 :
3690 3 : ret = ldb_msg_add_string(msg02, "cn", "test_unique_index");
3691 3 : assert_int_equal(ret, LDB_SUCCESS);
3692 :
3693 3 : ret = ldb_msg_add_string(msg02, "objectUUID",
3694 : "0123456789abcde2");
3695 :
3696 3 : ret = ldb_add(test_ctx->ldb, msg02);
3697 3 : assert_int_equal(ret, LDB_SUCCESS);
3698 3 : talloc_free(tmp_ctx);
3699 3 : }
3700 :
3701 3 : static void test_ldb_add_to_index_unique_values_required(void **state)
3702 : {
3703 3 : int ret;
3704 3 : struct ldb_message *msg01;
3705 3 : struct ldb_message *msg02;
3706 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
3707 : struct ldbtest_ctx);
3708 3 : TALLOC_CTX *tmp_ctx;
3709 :
3710 3 : unique_values = true;
3711 :
3712 3 : tmp_ctx = talloc_new(test_ctx);
3713 3 : assert_non_null(tmp_ctx);
3714 :
3715 :
3716 3 : msg01 = ldb_msg_new(tmp_ctx);
3717 3 : assert_non_null(msg01);
3718 :
3719 3 : msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
3720 3 : assert_non_null(msg01->dn);
3721 :
3722 3 : ret = ldb_msg_add_string(msg01, "cn", "test_unique_index");
3723 3 : assert_int_equal(ret, LDB_SUCCESS);
3724 :
3725 3 : ret = ldb_msg_add_string(msg01, "objectUUID",
3726 : "0123456789abcde1");
3727 :
3728 3 : ret = ldb_add(test_ctx->ldb, msg01);
3729 3 : assert_int_equal(ret, LDB_SUCCESS);
3730 :
3731 3 : msg02 = ldb_msg_new(tmp_ctx);
3732 3 : assert_non_null(msg02);
3733 :
3734 3 : msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02");
3735 3 : assert_non_null(msg02->dn);
3736 :
3737 3 : ret = ldb_msg_add_string(msg02, "cn", "test_unique_index");
3738 3 : assert_int_equal(ret, LDB_SUCCESS);
3739 :
3740 3 : ret = ldb_msg_add_string(msg02, "objectUUID",
3741 : "0123456789abcde2");
3742 :
3743 3 : ret = ldb_add(test_ctx->ldb, msg02);
3744 3 : assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION);
3745 3 : talloc_free(tmp_ctx);
3746 3 : }
3747 :
3748 314 : static void PRINTF_ATTRIBUTE(3, 0) ldb_debug_string(
3749 : void *context,
3750 : enum ldb_debug_level level,
3751 : const char *fmt, va_list ap)
3752 : {
3753 314 : struct ldbtest_ctx *test_ctx =
3754 314 : talloc_get_type_abort(context, struct ldbtest_ctx);
3755 :
3756 314 : if (level <= LDB_DEBUG_WARNING) {
3757 10 : test_ctx->debug_string = talloc_vasprintf(test_ctx, fmt, ap);
3758 : }
3759 314 : }
3760 :
3761 3 : static void test_ldb_unique_index_duplicate_logging(void **state)
3762 : {
3763 3 : int ret;
3764 3 : struct ldb_message *msg01;
3765 3 : struct ldb_message *msg02;
3766 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
3767 : struct ldbtest_ctx);
3768 3 : TALLOC_CTX *tmp_ctx;
3769 3 : char *p = NULL;
3770 :
3771 : /* The GUID mode is not compatible with this test */
3772 : #ifdef GUID_IDX
3773 2 : return;
3774 : #endif
3775 :
3776 1 : ldb_set_debug(test_ctx->ldb, ldb_debug_string, test_ctx);
3777 1 : tmp_ctx = talloc_new(test_ctx);
3778 1 : assert_non_null(tmp_ctx);
3779 :
3780 1 : msg01 = ldb_msg_new(tmp_ctx);
3781 1 : assert_non_null(msg01);
3782 :
3783 1 : msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
3784 1 : assert_non_null(msg01->dn);
3785 :
3786 1 : ret = ldb_msg_add_string(msg01, "cn", "test_unique_index");
3787 1 : assert_int_equal(ret, LDB_SUCCESS);
3788 :
3789 1 : ret = ldb_msg_add_string(msg01, "objectUUID",
3790 : "0123456789abcde1");
3791 :
3792 1 : ret = ldb_add(test_ctx->ldb, msg01);
3793 1 : assert_int_equal(ret, LDB_SUCCESS);
3794 :
3795 1 : msg02 = ldb_msg_new(tmp_ctx);
3796 1 : assert_non_null(msg02);
3797 :
3798 1 : msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02");
3799 1 : assert_non_null(msg02->dn);
3800 :
3801 1 : ret = ldb_msg_add_string(msg02, "cn", "test_unique_index");
3802 1 : assert_int_equal(ret, LDB_SUCCESS);
3803 :
3804 1 : ret = ldb_msg_add_string(msg02, "objectUUID",
3805 : "0123456789abcde2");
3806 :
3807 1 : ret = ldb_add(test_ctx->ldb, msg02);
3808 1 : assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION);
3809 :
3810 1 : assert_non_null(test_ctx->debug_string);
3811 1 : p = strstr(
3812 1 : test_ctx->debug_string,
3813 : "unique index violation on cn "
3814 : "in dc=test02, conflicts with dc=test01 in "
3815 : "@INDEX:CN:test_unique_index");
3816 1 : assert_non_null(p);
3817 1 : TALLOC_FREE(test_ctx->debug_string);
3818 1 : talloc_free(tmp_ctx);
3819 1 : }
3820 :
3821 3 : static void test_ldb_duplicate_dn_logging(void **state)
3822 : {
3823 3 : int ret;
3824 3 : struct ldb_message *msg01;
3825 3 : struct ldb_message *msg02;
3826 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
3827 : struct ldbtest_ctx);
3828 3 : TALLOC_CTX *tmp_ctx;
3829 :
3830 : /* The GUID mode is not compatible with this test */
3831 : #ifdef GUID_IDX
3832 2 : return;
3833 : #endif
3834 :
3835 1 : ldb_set_debug(test_ctx->ldb, ldb_debug_string, test_ctx);
3836 1 : tmp_ctx = talloc_new(test_ctx);
3837 1 : assert_non_null(tmp_ctx);
3838 :
3839 1 : msg01 = ldb_msg_new(tmp_ctx);
3840 1 : assert_non_null(msg01);
3841 :
3842 1 : msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
3843 1 : assert_non_null(msg01->dn);
3844 :
3845 1 : ret = ldb_msg_add_string(msg01, "cn", "test_unique_index01");
3846 1 : assert_int_equal(ret, LDB_SUCCESS);
3847 :
3848 1 : ret = ldb_msg_add_string(msg01, "objectUUID",
3849 : "0123456789abcde1");
3850 :
3851 1 : ret = ldb_add(test_ctx->ldb, msg01);
3852 1 : assert_int_equal(ret, LDB_SUCCESS);
3853 :
3854 1 : msg02 = ldb_msg_new(tmp_ctx);
3855 1 : assert_non_null(msg02);
3856 :
3857 1 : msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test01");
3858 1 : assert_non_null(msg02->dn);
3859 :
3860 1 : ret = ldb_msg_add_string(msg02, "cn", "test_unique_index02");
3861 1 : assert_int_equal(ret, LDB_SUCCESS);
3862 :
3863 1 : ret = ldb_msg_add_string(msg02, "objectUUID",
3864 : "0123456789abcde2");
3865 :
3866 1 : ret = ldb_add(test_ctx->ldb, msg02);
3867 1 : assert_int_equal(ret, LDB_ERR_ENTRY_ALREADY_EXISTS);
3868 :
3869 1 : assert_null(test_ctx->debug_string);
3870 1 : talloc_free(tmp_ctx);
3871 1 : }
3872 :
3873 6 : static int ldb_guid_index_test_setup(void **state)
3874 : {
3875 6 : int ret;
3876 6 : struct ldb_ldif *ldif;
3877 6 : struct ldbtest_ctx *ldb_test_ctx;
3878 6 : const char *attrs_ldif = \
3879 : "dn: @ATTRIBUTES\n"
3880 : "cn: UNIQUE_INDEX\n"
3881 : "\n";
3882 6 : const char *index_ldif = \
3883 : "dn: @INDEXLIST\n"
3884 : "@IDXATTR: cn\n"
3885 : "@IDXGUID: objectUUID\n"
3886 : "@IDX_DN_GUID: GUID\n"
3887 : "\n";
3888 :
3889 6 : ldbtest_noconn_setup((void **) &ldb_test_ctx);
3890 :
3891 :
3892 6 : ret = ldb_connect(ldb_test_ctx->ldb, ldb_test_ctx->dbpath, 0, NULL);
3893 6 : assert_int_equal(ret, 0);
3894 :
3895 12 : while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &attrs_ldif))) {
3896 6 : ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
3897 6 : assert_int_equal(ret, LDB_SUCCESS);
3898 : }
3899 :
3900 12 : while ((ldif = ldb_ldif_read_string(ldb_test_ctx->ldb, &index_ldif))) {
3901 6 : ret = ldb_add(ldb_test_ctx->ldb, ldif->msg);
3902 6 : assert_int_equal(ret, LDB_SUCCESS);
3903 : }
3904 :
3905 6 : *state = ldb_test_ctx;
3906 6 : return 0;
3907 : }
3908 :
3909 6 : static int ldb_guid_index_test_teardown(void **state)
3910 : {
3911 6 : int ret;
3912 6 : struct ldbtest_ctx *ldb_test_ctx = talloc_get_type_abort(*state,
3913 : struct ldbtest_ctx);
3914 6 : struct ldb_dn *del_dn;
3915 :
3916 6 : del_dn = ldb_dn_new_fmt(ldb_test_ctx,
3917 : ldb_test_ctx->ldb,
3918 : "@INDEXLIST");
3919 6 : assert_non_null(del_dn);
3920 :
3921 6 : ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
3922 6 : if (ret != LDB_ERR_NO_SUCH_OBJECT) {
3923 6 : assert_int_equal(ret, LDB_SUCCESS);
3924 : }
3925 :
3926 6 : assert_dn_doesnt_exist(ldb_test_ctx,
3927 : "@INDEXLIST");
3928 :
3929 6 : TALLOC_FREE(del_dn);
3930 :
3931 6 : del_dn = ldb_dn_new_fmt(ldb_test_ctx,
3932 : ldb_test_ctx->ldb,
3933 : "@ATTRIBUTES");
3934 6 : assert_non_null(del_dn);
3935 :
3936 6 : ret = ldb_delete(ldb_test_ctx->ldb, del_dn);
3937 6 : if (ret != LDB_ERR_NO_SUCH_OBJECT) {
3938 6 : assert_int_equal(ret, LDB_SUCCESS);
3939 : }
3940 :
3941 6 : assert_dn_doesnt_exist(ldb_test_ctx,
3942 : "@ATTRIBUTES");
3943 :
3944 6 : ldbtest_teardown((void **) &ldb_test_ctx);
3945 6 : return 0;
3946 : }
3947 :
3948 :
3949 3 : static void test_ldb_unique_index_duplicate_with_guid(void **state)
3950 : {
3951 3 : int ret;
3952 3 : struct ldb_message *msg01;
3953 3 : struct ldb_message *msg02;
3954 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
3955 : struct ldbtest_ctx);
3956 3 : TALLOC_CTX *tmp_ctx;
3957 3 : char *p = NULL;
3958 :
3959 3 : ldb_set_debug(test_ctx->ldb, ldb_debug_string, test_ctx);
3960 3 : tmp_ctx = talloc_new(test_ctx);
3961 3 : assert_non_null(tmp_ctx);
3962 :
3963 3 : msg01 = ldb_msg_new(tmp_ctx);
3964 3 : assert_non_null(msg01);
3965 :
3966 3 : msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
3967 3 : assert_non_null(msg01->dn);
3968 :
3969 3 : ret = ldb_msg_add_string(msg01, "cn", "test_unique_index");
3970 3 : assert_int_equal(ret, LDB_SUCCESS);
3971 :
3972 3 : ret = ldb_msg_add_string(msg01, "objectUUID", "0123456789abcdef");
3973 3 : assert_int_equal(ret, LDB_SUCCESS);
3974 :
3975 3 : ret = ldb_add(test_ctx->ldb, msg01);
3976 3 : assert_int_equal(ret, LDB_SUCCESS);
3977 :
3978 3 : msg02 = ldb_msg_new(tmp_ctx);
3979 3 : assert_non_null(msg02);
3980 :
3981 3 : msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test02");
3982 3 : assert_non_null(msg02->dn);
3983 :
3984 3 : ret = ldb_msg_add_string(msg02, "cn", "test_unique_index");
3985 3 : assert_int_equal(ret, LDB_SUCCESS);
3986 :
3987 3 : ret = ldb_msg_add_string(msg02, "objectUUID", "0123456789abcde0");
3988 3 : assert_int_equal(ret, LDB_SUCCESS);
3989 :
3990 3 : ret = ldb_add(test_ctx->ldb, msg02);
3991 3 : assert_int_equal(ret, LDB_ERR_CONSTRAINT_VIOLATION);
3992 :
3993 3 : assert_non_null(test_ctx->debug_string);
3994 3 : p = strstr(
3995 3 : test_ctx->debug_string,
3996 : "unique index violation on cn in dc=test02, conflicts with "
3997 : "objectUUID 0123456789abcdef in @INDEX:CN:test_unique_index");
3998 3 : assert_non_null(p);
3999 3 : TALLOC_FREE(test_ctx->debug_string);
4000 3 : talloc_free(tmp_ctx);
4001 3 : }
4002 :
4003 3 : static void test_ldb_guid_index_duplicate_dn_logging(void **state)
4004 : {
4005 3 : int ret;
4006 3 : struct ldb_message *msg01;
4007 3 : struct ldb_message *msg02;
4008 3 : struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
4009 : struct ldbtest_ctx);
4010 3 : TALLOC_CTX *tmp_ctx;
4011 :
4012 3 : ldb_set_debug(test_ctx->ldb, ldb_debug_string, test_ctx);
4013 3 : tmp_ctx = talloc_new(test_ctx);
4014 3 : assert_non_null(tmp_ctx);
4015 :
4016 3 : msg01 = ldb_msg_new(tmp_ctx);
4017 3 : assert_non_null(msg01);
4018 :
4019 3 : msg01->dn = ldb_dn_new_fmt(msg01, test_ctx->ldb, "dc=test01");
4020 3 : assert_non_null(msg01->dn);
4021 :
4022 3 : ret = ldb_msg_add_string(msg01, "cn", "test_unique_index01");
4023 3 : assert_int_equal(ret, LDB_SUCCESS);
4024 :
4025 3 : ret = ldb_msg_add_string(msg01, "objectUUID", "0123456789abcdef");
4026 3 : assert_int_equal(ret, LDB_SUCCESS);
4027 :
4028 3 : ret = ldb_add(test_ctx->ldb, msg01);
4029 3 : assert_int_equal(ret, LDB_SUCCESS);
4030 :
4031 3 : msg02 = ldb_msg_new(tmp_ctx);
4032 3 : assert_non_null(msg02);
4033 :
4034 3 : msg02->dn = ldb_dn_new_fmt(msg02, test_ctx->ldb, "dc=test01");
4035 3 : assert_non_null(msg02->dn);
4036 :
4037 3 : ret = ldb_msg_add_string(msg02, "cn", "test_unique_index02");
4038 3 : assert_int_equal(ret, LDB_SUCCESS);
4039 :
4040 3 : ret = ldb_msg_add_string(msg02, "objectUUID", "0123456789abcde1");
4041 3 : assert_int_equal(ret, LDB_SUCCESS);
4042 :
4043 3 : ret = ldb_add(test_ctx->ldb, msg02);
4044 3 : assert_int_equal(ret, LDB_ERR_ENTRY_ALREADY_EXISTS);
4045 :
4046 3 : assert_null(test_ctx->debug_string);
4047 3 : talloc_free(tmp_ctx);
4048 3 : }
4049 :
4050 3 : static void test_ldb_talloc_destructor_transaction_cleanup(void **state)
4051 : {
4052 3 : struct ldbtest_ctx *test_ctx = NULL;
4053 :
4054 3 : test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx);
4055 3 : assert_non_null(test_ctx);
4056 :
4057 3 : ldb_transaction_start(test_ctx->ldb);
4058 :
4059 : /*
4060 : * Trigger the destructor
4061 : */
4062 3 : TALLOC_FREE(test_ctx->ldb);
4063 :
4064 : /*
4065 : * Now ensure that a new connection can be opened
4066 : */
4067 : {
4068 3 : TALLOC_CTX *tctx = talloc_new(test_ctx);
4069 3 : struct ldbtest_ctx *ctx = talloc_zero(tctx, struct ldbtest_ctx);
4070 3 : struct ldb_dn *basedn;
4071 3 : struct ldb_result *result = NULL;
4072 3 : int ret;
4073 :
4074 3 : ldbtest_setup((void *)&ctx);
4075 :
4076 3 : basedn = ldb_dn_new_fmt(tctx, ctx->ldb, "dc=test");
4077 3 : assert_non_null(basedn);
4078 :
4079 3 : ret = ldb_search(ctx->ldb,
4080 : tctx,
4081 : &result,
4082 : basedn,
4083 : LDB_SCOPE_BASE,
4084 : NULL,
4085 : NULL);
4086 3 : assert_int_equal(ret, 0);
4087 3 : assert_non_null(result);
4088 3 : assert_int_equal(result->count, 0);
4089 :
4090 3 : ldbtest_teardown((void *)&ctx);
4091 : }
4092 3 : }
4093 :
4094 : #ifdef TEST_LMDB
4095 2 : static int test_ldb_multiple_connections_callback(struct ldb_request *req,
4096 : struct ldb_reply *ares)
4097 : {
4098 2 : int ret;
4099 2 : int pipes[2];
4100 2 : char buf[2];
4101 2 : int pid, child_pid;
4102 2 : int wstatus;
4103 :
4104 2 : switch (ares->type) {
4105 : case LDB_REPLY_ENTRY:
4106 : break;
4107 :
4108 : case LDB_REPLY_REFERRAL:
4109 : return LDB_SUCCESS;
4110 :
4111 1 : case LDB_REPLY_DONE:
4112 1 : return ldb_request_done(req, LDB_SUCCESS);
4113 : }
4114 :
4115 : {
4116 : /*
4117 : * We open a new ldb on an ldb that is already open and
4118 : * then close it.
4119 : *
4120 : * If the multiple connection wrapping is correct the
4121 : * underlying MDB_env will be left open and we should see
4122 : * an active reader in the child we fork next
4123 : */
4124 1 : struct ldb_context *ldb = NULL;
4125 1 : struct tevent_context *ev = NULL;
4126 1 : TALLOC_CTX *mem_ctx = talloc_new(NULL);
4127 :
4128 1 : ev = tevent_context_init(mem_ctx);
4129 1 : assert_non_null(ev);
4130 :
4131 1 : ldb = ldb_init(mem_ctx, ev);
4132 1 : assert_non_null(ldb);
4133 :
4134 1 : ret = ldb_connect(ldb, TEST_BE"://apitest.ldb" , 0, NULL);
4135 1 : if (ret != LDB_SUCCESS) {
4136 : return ret;
4137 : }
4138 1 : TALLOC_FREE(ldb);
4139 1 : TALLOC_FREE(mem_ctx);
4140 : }
4141 :
4142 1 : ret = pipe(pipes);
4143 1 : assert_int_equal(ret, 0);
4144 :
4145 1 : child_pid = fork();
4146 2 : if (child_pid == 0) {
4147 1 : struct MDB_env *env = NULL;
4148 1 : struct MDB_envinfo stat;
4149 1 : close(pipes[0]);
4150 :
4151 : /*
4152 : * Check that there are exactly two readers on the MDB file
4153 : * backing the ldb.
4154 : *
4155 : */
4156 1 : ret = mdb_env_create(&env);
4157 1 : if (ret != 0) {
4158 0 : print_error(__location__
4159 : " mdb_env_create returned (%d)",
4160 : ret);
4161 0 : exit(ret);
4162 : }
4163 :
4164 1 : ret = mdb_env_open(env,
4165 : "apitest.ldb",
4166 : MDB_NOSUBDIR | MDB_NOTLS,
4167 : 0644);
4168 1 : if (ret != 0) {
4169 0 : print_error(__location__
4170 : " mdb_env_open returned (%d)",
4171 : ret);
4172 0 : exit(ret);
4173 : }
4174 :
4175 1 : ret = mdb_env_info(env, &stat);
4176 1 : if (ret != 0) {
4177 0 : print_error(__location__
4178 : " mdb_env_info returned (%d)",
4179 : ret);
4180 0 : exit(ret);
4181 : }
4182 1 : if (stat.me_numreaders != 2) {
4183 0 : print_error(__location__
4184 : " Incorrect number of readers (%d)",
4185 : stat.me_numreaders);
4186 0 : exit(LDB_ERR_CONSTRAINT_VIOLATION);
4187 : }
4188 :
4189 1 : ret = write(pipes[1], "GO", 2);
4190 1 : if (ret != 2) {
4191 0 : print_error(__location__
4192 : " write returned (%d)",
4193 : ret);
4194 0 : exit(LDB_ERR_OPERATIONS_ERROR);
4195 : }
4196 1 : exit(LDB_SUCCESS);
4197 : }
4198 1 : close(pipes[1]);
4199 1 : ret = read(pipes[0], buf, 2);
4200 1 : assert_int_equal(ret, 2);
4201 :
4202 1 : pid = waitpid(child_pid, &wstatus, 0);
4203 1 : assert_int_equal(pid, child_pid);
4204 :
4205 1 : assert_true(WIFEXITED(wstatus));
4206 :
4207 1 : assert_int_equal(WEXITSTATUS(wstatus), 0);
4208 1 : return LDB_SUCCESS;
4209 :
4210 : }
4211 :
4212 1 : static void test_ldb_close_with_multiple_connections(void **state)
4213 : {
4214 1 : struct search_test_ctx *search_test_ctx = NULL;
4215 1 : struct ldb_dn *search_dn = NULL;
4216 1 : struct ldb_request *req = NULL;
4217 1 : int ret = 0;
4218 :
4219 1 : search_test_ctx = talloc_get_type_abort(*state, struct search_test_ctx);
4220 1 : assert_non_null(search_test_ctx);
4221 :
4222 2 : search_dn = ldb_dn_new_fmt(search_test_ctx,
4223 1 : search_test_ctx->ldb_test_ctx->ldb,
4224 : "cn=test_search_cn,"
4225 : "dc=search_test_entry");
4226 1 : assert_non_null(search_dn);
4227 :
4228 : /*
4229 : * The search just needs to call DONE, we don't care about the
4230 : * contents of the search for this test
4231 : */
4232 2 : ret = ldb_build_search_req(&req,
4233 1 : search_test_ctx->ldb_test_ctx->ldb,
4234 : search_test_ctx,
4235 : search_dn,
4236 : LDB_SCOPE_SUBTREE,
4237 : "(&(!(filterAttr=*))"
4238 : "(cn=test_search_cn))",
4239 : NULL,
4240 : NULL,
4241 : NULL,
4242 : test_ldb_multiple_connections_callback,
4243 : NULL);
4244 1 : assert_int_equal(ret, 0);
4245 :
4246 1 : ret = ldb_request(search_test_ctx->ldb_test_ctx->ldb, req);
4247 1 : assert_int_equal(ret, 0);
4248 :
4249 1 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
4250 1 : assert_int_equal(ret, 0);
4251 1 : }
4252 :
4253 : #endif
4254 :
4255 3 : static void test_transaction_start_across_fork(void **state)
4256 : {
4257 3 : struct ldb_context *ldb1 = NULL;
4258 3 : int ret;
4259 3 : struct ldbtest_ctx *test_ctx = NULL;
4260 3 : int pipes[2];
4261 3 : char buf[2];
4262 3 : int wstatus;
4263 3 : pid_t pid, child_pid;
4264 :
4265 3 : test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx);
4266 :
4267 : /*
4268 : * Open the database
4269 : */
4270 3 : ldb1 = ldb_init(test_ctx, test_ctx->ev);
4271 3 : ret = ldb_connect(ldb1, test_ctx->dbpath, 0, NULL);
4272 3 : assert_int_equal(ret, 0);
4273 :
4274 3 : ret = pipe(pipes);
4275 3 : assert_int_equal(ret, 0);
4276 :
4277 3 : child_pid = fork();
4278 6 : if (child_pid == 0) {
4279 3 : close(pipes[0]);
4280 3 : ret = ldb_transaction_start(ldb1);
4281 3 : if (ret != LDB_ERR_PROTOCOL_ERROR) {
4282 0 : print_error(__location__": ldb_transaction_start "
4283 : "returned (%d) %s\n",
4284 : ret,
4285 : ldb1->err_string);
4286 0 : exit(LDB_ERR_OTHER);
4287 : }
4288 :
4289 3 : ret = write(pipes[1], "GO", 2);
4290 3 : if (ret != 2) {
4291 0 : print_error(__location__
4292 : " write returned (%d)",
4293 : ret);
4294 0 : exit(LDB_ERR_OPERATIONS_ERROR);
4295 : }
4296 3 : exit(LDB_SUCCESS);
4297 : }
4298 3 : close(pipes[1]);
4299 3 : ret = read(pipes[0], buf, 2);
4300 3 : assert_int_equal(ret, 2);
4301 :
4302 3 : pid = waitpid(child_pid, &wstatus, 0);
4303 3 : assert_int_equal(pid, child_pid);
4304 :
4305 3 : assert_true(WIFEXITED(wstatus));
4306 :
4307 3 : assert_int_equal(WEXITSTATUS(wstatus), 0);
4308 3 : }
4309 :
4310 3 : static void test_transaction_commit_across_fork(void **state)
4311 : {
4312 3 : struct ldb_context *ldb1 = NULL;
4313 3 : int ret;
4314 3 : struct ldbtest_ctx *test_ctx = NULL;
4315 3 : int pipes[2];
4316 3 : char buf[2];
4317 3 : int wstatus;
4318 3 : pid_t pid, child_pid;
4319 :
4320 3 : test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx);
4321 :
4322 : /*
4323 : * Open the database
4324 : */
4325 3 : ldb1 = ldb_init(test_ctx, test_ctx->ev);
4326 3 : ret = ldb_connect(ldb1, test_ctx->dbpath, 0, NULL);
4327 3 : assert_int_equal(ret, 0);
4328 :
4329 3 : ret = ldb_transaction_start(ldb1);
4330 3 : assert_int_equal(ret, 0);
4331 :
4332 3 : ret = pipe(pipes);
4333 3 : assert_int_equal(ret, 0);
4334 :
4335 3 : child_pid = fork();
4336 6 : if (child_pid == 0) {
4337 3 : close(pipes[0]);
4338 3 : ret = ldb_transaction_commit(ldb1);
4339 :
4340 3 : if (ret != LDB_ERR_PROTOCOL_ERROR) {
4341 0 : print_error(__location__": ldb_transaction_commit "
4342 : "returned (%d) %s\n",
4343 : ret,
4344 : ldb1->err_string);
4345 0 : exit(LDB_ERR_OTHER);
4346 : }
4347 :
4348 3 : ret = write(pipes[1], "GO", 2);
4349 3 : if (ret != 2) {
4350 0 : print_error(__location__
4351 : " write returned (%d)",
4352 : ret);
4353 0 : exit(LDB_ERR_OPERATIONS_ERROR);
4354 : }
4355 3 : exit(LDB_SUCCESS);
4356 : }
4357 3 : close(pipes[1]);
4358 3 : ret = read(pipes[0], buf, 2);
4359 3 : assert_int_equal(ret, 2);
4360 :
4361 3 : pid = waitpid(child_pid, &wstatus, 0);
4362 3 : assert_int_equal(pid, child_pid);
4363 :
4364 3 : assert_true(WIFEXITED(wstatus));
4365 :
4366 3 : assert_int_equal(WEXITSTATUS(wstatus), 0);
4367 3 : }
4368 :
4369 3 : static void test_lock_read_across_fork(void **state)
4370 : {
4371 3 : struct ldb_context *ldb1 = NULL;
4372 3 : int ret;
4373 3 : struct ldbtest_ctx *test_ctx = NULL;
4374 3 : int pipes[2];
4375 3 : char buf[2];
4376 3 : int wstatus;
4377 3 : pid_t pid, child_pid;
4378 :
4379 3 : test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx);
4380 :
4381 : /*
4382 : * Open the database
4383 : */
4384 3 : ldb1 = ldb_init(test_ctx, test_ctx->ev);
4385 3 : ret = ldb_connect(ldb1, test_ctx->dbpath, 0, NULL);
4386 3 : assert_int_equal(ret, 0);
4387 :
4388 3 : ret = pipe(pipes);
4389 3 : assert_int_equal(ret, 0);
4390 :
4391 3 : child_pid = fork();
4392 6 : if (child_pid == 0) {
4393 3 : struct ldb_dn *basedn;
4394 3 : struct ldb_result *result = NULL;
4395 :
4396 3 : close(pipes[0]);
4397 :
4398 3 : basedn = ldb_dn_new_fmt(test_ctx, test_ctx->ldb, "dc=test");
4399 3 : assert_non_null(basedn);
4400 :
4401 3 : ret = ldb_search(test_ctx->ldb,
4402 : test_ctx,
4403 : &result,
4404 : basedn,
4405 : LDB_SCOPE_BASE,
4406 : NULL,
4407 : NULL);
4408 3 : if (ret != LDB_ERR_PROTOCOL_ERROR) {
4409 0 : print_error(__location__": ldb_search "
4410 : "returned (%d) %s\n",
4411 : ret,
4412 : ldb1->err_string);
4413 0 : exit(LDB_ERR_OTHER);
4414 : }
4415 :
4416 3 : ret = write(pipes[1], "GO", 2);
4417 3 : if (ret != 2) {
4418 0 : print_error(__location__
4419 : " write returned (%d)",
4420 : ret);
4421 0 : exit(LDB_ERR_OPERATIONS_ERROR);
4422 : }
4423 3 : exit(LDB_SUCCESS);
4424 : }
4425 3 : close(pipes[1]);
4426 3 : ret = read(pipes[0], buf, 2);
4427 3 : assert_int_equal(ret, 2);
4428 :
4429 3 : pid = waitpid(child_pid, &wstatus, 0);
4430 3 : assert_int_equal(pid, child_pid);
4431 :
4432 3 : assert_true(WIFEXITED(wstatus));
4433 :
4434 3 : assert_int_equal(WEXITSTATUS(wstatus), 0);
4435 :
4436 : {
4437 : /*
4438 : * Ensure that the search actually succeeds on the opening
4439 : * pid
4440 : */
4441 3 : struct ldb_dn *basedn;
4442 3 : struct ldb_result *result = NULL;
4443 :
4444 3 : close(pipes[0]);
4445 :
4446 3 : basedn = ldb_dn_new_fmt(test_ctx, test_ctx->ldb, "dc=test");
4447 3 : assert_non_null(basedn);
4448 :
4449 3 : ret = ldb_search(test_ctx->ldb,
4450 : test_ctx,
4451 : &result,
4452 : basedn,
4453 : LDB_SCOPE_BASE,
4454 : NULL,
4455 : NULL);
4456 3 : assert_int_equal(0, ret);
4457 : }
4458 3 : }
4459 :
4460 3 : static void test_multiple_opens_across_fork(void **state)
4461 : {
4462 3 : struct ldb_context *ldb1 = NULL;
4463 3 : struct ldb_context *ldb2 = NULL;
4464 3 : int ret;
4465 3 : struct ldbtest_ctx *test_ctx = NULL;
4466 3 : int pipes[2];
4467 3 : char buf[2];
4468 3 : int wstatus;
4469 3 : pid_t pid, child_pid;
4470 :
4471 3 : test_ctx = talloc_get_type_abort(*state, struct ldbtest_ctx);
4472 :
4473 : /*
4474 : * Open the database again
4475 : */
4476 3 : ldb1 = ldb_init(test_ctx, test_ctx->ev);
4477 3 : ret = ldb_connect(ldb1, test_ctx->dbpath, LDB_FLG_RDONLY, NULL);
4478 3 : assert_int_equal(ret, 0);
4479 :
4480 3 : ldb2 = ldb_init(test_ctx, test_ctx->ev);
4481 3 : ret = ldb_connect(ldb2, test_ctx->dbpath, 0, NULL);
4482 3 : assert_int_equal(ret, 0);
4483 :
4484 3 : ret = pipe(pipes);
4485 3 : assert_int_equal(ret, 0);
4486 :
4487 3 : child_pid = fork();
4488 6 : if (child_pid == 0) {
4489 3 : struct ldb_context *ldb3 = NULL;
4490 :
4491 3 : close(pipes[0]);
4492 3 : ldb3 = ldb_init(test_ctx, test_ctx->ev);
4493 3 : ret = ldb_connect(ldb3, test_ctx->dbpath, 0, NULL);
4494 3 : if (ret != 0) {
4495 0 : print_error(__location__": ldb_connect returned (%d)\n",
4496 : ret);
4497 0 : exit(ret);
4498 : }
4499 3 : ret = write(pipes[1], "GO", 2);
4500 3 : if (ret != 2) {
4501 0 : print_error(__location__
4502 : " write returned (%d)",
4503 : ret);
4504 0 : exit(LDB_ERR_OPERATIONS_ERROR);
4505 : }
4506 3 : exit(LDB_SUCCESS);
4507 : }
4508 3 : close(pipes[1]);
4509 3 : ret = read(pipes[0], buf, 2);
4510 3 : assert_int_equal(ret, 2);
4511 :
4512 3 : pid = waitpid(child_pid, &wstatus, 0);
4513 3 : assert_int_equal(pid, child_pid);
4514 :
4515 3 : assert_true(WIFEXITED(wstatus));
4516 :
4517 3 : assert_int_equal(WEXITSTATUS(wstatus), 0);
4518 3 : }
4519 :
4520 3 : int main(int argc, const char **argv)
4521 : {
4522 3 : const struct CMUnitTest tests[] = {
4523 : cmocka_unit_test_setup_teardown(test_connect,
4524 : ldbtest_noconn_setup,
4525 : ldbtest_noconn_teardown),
4526 : cmocka_unit_test_setup_teardown(test_ldif_message,
4527 : ldbtest_noconn_setup,
4528 : ldbtest_noconn_teardown),
4529 : cmocka_unit_test_setup_teardown(test_ldif_message_redacted,
4530 : ldbtest_noconn_setup,
4531 : ldbtest_noconn_teardown),
4532 : cmocka_unit_test_setup_teardown(test_ldb_add,
4533 : ldbtest_setup,
4534 : ldbtest_teardown),
4535 : cmocka_unit_test_setup_teardown(test_ldb_search,
4536 : ldbtest_setup,
4537 : ldbtest_teardown),
4538 : cmocka_unit_test_setup_teardown(test_ldb_del,
4539 : ldbtest_setup,
4540 : ldbtest_teardown),
4541 : cmocka_unit_test_setup_teardown(test_ldb_del_noexist,
4542 : ldbtest_setup,
4543 : ldbtest_teardown),
4544 : cmocka_unit_test_setup_teardown(test_ldb_handle,
4545 : ldbtest_setup,
4546 : ldbtest_teardown),
4547 : cmocka_unit_test_setup_teardown(test_ldb_build_search_req,
4548 : ldbtest_setup,
4549 : ldbtest_teardown),
4550 : cmocka_unit_test_setup_teardown(test_transactions,
4551 : ldbtest_setup,
4552 : ldbtest_teardown),
4553 : cmocka_unit_test_setup_teardown(test_nested_transactions,
4554 : ldbtest_setup,
4555 : ldbtest_teardown),
4556 : cmocka_unit_test_setup_teardown(test_ldb_modify_add_key,
4557 : ldb_modify_test_setup,
4558 : ldb_modify_test_teardown),
4559 : cmocka_unit_test_setup_teardown(test_ldb_modify_extend_key,
4560 : ldb_modify_test_setup,
4561 : ldb_modify_test_teardown),
4562 : cmocka_unit_test_setup_teardown(test_ldb_modify_add_key_noval,
4563 : ldb_modify_test_setup,
4564 : ldb_modify_test_teardown),
4565 : cmocka_unit_test_setup_teardown(test_ldb_modify_replace_key,
4566 : ldb_modify_test_setup,
4567 : ldb_modify_test_teardown),
4568 : cmocka_unit_test_setup_teardown(test_ldb_modify_replace_noexist_key,
4569 : ldb_modify_test_setup,
4570 : ldb_modify_test_teardown),
4571 : cmocka_unit_test_setup_teardown(test_ldb_modify_replace_zero_vals,
4572 : ldb_modify_test_setup,
4573 : ldb_modify_test_teardown),
4574 : cmocka_unit_test_setup_teardown(test_ldb_modify_replace_noexist_key_zero_vals,
4575 : ldb_modify_test_setup,
4576 : ldb_modify_test_teardown),
4577 : cmocka_unit_test_setup_teardown(test_ldb_modify_del_key,
4578 : ldb_modify_test_setup,
4579 : ldb_modify_test_teardown),
4580 : cmocka_unit_test_setup_teardown(test_ldb_modify_del_keyval,
4581 : ldb_modify_test_setup,
4582 : ldb_modify_test_teardown),
4583 : cmocka_unit_test_setup_teardown(test_search_match_none,
4584 : ldb_search_test_setup,
4585 : ldb_search_test_teardown),
4586 : cmocka_unit_test_setup_teardown(test_search_match_one,
4587 : ldb_search_test_setup,
4588 : ldb_search_test_teardown),
4589 : cmocka_unit_test_setup_teardown(test_search_match_filter,
4590 : ldb_search_test_setup,
4591 : ldb_search_test_teardown),
4592 : cmocka_unit_test_setup_teardown(test_search_match_both,
4593 : ldb_search_test_setup,
4594 : ldb_search_test_teardown),
4595 : cmocka_unit_test_setup_teardown(test_search_match_basedn,
4596 : ldb_search_test_setup,
4597 : ldb_search_test_teardown),
4598 : cmocka_unit_test_setup_teardown(test_ldb_search_against_transaction,
4599 : ldb_search_test_setup,
4600 : ldb_search_test_teardown),
4601 : cmocka_unit_test_setup_teardown(test_ldb_modify_during_unindexed_search,
4602 : ldb_search_test_setup,
4603 : ldb_search_test_teardown),
4604 : cmocka_unit_test_setup_teardown(test_ldb_modify_during_indexed_search,
4605 : ldb_search_test_setup,
4606 : ldb_search_test_teardown),
4607 : cmocka_unit_test_setup_teardown(test_ldb_rename_during_unindexed_search,
4608 : ldb_search_test_setup,
4609 : ldb_search_test_teardown),
4610 : cmocka_unit_test_setup_teardown(test_ldb_rename_during_indexed_search,
4611 : ldb_search_test_setup,
4612 : ldb_search_test_teardown),
4613 : cmocka_unit_test_setup_teardown(test_ldb_callback_rename_during_unindexed_search,
4614 : ldb_search_test_setup,
4615 : ldb_search_test_teardown),
4616 : cmocka_unit_test_setup_teardown(test_ldb_callback_rename_during_indexed_search,
4617 : ldb_search_test_setup,
4618 : ldb_search_test_teardown),
4619 : cmocka_unit_test_setup_teardown(test_ldb_callback_delete_during_unindexed_search,
4620 : ldb_search_test_setup,
4621 : ldb_search_test_teardown),
4622 : cmocka_unit_test_setup_teardown(test_ldb_callback_delete_during_indexed_search,
4623 : ldb_search_test_setup,
4624 : ldb_search_test_teardown),
4625 : cmocka_unit_test_setup_teardown(test_ldb_modify_during_whole_search,
4626 : ldb_search_test_setup,
4627 : ldb_search_test_teardown),
4628 : cmocka_unit_test_setup_teardown(test_ldb_modify_before_ldb_wait,
4629 : ldb_search_test_setup,
4630 : ldb_search_test_teardown),
4631 : cmocka_unit_test_setup_teardown(test_ldb_attrs_case_insensitive,
4632 : ldb_case_test_setup,
4633 : ldb_case_test_teardown),
4634 : cmocka_unit_test_setup_teardown(test_ldb_attrs_case_handler,
4635 : ldb_case_test_setup,
4636 : ldb_case_test_teardown),
4637 : cmocka_unit_test_setup_teardown(test_ldb_attrs_index_handler,
4638 : ldb_case_test_setup,
4639 : ldb_case_attrs_index_test_teardown),
4640 : cmocka_unit_test_setup_teardown(test_ldb_rename,
4641 : ldb_rename_test_setup,
4642 : ldb_rename_test_teardown),
4643 : cmocka_unit_test_setup_teardown(test_ldb_rename_from_doesnt_exist,
4644 : ldb_rename_test_setup,
4645 : ldb_rename_test_teardown),
4646 : cmocka_unit_test_setup_teardown(test_ldb_rename_to_exists,
4647 : ldb_rename_test_setup,
4648 : ldb_rename_test_teardown),
4649 : cmocka_unit_test_setup_teardown(test_ldb_rename_self,
4650 : ldb_rename_test_setup,
4651 : ldb_rename_test_teardown),
4652 : cmocka_unit_test_setup_teardown(test_ldb_rename_dn_case_change,
4653 : ldb_rename_test_setup,
4654 : ldb_rename_test_teardown),
4655 : cmocka_unit_test_setup_teardown(test_read_only,
4656 : ldb_read_only_setup,
4657 : ldb_read_only_teardown),
4658 : cmocka_unit_test_setup_teardown(
4659 : test_ldb_add_unique_value_to_unique_index,
4660 : ldb_unique_index_test_setup,
4661 : ldb_unique_index_test_teardown),
4662 : cmocka_unit_test_setup_teardown(
4663 : test_ldb_add_duplicate_value_to_unique_index,
4664 : ldb_unique_index_test_setup,
4665 : ldb_unique_index_test_teardown),
4666 : cmocka_unit_test_setup_teardown(
4667 : test_ldb_add_to_index_duplicates_allowed,
4668 : ldb_non_unique_index_test_setup,
4669 : ldb_non_unique_index_test_teardown),
4670 : cmocka_unit_test_setup_teardown(
4671 : test_ldb_add_to_index_unique_values_required,
4672 : ldb_non_unique_index_test_setup,
4673 : ldb_non_unique_index_test_teardown),
4674 : /* These tests are not compatible with mdb */
4675 : cmocka_unit_test_setup_teardown(
4676 : test_ldb_unique_index_duplicate_logging,
4677 : ldb_unique_index_test_setup,
4678 : ldb_unique_index_test_teardown),
4679 : cmocka_unit_test_setup_teardown(
4680 : test_ldb_duplicate_dn_logging,
4681 : ldb_unique_index_test_setup,
4682 : ldb_unique_index_test_teardown),
4683 : cmocka_unit_test_setup_teardown(
4684 : test_ldb_guid_index_duplicate_dn_logging,
4685 : ldb_guid_index_test_setup,
4686 : ldb_guid_index_test_teardown),
4687 : cmocka_unit_test_setup_teardown(
4688 : test_ldb_unique_index_duplicate_with_guid,
4689 : ldb_guid_index_test_setup,
4690 : ldb_guid_index_test_teardown),
4691 : cmocka_unit_test_setup_teardown(
4692 : test_ldb_talloc_destructor_transaction_cleanup,
4693 : ldbtest_setup,
4694 : ldbtest_teardown),
4695 : #ifdef TEST_LMDB
4696 : cmocka_unit_test_setup_teardown(
4697 : test_ldb_close_with_multiple_connections,
4698 : ldb_search_test_setup,
4699 : ldb_search_test_teardown),
4700 : #endif
4701 : cmocka_unit_test_setup_teardown(
4702 : test_transaction_start_across_fork,
4703 : ldbtest_setup,
4704 : ldbtest_teardown),
4705 : cmocka_unit_test_setup_teardown(
4706 : test_transaction_commit_across_fork,
4707 : ldbtest_setup,
4708 : ldbtest_teardown),
4709 : cmocka_unit_test_setup_teardown(
4710 : test_lock_read_across_fork,
4711 : ldbtest_setup,
4712 : ldbtest_teardown),
4713 : cmocka_unit_test_setup_teardown(
4714 : test_multiple_opens_across_fork,
4715 : ldbtest_setup,
4716 : ldbtest_teardown),
4717 : };
4718 :
4719 3 : if (argc > 1) {
4720 0 : cmocka_set_test_filter(argv[1]);
4721 : }
4722 :
4723 3 : cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
4724 :
4725 3 : return cmocka_run_group_tests(tests, NULL, NULL);
4726 : }
|