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

Generated by: LCOV version 1.13