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