LCOV - code coverage report
Current view: top level - lib/ldb/tests - ldb_key_value_sub_txn_test.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 315 317 99.4 %
Date: 2024-04-21 15:09:00 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Tests exercising the ldb key value operations.
       3             :  *
       4             :  *  Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             :  *
      19             :  */
      20             : 
      21             : /*
      22             :  * from cmocka.c:
      23             :  * These headers or their equivalents should be included prior to
      24             :  * including
      25             :  * this header file.
      26             :  *
      27             :  * #include <stdarg.h>
      28             :  * #include <stddef.h>
      29             :  * #include <setjmp.h>
      30             :  *
      31             :  * This allows test applications to use custom definitions of C standard
      32             :  * library functions and types.
      33             :  *
      34             :  */
      35             : 
      36             : /*
      37             :  */
      38             : #include <stdarg.h>
      39             : #include <stddef.h>
      40             : #include <stdint.h>
      41             : #include <setjmp.h>
      42             : #include <cmocka.h>
      43             : 
      44             : #include <limits.h>
      45             : #define NO_FAILURE INT_MAX
      46             : #define FAILURE_LDB_ERR LDB_ERR_OTHER
      47             : 
      48             : /*
      49             :  * To test failure in ldb_kv_add, ldb_kv_delete, ldb_kv_modify and ldb_kv_rename
      50             :  * we use the following global variables and macros to trigger a failure in
      51             :  * the ldb_kv_<op>_internal functions. This allows testing of the sub
      52             :  * transaction commits and roll backs in those operations.
      53             :  *
      54             :  * NOTE: Not all back ends support nested/sub transactions
      55             :  */
      56             : int cmocka_unit_test_fail_add_internal_after = NO_FAILURE;
      57             : #define CMOCKA_UNIT_TEST_ADD_INTERNAL_FAIL \
      58             :         {\
      59             :                 cmocka_unit_test_fail_add_internal_after--;\
      60             :                 if (cmocka_unit_test_fail_add_internal_after <= 0) {\
      61             :                         assert_int_equal(LDB_SUCCESS, ret);\
      62             :                         ret = FAILURE_LDB_ERR;\
      63             :                 }\
      64             :         }\
      65             : 
      66             : int cmocka_unit_test_fail_delete_internal_after = NO_FAILURE;
      67             : #define CMOCKA_UNIT_TEST_DELETE_INTERNAL_FAIL \
      68             :         {\
      69             :                 cmocka_unit_test_fail_delete_internal_after--;\
      70             :                 if (cmocka_unit_test_fail_delete_internal_after <= 0) {\
      71             :                         assert_int_equal(LDB_SUCCESS, ret);\
      72             :                         ret = FAILURE_LDB_ERR;\
      73             :                 }\
      74             :         }\
      75             : 
      76             : int cmocka_unit_test_fail_rename_internal_after = NO_FAILURE;
      77             : #define CMOCKA_UNIT_TEST_RENAME_INTERNAL_FAIL \
      78             :         {\
      79             :                 cmocka_unit_test_fail_rename_internal_after--;\
      80             :                 if (cmocka_unit_test_fail_rename_internal_after <= 0) {\
      81             :                         assert_int_equal(LDB_SUCCESS, ret);\
      82             :                         ret = FAILURE_LDB_ERR;\
      83             :                 }\
      84             :         }\
      85             : 
      86             : int cmocka_unit_test_fail_modify_internal_after = NO_FAILURE;
      87             : #define CMOCKA_UNIT_TEST_MODIFY_INTERNAL_FAIL \
      88             :         {\
      89             :                 cmocka_unit_test_fail_modify_internal_after--;\
      90             :                 if (cmocka_unit_test_fail_modify_internal_after <= 0) {\
      91             :                         assert_int_equal(LDB_SUCCESS, ret);\
      92             :                         ret = FAILURE_LDB_ERR;\
      93             :                 }\
      94             :         }\
      95             : 
      96             : #include "ldb_key_value/ldb_kv.c"
      97             : 
      98             : 
      99             : #define DEFAULT_BE  "tdb"
     100             : 
     101             : #ifndef TEST_BE
     102             : #define TEST_BE DEFAULT_BE
     103             : #endif /* TEST_BE */
     104             : 
     105             : #define NUM_RECS 1024
     106             : 
     107             : 
     108             : struct test_ctx {
     109             :         struct tevent_context *ev;
     110             :         struct ldb_context *ldb;
     111             : 
     112             :         const char *dbfile;
     113             :         const char *lockfile;   /* lockfile is separate */
     114             : 
     115             :         const char *dbpath;
     116             : };
     117             : 
     118             : /*
     119             :  * Remove the database files
     120             :  */
     121           8 : static void unlink_old_db(struct test_ctx *test_ctx)
     122             : {
     123           8 :         int ret;
     124             : 
     125           8 :         errno = 0;
     126           8 :         ret = unlink(test_ctx->lockfile);
     127           8 :         if (ret == -1 && errno != ENOENT) {
     128           0 :                 fail();
     129             :         }
     130             : 
     131           8 :         errno = 0;
     132           8 :         ret = unlink(test_ctx->dbfile);
     133           8 :         if (ret == -1 && errno != ENOENT) {
     134           0 :                 fail();
     135             :         }
     136           8 : }
     137             : 
     138             : /*
     139             :  * Test setup
     140             :  */
     141           4 : static int noconn_setup(void **state)
     142             : {
     143           4 :         struct test_ctx *test_ctx;
     144           4 :         cmocka_unit_test_fail_add_internal_after = NO_FAILURE;
     145           4 :         cmocka_unit_test_fail_delete_internal_after = NO_FAILURE;
     146           4 :         cmocka_unit_test_fail_rename_internal_after = NO_FAILURE;
     147           4 :         cmocka_unit_test_fail_modify_internal_after = NO_FAILURE;
     148             : 
     149           4 :         test_ctx = talloc_zero(NULL, struct test_ctx);
     150           4 :         assert_non_null(test_ctx);
     151             : 
     152           4 :         test_ctx->ev = tevent_context_init(test_ctx);
     153           4 :         assert_non_null(test_ctx->ev);
     154             : 
     155           4 :         test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
     156           4 :         assert_non_null(test_ctx->ldb);
     157             : 
     158           4 :         test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb");
     159           4 :         assert_non_null(test_ctx->dbfile);
     160             : 
     161           4 :         test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
     162             :                                              test_ctx->dbfile);
     163           4 :         assert_non_null(test_ctx->lockfile);
     164             : 
     165           4 :         test_ctx->dbpath = talloc_asprintf(test_ctx,
     166             :                         TEST_BE"://%s", test_ctx->dbfile);
     167           4 :         assert_non_null(test_ctx->dbpath);
     168             : 
     169           4 :         unlink_old_db(test_ctx);
     170           4 :         *state = test_ctx;
     171           4 :         return 0;
     172             : }
     173             : 
     174             : /*
     175             :  * Test teardown
     176             :  */
     177           4 : static int noconn_teardown(void **state)
     178             : {
     179           4 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     180             :                                                           struct test_ctx);
     181             : 
     182           4 :         unlink_old_db(test_ctx);
     183           4 :         talloc_free(test_ctx);
     184           4 :         return 0;
     185             : }
     186             : 
     187             : /*
     188             :  * Test setup
     189             :  */
     190           4 : static int setup(void **state)
     191             : {
     192           4 :         struct test_ctx *test_ctx;
     193           4 :         int ret;
     194           4 :         struct ldb_ldif *ldif;
     195           4 :         const char *index_ldif =                \
     196             :                 "dn: @INDEXLIST\n"
     197             :                 "@IDXGUID: objectUUID\n"
     198             :                 "@IDX_DN_GUID: GUID\n"
     199             :                 "\n";
     200             : 
     201           4 :         noconn_setup((void **) &test_ctx);
     202             : 
     203           4 :         ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
     204           4 :         assert_int_equal(ret, 0);
     205             : 
     206           8 :         while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) {
     207           4 :                 ret = ldb_add(test_ctx->ldb, ldif->msg);
     208           4 :                 assert_int_equal(ret, LDB_SUCCESS);
     209             :         }
     210           4 :         *state = test_ctx;
     211           4 :         return 0;
     212             : }
     213             : 
     214             : /*
     215             :  * Test teardown
     216             :  */
     217           4 : static int teardown(void **state)
     218             : {
     219           4 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     220             :                                                           struct test_ctx);
     221           4 :         noconn_teardown((void **) &test_ctx);
     222           4 :         return 0;
     223             : }
     224             : 
     225             : /*
     226             :  * Build an ldb_kv_context that can be passed to the ldb_kv operation under test
     227             :  */
     228          10 : static struct ldb_kv_context* build_ldb_kv_context(
     229             :         TALLOC_CTX *ctx,
     230             :         struct ldb_module *module,
     231             :         struct ldb_request *req)
     232             : {
     233          10 :         struct ldb_kv_context *ldb_kv_ctx = NULL;
     234             : 
     235          10 :         ldb_kv_ctx = talloc_zero(ctx, struct ldb_kv_context);
     236          10 :         assert_non_null(ldb_kv_ctx);
     237             : 
     238          10 :         ldb_kv_ctx->module = module;
     239          10 :         ldb_kv_ctx->req = req;
     240             : 
     241          10 :         return ldb_kv_ctx;
     242             : }
     243             : 
     244             : /*
     245             :  * Build an add request
     246             :  */
     247           4 : static struct ldb_request *build_add_request(
     248             :         TALLOC_CTX *ctx,
     249             :         struct ldb_context *ldb,
     250             :         const char* dc,
     251             :         const char* uuid,
     252             :         const char* cn)
     253             : {
     254           4 :         int ret;
     255           4 :         struct ldb_message *msg;
     256           4 :         struct ldb_request *req;
     257             : 
     258           4 :         msg = ldb_msg_new(ctx);
     259           4 :         assert_non_null(msg);
     260             : 
     261           4 :         msg->dn = ldb_dn_new_fmt(msg, ldb, "dc=%s", dc);
     262           4 :         assert_non_null(msg->dn);
     263             : 
     264           4 :         ret = ldb_msg_add_string(msg, "cn", cn);
     265           4 :         assert_int_equal(ret, 0);
     266             : 
     267           4 :         ret = ldb_msg_add_string(msg, "objectUUID", uuid);
     268           4 :         assert_int_equal(ret, 0);
     269             : 
     270           4 :         ret = ldb_msg_sanity_check(ldb, msg);
     271           4 :         assert_int_equal(ret, LDB_SUCCESS);
     272             : 
     273           4 :         ret = ldb_build_add_req(
     274             :             &req, ldb, ldb, msg, NULL, NULL, ldb_op_default_callback, NULL);
     275           4 :         assert_int_equal(ret, LDB_SUCCESS);
     276           4 :         return req;
     277             : }
     278             : 
     279             : /*
     280             :  * Build a delete request
     281             :  */
     282           4 : static struct ldb_request *build_delete_request(
     283             :         TALLOC_CTX *ctx,
     284             :         struct ldb_context *ldb,
     285             :         const char* dc)
     286             : {
     287           4 :         int ret = LDB_SUCCESS;
     288           4 :         struct ldb_dn *dn = NULL;
     289           4 :         struct ldb_request *req = NULL;
     290             : 
     291           4 :         dn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", dc);
     292           4 :         assert_non_null(dn);
     293             : 
     294           4 :         ret = ldb_build_del_req(
     295             :             &req, ldb, ctx, dn, NULL, NULL, ldb_op_default_callback, NULL);
     296           4 :         assert_int_equal(ret, LDB_SUCCESS);
     297           4 :         return req;
     298             : }
     299             : 
     300             : /*
     301             :  * Build a rename request
     302             :  */
     303           1 : static struct ldb_request *build_rename_request(
     304             :         TALLOC_CTX *ctx,
     305             :         struct ldb_context *ldb,
     306             :         const char* old_dc,
     307             :         const char* new_dc)
     308             : {
     309           1 :         int ret = LDB_SUCCESS;
     310           1 :         struct ldb_dn *old_dn = NULL;
     311           1 :         struct ldb_dn *new_dn = NULL;
     312           1 :         struct ldb_request *req = NULL;
     313             : 
     314           1 :         old_dn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", old_dc);
     315           1 :         assert_non_null(old_dn);
     316             : 
     317           1 :         new_dn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", new_dc);
     318           1 :         assert_non_null(new_dn);
     319             : 
     320           1 :         ret = ldb_build_rename_req(
     321             :                 &req,
     322             :                 ldb,
     323             :                 ctx,
     324             :                 old_dn,
     325             :                 new_dn,
     326             :                 NULL,
     327             :                 NULL,
     328             :                 ldb_op_default_callback,
     329             :                 NULL);
     330           1 :         assert_int_equal(ret, LDB_SUCCESS);
     331           1 :         return req;
     332             : }
     333             : 
     334             : /*
     335             :  * Build a ldb modify request
     336             :  */
     337           1 : static struct ldb_request *build_modify_request(
     338             :         TALLOC_CTX *ctx,
     339             :         struct ldb_context *ldb,
     340             :         const char* dc,
     341             :         const char* cn)
     342             : {
     343           1 :         int ret;
     344           1 :         struct ldb_message *msg;
     345           1 :         struct ldb_request *req;
     346             : 
     347           1 :         msg = ldb_msg_new(ctx);
     348           1 :         assert_non_null(msg);
     349             : 
     350           1 :         msg->dn = ldb_dn_new_fmt(msg, ldb, "dc=%s", dc);
     351           1 :         assert_non_null(msg->dn);
     352             : 
     353           1 :         ret = ldb_msg_add_empty(msg, "cn", LDB_FLAG_MOD_REPLACE, NULL);
     354           1 :         assert_int_equal(ret, LDB_SUCCESS);
     355           1 :         ret = ldb_msg_add_string(msg, "cn", cn);
     356           1 :         assert_int_equal(ret, LDB_SUCCESS);
     357             : 
     358           1 :         ret = ldb_msg_sanity_check(ldb, msg);
     359           1 :         assert_int_equal(ret, LDB_SUCCESS);
     360             : 
     361           1 :         ret = ldb_build_mod_req(
     362             :             &req, ldb, ldb, msg, NULL, NULL, ldb_op_default_callback, NULL);
     363           1 :         assert_int_equal(ret, LDB_SUCCESS);
     364           1 :         return req;
     365             : }
     366             : 
     367             : /*
     368             :  * Delete a record from the database
     369             :  */
     370           3 : static void delete_record(
     371             :         TALLOC_CTX *ctx,
     372             :         struct ldb_context *ldb,
     373             :         const char* dc)
     374             : {
     375           3 :         struct ldb_kv_context *ldb_kv_ctx = NULL;
     376           3 :         struct ldb_dn *basedn = NULL;
     377           3 :         struct ldb_result *result = NULL;
     378           3 :         struct ldb_request *req = NULL;
     379           3 :         int ret = LDB_SUCCESS;
     380             : 
     381           3 :         req = build_delete_request(ctx, ldb, dc);
     382           3 :         ldb_kv_ctx = build_ldb_kv_context(ctx, ldb->modules, req);
     383             : 
     384           3 :         ret = ldb_transaction_start(ldb);
     385           3 :         assert_int_equal(ret, LDB_SUCCESS);
     386             : 
     387           3 :         cmocka_unit_test_fail_delete_internal_after = NO_FAILURE;
     388           3 :         cmocka_unit_test_fail_modify_internal_after = NO_FAILURE;
     389           3 :         ret = ldb_kv_delete(ldb_kv_ctx);
     390           3 :         assert_int_equal(ret, LDB_SUCCESS);
     391           3 :         TALLOC_FREE(ldb_kv_ctx);
     392           3 :         TALLOC_FREE(req);
     393             : 
     394           3 :         ret = ldb_transaction_commit(ldb);
     395           3 :         assert_int_equal(ret, LDB_SUCCESS);
     396             : 
     397             :         /*
     398             :          * Ensure that the record was actually deleted.
     399             :          */
     400           3 :         basedn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", dc);
     401           3 :         assert_non_null(basedn);
     402             : 
     403             :         /*
     404             :          * DN search, indexed
     405             :          */
     406           3 :         ret = ldb_search(ldb, ctx, &result, basedn, LDB_SCOPE_BASE, NULL, NULL);
     407           3 :         assert_int_equal(ret, LDB_SUCCESS);
     408           3 :         assert_non_null(result);
     409           3 :         assert_int_equal(result->count, 0);
     410           3 :         TALLOC_FREE(basedn);
     411           3 :         TALLOC_FREE(result);
     412           3 : }
     413             : 
     414             : /*
     415             :  * Add a record to the database
     416             :  */
     417           3 : static void add_record(
     418             :         TALLOC_CTX *ctx,
     419             :         struct ldb_context *ldb,
     420             :         const char* dc,
     421             :         const char* uuid,
     422             :         const char* cn)
     423             : {
     424             : 
     425           3 :         struct ldb_request *req = NULL;
     426           3 :         int ret = LDB_SUCCESS;
     427           3 :         struct ldb_kv_context *ldb_kv_ctx = NULL;
     428           3 :         struct ldb_dn *basedn = NULL;
     429           3 :         struct ldb_result *result = NULL;
     430             : 
     431           3 :         req = build_add_request(ctx, ldb, dc, uuid, cn);
     432             : 
     433           3 :         ldb_req_set_location(req, "add_record");
     434             : 
     435           3 :         assert_int_equal(ret, LDB_SUCCESS);
     436             : 
     437             : 
     438           3 :         ldb_kv_ctx = build_ldb_kv_context(ctx, ldb->modules, req);
     439           3 :         cmocka_unit_test_fail_add_internal_after = NO_FAILURE;
     440           3 :         cmocka_unit_test_fail_modify_internal_after = NO_FAILURE;
     441             : 
     442           3 :         ret = ldb_transaction_start(ldb);
     443           3 :         assert_int_equal(ret, LDB_SUCCESS);
     444             : 
     445           3 :         ret = ldb_kv_add(ldb_kv_ctx);
     446           3 :         assert_int_equal(ret, LDB_SUCCESS);
     447           3 :         TALLOC_FREE(ldb_kv_ctx);
     448           3 :         TALLOC_FREE(req);
     449             : 
     450           3 :         ret = ldb_transaction_commit(ldb);
     451           3 :         assert_int_equal(ret, LDB_SUCCESS);
     452             : 
     453             :         /*
     454             :          * Ensure that the record was actually written.
     455             :          */
     456           3 :         basedn = ldb_dn_new_fmt(ctx, ldb, "dc=%s", dc);
     457           3 :         assert_non_null(basedn);
     458             : 
     459             :         /*
     460             :          * DN search, indexed
     461             :          */
     462           3 :         ret = ldb_search(ldb, ctx, &result, basedn, LDB_SCOPE_BASE, NULL, NULL);
     463           3 :         assert_int_equal(ret, LDB_SUCCESS);
     464           3 :         assert_non_null(result);
     465           3 :         assert_int_equal(result->count, 1);
     466           3 :         TALLOC_FREE(result);
     467             : 
     468             : 
     469             :         /*
     470             :          * CN search unindexed
     471             :          */
     472           3 :         ret = ldb_search(
     473             :                 ldb,
     474             :                 ctx,
     475             :                 &result,
     476             :                 basedn,
     477             :                 LDB_SCOPE_SUBTREE,
     478             :                 NULL,
     479             :                 "(cn=%s)",
     480             :                 cn);
     481           3 :         assert_int_equal(ret, LDB_SUCCESS);
     482           3 :         assert_non_null(result);
     483           3 :         assert_int_equal(result->count, 1);
     484           3 :         TALLOC_FREE(result);
     485           3 :         TALLOC_FREE(basedn);
     486           3 : }
     487             : 
     488             : /*
     489             :  * Test that a failed add operation does not change the database.
     490             :  */
     491           1 : static void test_add_failure(void **state)
     492             : {
     493           1 :         int ret = LDB_SUCCESS;
     494           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     495             :                                                           struct test_ctx);
     496           1 :         struct ldb_request *req = NULL;
     497           1 :         struct ldb_dn *basedn = NULL;
     498           1 :         struct ldb_result *result = NULL;
     499           1 :         struct ldb_kv_context *ldb_kv_ctx = NULL;
     500             : 
     501           1 :         TALLOC_CTX *tmp_ctx = talloc_new(test_ctx);
     502           1 :         assert_non_null(tmp_ctx);
     503             : 
     504           1 :         req = build_add_request(
     505             :                 tmp_ctx,
     506             :                 test_ctx->ldb,
     507             :                 "test_add_failure",
     508             :                 "0123456789abcdef",
     509             :                 "test_add_failure_value");
     510             : 
     511           1 :         ldb_req_set_location(req, "test_add_failure");
     512             : 
     513           1 :         ldb_kv_ctx = build_ldb_kv_context(tmp_ctx, test_ctx->ldb->modules, req);
     514           1 :         cmocka_unit_test_fail_add_internal_after = 1;
     515             : 
     516           1 :         ret = ldb_transaction_start(test_ctx->ldb);
     517           1 :         assert_int_equal(ret, LDB_SUCCESS);
     518             : 
     519           1 :         ret = ldb_kv_add(ldb_kv_ctx);
     520             : 
     521           1 :         assert_int_equal(ret, FAILURE_LDB_ERR);
     522           1 :         TALLOC_FREE(ldb_kv_ctx);
     523           1 :         TALLOC_FREE(req);
     524             : 
     525             : 
     526             :         /*
     527             :          * a search for "cn=test_add_failure_value" should fail
     528             :          * as the transaction containing the operation should have been
     529             :          * rolled back leaving the database consistent
     530             :          *
     531             :          * This should be an un-indexed search so the index caches won't be
     532             :          * used.
     533             :          */
     534           1 :         basedn = ldb_dn_new_fmt(
     535             :                 tmp_ctx,
     536             :                 test_ctx->ldb,
     537             :                 "dc=%s",
     538             :                 "test_add_failure");
     539           1 :         assert_non_null(basedn);
     540             : 
     541           1 :         ret = ldb_search(
     542             :                 test_ctx->ldb, tmp_ctx,
     543             :                 &result,
     544             :                 basedn,
     545             :                 LDB_SCOPE_SUBTREE,
     546             :                 NULL,
     547             :                 "(cn=%s)",
     548             :                 "test_add_failure_value");
     549           1 :         assert_int_equal(ret, LDB_SUCCESS);
     550           1 :         assert_non_null(result);
     551           1 :         assert_int_equal(result->count, 0);
     552           1 :         TALLOC_FREE(basedn);
     553           1 :         TALLOC_FREE(result);
     554             : 
     555           1 :         ldb_transaction_cancel(test_ctx->ldb);
     556           1 :         TALLOC_FREE(tmp_ctx);
     557           1 : }
     558             : 
     559             : 
     560             : /*
     561             :  * Test that a failed delete operation does not modify the database.
     562             :  */
     563           1 : static void test_delete_failure(void **state)
     564             : {
     565           1 :         int ret = LDB_SUCCESS;
     566           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     567             :                                                           struct test_ctx);
     568           1 :         struct ldb_request *req = NULL;
     569           1 :         struct ldb_dn *basedn = NULL;
     570           1 :         struct ldb_result *result = NULL;
     571           1 :         struct ldb_kv_context *ldb_kv_ctx = NULL;
     572             : 
     573           1 :         TALLOC_CTX *tmp_ctx = talloc_new(test_ctx);
     574           1 :         assert_non_null(tmp_ctx);
     575             : 
     576           1 :         add_record(
     577             :                 tmp_ctx,
     578             :                 test_ctx->ldb,
     579             :                 "test_delete_failure",
     580             :                 "0123456789abcded",
     581             :                 "test_delete_failure_value");
     582             : 
     583           1 :         req = build_delete_request(
     584             :                 tmp_ctx,
     585             :                 test_ctx->ldb,
     586             :                 "test_delete_failure");
     587             : 
     588           1 :         ldb_kv_ctx = build_ldb_kv_context(tmp_ctx, test_ctx->ldb->modules, req);
     589           1 :         cmocka_unit_test_fail_delete_internal_after = 1;
     590             : 
     591           1 :         ret = ldb_transaction_start(test_ctx->ldb);
     592           1 :         assert_int_equal(ret, LDB_SUCCESS);
     593             : 
     594           1 :         ret = ldb_kv_delete(ldb_kv_ctx);
     595           1 :         assert_int_equal(ret, FAILURE_LDB_ERR);
     596           1 :         TALLOC_FREE(ldb_kv_ctx);
     597           1 :         TALLOC_FREE(req);
     598             : 
     599             :         /*
     600             :          * a search for "cn=test_add_failure_value" should succeed
     601             :          * as the transaction containing the operation should have been
     602             :          * rolled back leaving the database consistent
     603             :          *
     604             :          * This should be an un-indexed search so the index caches won't be
     605             :          * used.
     606             :          */
     607           1 :         basedn = ldb_dn_new_fmt(
     608             :                 tmp_ctx,
     609             :                 test_ctx->ldb,
     610             :                 "dc=%s",
     611             :                 "test_delete_failure");
     612           1 :         assert_non_null(basedn);
     613             : 
     614           1 :         ret = ldb_search(
     615             :                 test_ctx->ldb, tmp_ctx,
     616             :                 &result,
     617             :                 basedn,
     618             :                 LDB_SCOPE_SUBTREE,
     619             :                 NULL,
     620             :                 "(cn=%s)",
     621             :                 "test_delete_failure_value");
     622           1 :         assert_int_equal(ret, LDB_SUCCESS);
     623           1 :         assert_non_null(result);
     624           1 :         assert_int_equal(result->count, 1);
     625           1 :         TALLOC_FREE(basedn);
     626           1 :         TALLOC_FREE(result);
     627             : 
     628             : 
     629           1 :         ldb_transaction_cancel(test_ctx->ldb);
     630           1 :         delete_record(
     631             :                 tmp_ctx,
     632             :                 test_ctx->ldb,
     633             :                 "test_delete_failure");
     634           1 :         TALLOC_FREE(tmp_ctx);
     635           1 : }
     636             : 
     637             : /*
     638             :  * Test that a failed rename operation dies not change the database
     639             :  */
     640           1 : static void test_rename_failure(void **state)
     641             : {
     642           1 :         int ret = LDB_SUCCESS;
     643           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     644             :                                                           struct test_ctx);
     645           1 :         struct ldb_request *req = NULL;
     646           1 :         struct ldb_dn *basedn = NULL;
     647           1 :         struct ldb_result *result = NULL;
     648           1 :         struct ldb_kv_context *ldb_kv_ctx = NULL;
     649             : 
     650           1 :         TALLOC_CTX *tmp_ctx = talloc_new(test_ctx);
     651           1 :         assert_non_null(tmp_ctx);
     652             : 
     653           1 :         add_record(
     654             :                 tmp_ctx,
     655             :                 test_ctx->ldb,
     656             :                 "test_rename_failure",
     657             :                 "0123456789abcdec",
     658             :                 "test_rename_failure_value");
     659             : 
     660           1 :         req = build_rename_request(
     661             :                 tmp_ctx,
     662             :                 test_ctx->ldb,
     663             :                 "test_rename_failure",
     664             :                 "test_rename_failure_renamed");
     665             : 
     666           1 :         ldb_kv_ctx = build_ldb_kv_context(tmp_ctx, test_ctx->ldb->modules, req);
     667           1 :         cmocka_unit_test_fail_rename_internal_after = 1;
     668             : 
     669           1 :         ret = ldb_transaction_start(test_ctx->ldb);
     670           1 :         assert_int_equal(ret, LDB_SUCCESS);
     671             : 
     672           1 :         ret = ldb_kv_rename(ldb_kv_ctx);
     673           1 :         assert_int_equal(ret, FAILURE_LDB_ERR);
     674           1 :         TALLOC_FREE(ldb_kv_ctx);
     675           1 :         TALLOC_FREE(req);
     676             : 
     677             :         /*
     678             :          * The original record should be present
     679             :          */
     680           1 :         basedn = ldb_dn_new_fmt(
     681             :                 tmp_ctx,
     682             :                 test_ctx->ldb,
     683             :                 "dc=%s",
     684             :                 "test_rename_failure");
     685           1 :         assert_non_null(basedn);
     686             : 
     687           1 :         ret = ldb_search(
     688             :                 test_ctx->ldb, tmp_ctx,
     689             :                 &result,
     690             :                 basedn,
     691             :                 LDB_SCOPE_SUBTREE,
     692             :                 NULL,
     693             :                 "(cn=%s)",
     694             :                 "test_rename_failure_value");
     695           1 :         assert_int_equal(ret, LDB_SUCCESS);
     696           1 :         assert_non_null(result);
     697           1 :         assert_int_equal(result->count, 1);
     698           1 :         TALLOC_FREE(basedn);
     699           1 :         TALLOC_FREE(result);
     700             : 
     701             :         /*
     702             :          * And the renamed record should not be present
     703             :          */
     704           1 :         basedn = ldb_dn_new_fmt(
     705             :                 tmp_ctx,
     706             :                 test_ctx->ldb,
     707             :                 "dc=%s",
     708             :                 "test_rename_failure_renamed");
     709           1 :         assert_non_null(basedn);
     710             : 
     711           1 :         ret = ldb_search(
     712             :                 test_ctx->ldb, tmp_ctx,
     713             :                 &result,
     714             :                 basedn,
     715             :                 LDB_SCOPE_SUBTREE,
     716             :                 NULL,
     717             :                 "(cn=%s)",
     718             :                 "test_rename_failure_value");
     719           1 :         assert_int_equal(ret, LDB_SUCCESS);
     720           1 :         assert_non_null(result);
     721           1 :         assert_int_equal(result->count, 0);
     722           1 :         TALLOC_FREE(basedn);
     723           1 :         TALLOC_FREE(result);
     724             : 
     725           1 :         ldb_transaction_cancel(test_ctx->ldb);
     726           1 :         delete_record(
     727             :                 tmp_ctx,
     728             :                 test_ctx->ldb,
     729             :                 "test_rename_failure");
     730           1 :         TALLOC_FREE(tmp_ctx);
     731           1 : }
     732             : 
     733             : /*
     734             :  * Test that a failed modification operation does not change the database
     735             :  */
     736           1 : static void test_modify_failure(void **state)
     737             : {
     738           1 :         int ret = LDB_SUCCESS;
     739           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     740             :                                                           struct test_ctx);
     741           1 :         struct ldb_request *req = NULL;
     742           1 :         struct ldb_dn *basedn = NULL;
     743           1 :         struct ldb_result *result = NULL;
     744           1 :         struct ldb_kv_context *ldb_kv_ctx = NULL;
     745             : 
     746           1 :         TALLOC_CTX *tmp_ctx = talloc_new(test_ctx);
     747           1 :         assert_non_null(tmp_ctx);
     748             : 
     749           1 :         add_record(
     750             :                 tmp_ctx,
     751             :                 test_ctx->ldb,
     752             :                 "test_modify_failure",
     753             :                 "0123456789abcdeb",
     754             :                 "test_modify_failure_value");
     755             : 
     756           1 :         req = build_modify_request(
     757             :                 tmp_ctx,
     758             :                 test_ctx->ldb,
     759             :                 "test_modify_failure",
     760             :                 "test_modify_failure_value_modified");
     761             : 
     762           1 :         ldb_kv_ctx = build_ldb_kv_context(tmp_ctx, test_ctx->ldb->modules, req);
     763           1 :         cmocka_unit_test_fail_modify_internal_after = 2;
     764             : 
     765           1 :         ret = ldb_transaction_start(test_ctx->ldb);
     766           1 :         assert_int_equal(ret, LDB_SUCCESS);
     767             : 
     768           1 :         ret = ldb_kv_modify(ldb_kv_ctx);
     769           1 :         assert_int_equal(ret, FAILURE_LDB_ERR);
     770           1 :         TALLOC_FREE(ldb_kv_ctx);
     771           1 :         TALLOC_FREE(req);
     772             : 
     773             : 
     774             :         /*
     775             :          * The original value should be present
     776             :          */
     777           1 :         basedn = ldb_dn_new_fmt(
     778             :                 tmp_ctx,
     779             :                 test_ctx->ldb,
     780             :                 "dc=%s",
     781             :                 "test_modify_failure");
     782           1 :         assert_non_null(basedn);
     783             : 
     784           1 :         ret = ldb_search(
     785             :                 test_ctx->ldb, tmp_ctx,
     786             :                 &result,
     787             :                 basedn,
     788             :                 LDB_SCOPE_SUBTREE,
     789             :                 NULL,
     790             :                 "(cn=%s)",
     791             :                 "test_modify_failure_value");
     792           1 :         assert_int_equal(ret, LDB_SUCCESS);
     793           1 :         assert_non_null(result);
     794           1 :         assert_int_equal(result->count, 1);
     795           1 :         TALLOC_FREE(result);
     796             : 
     797             :         /*
     798             :          * And the modified record should not be present
     799             :          */
     800           1 :         ret = ldb_search(
     801             :                 test_ctx->ldb, tmp_ctx,
     802             :                 &result,
     803             :                 basedn,
     804             :                 LDB_SCOPE_SUBTREE,
     805             :                 NULL,
     806             :                 "(cn=%s)",
     807             :                 "test_modify_failure_value_modified");
     808           1 :         assert_int_equal(ret, LDB_SUCCESS);
     809           1 :         assert_non_null(result);
     810           1 :         assert_int_equal(result->count, 0);
     811           1 :         TALLOC_FREE(basedn);
     812           1 :         TALLOC_FREE(result);
     813             : 
     814           1 :         ldb_transaction_cancel(test_ctx->ldb);
     815           1 :         delete_record(
     816             :                 tmp_ctx,
     817             :                 test_ctx->ldb,
     818             :                 "test_modify_failure");
     819           1 :         TALLOC_FREE(tmp_ctx);
     820           1 : }
     821             : 
     822           1 : int main(int argc, const char **argv)
     823             : {
     824           1 :         const struct CMUnitTest tests[] = {
     825             :                 cmocka_unit_test_setup_teardown(
     826             :                         test_add_failure,
     827             :                         setup,
     828             :                         teardown),
     829             :                 cmocka_unit_test_setup_teardown(
     830             :                         test_delete_failure,
     831             :                         setup,
     832             :                         teardown),
     833             :                 cmocka_unit_test_setup_teardown(
     834             :                         test_rename_failure,
     835             :                         setup,
     836             :                         teardown),
     837             :                 cmocka_unit_test_setup_teardown(
     838             :                         test_modify_failure,
     839             :                         setup,
     840             :                         teardown),
     841             :         };
     842             : 
     843           1 :         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
     844             : 
     845           1 :         return cmocka_run_group_tests(tests, NULL, NULL);
     846             : }

Generated by: LCOV version 1.14