2 * Tests exercising the ldb key value operations.
4 * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 * These headers or their equivalents should be included prior to
31 * This allows test applications to use custom definitions of C standard
32 * library functions and types.
44 #define NO_FAILURE INT_MAX
45 #define FAILURE_LDB_ERR LDB_ERR_OTHER
48 * To test failure in ldb_kv_add, ldb_kv_delete, ldb_kv_modify and ldb_kv_rename
49 * we use the following global variables and macros to trigger a failure in
50 * the ldb_kv_<op>_internal functions. This allows testing of the sub
51 * transaction commits and roll backs in those operations.
53 * NOTE: Not all back ends support nested/sub transactions
55 int cmocka_unit_test_fail_add_internal_after
= NO_FAILURE
;
56 #define CMOCKA_UNIT_TEST_ADD_INTERNAL_FAIL \
58 cmocka_unit_test_fail_add_internal_after--;\
59 if (cmocka_unit_test_fail_add_internal_after <= 0) {\
60 assert_int_equal(LDB_SUCCESS, ret);\
61 ret = FAILURE_LDB_ERR;\
65 int cmocka_unit_test_fail_delete_internal_after = NO_FAILURE;
66 #define CMOCKA_UNIT_TEST_DELETE_INTERNAL_FAIL \
68 cmocka_unit_test_fail_delete_internal_after--;\
69 if (cmocka_unit_test_fail_delete_internal_after <= 0) {\
70 assert_int_equal(LDB_SUCCESS, ret);\
71 ret = FAILURE_LDB_ERR;\
75 int cmocka_unit_test_fail_rename_internal_after = NO_FAILURE;
76 #define CMOCKA_UNIT_TEST_RENAME_INTERNAL_FAIL \
78 cmocka_unit_test_fail_rename_internal_after--;\
79 if (cmocka_unit_test_fail_rename_internal_after <= 0) {\
80 assert_int_equal(LDB_SUCCESS, ret);\
81 ret = FAILURE_LDB_ERR;\
85 int cmocka_unit_test_fail_modify_internal_after = NO_FAILURE;
86 #define CMOCKA_UNIT_TEST_MODIFY_INTERNAL_FAIL \
88 cmocka_unit_test_fail_modify_internal_after--;\
89 if (cmocka_unit_test_fail_modify_internal_after <= 0) {\
90 assert_int_equal(LDB_SUCCESS, ret);\
91 ret = FAILURE_LDB_ERR;\
95 #include "ldb_key_value/ldb_kv.c"
98 #define DEFAULT_BE "tdb"
101 #define TEST_BE DEFAULT_BE
104 #define NUM_RECS 1024
108 struct tevent_context
*ev
;
109 struct ldb_context
*ldb
;
112 const char *lockfile
; /* lockfile is separate */
118 * Remove the database files
120 static void unlink_old_db(struct test_ctx
*test_ctx
)
125 ret
= unlink(test_ctx
->lockfile
);
126 if (ret
== -1 && errno
!= ENOENT
) {
131 ret
= unlink(test_ctx
->dbfile
);
132 if (ret
== -1 && errno
!= ENOENT
) {
140 static int noconn_setup(void **state
)
142 struct test_ctx
*test_ctx
;
143 cmocka_unit_test_fail_add_internal_after
= NO_FAILURE
;
144 cmocka_unit_test_fail_delete_internal_after
= NO_FAILURE
;
145 cmocka_unit_test_fail_rename_internal_after
= NO_FAILURE
;
146 cmocka_unit_test_fail_modify_internal_after
= NO_FAILURE
;
148 test_ctx
= talloc_zero(NULL
, struct test_ctx
);
149 assert_non_null(test_ctx
);
151 test_ctx
->ev
= tevent_context_init(test_ctx
);
152 assert_non_null(test_ctx
->ev
);
154 test_ctx
->ldb
= ldb_init(test_ctx
, test_ctx
->ev
);
155 assert_non_null(test_ctx
->ldb
);
157 test_ctx
->dbfile
= talloc_strdup(test_ctx
, "kvopstest.ldb");
158 assert_non_null(test_ctx
->dbfile
);
160 test_ctx
->lockfile
= talloc_asprintf(test_ctx
, "%s-lock",
162 assert_non_null(test_ctx
->lockfile
);
164 test_ctx
->dbpath
= talloc_asprintf(test_ctx
,
165 TEST_BE
"://%s", test_ctx
->dbfile
);
166 assert_non_null(test_ctx
->dbpath
);
168 unlink_old_db(test_ctx
);
176 static int noconn_teardown(void **state
)
178 struct test_ctx
*test_ctx
= talloc_get_type_abort(*state
,
181 unlink_old_db(test_ctx
);
182 talloc_free(test_ctx
);
189 static int setup(void **state
)
191 struct test_ctx
*test_ctx
;
193 struct ldb_ldif
*ldif
;
194 const char *index_ldif
= \
196 "@IDXGUID: objectUUID\n"
197 "@IDX_DN_GUID: GUID\n"
200 noconn_setup((void **) &test_ctx
);
202 ret
= ldb_connect(test_ctx
->ldb
, test_ctx
->dbpath
, 0, NULL
);
203 assert_int_equal(ret
, 0);
205 while ((ldif
= ldb_ldif_read_string(test_ctx
->ldb
, &index_ldif
))) {
206 ret
= ldb_add(test_ctx
->ldb
, ldif
->msg
);
207 assert_int_equal(ret
, LDB_SUCCESS
);
216 static int teardown(void **state
)
218 struct test_ctx
*test_ctx
= talloc_get_type_abort(*state
,
220 noconn_teardown((void **) &test_ctx
);
225 * Build an ldb_kv_context that can be passed to the ldb_kv operation under test
227 static struct ldb_kv_context
* build_ldb_kv_context(
229 struct ldb_module
*module
,
230 struct ldb_request
*req
)
232 struct ldb_kv_context
*ldb_kv_ctx
= NULL
;
234 ldb_kv_ctx
= talloc_zero(ctx
, struct ldb_kv_context
);
235 assert_non_null(ldb_kv_ctx
);
237 ldb_kv_ctx
->module
= module
;
238 ldb_kv_ctx
->req
= req
;
244 * Build an add request
246 static struct ldb_request
*build_add_request(
248 struct ldb_context
*ldb
,
254 struct ldb_message
*msg
;
255 struct ldb_request
*req
;
257 msg
= ldb_msg_new(ctx
);
258 assert_non_null(msg
);
260 msg
->dn
= ldb_dn_new_fmt(msg
, ldb
, "dc=%s", dc
);
261 assert_non_null(msg
->dn
);
263 ret
= ldb_msg_add_string(msg
, "cn", cn
);
264 assert_int_equal(ret
, 0);
266 ret
= ldb_msg_add_string(msg
, "objectUUID", uuid
);
267 assert_int_equal(ret
, 0);
269 ret
= ldb_msg_sanity_check(ldb
, msg
);
270 assert_int_equal(ret
, LDB_SUCCESS
);
272 ret
= ldb_build_add_req(
273 &req
, ldb
, ldb
, msg
, NULL
, NULL
, ldb_op_default_callback
, NULL
);
274 assert_int_equal(ret
, LDB_SUCCESS
);
279 * Build a delete request
281 static struct ldb_request
*build_delete_request(
283 struct ldb_context
*ldb
,
286 int ret
= LDB_SUCCESS
;
287 struct ldb_dn
*dn
= NULL
;
288 struct ldb_request
*req
= NULL
;
290 dn
= ldb_dn_new_fmt(ctx
, ldb
, "dc=%s", dc
);
293 ret
= ldb_build_del_req(
294 &req
, ldb
, ctx
, dn
, NULL
, NULL
, ldb_op_default_callback
, NULL
);
295 assert_int_equal(ret
, LDB_SUCCESS
);
300 * Build a rename request
302 static struct ldb_request
*build_rename_request(
304 struct ldb_context
*ldb
,
308 int ret
= LDB_SUCCESS
;
309 struct ldb_dn
*old_dn
= NULL
;
310 struct ldb_dn
*new_dn
= NULL
;
311 struct ldb_request
*req
= NULL
;
313 old_dn
= ldb_dn_new_fmt(ctx
, ldb
, "dc=%s", old_dc
);
314 assert_non_null(old_dn
);
316 new_dn
= ldb_dn_new_fmt(ctx
, ldb
, "dc=%s", new_dc
);
317 assert_non_null(new_dn
);
319 ret
= ldb_build_rename_req(
327 ldb_op_default_callback
,
329 assert_int_equal(ret
, LDB_SUCCESS
);
334 * Build a ldb modify request
336 static struct ldb_request
*build_modify_request(
338 struct ldb_context
*ldb
,
343 struct ldb_message
*msg
;
344 struct ldb_request
*req
;
346 msg
= ldb_msg_new(ctx
);
347 assert_non_null(msg
);
349 msg
->dn
= ldb_dn_new_fmt(msg
, ldb
, "dc=%s", dc
);
350 assert_non_null(msg
->dn
);
352 ret
= ldb_msg_add_empty(msg
, "cn", LDB_FLAG_MOD_REPLACE
, NULL
);
353 assert_int_equal(ret
, LDB_SUCCESS
);
354 ret
= ldb_msg_add_string(msg
, "cn", cn
);
355 assert_int_equal(ret
, LDB_SUCCESS
);
357 ret
= ldb_msg_sanity_check(ldb
, msg
);
358 assert_int_equal(ret
, LDB_SUCCESS
);
360 ret
= ldb_build_mod_req(
361 &req
, ldb
, ldb
, msg
, NULL
, NULL
, ldb_op_default_callback
, NULL
);
362 assert_int_equal(ret
, LDB_SUCCESS
);
367 * Delete a record from the database
369 static void delete_record(
371 struct ldb_context
*ldb
,
374 struct ldb_kv_context
*ldb_kv_ctx
= NULL
;
375 struct ldb_dn
*basedn
= NULL
;
376 struct ldb_result
*result
= NULL
;
377 struct ldb_request
*req
= NULL
;
378 int ret
= LDB_SUCCESS
;
380 req
= build_delete_request(ctx
, ldb
, dc
);
381 ldb_kv_ctx
= build_ldb_kv_context(ctx
, ldb
->modules
, req
);
383 ret
= ldb_transaction_start(ldb
);
384 assert_int_equal(ret
, LDB_SUCCESS
);
386 cmocka_unit_test_fail_delete_internal_after
= NO_FAILURE
;
387 cmocka_unit_test_fail_modify_internal_after
= NO_FAILURE
;
388 ret
= ldb_kv_delete(ldb_kv_ctx
);
389 assert_int_equal(ret
, LDB_SUCCESS
);
390 TALLOC_FREE(ldb_kv_ctx
);
393 ret
= ldb_transaction_commit(ldb
);
394 assert_int_equal(ret
, LDB_SUCCESS
);
397 * Ensure that the record was actually deleted.
399 basedn
= ldb_dn_new_fmt(ctx
, ldb
, "dc=%s", dc
);
400 assert_non_null(basedn
);
405 ret
= ldb_search(ldb
, ctx
, &result
, basedn
, LDB_SCOPE_BASE
, NULL
, NULL
);
406 assert_int_equal(ret
, LDB_SUCCESS
);
407 assert_non_null(result
);
408 assert_int_equal(result
->count
, 0);
414 * Add a record to the database
416 static void add_record(
418 struct ldb_context
*ldb
,
424 struct ldb_request
*req
= NULL
;
425 int ret
= LDB_SUCCESS
;
426 struct ldb_kv_context
*ldb_kv_ctx
= NULL
;
427 struct ldb_dn
*basedn
= NULL
;
428 struct ldb_result
*result
= NULL
;
430 req
= build_add_request(ctx
, ldb
, dc
, uuid
, cn
);
432 ldb_req_set_location(req
, "add_record");
434 assert_int_equal(ret
, LDB_SUCCESS
);
437 ldb_kv_ctx
= build_ldb_kv_context(ctx
, ldb
->modules
, req
);
438 cmocka_unit_test_fail_add_internal_after
= NO_FAILURE
;
439 cmocka_unit_test_fail_modify_internal_after
= NO_FAILURE
;
441 ret
= ldb_transaction_start(ldb
);
442 assert_int_equal(ret
, LDB_SUCCESS
);
444 ret
= ldb_kv_add(ldb_kv_ctx
);
445 assert_int_equal(ret
, LDB_SUCCESS
);
446 TALLOC_FREE(ldb_kv_ctx
);
449 ret
= ldb_transaction_commit(ldb
);
450 assert_int_equal(ret
, LDB_SUCCESS
);
453 * Ensure that the record was actually written.
455 basedn
= ldb_dn_new_fmt(ctx
, ldb
, "dc=%s", dc
);
456 assert_non_null(basedn
);
461 ret
= ldb_search(ldb
, ctx
, &result
, basedn
, LDB_SCOPE_BASE
, NULL
, NULL
);
462 assert_int_equal(ret
, LDB_SUCCESS
);
463 assert_non_null(result
);
464 assert_int_equal(result
->count
, 1);
469 * CN search unindexed
480 assert_int_equal(ret
, LDB_SUCCESS
);
481 assert_non_null(result
);
482 assert_int_equal(result
->count
, 1);
488 * Test that a failed add operation does not change the database.
490 static void test_add_failure(void **state
)
492 int ret
= LDB_SUCCESS
;
493 struct test_ctx
*test_ctx
= talloc_get_type_abort(*state
,
495 struct ldb_request
*req
= NULL
;
496 struct ldb_dn
*basedn
= NULL
;
497 struct ldb_result
*result
= NULL
;
498 struct ldb_kv_context
*ldb_kv_ctx
= NULL
;
500 TALLOC_CTX
*tmp_ctx
= talloc_new(test_ctx
);
501 assert_non_null(tmp_ctx
);
503 req
= build_add_request(
508 "test_add_failure_value");
510 ldb_req_set_location(req
, "test_add_failure");
512 ldb_kv_ctx
= build_ldb_kv_context(tmp_ctx
, test_ctx
->ldb
->modules
, req
);
513 cmocka_unit_test_fail_add_internal_after
= 1;
515 ret
= ldb_transaction_start(test_ctx
->ldb
);
516 assert_int_equal(ret
, LDB_SUCCESS
);
518 ret
= ldb_kv_add(ldb_kv_ctx
);
520 assert_int_equal(ret
, FAILURE_LDB_ERR
);
521 TALLOC_FREE(ldb_kv_ctx
);
526 * a search for "cn=test_add_failure_value" should fail
527 * as the transaction containing the operation should have been
528 * rolled back leaving the database consistent
530 * This should be an un-indexed search so the index caches won't be
533 basedn
= ldb_dn_new_fmt(
538 assert_non_null(basedn
);
541 test_ctx
->ldb
, tmp_ctx
,
547 "test_add_failure_value");
548 assert_int_equal(ret
, LDB_SUCCESS
);
549 assert_non_null(result
);
550 assert_int_equal(result
->count
, 0);
554 ldb_transaction_cancel(test_ctx
->ldb
);
555 TALLOC_FREE(tmp_ctx
);
560 * Test that a failed delete operation does not modify the database.
562 static void test_delete_failure(void **state
)
564 int ret
= LDB_SUCCESS
;
565 struct test_ctx
*test_ctx
= talloc_get_type_abort(*state
,
567 struct ldb_request
*req
= NULL
;
568 struct ldb_dn
*basedn
= NULL
;
569 struct ldb_result
*result
= NULL
;
570 struct ldb_kv_context
*ldb_kv_ctx
= NULL
;
572 TALLOC_CTX
*tmp_ctx
= talloc_new(test_ctx
);
573 assert_non_null(tmp_ctx
);
578 "test_delete_failure",
580 "test_delete_failure_value");
582 req
= build_delete_request(
585 "test_delete_failure");
587 ldb_kv_ctx
= build_ldb_kv_context(tmp_ctx
, test_ctx
->ldb
->modules
, req
);
588 cmocka_unit_test_fail_delete_internal_after
= 1;
590 ret
= ldb_transaction_start(test_ctx
->ldb
);
591 assert_int_equal(ret
, LDB_SUCCESS
);
593 ret
= ldb_kv_delete(ldb_kv_ctx
);
594 assert_int_equal(ret
, FAILURE_LDB_ERR
);
595 TALLOC_FREE(ldb_kv_ctx
);
599 * a search for "cn=test_add_failure_value" should succeed
600 * as the transaction containing the operation should have been
601 * rolled back leaving the database consistent
603 * This should be an un-indexed search so the index caches won't be
606 basedn
= ldb_dn_new_fmt(
610 "test_delete_failure");
611 assert_non_null(basedn
);
614 test_ctx
->ldb
, tmp_ctx
,
620 "test_delete_failure_value");
621 assert_int_equal(ret
, LDB_SUCCESS
);
622 assert_non_null(result
);
623 assert_int_equal(result
->count
, 1);
628 ldb_transaction_cancel(test_ctx
->ldb
);
632 "test_delete_failure");
633 TALLOC_FREE(tmp_ctx
);
637 * Test that a failed rename operation dies not change the database
639 static void test_rename_failure(void **state
)
641 int ret
= LDB_SUCCESS
;
642 struct test_ctx
*test_ctx
= talloc_get_type_abort(*state
,
644 struct ldb_request
*req
= NULL
;
645 struct ldb_dn
*basedn
= NULL
;
646 struct ldb_result
*result
= NULL
;
647 struct ldb_kv_context
*ldb_kv_ctx
= NULL
;
649 TALLOC_CTX
*tmp_ctx
= talloc_new(test_ctx
);
650 assert_non_null(tmp_ctx
);
655 "test_rename_failure",
657 "test_rename_failure_value");
659 req
= build_rename_request(
662 "test_rename_failure",
663 "test_rename_failure_renamed");
665 ldb_kv_ctx
= build_ldb_kv_context(tmp_ctx
, test_ctx
->ldb
->modules
, req
);
666 cmocka_unit_test_fail_rename_internal_after
= 1;
668 ret
= ldb_transaction_start(test_ctx
->ldb
);
669 assert_int_equal(ret
, LDB_SUCCESS
);
671 ret
= ldb_kv_rename(ldb_kv_ctx
);
672 assert_int_equal(ret
, FAILURE_LDB_ERR
);
673 TALLOC_FREE(ldb_kv_ctx
);
677 * The original record should be present
679 basedn
= ldb_dn_new_fmt(
683 "test_rename_failure");
684 assert_non_null(basedn
);
687 test_ctx
->ldb
, tmp_ctx
,
693 "test_rename_failure_value");
694 assert_int_equal(ret
, LDB_SUCCESS
);
695 assert_non_null(result
);
696 assert_int_equal(result
->count
, 1);
701 * And the renamed record should not be present
703 basedn
= ldb_dn_new_fmt(
707 "test_rename_failure_renamed");
708 assert_non_null(basedn
);
711 test_ctx
->ldb
, tmp_ctx
,
717 "test_rename_failure_value");
718 assert_int_equal(ret
, LDB_SUCCESS
);
719 assert_non_null(result
);
720 assert_int_equal(result
->count
, 0);
724 ldb_transaction_cancel(test_ctx
->ldb
);
728 "test_rename_failure");
729 TALLOC_FREE(tmp_ctx
);
733 * Test that a failed modification operation does not change the database
735 static void test_modify_failure(void **state
)
737 int ret
= LDB_SUCCESS
;
738 struct test_ctx
*test_ctx
= talloc_get_type_abort(*state
,
740 struct ldb_request
*req
= NULL
;
741 struct ldb_dn
*basedn
= NULL
;
742 struct ldb_result
*result
= NULL
;
743 struct ldb_kv_context
*ldb_kv_ctx
= NULL
;
745 TALLOC_CTX
*tmp_ctx
= talloc_new(test_ctx
);
746 assert_non_null(tmp_ctx
);
751 "test_modify_failure",
753 "test_modify_failure_value");
755 req
= build_modify_request(
758 "test_modify_failure",
759 "test_modify_failure_value_modified");
761 ldb_kv_ctx
= build_ldb_kv_context(tmp_ctx
, test_ctx
->ldb
->modules
, req
);
762 cmocka_unit_test_fail_modify_internal_after
= 2;
764 ret
= ldb_transaction_start(test_ctx
->ldb
);
765 assert_int_equal(ret
, LDB_SUCCESS
);
767 ret
= ldb_kv_modify(ldb_kv_ctx
);
768 assert_int_equal(ret
, FAILURE_LDB_ERR
);
769 TALLOC_FREE(ldb_kv_ctx
);
774 * The original value should be present
776 basedn
= ldb_dn_new_fmt(
780 "test_modify_failure");
781 assert_non_null(basedn
);
784 test_ctx
->ldb
, tmp_ctx
,
790 "test_modify_failure_value");
791 assert_int_equal(ret
, LDB_SUCCESS
);
792 assert_non_null(result
);
793 assert_int_equal(result
->count
, 1);
797 * And the modified record should not be present
800 test_ctx
->ldb
, tmp_ctx
,
806 "test_modify_failure_value_modified");
807 assert_int_equal(ret
, LDB_SUCCESS
);
808 assert_non_null(result
);
809 assert_int_equal(result
->count
, 0);
813 ldb_transaction_cancel(test_ctx
->ldb
);
817 "test_modify_failure");
818 TALLOC_FREE(tmp_ctx
);
821 int main(int argc
, const char **argv
)
823 const struct CMUnitTest tests
[] = {
824 cmocka_unit_test_setup_teardown(
828 cmocka_unit_test_setup_teardown(
832 cmocka_unit_test_setup_teardown(
836 cmocka_unit_test_setup_teardown(
842 return cmocka_run_group_tests(tests
, NULL
, NULL
);