LCOV - code coverage report
Current view: top level - lib/ldb/tests - ldb_mod_op_test.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 2153 2243 96.0 %
Date: 2024-04-21 15:09:00 Functions: 113 114 99.1 %

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

Generated by: LCOV version 1.14