LCOV - code coverage report
Current view: top level - lib/ldb/tests - ldb_kv_ops_test.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 605 697 86.8 %
Date: 2021-08-25 13:27:56 Functions: 25 25 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             :  * A KV module is expected to have the following behaviour
      38             :  *
      39             :  * - A transaction must be open to perform any read, write or delete operation
      40             :  * - Writes and Deletes should not be visible until a transaction is commited
      41             :  * - Nested transactions are not permitted
      42             :  * - transactions can be rolled back and commited.
      43             :  * - supports iteration over all records in the database
      44             :  * - supports the update_in_iterate operation allowing entries to be
      45             :  *   re-keyed.
      46             :  * - has a get_size implementation that returns an estimate of the number of
      47             :  *   records in the database.  Note that this can be an estimate rather than
      48             :  *   an accurate size.
      49             :  */
      50             : #include <stdarg.h>
      51             : #include <stddef.h>
      52             : #include <stdint.h>
      53             : #include <setjmp.h>
      54             : #include <cmocka.h>
      55             : 
      56             : #include <errno.h>
      57             : #include <unistd.h>
      58             : #include <talloc.h>
      59             : #include <tevent.h>
      60             : #include <ldb.h>
      61             : #include <ldb_module.h>
      62             : #include <ldb_private.h>
      63             : #include <string.h>
      64             : #include <ctype.h>
      65             : 
      66             : #include <sys/wait.h>
      67             : 
      68             : #include "ldb_tdb/ldb_tdb.h"
      69             : #include "ldb_key_value/ldb_kv.h"
      70             : 
      71             : 
      72             : #define DEFAULT_BE  "tdb"
      73             : 
      74             : #ifndef TEST_BE
      75             : #define TEST_BE DEFAULT_BE
      76             : #endif /* TEST_BE */
      77             : 
      78             : #define NUM_RECS 1024
      79             : 
      80             : 
      81             : struct test_ctx {
      82             :         struct tevent_context *ev;
      83             :         struct ldb_context *ldb;
      84             : 
      85             :         const char *dbfile;
      86             :         const char *lockfile;   /* lockfile is separate */
      87             : 
      88             :         const char *dbpath;
      89             : };
      90             : 
      91          26 : static void unlink_old_db(struct test_ctx *test_ctx)
      92             : {
      93             :         int ret;
      94             : 
      95          26 :         errno = 0;
      96          26 :         ret = unlink(test_ctx->lockfile);
      97          26 :         if (ret == -1 && errno != ENOENT) {
      98           0 :                 fail();
      99             :         }
     100             : 
     101          26 :         errno = 0;
     102          26 :         ret = unlink(test_ctx->dbfile);
     103          26 :         if (ret == -1 && errno != ENOENT) {
     104           0 :                 fail();
     105             :         }
     106          26 : }
     107             : 
     108          13 : static int noconn_setup(void **state)
     109             : {
     110             :         struct test_ctx *test_ctx;
     111             : 
     112          13 :         test_ctx = talloc_zero(NULL, struct test_ctx);
     113          13 :         assert_non_null(test_ctx);
     114             : 
     115          13 :         test_ctx->ev = tevent_context_init(test_ctx);
     116          13 :         assert_non_null(test_ctx->ev);
     117             : 
     118          13 :         test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
     119          13 :         assert_non_null(test_ctx->ldb);
     120             : 
     121          13 :         test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb");
     122          13 :         assert_non_null(test_ctx->dbfile);
     123             : 
     124          13 :         test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
     125             :                                              test_ctx->dbfile);
     126          13 :         assert_non_null(test_ctx->lockfile);
     127             : 
     128          13 :         test_ctx->dbpath = talloc_asprintf(test_ctx,
     129             :                         TEST_BE"://%s", test_ctx->dbfile);
     130          13 :         assert_non_null(test_ctx->dbpath);
     131             : 
     132          13 :         unlink_old_db(test_ctx);
     133          13 :         *state = test_ctx;
     134          13 :         return 0;
     135             : }
     136             : 
     137          13 : static int noconn_teardown(void **state)
     138             : {
     139          13 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     140             :                                                           struct test_ctx);
     141             : 
     142          13 :         unlink_old_db(test_ctx);
     143          13 :         talloc_free(test_ctx);
     144          13 :         return 0;
     145             : }
     146             : 
     147          13 : static int setup(void **state)
     148             : {
     149             :         struct test_ctx *test_ctx;
     150             :         int ret;
     151             :         struct ldb_ldif *ldif;
     152          13 :         const char *index_ldif =                \
     153             :                 "dn: @INDEXLIST\n"
     154             :                 "@IDXGUID: objectUUID\n"
     155             :                 "@IDX_DN_GUID: GUID\n"
     156             :                 "\n";
     157             : 
     158          13 :         noconn_setup((void **) &test_ctx);
     159             : 
     160          13 :         ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
     161          13 :         assert_int_equal(ret, 0);
     162             : 
     163          39 :         while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) {
     164          13 :                 ret = ldb_add(test_ctx->ldb, ldif->msg);
     165          13 :                 assert_int_equal(ret, LDB_SUCCESS);
     166             :         }
     167          13 :         *state = test_ctx;
     168          13 :         return 0;
     169             : }
     170             : 
     171          13 : static int teardown(void **state)
     172             : {
     173          13 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     174             :                                                           struct test_ctx);
     175          13 :         noconn_teardown((void **) &test_ctx);
     176          13 :         return 0;
     177             : }
     178             : 
     179          20 : static struct ldb_kv_private *get_ldb_kv(struct ldb_context *ldb)
     180             : {
     181          20 :         void *data = NULL;
     182          20 :         struct ldb_kv_private *ldb_kv = NULL;
     183             : 
     184          20 :         data = ldb_module_get_private(ldb->modules);
     185          20 :         assert_non_null(data);
     186             : 
     187          20 :         ldb_kv = talloc_get_type(data, struct ldb_kv_private);
     188          20 :         assert_non_null(ldb_kv);
     189             : 
     190          20 :         return ldb_kv;
     191             : }
     192             : 
     193          13 : static int parse(struct ldb_val key,
     194             :                  struct ldb_val data,
     195             :                  void *private_data)
     196             : {
     197          13 :         struct ldb_val* read = private_data;
     198             : 
     199             :         /* Yes, we leak this.  That is OK */
     200          13 :         read->data = talloc_size(NULL,
     201             :                                  data.length);
     202          13 :         assert_non_null(read->data);
     203             : 
     204          13 :         memcpy(read->data, data.data, data.length);
     205          13 :         read->length = data.length;
     206          13 :         return LDB_SUCCESS;
     207             : }
     208             : 
     209             : /*
     210             :  * Parse function that just returns the int we pass it.
     211             :  */
     212          50 : static int parse_return(struct ldb_val key,
     213             :                         struct ldb_val data,
     214             :                         void *private_data)
     215             : {
     216          50 :         int *rcode = private_data;
     217          50 :         return *rcode;
     218             : }
     219             : 
     220             : /*
     221             :  * Test that data can be written to the kv store and be read back.
     222             :  */
     223           1 : static void test_add_get(void **state)
     224             : {
     225             :         int ret;
     226           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     227             :                                                           struct test_ctx);
     228           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     229           1 :         uint8_t key_val[] = "TheKey";
     230           1 :         struct ldb_val key = {
     231             :                 .data   = key_val,
     232             :                 .length = sizeof(key_val)
     233             :         };
     234             : 
     235           1 :         uint8_t value[] = "The record contents";
     236           1 :         struct ldb_val data = {
     237             :                 .data    = value,
     238             :                 .length = sizeof(value)
     239             :         };
     240             : 
     241             :         struct ldb_val read;
     242             :         int rcode;
     243             : 
     244           1 :         int flags = 0;
     245             :         TALLOC_CTX *tmp_ctx;
     246             : 
     247           1 :         tmp_ctx = talloc_new(test_ctx);
     248           1 :         assert_non_null(tmp_ctx);
     249             : 
     250             :         /*
     251             :          * Begin a transaction
     252             :          */
     253           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     254           1 :         assert_int_equal(ret, 0);
     255             : 
     256             :         /*
     257             :          * Write the record
     258             :          */
     259           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     260           1 :         assert_int_equal(ret, 0);
     261             : 
     262             :         /*
     263             :          * Commit the transaction
     264             :          */
     265           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     266           1 :         assert_int_equal(ret, 0);
     267             : 
     268             :         /*
     269             :          * And now read it back
     270             :          */
     271           1 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     272           1 :         assert_int_equal(ret, 0);
     273             : 
     274           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     275           1 :         assert_int_equal(ret, 0);
     276             : 
     277           1 :         assert_int_equal(sizeof(value), read.length);
     278           1 :         assert_memory_equal(value, read.data, sizeof(value));
     279             : 
     280             :         /*
     281             :          * Now check that the error code we return in the
     282             :          * parse function is returned by fetch_and_parse.
     283             :          */
     284          51 :         for (rcode=0; rcode<50; rcode++) {
     285          50 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key,
     286             :                                                       parse_return,
     287             :                                                       &rcode);
     288          50 :                 assert_int_equal(ret, rcode);
     289             :         }
     290             : 
     291           1 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     292           1 :         assert_int_equal(ret, 0);
     293           1 :         talloc_free(tmp_ctx);
     294           1 : }
     295             : 
     296             : /*
     297             :  * Test that attempts to read data without a read transaction fail.
     298             :  */
     299           1 : static void test_read_outside_transaction(void **state)
     300             : {
     301             :         int ret;
     302           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     303             :                                                           struct test_ctx);
     304           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     305           1 :         uint8_t key_val[] = "TheKey";
     306           1 :         struct ldb_val key = {
     307             :                 .data   = key_val,
     308             :                 .length = sizeof(key_val)
     309             :         };
     310             : 
     311           1 :         uint8_t value[] = "The record contents";
     312           1 :         struct ldb_val data = {
     313             :                 .data    = value,
     314             :                 .length = sizeof(value)
     315             :         };
     316             : 
     317             :         struct ldb_val read;
     318             : 
     319           1 :         int flags = 0;
     320             :         TALLOC_CTX *tmp_ctx;
     321             : 
     322           1 :         tmp_ctx = talloc_new(test_ctx);
     323           1 :         assert_non_null(tmp_ctx);
     324             : 
     325             :         /*
     326             :          * Begin a transaction
     327             :          */
     328           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     329           1 :         assert_int_equal(ret, 0);
     330             : 
     331             :         /*
     332             :          * Write the record
     333             :          */
     334           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     335           1 :         assert_int_equal(ret, 0);
     336             : 
     337             :         /*
     338             :          * Commit the transaction
     339             :          */
     340           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     341           1 :         assert_int_equal(ret, 0);
     342             : 
     343             :         /*
     344             :          * And now read it back
     345             :          * Note there is no read transaction active
     346             :          */
     347           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     348           1 :         assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
     349             : 
     350           1 :         talloc_free(tmp_ctx);
     351           1 : }
     352             : 
     353             : /*
     354             :  * Test that data can be deleted from the kv store
     355             :  */
     356           1 : static void test_delete(void **state)
     357             : {
     358             :         int ret;
     359           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     360             :                                                           struct test_ctx);
     361           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     362           1 :         uint8_t key_val[] = "TheKey";
     363           1 :         struct ldb_val key = {
     364             :                 .data   = key_val,
     365             :                 .length = sizeof(key_val)
     366             :         };
     367             : 
     368           1 :         uint8_t value[] = "The record contents";
     369           1 :         struct ldb_val data = {
     370             :                 .data    = value,
     371             :                 .length = sizeof(value)
     372             :         };
     373             : 
     374             :         struct ldb_val read;
     375             : 
     376           1 :         int flags = 0;
     377             :         TALLOC_CTX *tmp_ctx;
     378             : 
     379           1 :         tmp_ctx = talloc_new(test_ctx);
     380           1 :         assert_non_null(tmp_ctx);
     381             : 
     382             :         /*
     383             :          * Begin a transaction
     384             :          */
     385           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     386           1 :         assert_int_equal(ret, 0);
     387             : 
     388             :         /*
     389             :          * Write the record
     390             :          */
     391           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     392           1 :         assert_int_equal(ret, 0);
     393             : 
     394             :         /*
     395             :          * Commit the transaction
     396             :          */
     397           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     398           1 :         assert_int_equal(ret, 0);
     399             : 
     400             :         /*
     401             :          * And now read it back
     402             :          */
     403           1 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     404           1 :         assert_int_equal(ret, 0);
     405           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     406           1 :         assert_int_equal(ret, 0);
     407           1 :         assert_int_equal(sizeof(value), read.length);
     408           1 :         assert_memory_equal(value, read.data, sizeof(value));
     409           1 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     410           1 :         assert_int_equal(ret, 0);
     411             : 
     412             :         /*
     413             :          * Begin a transaction
     414             :          */
     415           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     416           1 :         assert_int_equal(ret, 0);
     417             : 
     418             :         /*
     419             :          * Now delete it.
     420             :          */
     421           1 :         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
     422           1 :         assert_int_equal(ret, 0);
     423             : 
     424             :         /*
     425             :          * Commit the transaction
     426             :          */
     427           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     428           1 :         assert_int_equal(ret, 0);
     429             : 
     430             :         /*
     431             :          * And now try to read it back
     432             :          */
     433           1 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     434           1 :         assert_int_equal(ret, 0);
     435           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     436           1 :         assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
     437           1 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     438           1 :         assert_int_equal(ret, 0);
     439             : 
     440           1 :         talloc_free(tmp_ctx);
     441           1 : }
     442             : 
     443             : /*
     444             :  * Check that writes are correctly rolled back when a transaction
     445             :  * is rolled back.
     446             :  */
     447           1 : static void test_transaction_abort_write(void **state)
     448             : {
     449             :         int ret;
     450           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     451             :                                                           struct test_ctx);
     452           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     453           1 :         uint8_t key_val[] = "TheKey";
     454           1 :         struct ldb_val key = {
     455             :                 .data   = key_val,
     456             :                 .length = sizeof(key_val)
     457             :         };
     458             : 
     459           1 :         uint8_t value[] = "The record contents";
     460           1 :         struct ldb_val data = {
     461             :                 .data    = value,
     462             :                 .length = sizeof(value)
     463             :         };
     464             : 
     465             :         struct ldb_val read;
     466             : 
     467           1 :         int flags = 0;
     468             :         TALLOC_CTX *tmp_ctx;
     469             : 
     470           1 :         tmp_ctx = talloc_new(test_ctx);
     471           1 :         assert_non_null(tmp_ctx);
     472             : 
     473             :         /*
     474             :          * Begin a transaction
     475             :          */
     476           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     477           1 :         assert_int_equal(ret, 0);
     478             : 
     479             :         /*
     480             :          * Write the record
     481             :          */
     482           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     483           1 :         assert_int_equal(ret, 0);
     484             : 
     485             :         /*
     486             :          * And now read it back
     487             :          */
     488           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     489           1 :         assert_int_equal(ret, 0);
     490           1 :         assert_int_equal(sizeof(value), read.length);
     491           1 :         assert_memory_equal(value, read.data, sizeof(value));
     492             : 
     493             : 
     494             :         /*
     495             :          * Now abort the transaction
     496             :          */
     497           1 :         ret = ldb_kv->kv_ops->abort_write(ldb_kv);
     498           1 :         assert_int_equal(ret, 0);
     499             : 
     500             :         /*
     501             :          * And now read it back, should not be there
     502             :          */
     503           1 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     504           1 :         assert_int_equal(ret, 0);
     505           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     506           1 :         assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
     507           1 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     508           1 :         assert_int_equal(ret, 0);
     509             : 
     510           1 :         talloc_free(tmp_ctx);
     511           1 : }
     512             : 
     513             : /*
     514             :  * Check that deletes are correctly rolled back when a transaction is
     515             :  * aborted.
     516             :  */
     517           1 : static void test_transaction_abort_delete(void **state)
     518             : {
     519             :         int ret;
     520           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     521             :                                                           struct test_ctx);
     522           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     523           1 :         uint8_t key_val[] = "TheKey";
     524           1 :         struct ldb_val key = {
     525             :                 .data   = key_val,
     526             :                 .length = sizeof(key_val)
     527             :         };
     528             : 
     529           1 :         uint8_t value[] = "The record contents";
     530           1 :         struct ldb_val data = {
     531             :                 .data    = value,
     532             :                 .length = sizeof(value)
     533             :         };
     534             : 
     535             :         struct ldb_val read;
     536             : 
     537           1 :         int flags = 0;
     538             :         TALLOC_CTX *tmp_ctx;
     539             : 
     540           1 :         tmp_ctx = talloc_new(test_ctx);
     541           1 :         assert_non_null(tmp_ctx);
     542             : 
     543             :         /*
     544             :          * Begin a transaction
     545             :          */
     546           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     547           1 :         assert_int_equal(ret, 0);
     548             : 
     549             :         /*
     550             :          * Write the record
     551             :          */
     552           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     553           1 :         assert_int_equal(ret, 0);
     554             : 
     555             :         /*
     556             :          * Commit the transaction
     557             :          */
     558           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     559           1 :         assert_int_equal(ret, 0);
     560             : 
     561             :         /*
     562             :          * And now read it back
     563             :          */
     564           1 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     565           1 :         assert_int_equal(ret, 0);
     566           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     567           1 :         assert_int_equal(ret, 0);
     568           1 :         assert_int_equal(sizeof(value), read.length);
     569           1 :         assert_memory_equal(value, read.data, sizeof(value));
     570           1 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     571           1 :         assert_int_equal(ret, 0);
     572             : 
     573             :         /*
     574             :          * Begin a transaction
     575             :          */
     576           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     577           1 :         assert_int_equal(ret, 0);
     578             : 
     579             :         /*
     580             :          * Now delete it.
     581             :          */
     582           1 :         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
     583           1 :         assert_int_equal(ret, 0);
     584             : 
     585             :         /*
     586             :          * And now read it back
     587             :          */
     588           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     589           1 :         assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
     590             : 
     591             :         /*
     592             :          * Abort the transaction
     593             :          */
     594           1 :         ret = ldb_kv->kv_ops->abort_write(ldb_kv);
     595           1 :         assert_int_equal(ret, 0);
     596             : 
     597             :         /*
     598             :          * And now try to read it back
     599             :          */
     600           1 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     601           1 :         assert_int_equal(ret, 0);
     602           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     603           1 :         assert_int_equal(ret, 0);
     604           1 :         assert_int_equal(sizeof(value), read.length);
     605           1 :         assert_memory_equal(value, read.data, sizeof(value));
     606           1 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     607           1 :         assert_int_equal(ret, 0);
     608             : 
     609           1 :         talloc_free(tmp_ctx);
     610           1 : }
     611             : 
     612             : /*
     613             :  * Test that writes outside a transaction fail
     614             :  */
     615           1 : static void test_write_outside_transaction(void **state)
     616             : {
     617             :         int ret;
     618           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     619             :                                                           struct test_ctx);
     620           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     621           1 :         uint8_t key_val[] = "TheKey";
     622           1 :         struct ldb_val key = {
     623             :                 .data   = key_val,
     624             :                 .length = sizeof(key_val)
     625             :         };
     626             : 
     627           1 :         uint8_t value[] = "The record contents";
     628           1 :         struct ldb_val data = {
     629             :                 .data    = value,
     630             :                 .length = sizeof(value)
     631             :         };
     632             : 
     633             : 
     634           1 :         int flags = 0;
     635             :         TALLOC_CTX *tmp_ctx;
     636             : 
     637           1 :         tmp_ctx = talloc_new(test_ctx);
     638           1 :         assert_non_null(tmp_ctx);
     639             : 
     640             :         /*
     641             :          * Attempt to write the record
     642             :          */
     643           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     644           1 :         assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
     645             : 
     646           1 :         talloc_free(tmp_ctx);
     647           1 : }
     648             : 
     649             : /*
     650             :  * Test data can not be deleted outside a transaction
     651             :  */
     652           1 : static void test_delete_outside_transaction(void **state)
     653             : {
     654             :         int ret;
     655           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     656             :                                                           struct test_ctx);
     657           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     658           1 :         uint8_t key_val[] = "TheKey";
     659           1 :         struct ldb_val key = {
     660             :                 .data   = key_val,
     661             :                 .length = sizeof(key_val)
     662             :         };
     663             : 
     664           1 :         uint8_t value[] = "The record contents";
     665           1 :         struct ldb_val data = {
     666             :                 .data    = value,
     667             :                 .length = sizeof(value)
     668             :         };
     669             : 
     670             :         struct ldb_val read;
     671             : 
     672           1 :         int flags = 0;
     673             :         TALLOC_CTX *tmp_ctx;
     674             : 
     675           1 :         tmp_ctx = talloc_new(test_ctx);
     676           1 :         assert_non_null(tmp_ctx);
     677             : 
     678             :         /*
     679             :          * Begin a transaction
     680             :          */
     681           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     682           1 :         assert_int_equal(ret, 0);
     683             : 
     684             :         /*
     685             :          * Write the record
     686             :          */
     687           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     688           1 :         assert_int_equal(ret, 0);
     689             : 
     690             :         /*
     691             :          * Commit the transaction
     692             :          */
     693           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     694           1 :         assert_int_equal(ret, 0);
     695             : 
     696             :         /*
     697             :          * And now read it back
     698             :          */
     699           1 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     700           1 :         assert_int_equal(ret, 0);
     701           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     702           1 :         assert_int_equal(ret, 0);
     703           1 :         assert_int_equal(sizeof(value), read.length);
     704           1 :         assert_memory_equal(value, read.data, sizeof(value));
     705           1 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     706           1 :         assert_int_equal(ret, 0);
     707             : 
     708             :         /*
     709             :          * Now attempt to delete a record
     710             :          */
     711           1 :         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
     712           1 :         assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
     713             : 
     714             :         /*
     715             :          * And now read it back
     716             :          */
     717           1 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     718           1 :         assert_int_equal(ret, 0);
     719           1 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     720           1 :         assert_int_equal(ret, 0);
     721           1 :         assert_int_equal(sizeof(value), read.length);
     722           1 :         assert_memory_equal(value, read.data, sizeof(value));
     723           1 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     724           1 :         assert_int_equal(ret, 0);
     725             : 
     726           1 :         talloc_free(tmp_ctx);
     727           1 : }
     728             : 
     729        1026 : static int traverse_fn(struct ldb_kv_private *ldb_kv,
     730             :                        struct ldb_val key,
     731             :                        struct ldb_val data,
     732             :                        void *ctx)
     733             : {
     734             : 
     735        1026 :         int *visits = ctx;
     736             :         int i;
     737             : 
     738        1026 :         if (strncmp("key ", (char *) key.data, 4) == 0) {
     739        1024 :                 i = strtol((char *) &key.data[4], NULL, 10);
     740        1024 :                 visits[i]++;
     741             :         }
     742        1026 :         return LDB_SUCCESS;
     743             : }
     744             : 
     745             : /*
     746             :  * Test that iterate visits all the records.
     747             :  */
     748           1 : static void test_iterate(void **state)
     749           1 : {
     750             :         int ret;
     751           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     752             :                                                           struct test_ctx);
     753           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     754             :         int i;
     755           1 :         int num_recs = 1024;
     756           1 :         int visits[num_recs];
     757             : 
     758             :         TALLOC_CTX *tmp_ctx;
     759             : 
     760           1 :         tmp_ctx = talloc_new(test_ctx);
     761           1 :         assert_non_null(tmp_ctx);
     762             : 
     763             :         /*
     764             :          * Begin a transaction
     765             :          */
     766           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     767           1 :         assert_int_equal(ret, 0);
     768             : 
     769             :         /*
     770             :          * Write the records
     771             :          */
     772        1025 :         for (i = 0; i < num_recs; i++) {
     773             :                 struct ldb_val key;
     774             :                 struct ldb_val rec;
     775        1024 :                 int flags = 0;
     776             : 
     777        1024 :                 visits[i] = 0;
     778        1024 :                 key.data   = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
     779        1024 :                 key.length = strlen((char *)key.data) + 1;
     780             : 
     781        1024 :                 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
     782             :                                                        "data for record (%04d)",
     783             :                                                        i);
     784        1024 :                 rec.length = strlen((char *)rec.data) + 1;
     785             : 
     786        1024 :                 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
     787        1024 :                 assert_int_equal(ret, 0);
     788             : 
     789        1024 :                 TALLOC_FREE(key.data);
     790        1024 :                 TALLOC_FREE(rec.data);
     791             :         }
     792             : 
     793             :         /*
     794             :          * Commit the transaction
     795             :          */
     796           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     797           1 :         assert_int_equal(ret, 0);
     798             : 
     799             :         /*
     800             :          * Now iterate over the kv store and ensure that all the
     801             :          * records are visited.
     802             :          */
     803           1 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     804           1 :         assert_int_equal(ret, 0);
     805           1 :         ret = ldb_kv->kv_ops->iterate(ldb_kv, traverse_fn, visits);
     806        1025 :         for (i = 0; i <num_recs; i++) {
     807        1024 :                 assert_int_equal(1, visits[i]);
     808             :         }
     809           1 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     810           1 :         assert_int_equal(ret, 0);
     811             : 
     812           1 :         TALLOC_FREE(tmp_ctx);
     813           1 : }
     814             : 
     815           6 : static void do_iterate_range_test(void **state, int range_start,
     816             :                                   int range_end, bool fail)
     817           6 : {
     818             :         int ret;
     819           6 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     820             :                                                           struct test_ctx);
     821           6 :         struct ldb_kv_private *ldb_kv = NULL;
     822             :         int i;
     823           6 :         int num_recs = 1024;
     824           6 :         int skip_recs = 10;
     825           6 :         int visits[num_recs];
     826             :         struct ldb_val sk, ek;
     827             : 
     828             :         TALLOC_CTX *tmp_ctx;
     829             : 
     830           6 :         ldb_kv = get_ldb_kv(test_ctx->ldb);
     831           6 :         assert_non_null(ldb_kv);
     832             : 
     833        6150 :         for (i = 0; i < num_recs; i++){
     834        6144 :                 visits[i] = 0;
     835             :         }
     836             : 
     837             :         /*
     838             :          * No iterate_range on tdb
     839             :          */
     840             :         if (strcmp(TEST_BE, "tdb") == 0) {
     841           6 :                 return;
     842             :         }
     843             : 
     844             :         tmp_ctx = talloc_new(test_ctx);
     845             :         assert_non_null(tmp_ctx);
     846             : 
     847             :         /*
     848             :          * Begin a transaction
     849             :          */
     850             :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     851             :         assert_int_equal(ret, 0);
     852             : 
     853             :         /*
     854             :          * Write the records
     855             :          */
     856             :         for (i = skip_recs; i <= num_recs - skip_recs; i++) {
     857             :                 struct ldb_val key;
     858             :                 struct ldb_val rec;
     859             :                 int flags = 0;
     860             : 
     861             :                 key.data   = (uint8_t *)talloc_asprintf(tmp_ctx,
     862             :                                                         "key %04d",
     863             :                                                         i);
     864             :                 key.length = strlen((char *)key.data);
     865             : 
     866             :                 rec.data = (uint8_t *)talloc_asprintf(tmp_ctx,
     867             :                                                       "data for record (%04d)",
     868             :                                                       i);
     869             :                 rec.length = strlen((char *)rec.data) + 1;
     870             : 
     871             :                 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
     872             :                 assert_int_equal(ret, 0);
     873             : 
     874             :                 TALLOC_FREE(key.data);
     875             :                 TALLOC_FREE(rec.data);
     876             :         }
     877             : 
     878             :         /*
     879             :          * Commit the transaction
     880             :          */
     881             :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     882             :         assert_int_equal(ret, 0);
     883             : 
     884             :         sk.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_start);
     885             :         sk.length = strlen((char *)sk.data);
     886             : 
     887             :         ek.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_end);
     888             :         ek.length = strlen((char *)ek.data) + 1;
     889             : 
     890             :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     891             :         assert_int_equal(ret, 0);
     892             :         ret = ldb_kv->kv_ops->iterate_range(ldb_kv, sk, ek,
     893             :                                             traverse_fn, visits);
     894             :         if (fail){
     895             :                 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
     896             :                 TALLOC_FREE(tmp_ctx);
     897             :                 return;
     898             :         } else{
     899             :                 assert_int_equal(ret, 0);
     900             :         }
     901             :         for (i = 0; i < num_recs; i++) {
     902             :                 if (i >= skip_recs && i <= num_recs - skip_recs &&
     903             :                     i >= range_start && i <= range_end){
     904             :                         assert_int_equal(1, visits[i]);
     905             :                 } else {
     906             :                         assert_int_equal(0, visits[i]);
     907             :                 }
     908             :         }
     909             : 
     910             :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     911             :         assert_int_equal(ret, 0);
     912             : 
     913             :         TALLOC_FREE(tmp_ctx);
     914             : }
     915             : 
     916             : /*
     917             :  * Test that iterate_range visits all the records between two keys.
     918             :  */
     919           1 : static void test_iterate_range(void **state)
     920             : {
     921           1 :         do_iterate_range_test(state, 300, 900, false);
     922             : 
     923             :         /*
     924             :          * test start_key = end_key
     925             :          */
     926           1 :         do_iterate_range_test(state, 20, 20, false);
     927             : 
     928             :         /*
     929             :          * test reverse range fails
     930             :          */
     931           1 :         do_iterate_range_test(state, 50, 40, true);
     932             : 
     933             :         /*
     934             :          * keys are between 10-1014 so test with keys outside that range
     935             :          */
     936           1 :         do_iterate_range_test(state, 0, 20, false);
     937           1 :         do_iterate_range_test(state, 1010, 1030, false);
     938           1 :         do_iterate_range_test(state, 0, 1030, false);
     939           1 : }
     940             : 
     941             : struct update_context {
     942             :         struct ldb_context* ldb;
     943             :         int visits[NUM_RECS];
     944             : };
     945             : 
     946        1829 : static int update_fn(struct ldb_kv_private *ldb_kv,
     947             :                      struct ldb_val key,
     948             :                      struct ldb_val data,
     949             :                      void *ctx)
     950             : {
     951             : 
     952             :         struct ldb_val new_key;
     953        1829 :         struct ldb_module *module = NULL;
     954        1829 :         struct update_context *context =NULL;
     955        1829 :         int ret = LDB_SUCCESS;
     956             :         TALLOC_CTX *tmp_ctx;
     957             : 
     958        1829 :         tmp_ctx = talloc_new(ldb_kv);
     959        1829 :         assert_non_null(tmp_ctx);
     960             : 
     961        1829 :         context = talloc_get_type_abort(ctx, struct update_context);
     962             : 
     963        1829 :         module = talloc_zero(tmp_ctx, struct ldb_module);
     964        1829 :         module->ldb = context->ldb;
     965             : 
     966        1829 :         if (strncmp("key ", (char *) key.data, 4) == 0) {
     967        1024 :                 int i = strtol((char *) &key.data[4], NULL, 10);
     968        1024 :                 context->visits[i]++;
     969        1024 :                 new_key.data = talloc_memdup(tmp_ctx, key.data, key.length);
     970        1024 :                 new_key.length  = key.length;
     971        1024 :                 new_key.data[0] = 'K';
     972             : 
     973        1024 :                 ret = ldb_kv->kv_ops->update_in_iterate(
     974             :                     ldb_kv, key, new_key, data, &module);
     975             :         }
     976        1829 :         TALLOC_FREE(tmp_ctx);
     977        1829 :         return ret;
     978             : }
     979             : 
     980             : /*
     981             :  * Test that update_in_iterate behaves as expected.
     982             :  */
     983           1 : static void test_update_in_iterate(void **state)
     984             : {
     985             :         int ret;
     986           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     987             :                                                           struct test_ctx);
     988           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     989             :         int i;
     990           1 :         struct update_context *context = NULL;
     991             : 
     992             : 
     993             :         TALLOC_CTX *tmp_ctx;
     994             : 
     995           1 :         tmp_ctx = talloc_new(test_ctx);
     996           1 :         assert_non_null(tmp_ctx);
     997             : 
     998           1 :         context = talloc_zero(tmp_ctx, struct update_context);
     999           1 :         assert_non_null(context);
    1000           1 :         context->ldb = test_ctx->ldb;
    1001             :         /*
    1002             :          * Begin a transaction
    1003             :          */
    1004           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1005           1 :         assert_int_equal(ret, 0);
    1006             : 
    1007             :         /*
    1008             :          * Write the records
    1009             :          */
    1010        1025 :         for (i = 0; i < NUM_RECS; i++) {
    1011             :                 struct ldb_val key;
    1012             :                 struct ldb_val rec;
    1013        1024 :                 int flags = 0;
    1014             : 
    1015        1024 :                 key.data   = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
    1016        1024 :                 key.length = strlen((char *)key.data) + 1;
    1017             : 
    1018        1024 :                 rec.data   = (uint8_t *) talloc_asprintf(tmp_ctx,
    1019             :                                                          "data for record (%04d)",
    1020             :                                                          i);
    1021        1024 :                 rec.length = strlen((char *)rec.data) + 1;
    1022             : 
    1023        1024 :                 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
    1024        1024 :                 assert_int_equal(ret, 0);
    1025             : 
    1026        1024 :                 TALLOC_FREE(key.data);
    1027        1024 :                 TALLOC_FREE(rec.data);
    1028             :         }
    1029             : 
    1030             :         /*
    1031             :          * Commit the transaction
    1032             :          */
    1033           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1034           1 :         assert_int_equal(ret, 0);
    1035             : 
    1036             :         /*
    1037             :          * Now iterate over the kv store and ensure that all the
    1038             :          * records are visited.
    1039             :          */
    1040             : 
    1041             :         /*
    1042             :          * Needs to be done inside a transaction
    1043             :          */
    1044           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1045           1 :         assert_int_equal(ret, 0);
    1046             : 
    1047           1 :         ret = ldb_kv->kv_ops->iterate(ldb_kv, update_fn, context);
    1048        1025 :         for (i = 0; i < NUM_RECS; i++) {
    1049        1024 :                 assert_int_equal(1, context->visits[i]);
    1050             :         }
    1051             : 
    1052           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1053           1 :         assert_int_equal(ret, 0);
    1054             : 
    1055           1 :         TALLOC_FREE(tmp_ctx);
    1056           1 : }
    1057             : 
    1058             : /*
    1059             :  * Ensure that writes are not visible until the transaction has been
    1060             :  * committed.
    1061             :  */
    1062           1 : static void test_write_transaction_isolation(void **state)
    1063             : {
    1064             :         int ret;
    1065           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
    1066             :                                                           struct test_ctx);
    1067           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
    1068             :         struct ldb_val key;
    1069             :         struct ldb_val val;
    1070             : 
    1071           1 :         const char *KEY1 = "KEY01";
    1072           1 :         const char *VAL1 = "VALUE01";
    1073             : 
    1074           1 :         const char *KEY2 = "KEY02";
    1075           1 :         const char *VAL2 = "VALUE02";
    1076             : 
    1077             :         /*
    1078             :          * Pipes etc to co-ordinate the processes
    1079             :          */
    1080             :         int to_child[2];
    1081             :         int to_parent[2];
    1082             :         char buf[2];
    1083             :         pid_t pid, w_pid;
    1084             :         int wstatus;
    1085             : 
    1086             :         TALLOC_CTX *tmp_ctx;
    1087           1 :         tmp_ctx = talloc_new(test_ctx);
    1088           1 :         assert_non_null(tmp_ctx);
    1089             : 
    1090             : 
    1091             :         /*
    1092             :          * Add a record to the database
    1093             :          */
    1094           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1095           1 :         assert_int_equal(ret, 0);
    1096             : 
    1097           1 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1098           1 :         key.length = strlen(KEY1) + 1;
    1099             : 
    1100           1 :         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
    1101           1 :         val.length = strlen(VAL1) + 1;
    1102             : 
    1103           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
    1104           1 :         assert_int_equal(ret, 0);
    1105             : 
    1106           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1107           1 :         assert_int_equal(ret, 0);
    1108             : 
    1109             : 
    1110           1 :         ret = pipe(to_child);
    1111           1 :         assert_int_equal(ret, 0);
    1112           1 :         ret = pipe(to_parent);
    1113           1 :         assert_int_equal(ret, 0);
    1114             :         /*
    1115             :          * Now fork a new process
    1116             :          */
    1117             : 
    1118           1 :         pid = fork();
    1119           2 :         if (pid == 0) {
    1120             : 
    1121           1 :                 struct ldb_context *ldb = NULL;
    1122           1 :                 close(to_child[1]);
    1123           1 :                 close(to_parent[0]);
    1124             : 
    1125             :                 /*
    1126             :                  * Wait for the transaction to start
    1127             :                  */
    1128           1 :                 ret = read(to_child[0], buf, 2);
    1129           1 :                 if (ret != 2) {
    1130           0 :                         print_error(__location__": read returned (%d)\n",
    1131             :                                     ret);
    1132           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1133             :                 }
    1134           1 :                 ldb = ldb_init(test_ctx, test_ctx->ev);
    1135           1 :                 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
    1136           1 :                 if (ret != LDB_SUCCESS) {
    1137           0 :                         print_error(__location__": ldb_connect returned (%d)\n",
    1138             :                                     ret);
    1139           0 :                         exit(ret);
    1140             :                 }
    1141             : 
    1142           1 :                 ldb_kv = get_ldb_kv(ldb);
    1143             : 
    1144           1 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1145           1 :                 if (ret != LDB_SUCCESS) {
    1146           0 :                         print_error(__location__": lock_read returned (%d)\n",
    1147             :                                     ret);
    1148           0 :                         exit(ret);
    1149             :                 }
    1150             : 
    1151             :                 /*
    1152             :                  * Check that KEY1 is there
    1153             :                  */
    1154           1 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1155           1 :                 key.length = strlen(KEY1) + 1;
    1156             : 
    1157           1 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1158           1 :                 if (ret != LDB_SUCCESS) {
    1159           0 :                         print_error(__location__": fetch_and_parse returned "
    1160             :                                     "(%d)\n",
    1161             :                                     ret);
    1162           0 :                         exit(ret);
    1163             :                 }
    1164             : 
    1165           1 :                 if ((strlen(VAL1) + 1) != val.length) {
    1166           0 :                         print_error(__location__": KEY1 value lengths different"
    1167             :                                     ", expected (%d) actual(%d)\n",
    1168           0 :                                     (int)(strlen(VAL1) + 1), (int)val.length);
    1169           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1170             :                 }
    1171           1 :                 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
    1172           0 :                         print_error(__location__": KEY1 values different, "
    1173             :                                     "expected (%s) actual(%s)\n",
    1174             :                                     VAL1,
    1175             :                                     val.data);
    1176           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1177             :                 }
    1178             : 
    1179           1 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1180           1 :                 if (ret != LDB_SUCCESS) {
    1181           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1182             :                                     ret);
    1183           0 :                         exit(ret);
    1184             :                 }
    1185             : 
    1186             :                 /*
    1187             :                  * Check that KEY2 is not there
    1188             :                  */
    1189           1 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1190           1 :                 key.length = strlen(KEY2 + 1);
    1191             : 
    1192           1 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1193           1 :                 if (ret != LDB_SUCCESS) {
    1194           0 :                         print_error(__location__": lock_read returned (%d)\n",
    1195             :                                     ret);
    1196           0 :                         exit(ret);
    1197             :                 }
    1198             : 
    1199           1 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1200           1 :                 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
    1201           0 :                         print_error(__location__": fetch_and_parse returned "
    1202             :                                     "(%d)\n",
    1203             :                                     ret);
    1204           0 :                         exit(ret);
    1205             :                 }
    1206             : 
    1207           1 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1208           1 :                 if (ret != LDB_SUCCESS) {
    1209           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1210             :                                     ret);
    1211           0 :                         exit(ret);
    1212             :                 }
    1213             : 
    1214             :                 /*
    1215             :                  * Signal the other process to commit the transaction
    1216             :                  */
    1217           1 :                 ret = write(to_parent[1], "GO", 2);
    1218           1 :                 if (ret != 2) {
    1219           0 :                         print_error(__location__": write returned (%d)\n",
    1220             :                                     ret);
    1221           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1222             :                 }
    1223             : 
    1224             :                 /*
    1225             :                  * Wait for the transaction to be commited
    1226             :                  */
    1227           1 :                 ret = read(to_child[0], buf, 2);
    1228           1 :                 if (ret != 2) {
    1229           0 :                         print_error(__location__": read returned (%d)\n",
    1230             :                                     ret);
    1231           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1232             :                 }
    1233             : 
    1234             :                 /*
    1235             :                  * Check that KEY1 is there
    1236             :                  */
    1237           1 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1238           1 :                 if (ret != LDB_SUCCESS) {
    1239           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1240             :                                     ret);
    1241           0 :                         exit(ret);
    1242             :                 }
    1243           1 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1244           1 :                 key.length = strlen(KEY1) + 1;
    1245             : 
    1246           1 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1247           1 :                 if (ret != LDB_SUCCESS) {
    1248           0 :                         print_error(__location__": fetch_and_parse returned "
    1249             :                                     "(%d)\n",
    1250             :                                     ret);
    1251           0 :                         exit(ret);
    1252             :                 }
    1253             : 
    1254           1 :                 if ((strlen(VAL1) + 1) != val.length) {
    1255           0 :                         print_error(__location__": KEY1 value lengths different"
    1256             :                                     ", expected (%d) actual(%d)\n",
    1257           0 :                                     (int)(strlen(VAL1) + 1), (int)val.length);
    1258           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1259             :                 }
    1260           1 :                 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
    1261           0 :                         print_error(__location__": KEY1 values different, "
    1262             :                                     "expected (%s) actual(%s)\n",
    1263             :                                     VAL1,
    1264             :                                     val.data);
    1265           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1266             :                 }
    1267             : 
    1268           1 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1269           1 :                 if (ret != LDB_SUCCESS) {
    1270           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1271             :                                     ret);
    1272           0 :                         exit(ret);
    1273             :                 }
    1274             : 
    1275             : 
    1276             :                 /*
    1277             :                  * Check that KEY2 is there
    1278             :                  */
    1279           1 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1280           1 :                 if (ret != LDB_SUCCESS) {
    1281           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1282             :                                     ret);
    1283           0 :                         exit(ret);
    1284             :                 }
    1285             : 
    1286           1 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1287           1 :                 key.length = strlen(KEY2) + 1;
    1288             : 
    1289           1 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1290           1 :                 if (ret != LDB_SUCCESS) {
    1291           0 :                         print_error(__location__": fetch_and_parse returned "
    1292             :                                     "(%d)\n",
    1293             :                                     ret);
    1294           0 :                         exit(ret);
    1295             :                 }
    1296             : 
    1297           1 :                 if ((strlen(VAL2) + 1) != val.length) {
    1298           0 :                         print_error(__location__": KEY2 value lengths different"
    1299             :                                     ", expected (%d) actual(%d)\n",
    1300           0 :                                     (int)(strlen(VAL2) + 1), (int)val.length);
    1301           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1302             :                 }
    1303           1 :                 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
    1304           0 :                         print_error(__location__": KEY2 values different, "
    1305             :                                     "expected (%s) actual(%s)\n",
    1306             :                                     VAL2,
    1307             :                                     val.data);
    1308           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1309             :                 }
    1310             : 
    1311           1 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1312           1 :                 if (ret != LDB_SUCCESS) {
    1313           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1314             :                                     ret);
    1315           0 :                         exit(ret);
    1316             :                 }
    1317             : 
    1318           1 :                 exit(0);
    1319             :         }
    1320           1 :         close(to_child[0]);
    1321           1 :         close(to_parent[1]);
    1322             : 
    1323             :         /*
    1324             :          * Begin a transaction and add a record to the database
    1325             :          * but leave the transaction open
    1326             :          */
    1327           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1328           1 :         assert_int_equal(ret, 0);
    1329             : 
    1330           1 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1331           1 :         key.length = strlen(KEY2) + 1;
    1332             : 
    1333           1 :         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
    1334           1 :         val.length = strlen(VAL2) + 1;
    1335             : 
    1336           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
    1337           1 :         assert_int_equal(ret, 0);
    1338             : 
    1339             :         /*
    1340             :          * Signal the child process
    1341             :          */
    1342           1 :         ret = write(to_child[1], "GO", 2);
    1343           1 :         assert_int_equal(2, ret);
    1344             : 
    1345             :         /*
    1346             :          * Wait for the child process to check the DB state while the
    1347             :          * transaction is active
    1348             :          */
    1349           1 :         ret = read(to_parent[0], buf, 2);
    1350           1 :         assert_int_equal(2, ret);
    1351             : 
    1352             :         /*
    1353             :          * commit the transaction
    1354             :          */
    1355           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1356           1 :         assert_int_equal(0, ret);
    1357             : 
    1358             :         /*
    1359             :          * Signal the child process
    1360             :          */
    1361           1 :         ret = write(to_child[1], "GO", 2);
    1362           1 :         assert_int_equal(2, ret);
    1363             : 
    1364           1 :         w_pid = waitpid(pid, &wstatus, 0);
    1365           1 :         assert_int_equal(pid, w_pid);
    1366             : 
    1367           1 :         assert_true(WIFEXITED(wstatus));
    1368             : 
    1369           1 :         assert_int_equal(WEXITSTATUS(wstatus), 0);
    1370             : 
    1371             : 
    1372           1 :         TALLOC_FREE(tmp_ctx);
    1373           1 : }
    1374             : 
    1375             : /*
    1376             :  * Ensure that deletes are not visible until the transaction has been
    1377             :  * committed.
    1378             :  */
    1379           1 : static void test_delete_transaction_isolation(void **state)
    1380             : {
    1381             :         int ret;
    1382           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
    1383             :                                                           struct test_ctx);
    1384           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
    1385             :         struct ldb_val key;
    1386             :         struct ldb_val val;
    1387             : 
    1388           1 :         const char *KEY1 = "KEY01";
    1389           1 :         const char *VAL1 = "VALUE01";
    1390             : 
    1391           1 :         const char *KEY2 = "KEY02";
    1392           1 :         const char *VAL2 = "VALUE02";
    1393             : 
    1394             :         /*
    1395             :          * Pipes etc to co-ordinate the processes
    1396             :          */
    1397             :         int to_child[2];
    1398             :         int to_parent[2];
    1399             :         char buf[2];
    1400             :         pid_t pid, w_pid;
    1401             :         int wstatus;
    1402             : 
    1403             :         TALLOC_CTX *tmp_ctx;
    1404           1 :         tmp_ctx = talloc_new(test_ctx);
    1405           1 :         assert_non_null(tmp_ctx);
    1406             : 
    1407             : 
    1408             :         /*
    1409             :          * Add records to the database
    1410             :          */
    1411           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1412           1 :         assert_int_equal(ret, 0);
    1413             : 
    1414           1 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1415           1 :         key.length = strlen(KEY1) + 1;
    1416             : 
    1417           1 :         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
    1418           1 :         val.length = strlen(VAL1) + 1;
    1419             : 
    1420           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
    1421           1 :         assert_int_equal(ret, 0);
    1422             : 
    1423           1 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1424           1 :         key.length = strlen(KEY2) + 1;
    1425             : 
    1426           1 :         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
    1427           1 :         val.length = strlen(VAL2) + 1;
    1428             : 
    1429           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
    1430           1 :         assert_int_equal(ret, 0);
    1431             : 
    1432           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1433           1 :         assert_int_equal(ret, 0);
    1434             : 
    1435             : 
    1436           1 :         ret = pipe(to_child);
    1437           1 :         assert_int_equal(ret, 0);
    1438           1 :         ret = pipe(to_parent);
    1439           1 :         assert_int_equal(ret, 0);
    1440             :         /*
    1441             :          * Now fork a new process
    1442             :          */
    1443             : 
    1444           1 :         pid = fork();
    1445           2 :         if (pid == 0) {
    1446             : 
    1447           1 :                 struct ldb_context *ldb = NULL;
    1448           1 :                 close(to_child[1]);
    1449           1 :                 close(to_parent[0]);
    1450             : 
    1451             :                 /*
    1452             :                  * Wait for the transaction to be started
    1453             :                  */
    1454           1 :                 ret = read(to_child[0], buf, 2);
    1455           1 :                 if (ret != 2) {
    1456           0 :                         print_error(__location__": read returned (%d)\n",
    1457             :                                     ret);
    1458           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1459             :                 }
    1460             : 
    1461           1 :                 ldb = ldb_init(test_ctx, test_ctx->ev);
    1462           1 :                 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
    1463           1 :                 if (ret != LDB_SUCCESS) {
    1464           0 :                         print_error(__location__": ldb_connect returned (%d)\n",
    1465             :                                     ret);
    1466           0 :                         exit(ret);
    1467             :                 }
    1468             : 
    1469           1 :                 ldb_kv = get_ldb_kv(ldb);
    1470             : 
    1471           1 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1472           1 :                 if (ret != LDB_SUCCESS) {
    1473           0 :                         print_error(__location__": lock_read returned (%d)\n",
    1474             :                                     ret);
    1475           0 :                         exit(ret);
    1476             :                 }
    1477             : 
    1478             :                 /*
    1479             :                  * Check that KEY1 is there
    1480             :                  */
    1481           1 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1482           1 :                 key.length = strlen(KEY1) + 1;
    1483             : 
    1484           1 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1485           1 :                 if (ret != LDB_SUCCESS) {
    1486           0 :                         print_error(__location__": fetch_and_parse returned "
    1487             :                                     "(%d)\n",
    1488             :                                     ret);
    1489           0 :                         exit(ret);
    1490             :                 }
    1491             : 
    1492           1 :                 if ((strlen(VAL1) + 1) != val.length) {
    1493           0 :                         print_error(__location__": KEY1 value lengths different"
    1494             :                                     ", expected (%d) actual(%d)\n",
    1495           0 :                                     (int)(strlen(VAL1) + 1), (int)val.length);
    1496           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1497             :                 }
    1498           1 :                 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
    1499           0 :                         print_error(__location__": KEY1 values different, "
    1500             :                                     "expected (%s) actual(%s)\n",
    1501             :                                     VAL1,
    1502             :                                     val.data);
    1503           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1504             :                 }
    1505             : 
    1506             :                 /*
    1507             :                  * Check that KEY2 is there
    1508             :                  */
    1509             : 
    1510           1 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1511           1 :                 key.length = strlen(KEY2) + 1;
    1512             : 
    1513           1 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1514           1 :                 if (ret != LDB_SUCCESS) {
    1515           0 :                         print_error(__location__": fetch_and_parse returned "
    1516             :                                     "(%d)\n",
    1517             :                                     ret);
    1518           0 :                         exit(ret);
    1519             :                 }
    1520             : 
    1521           1 :                 if ((strlen(VAL2) + 1) != val.length) {
    1522           0 :                         print_error(__location__": KEY2 value lengths different"
    1523             :                                     ", expected (%d) actual(%d)\n",
    1524           0 :                                     (int)(strlen(VAL2) + 1), (int)val.length);
    1525           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1526             :                 }
    1527           1 :                 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
    1528           0 :                         print_error(__location__": KEY2 values different, "
    1529             :                                     "expected (%s) actual(%s)\n",
    1530             :                                     VAL2,
    1531             :                                     val.data);
    1532           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1533             :                 }
    1534             : 
    1535           1 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1536           1 :                 if (ret != LDB_SUCCESS) {
    1537           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1538             :                                     ret);
    1539           0 :                         exit(ret);
    1540             :                 }
    1541             : 
    1542             :                 /*
    1543             :                  * Signal the other process to commit the transaction
    1544             :                  */
    1545           1 :                 ret = write(to_parent[1], "GO", 2);
    1546           1 :                 if (ret != 2) {
    1547           0 :                         print_error(__location__": write returned (%d)\n",
    1548             :                                     ret);
    1549           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1550             :                 }
    1551             : 
    1552             :                 /*
    1553             :                  * Wait for the transaction to be commited
    1554             :                  */
    1555           1 :                 ret = read(to_child[0], buf, 2);
    1556           1 :                 if (ret != 2) {
    1557           0 :                         print_error(__location__": read returned (%d)\n",
    1558             :                                     ret);
    1559           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1560             :                 }
    1561             : 
    1562             :                 /*
    1563             :                  * Check that KEY1 is there
    1564             :                  */
    1565           1 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1566           1 :                 if (ret != LDB_SUCCESS) {
    1567           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1568             :                                     ret);
    1569           0 :                         exit(ret);
    1570             :                 }
    1571           1 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1572           1 :                 key.length = strlen(KEY1) + 1;
    1573             : 
    1574           1 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1575           1 :                 if (ret != LDB_SUCCESS) {
    1576           0 :                         print_error(__location__": fetch_and_parse returned "
    1577             :                                     "(%d)\n",
    1578             :                                     ret);
    1579           0 :                         exit(ret);
    1580             :                 }
    1581             : 
    1582           1 :                 if ((strlen(VAL1) + 1) != val.length) {
    1583           0 :                         print_error(__location__": KEY1 value lengths different"
    1584             :                                     ", expected (%d) actual(%d)\n",
    1585           0 :                                     (int)(strlen(VAL1) + 1), (int)val.length);
    1586           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1587             :                 }
    1588           1 :                 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
    1589           0 :                         print_error(__location__": KEY1 values different, "
    1590             :                                     "expected (%s) actual(%s)\n",
    1591             :                                     VAL1,
    1592             :                                     val.data);
    1593           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1594             :                 }
    1595           1 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1596           1 :                 if (ret != LDB_SUCCESS) {
    1597           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1598             :                                     ret);
    1599           0 :                         exit(ret);
    1600             :                 }
    1601             : 
    1602             :                 /*
    1603             :                  * Check that KEY2 is not there
    1604             :                  */
    1605           1 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1606           1 :                 key.length = strlen(KEY2 + 1);
    1607             : 
    1608           1 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1609           1 :                 if (ret != LDB_SUCCESS) {
    1610           0 :                         print_error(__location__": lock_read returned (%d)\n",
    1611             :                                     ret);
    1612           0 :                         exit(ret);
    1613             :                 }
    1614             : 
    1615           1 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1616           1 :                 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
    1617           0 :                         print_error(__location__": fetch_and_parse returned "
    1618             :                                     "(%d)\n",
    1619             :                                     ret);
    1620           0 :                         exit(ret);
    1621             :                 }
    1622             : 
    1623           1 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1624           1 :                 if (ret != LDB_SUCCESS) {
    1625           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1626             :                                     ret);
    1627           0 :                         exit(ret);
    1628             :                 }
    1629           1 :                 TALLOC_FREE(tmp_ctx);
    1630           1 :                 exit(0);
    1631             :         }
    1632           1 :         close(to_child[0]);
    1633           1 :         close(to_parent[1]);
    1634             : 
    1635             :         /*
    1636             :          * Begin a transaction and delete a record from the database
    1637             :          * but leave the transaction open
    1638             :          */
    1639           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1640           1 :         assert_int_equal(ret, 0);
    1641             : 
    1642           1 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1643           1 :         key.length = strlen(KEY2) + 1;
    1644             : 
    1645           1 :         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
    1646           1 :         assert_int_equal(ret, 0);
    1647             :         /*
    1648             :          * Signal the child process
    1649             :          */
    1650           1 :         ret = write(to_child[1], "GO", 2);
    1651           1 :         assert_int_equal(2, ret);
    1652             : 
    1653             :         /*
    1654             :          * Wait for the child process to check the DB state while the
    1655             :          * transaction is active
    1656             :          */
    1657           1 :         ret = read(to_parent[0], buf, 2);
    1658           1 :         assert_int_equal(2, ret);
    1659             : 
    1660             :         /*
    1661             :          * commit the transaction
    1662             :          */
    1663           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1664           1 :         assert_int_equal(0, ret);
    1665             : 
    1666             :         /*
    1667             :          * Signal the child process
    1668             :          */
    1669           1 :         ret = write(to_child[1], "GO", 2);
    1670           1 :         assert_int_equal(2, ret);
    1671             : 
    1672           1 :         w_pid = waitpid(pid, &wstatus, 0);
    1673           1 :         assert_int_equal(pid, w_pid);
    1674             : 
    1675           1 :         assert_true(WIFEXITED(wstatus));
    1676             : 
    1677           1 :         assert_int_equal(WEXITSTATUS(wstatus), 0);
    1678             : 
    1679             : 
    1680           1 :         TALLOC_FREE(tmp_ctx);
    1681           1 : }
    1682             : 
    1683             : 
    1684             : /*
    1685             :  * Test that get_size returns a sensible estimate of the number of records
    1686             :  * in the database.
    1687             :  */
    1688           1 : static void test_get_size(void **state)
    1689             : {
    1690             :         int ret;
    1691           1 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
    1692             :                                                           struct test_ctx);
    1693           1 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
    1694           1 :         uint8_t key_val[] = "TheKey";
    1695           1 :         struct ldb_val key = {
    1696             :                 .data   = key_val,
    1697             :                 .length = sizeof(key_val)
    1698             :         };
    1699             : 
    1700           1 :         uint8_t value[] = "The record contents";
    1701           1 :         struct ldb_val data = {
    1702             :                 .data    = value,
    1703             :                 .length = sizeof(value)
    1704             :         };
    1705           1 :         size_t size = 0;
    1706             : 
    1707           1 :         int flags = 0;
    1708             :         TALLOC_CTX *tmp_ctx;
    1709             : 
    1710           1 :         tmp_ctx = talloc_new(test_ctx);
    1711           1 :         assert_non_null(tmp_ctx);
    1712             : 
    1713           1 :         size = ldb_kv->kv_ops->get_size(ldb_kv);
    1714             : #if defined(TEST_LMDB)
    1715             :         assert_int_equal(2, size);
    1716             : #else
    1717             :         /*
    1718             :          * The tdb implementation of get_size over estimates for sparse files
    1719             :          * which is perfectly acceptable for it's intended use.
    1720             :          * mipsel, ia64: 9994
    1721             :          * ppc64el, powerpc, ppc64: 13369
    1722             :          * sparc64: 5046
    1723             :          */
    1724           1 :         assert_in_range(size, 2500, 15000);
    1725             : #endif
    1726             : 
    1727             :         /*
    1728             :          * Begin a transaction
    1729             :          */
    1730           1 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1731           1 :         assert_int_equal(ret, 0);
    1732             : 
    1733             :         /*
    1734             :          * Write the record
    1735             :          */
    1736           1 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
    1737           1 :         assert_int_equal(ret, 0);
    1738             : 
    1739             :         /*
    1740             :          * Commit the transaction
    1741             :          */
    1742           1 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1743           1 :         assert_int_equal(ret, 0);
    1744             : 
    1745           1 :         size = ldb_kv->kv_ops->get_size(ldb_kv);
    1746             : #ifdef TEST_LMDB
    1747             :         assert_int_equal(3, size);
    1748             : #else
    1749             :         /*
    1750             :          * The tdb implementation of get_size over estimates for sparse files
    1751             :          * which is perfectly acceptable for it's intended use.
    1752             :          * mipsel, ia64: 9994
    1753             :          * ppc64el, powerpc, ppc64: 13369
    1754             :          * sparc64: 5046
    1755             :          */
    1756           1 :         assert_in_range(size, 2500, 15000);
    1757             : #endif
    1758           1 :         talloc_free(tmp_ctx);
    1759           1 : }
    1760             : 
    1761           1 : int main(int argc, const char **argv)
    1762             : {
    1763           1 :         const struct CMUnitTest tests[] = {
    1764             :                 cmocka_unit_test_setup_teardown(
    1765             :                         test_add_get,
    1766             :                         setup,
    1767             :                         teardown),
    1768             :                 cmocka_unit_test_setup_teardown(
    1769             :                         test_delete,
    1770             :                         setup,
    1771             :                         teardown),
    1772             :                 cmocka_unit_test_setup_teardown(
    1773             :                         test_transaction_abort_write,
    1774             :                         setup,
    1775             :                         teardown),
    1776             :                 cmocka_unit_test_setup_teardown(
    1777             :                         test_transaction_abort_delete,
    1778             :                         setup,
    1779             :                         teardown),
    1780             :                 cmocka_unit_test_setup_teardown(
    1781             :                         test_read_outside_transaction,
    1782             :                         setup,
    1783             :                         teardown),
    1784             :                 cmocka_unit_test_setup_teardown(
    1785             :                         test_write_outside_transaction,
    1786             :                         setup,
    1787             :                         teardown),
    1788             :                 cmocka_unit_test_setup_teardown(
    1789             :                         test_delete_outside_transaction,
    1790             :                         setup,
    1791             :                         teardown),
    1792             :                 cmocka_unit_test_setup_teardown(
    1793             :                         test_iterate,
    1794             :                         setup,
    1795             :                         teardown),
    1796             :                 cmocka_unit_test_setup_teardown(
    1797             :                         test_iterate_range,
    1798             :                         setup,
    1799             :                         teardown),
    1800             :                 cmocka_unit_test_setup_teardown(
    1801             :                         test_update_in_iterate,
    1802             :                         setup,
    1803             :                         teardown),
    1804             :                 cmocka_unit_test_setup_teardown(
    1805             :                         test_write_transaction_isolation,
    1806             :                         setup,
    1807             :                         teardown),
    1808             :                 cmocka_unit_test_setup_teardown(
    1809             :                         test_delete_transaction_isolation,
    1810             :                         setup,
    1811             :                         teardown),
    1812             :                 cmocka_unit_test_setup_teardown(
    1813             :                         test_get_size,
    1814             :                         setup,
    1815             :                         teardown),
    1816             :         };
    1817             : 
    1818           1 :         return cmocka_run_group_tests(tests, NULL, NULL);
    1819             : }

Generated by: LCOV version 1.13