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 98b443d9 Lines: 710 796 89.2 %
Date: 2024-05-31 13:13:24 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 committed
      41             :  * - Nested transactions are not permitted
      42             :  * - transactions can be rolled back and committed.
      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          52 : static void unlink_old_db(struct test_ctx *test_ctx)
      92             : {
      93          52 :         int ret;
      94             : 
      95          52 :         errno = 0;
      96          52 :         ret = unlink(test_ctx->lockfile);
      97          52 :         if (ret == -1 && errno != ENOENT) {
      98           0 :                 fail();
      99             :         }
     100             : 
     101          52 :         errno = 0;
     102          52 :         ret = unlink(test_ctx->dbfile);
     103          52 :         if (ret == -1 && errno != ENOENT) {
     104           0 :                 fail();
     105             :         }
     106          52 : }
     107             : 
     108          26 : static int noconn_setup(void **state)
     109             : {
     110          26 :         struct test_ctx *test_ctx;
     111             : 
     112          26 :         test_ctx = talloc_zero(NULL, struct test_ctx);
     113          26 :         assert_non_null(test_ctx);
     114             : 
     115          26 :         test_ctx->ev = tevent_context_init(test_ctx);
     116          26 :         assert_non_null(test_ctx->ev);
     117             : 
     118          26 :         test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
     119          26 :         assert_non_null(test_ctx->ldb);
     120             : 
     121          26 :         test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb");
     122          26 :         assert_non_null(test_ctx->dbfile);
     123             : 
     124          26 :         test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
     125             :                                              test_ctx->dbfile);
     126          26 :         assert_non_null(test_ctx->lockfile);
     127             : 
     128          26 :         test_ctx->dbpath = talloc_asprintf(test_ctx,
     129             :                         TEST_BE"://%s", test_ctx->dbfile);
     130          26 :         assert_non_null(test_ctx->dbpath);
     131             : 
     132          26 :         unlink_old_db(test_ctx);
     133          26 :         *state = test_ctx;
     134          26 :         return 0;
     135             : }
     136             : 
     137          26 : static int noconn_teardown(void **state)
     138             : {
     139          26 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     140             :                                                           struct test_ctx);
     141             : 
     142          26 :         unlink_old_db(test_ctx);
     143          26 :         talloc_free(test_ctx);
     144          26 :         return 0;
     145             : }
     146             : 
     147          26 : static int setup(void **state)
     148             : {
     149          26 :         struct test_ctx *test_ctx;
     150          26 :         int ret;
     151          26 :         struct ldb_ldif *ldif;
     152          26 :         const char *index_ldif =                \
     153             :                 "dn: @INDEXLIST\n"
     154             :                 "@IDXGUID: objectUUID\n"
     155             :                 "@IDX_DN_GUID: GUID\n"
     156             :                 "\n";
     157             : 
     158          26 :         noconn_setup((void **) &test_ctx);
     159             : 
     160          26 :         ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
     161          26 :         assert_int_equal(ret, 0);
     162             : 
     163          52 :         while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) {
     164          26 :                 ret = ldb_add(test_ctx->ldb, ldif->msg);
     165          26 :                 assert_int_equal(ret, LDB_SUCCESS);
     166             :         }
     167          26 :         *state = test_ctx;
     168          26 :         return 0;
     169             : }
     170             : 
     171          26 : static int teardown(void **state)
     172             : {
     173          26 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     174             :                                                           struct test_ctx);
     175          26 :         noconn_teardown((void **) &test_ctx);
     176          26 :         return 0;
     177             : }
     178             : 
     179          40 : static struct ldb_kv_private *get_ldb_kv(struct ldb_context *ldb)
     180             : {
     181          40 :         void *data = NULL;
     182          40 :         struct ldb_kv_private *ldb_kv = NULL;
     183             : 
     184          40 :         data = ldb_module_get_private(ldb->modules);
     185          40 :         assert_non_null(data);
     186             : 
     187          40 :         ldb_kv = talloc_get_type(data, struct ldb_kv_private);
     188          40 :         assert_non_null(ldb_kv);
     189             : 
     190          40 :         return ldb_kv;
     191             : }
     192             : 
     193          26 : static int parse(struct ldb_val key,
     194             :                  struct ldb_val data,
     195             :                  void *private_data)
     196             : {
     197          26 :         struct ldb_val* read = private_data;
     198             : 
     199             :         /* Yes, we leak this.  That is OK */
     200          26 :         read->data = talloc_size(NULL,
     201             :                                  data.length);
     202          26 :         assert_non_null(read->data);
     203             : 
     204          26 :         memcpy(read->data, data.data, data.length);
     205          26 :         read->length = data.length;
     206          26 :         return LDB_SUCCESS;
     207             : }
     208             : 
     209             : /*
     210             :  * Parse function that just returns the int we pass it.
     211             :  */
     212         100 : static int parse_return(struct ldb_val key,
     213             :                         struct ldb_val data,
     214             :                         void *private_data)
     215             : {
     216         100 :         int *rcode = private_data;
     217         100 :         return *rcode;
     218             : }
     219             : 
     220             : /*
     221             :  * Test that data can be written to the kv store and be read back.
     222             :  */
     223           2 : static void test_add_get(void **state)
     224             : {
     225           2 :         int ret;
     226           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     227             :                                                           struct test_ctx);
     228           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     229           2 :         uint8_t key_val[] = "TheKey";
     230           2 :         struct ldb_val key = {
     231             :                 .data   = key_val,
     232             :                 .length = sizeof(key_val)
     233             :         };
     234             : 
     235           2 :         uint8_t value[] = "The record contents";
     236           2 :         struct ldb_val data = {
     237             :                 .data    = value,
     238             :                 .length = sizeof(value)
     239             :         };
     240             : 
     241           2 :         struct ldb_val read;
     242           2 :         int rcode;
     243             : 
     244           2 :         int flags = 0;
     245           2 :         TALLOC_CTX *tmp_ctx;
     246             : 
     247           2 :         tmp_ctx = talloc_new(test_ctx);
     248           2 :         assert_non_null(tmp_ctx);
     249             : 
     250             :         /*
     251             :          * Begin a transaction
     252             :          */
     253           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     254           2 :         assert_int_equal(ret, 0);
     255             : 
     256             :         /*
     257             :          * Write the record
     258             :          */
     259           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     260           2 :         assert_int_equal(ret, 0);
     261             : 
     262             :         /*
     263             :          * Commit the transaction
     264             :          */
     265           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     266           2 :         assert_int_equal(ret, 0);
     267             : 
     268             :         /*
     269             :          * And now read it back
     270             :          */
     271           2 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     272           2 :         assert_int_equal(ret, 0);
     273             : 
     274           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     275           2 :         assert_int_equal(ret, 0);
     276             : 
     277           2 :         assert_int_equal(sizeof(value), read.length);
     278           2 :         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         102 :         for (rcode=0; rcode<50; rcode++) {
     285         100 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key,
     286             :                                                       parse_return,
     287             :                                                       &rcode);
     288         100 :                 assert_int_equal(ret, rcode);
     289             :         }
     290             : 
     291           2 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     292           2 :         assert_int_equal(ret, 0);
     293           2 :         talloc_free(tmp_ctx);
     294           2 : }
     295             : 
     296             : /*
     297             :  * Test that attempts to read data without a read transaction fail.
     298             :  */
     299           2 : static void test_read_outside_transaction(void **state)
     300             : {
     301           2 :         int ret;
     302           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     303             :                                                           struct test_ctx);
     304           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     305           2 :         uint8_t key_val[] = "TheKey";
     306           2 :         struct ldb_val key = {
     307             :                 .data   = key_val,
     308             :                 .length = sizeof(key_val)
     309             :         };
     310             : 
     311           2 :         uint8_t value[] = "The record contents";
     312           2 :         struct ldb_val data = {
     313             :                 .data    = value,
     314             :                 .length = sizeof(value)
     315             :         };
     316             : 
     317           2 :         struct ldb_val read;
     318             : 
     319           2 :         int flags = 0;
     320           2 :         TALLOC_CTX *tmp_ctx;
     321             : 
     322           2 :         tmp_ctx = talloc_new(test_ctx);
     323           2 :         assert_non_null(tmp_ctx);
     324             : 
     325             :         /*
     326             :          * Begin a transaction
     327             :          */
     328           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     329           2 :         assert_int_equal(ret, 0);
     330             : 
     331             :         /*
     332             :          * Write the record
     333             :          */
     334           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     335           2 :         assert_int_equal(ret, 0);
     336             : 
     337             :         /*
     338             :          * Commit the transaction
     339             :          */
     340           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     341           2 :         assert_int_equal(ret, 0);
     342             : 
     343             :         /*
     344             :          * And now read it back
     345             :          * Note there is no read transaction active
     346             :          */
     347           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     348           2 :         assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
     349             : 
     350           2 :         talloc_free(tmp_ctx);
     351           2 : }
     352             : 
     353             : /*
     354             :  * Test that data can be deleted from the kv store
     355             :  */
     356           2 : static void test_delete(void **state)
     357             : {
     358           2 :         int ret;
     359           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     360             :                                                           struct test_ctx);
     361           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     362           2 :         uint8_t key_val[] = "TheKey";
     363           2 :         struct ldb_val key = {
     364             :                 .data   = key_val,
     365             :                 .length = sizeof(key_val)
     366             :         };
     367             : 
     368           2 :         uint8_t value[] = "The record contents";
     369           2 :         struct ldb_val data = {
     370             :                 .data    = value,
     371             :                 .length = sizeof(value)
     372             :         };
     373             : 
     374           2 :         struct ldb_val read;
     375             : 
     376           2 :         int flags = 0;
     377           2 :         TALLOC_CTX *tmp_ctx;
     378             : 
     379           2 :         tmp_ctx = talloc_new(test_ctx);
     380           2 :         assert_non_null(tmp_ctx);
     381             : 
     382             :         /*
     383             :          * Begin a transaction
     384             :          */
     385           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     386           2 :         assert_int_equal(ret, 0);
     387             : 
     388             :         /*
     389             :          * Write the record
     390             :          */
     391           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     392           2 :         assert_int_equal(ret, 0);
     393             : 
     394             :         /*
     395             :          * Commit the transaction
     396             :          */
     397           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     398           2 :         assert_int_equal(ret, 0);
     399             : 
     400             :         /*
     401             :          * And now read it back
     402             :          */
     403           2 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     404           2 :         assert_int_equal(ret, 0);
     405           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     406           2 :         assert_int_equal(ret, 0);
     407           2 :         assert_int_equal(sizeof(value), read.length);
     408           2 :         assert_memory_equal(value, read.data, sizeof(value));
     409           2 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     410           2 :         assert_int_equal(ret, 0);
     411             : 
     412             :         /*
     413             :          * Begin a transaction
     414             :          */
     415           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     416           2 :         assert_int_equal(ret, 0);
     417             : 
     418             :         /*
     419             :          * Now delete it.
     420             :          */
     421           2 :         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
     422           2 :         assert_int_equal(ret, 0);
     423             : 
     424             :         /*
     425             :          * Commit the transaction
     426             :          */
     427           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     428           2 :         assert_int_equal(ret, 0);
     429             : 
     430             :         /*
     431             :          * And now try to read it back
     432             :          */
     433           2 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     434           2 :         assert_int_equal(ret, 0);
     435           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     436           2 :         assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
     437           2 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     438           2 :         assert_int_equal(ret, 0);
     439             : 
     440           2 :         talloc_free(tmp_ctx);
     441           2 : }
     442             : 
     443             : /*
     444             :  * Check that writes are correctly rolled back when a transaction
     445             :  * is rolled back.
     446             :  */
     447           2 : static void test_transaction_abort_write(void **state)
     448             : {
     449           2 :         int ret;
     450           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     451             :                                                           struct test_ctx);
     452           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     453           2 :         uint8_t key_val[] = "TheKey";
     454           2 :         struct ldb_val key = {
     455             :                 .data   = key_val,
     456             :                 .length = sizeof(key_val)
     457             :         };
     458             : 
     459           2 :         uint8_t value[] = "The record contents";
     460           2 :         struct ldb_val data = {
     461             :                 .data    = value,
     462             :                 .length = sizeof(value)
     463             :         };
     464             : 
     465           2 :         struct ldb_val read;
     466             : 
     467           2 :         int flags = 0;
     468           2 :         TALLOC_CTX *tmp_ctx;
     469             : 
     470           2 :         tmp_ctx = talloc_new(test_ctx);
     471           2 :         assert_non_null(tmp_ctx);
     472             : 
     473             :         /*
     474             :          * Begin a transaction
     475             :          */
     476           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     477           2 :         assert_int_equal(ret, 0);
     478             : 
     479             :         /*
     480             :          * Write the record
     481             :          */
     482           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     483           2 :         assert_int_equal(ret, 0);
     484             : 
     485             :         /*
     486             :          * And now read it back
     487             :          */
     488           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     489           2 :         assert_int_equal(ret, 0);
     490           2 :         assert_int_equal(sizeof(value), read.length);
     491           2 :         assert_memory_equal(value, read.data, sizeof(value));
     492             : 
     493             : 
     494             :         /*
     495             :          * Now abort the transaction
     496             :          */
     497           2 :         ret = ldb_kv->kv_ops->abort_write(ldb_kv);
     498           2 :         assert_int_equal(ret, 0);
     499             : 
     500             :         /*
     501             :          * And now read it back, should not be there
     502             :          */
     503           2 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     504           2 :         assert_int_equal(ret, 0);
     505           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     506           2 :         assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
     507           2 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     508           2 :         assert_int_equal(ret, 0);
     509             : 
     510           2 :         talloc_free(tmp_ctx);
     511           2 : }
     512             : 
     513             : /*
     514             :  * Check that deletes are correctly rolled back when a transaction is
     515             :  * aborted.
     516             :  */
     517           2 : static void test_transaction_abort_delete(void **state)
     518             : {
     519           2 :         int ret;
     520           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     521             :                                                           struct test_ctx);
     522           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     523           2 :         uint8_t key_val[] = "TheKey";
     524           2 :         struct ldb_val key = {
     525             :                 .data   = key_val,
     526             :                 .length = sizeof(key_val)
     527             :         };
     528             : 
     529           2 :         uint8_t value[] = "The record contents";
     530           2 :         struct ldb_val data = {
     531             :                 .data    = value,
     532             :                 .length = sizeof(value)
     533             :         };
     534             : 
     535           2 :         struct ldb_val read;
     536             : 
     537           2 :         int flags = 0;
     538           2 :         TALLOC_CTX *tmp_ctx;
     539             : 
     540           2 :         tmp_ctx = talloc_new(test_ctx);
     541           2 :         assert_non_null(tmp_ctx);
     542             : 
     543             :         /*
     544             :          * Begin a transaction
     545             :          */
     546           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     547           2 :         assert_int_equal(ret, 0);
     548             : 
     549             :         /*
     550             :          * Write the record
     551             :          */
     552           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     553           2 :         assert_int_equal(ret, 0);
     554             : 
     555             :         /*
     556             :          * Commit the transaction
     557             :          */
     558           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     559           2 :         assert_int_equal(ret, 0);
     560             : 
     561             :         /*
     562             :          * And now read it back
     563             :          */
     564           2 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     565           2 :         assert_int_equal(ret, 0);
     566           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     567           2 :         assert_int_equal(ret, 0);
     568           2 :         assert_int_equal(sizeof(value), read.length);
     569           2 :         assert_memory_equal(value, read.data, sizeof(value));
     570           2 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     571           2 :         assert_int_equal(ret, 0);
     572             : 
     573             :         /*
     574             :          * Begin a transaction
     575             :          */
     576           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     577           2 :         assert_int_equal(ret, 0);
     578             : 
     579             :         /*
     580             :          * Now delete it.
     581             :          */
     582           2 :         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
     583           2 :         assert_int_equal(ret, 0);
     584             : 
     585             :         /*
     586             :          * And now read it back
     587             :          */
     588           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     589           2 :         assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
     590             : 
     591             :         /*
     592             :          * Abort the transaction
     593             :          */
     594           2 :         ret = ldb_kv->kv_ops->abort_write(ldb_kv);
     595           2 :         assert_int_equal(ret, 0);
     596             : 
     597             :         /*
     598             :          * And now try to read it back
     599             :          */
     600           2 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     601           2 :         assert_int_equal(ret, 0);
     602           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     603           2 :         assert_int_equal(ret, 0);
     604           2 :         assert_int_equal(sizeof(value), read.length);
     605           2 :         assert_memory_equal(value, read.data, sizeof(value));
     606           2 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     607           2 :         assert_int_equal(ret, 0);
     608             : 
     609           2 :         talloc_free(tmp_ctx);
     610           2 : }
     611             : 
     612             : /*
     613             :  * Test that writes outside a transaction fail
     614             :  */
     615           2 : static void test_write_outside_transaction(void **state)
     616             : {
     617           2 :         int ret;
     618           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     619             :                                                           struct test_ctx);
     620           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     621           2 :         uint8_t key_val[] = "TheKey";
     622           2 :         struct ldb_val key = {
     623             :                 .data   = key_val,
     624             :                 .length = sizeof(key_val)
     625             :         };
     626             : 
     627           2 :         uint8_t value[] = "The record contents";
     628           2 :         struct ldb_val data = {
     629             :                 .data    = value,
     630             :                 .length = sizeof(value)
     631             :         };
     632             : 
     633             : 
     634           2 :         int flags = 0;
     635           2 :         TALLOC_CTX *tmp_ctx;
     636             : 
     637           2 :         tmp_ctx = talloc_new(test_ctx);
     638           2 :         assert_non_null(tmp_ctx);
     639             : 
     640             :         /*
     641             :          * Attempt to write the record
     642             :          */
     643           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     644           2 :         assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
     645             : 
     646           2 :         talloc_free(tmp_ctx);
     647           2 : }
     648             : 
     649             : /*
     650             :  * Test data can not be deleted outside a transaction
     651             :  */
     652           2 : static void test_delete_outside_transaction(void **state)
     653             : {
     654           2 :         int ret;
     655           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     656             :                                                           struct test_ctx);
     657           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     658           2 :         uint8_t key_val[] = "TheKey";
     659           2 :         struct ldb_val key = {
     660             :                 .data   = key_val,
     661             :                 .length = sizeof(key_val)
     662             :         };
     663             : 
     664           2 :         uint8_t value[] = "The record contents";
     665           2 :         struct ldb_val data = {
     666             :                 .data    = value,
     667             :                 .length = sizeof(value)
     668             :         };
     669             : 
     670           2 :         struct ldb_val read;
     671             : 
     672           2 :         int flags = 0;
     673           2 :         TALLOC_CTX *tmp_ctx;
     674             : 
     675           2 :         tmp_ctx = talloc_new(test_ctx);
     676           2 :         assert_non_null(tmp_ctx);
     677             : 
     678             :         /*
     679             :          * Begin a transaction
     680             :          */
     681           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     682           2 :         assert_int_equal(ret, 0);
     683             : 
     684             :         /*
     685             :          * Write the record
     686             :          */
     687           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
     688           2 :         assert_int_equal(ret, 0);
     689             : 
     690             :         /*
     691             :          * Commit the transaction
     692             :          */
     693           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     694           2 :         assert_int_equal(ret, 0);
     695             : 
     696             :         /*
     697             :          * And now read it back
     698             :          */
     699           2 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     700           2 :         assert_int_equal(ret, 0);
     701           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     702           2 :         assert_int_equal(ret, 0);
     703           2 :         assert_int_equal(sizeof(value), read.length);
     704           2 :         assert_memory_equal(value, read.data, sizeof(value));
     705           2 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     706           2 :         assert_int_equal(ret, 0);
     707             : 
     708             :         /*
     709             :          * Now attempt to delete a record
     710             :          */
     711           2 :         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
     712           2 :         assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
     713             : 
     714             :         /*
     715             :          * And now read it back
     716             :          */
     717           2 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     718           2 :         assert_int_equal(ret, 0);
     719           2 :         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
     720           2 :         assert_int_equal(ret, 0);
     721           2 :         assert_int_equal(sizeof(value), read.length);
     722           2 :         assert_memory_equal(value, read.data, sizeof(value));
     723           2 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     724           2 :         assert_int_equal(ret, 0);
     725             : 
     726           2 :         talloc_free(tmp_ctx);
     727           2 : }
     728             : 
     729        3675 : 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        3675 :         int *visits = ctx;
     736        3675 :         int i;
     737             : 
     738        3675 :         if (strncmp("key ", (char *) key.data, 4) == 0) {
     739        3671 :                 i = strtol((char *) &key.data[4], NULL, 10);
     740        3671 :                 visits[i]++;
     741             :         }
     742        3675 :         return LDB_SUCCESS;
     743             : }
     744             : 
     745             : /*
     746             :  * Test that iterate visits all the records.
     747             :  */
     748           2 : static void test_iterate(void **state)
     749           2 : {
     750           2 :         int ret;
     751           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     752             :                                                           struct test_ctx);
     753           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     754           2 :         int i;
     755           2 :         int num_recs = 1024;
     756           2 :         int visits[num_recs];
     757             : 
     758           2 :         TALLOC_CTX *tmp_ctx;
     759             : 
     760           2 :         tmp_ctx = talloc_new(test_ctx);
     761           2 :         assert_non_null(tmp_ctx);
     762             : 
     763             :         /*
     764             :          * Begin a transaction
     765             :          */
     766           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     767           2 :         assert_int_equal(ret, 0);
     768             : 
     769             :         /*
     770             :          * Write the records
     771             :          */
     772        2052 :         for (i = 0; i < num_recs; i++) {
     773        2048 :                 struct ldb_val key;
     774        2048 :                 struct ldb_val rec;
     775        2048 :                 int flags = 0;
     776             : 
     777        2048 :                 visits[i] = 0;
     778        2048 :                 key.data   = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
     779        2048 :                 key.length = strlen((char *)key.data) + 1;
     780             : 
     781        2048 :                 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
     782             :                                                        "data for record (%04d)",
     783             :                                                        i);
     784        2048 :                 rec.length = strlen((char *)rec.data) + 1;
     785             : 
     786        2048 :                 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
     787        2048 :                 assert_int_equal(ret, 0);
     788             : 
     789        2048 :                 TALLOC_FREE(key.data);
     790        2048 :                 TALLOC_FREE(rec.data);
     791             :         }
     792             : 
     793             :         /*
     794             :          * Commit the transaction
     795             :          */
     796           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     797           2 :         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           2 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     804           2 :         assert_int_equal(ret, 0);
     805           2 :         ret = ldb_kv->kv_ops->iterate(ldb_kv, traverse_fn, visits);
     806        2052 :         for (i = 0; i <num_recs; i++) {
     807        2048 :                 assert_int_equal(1, visits[i]);
     808             :         }
     809           2 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     810           2 :         assert_int_equal(ret, 0);
     811             : 
     812           2 :         TALLOC_FREE(tmp_ctx);
     813           2 : }
     814             : 
     815          12 : static void do_iterate_range_test(void **state, int range_start,
     816             :                                   int range_end, bool fail)
     817          12 : {
     818          12 :         int ret;
     819          12 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     820             :                                                           struct test_ctx);
     821          12 :         struct ldb_kv_private *ldb_kv = NULL;
     822          12 :         int i;
     823          12 :         int num_recs = 1024;
     824          12 :         int skip_recs = 10;
     825          12 :         int visits[num_recs];
     826          12 :         struct ldb_val sk, ek;
     827             : 
     828          12 :         TALLOC_CTX *tmp_ctx;
     829             : 
     830          12 :         ldb_kv = get_ldb_kv(test_ctx->ldb);
     831          12 :         assert_non_null(ldb_kv);
     832             : 
     833        6162 :         for (i = 0; i < num_recs; i++){
     834        6144 :                 visits[i] = 0;
     835             :         }
     836             : 
     837             :         /*
     838             :          * No iterate_range on tdb
     839             :          */
     840          12 :         if (strcmp(TEST_BE, "tdb") == 0) {
     841           7 :                 return;
     842             :         }
     843             : 
     844           6 :         tmp_ctx = talloc_new(test_ctx);
     845           6 :         assert_non_null(tmp_ctx);
     846             : 
     847             :         /*
     848             :          * Begin a transaction
     849             :          */
     850           6 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
     851           6 :         assert_int_equal(ret, 0);
     852             : 
     853             :         /*
     854             :          * Write the records
     855             :          */
     856        6042 :         for (i = skip_recs; i <= num_recs - skip_recs; i++) {
     857        6030 :                 struct ldb_val key;
     858        6030 :                 struct ldb_val rec;
     859        6030 :                 int flags = 0;
     860             : 
     861        6030 :                 key.data   = (uint8_t *)talloc_asprintf(tmp_ctx,
     862             :                                                         "key %04d",
     863             :                                                         i);
     864        6030 :                 key.length = strlen((char *)key.data);
     865             : 
     866        6030 :                 rec.data = (uint8_t *)talloc_asprintf(tmp_ctx,
     867             :                                                       "data for record (%04d)",
     868             :                                                       i);
     869        6030 :                 rec.length = strlen((char *)rec.data) + 1;
     870             : 
     871        6030 :                 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
     872        6030 :                 assert_int_equal(ret, 0);
     873             : 
     874        6030 :                 TALLOC_FREE(key.data);
     875        6030 :                 TALLOC_FREE(rec.data);
     876             :         }
     877             : 
     878             :         /*
     879             :          * Commit the transaction
     880             :          */
     881           6 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
     882           6 :         assert_int_equal(ret, 0);
     883             : 
     884           6 :         sk.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_start);
     885           6 :         sk.length = strlen((char *)sk.data);
     886             : 
     887           6 :         ek.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_end);
     888           6 :         ek.length = strlen((char *)ek.data) + 1;
     889             : 
     890           6 :         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
     891           6 :         assert_int_equal(ret, 0);
     892           6 :         ret = ldb_kv->kv_ops->iterate_range(ldb_kv, sk, ek,
     893             :                                             traverse_fn, visits);
     894           6 :         if (fail){
     895           1 :                 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
     896           1 :                 TALLOC_FREE(tmp_ctx);
     897           1 :                 return;
     898             :         } else{
     899           5 :                 assert_int_equal(ret, 0);
     900             :         }
     901        5130 :         for (i = 0; i < num_recs; i++) {
     902        5120 :                 if (i >= skip_recs && i <= num_recs - skip_recs &&
     903        5025 :                     i >= range_start && i <= range_end){
     904        1623 :                         assert_int_equal(1, visits[i]);
     905             :                 } else {
     906        3497 :                         assert_int_equal(0, visits[i]);
     907             :                 }
     908             :         }
     909             : 
     910           5 :         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
     911           5 :         assert_int_equal(ret, 0);
     912             : 
     913           5 :         TALLOC_FREE(tmp_ctx);
     914             : }
     915             : 
     916             : /*
     917             :  * Test that iterate_range visits all the records between two keys.
     918             :  */
     919           2 : static void test_iterate_range(void **state)
     920             : {
     921           2 :         do_iterate_range_test(state, 300, 900, false);
     922             : 
     923             :         /*
     924             :          * test start_key = end_key
     925             :          */
     926           2 :         do_iterate_range_test(state, 20, 20, false);
     927             : 
     928             :         /*
     929             :          * test reverse range fails
     930             :          */
     931           2 :         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           2 :         do_iterate_range_test(state, 0, 20, false);
     937           2 :         do_iterate_range_test(state, 1010, 1030, false);
     938           2 :         do_iterate_range_test(state, 0, 1030, false);
     939           2 : }
     940             : 
     941             : struct update_context {
     942             :         struct ldb_context* ldb;
     943             :         int visits[NUM_RECS];
     944             : };
     945             : 
     946        2855 : 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        2855 :         struct ldb_val new_key;
     953        2855 :         struct ldb_module *module = NULL;
     954        2855 :         struct update_context *context =NULL;
     955        2855 :         int ret = LDB_SUCCESS;
     956        2855 :         TALLOC_CTX *tmp_ctx;
     957             : 
     958        2855 :         tmp_ctx = talloc_new(ldb_kv);
     959        2855 :         assert_non_null(tmp_ctx);
     960             : 
     961        2855 :         context = talloc_get_type_abort(ctx, struct update_context);
     962             : 
     963        2855 :         module = talloc_zero(tmp_ctx, struct ldb_module);
     964        2855 :         module->ldb = context->ldb;
     965             : 
     966        2855 :         if (strncmp("key ", (char *) key.data, 4) == 0) {
     967        2048 :                 int i = strtol((char *) &key.data[4], NULL, 10);
     968        2048 :                 context->visits[i]++;
     969        2048 :                 new_key.data = talloc_memdup(tmp_ctx, key.data, key.length);
     970        2048 :                 new_key.length  = key.length;
     971        2048 :                 new_key.data[0] = 'K';
     972             : 
     973        2048 :                 ret = ldb_kv->kv_ops->update_in_iterate(
     974             :                     ldb_kv, key, new_key, data, &module);
     975             :         }
     976        2855 :         TALLOC_FREE(tmp_ctx);
     977        2855 :         return ret;
     978             : }
     979             : 
     980             : /*
     981             :  * Test that update_in_iterate behaves as expected.
     982             :  */
     983           2 : static void test_update_in_iterate(void **state)
     984             : {
     985           2 :         int ret;
     986           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
     987             :                                                           struct test_ctx);
     988           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
     989           2 :         int i;
     990           2 :         struct update_context *context = NULL;
     991             : 
     992             : 
     993           2 :         TALLOC_CTX *tmp_ctx;
     994             : 
     995           2 :         tmp_ctx = talloc_new(test_ctx);
     996           2 :         assert_non_null(tmp_ctx);
     997             : 
     998           2 :         context = talloc_zero(tmp_ctx, struct update_context);
     999           2 :         assert_non_null(context);
    1000           2 :         context->ldb = test_ctx->ldb;
    1001             :         /*
    1002             :          * Begin a transaction
    1003             :          */
    1004           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1005           2 :         assert_int_equal(ret, 0);
    1006             : 
    1007             :         /*
    1008             :          * Write the records
    1009             :          */
    1010        2052 :         for (i = 0; i < NUM_RECS; i++) {
    1011        2048 :                 struct ldb_val key;
    1012        2048 :                 struct ldb_val rec;
    1013        2048 :                 int flags = 0;
    1014             : 
    1015        2048 :                 key.data   = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
    1016        2048 :                 key.length = strlen((char *)key.data) + 1;
    1017             : 
    1018        2048 :                 rec.data   = (uint8_t *) talloc_asprintf(tmp_ctx,
    1019             :                                                          "data for record (%04d)",
    1020             :                                                          i);
    1021        2048 :                 rec.length = strlen((char *)rec.data) + 1;
    1022             : 
    1023        2048 :                 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
    1024        2048 :                 assert_int_equal(ret, 0);
    1025             : 
    1026        2048 :                 TALLOC_FREE(key.data);
    1027        2048 :                 TALLOC_FREE(rec.data);
    1028             :         }
    1029             : 
    1030             :         /*
    1031             :          * Commit the transaction
    1032             :          */
    1033           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1034           2 :         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           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1045           2 :         assert_int_equal(ret, 0);
    1046             : 
    1047           2 :         ret = ldb_kv->kv_ops->iterate(ldb_kv, update_fn, context);
    1048        2052 :         for (i = 0; i < NUM_RECS; i++) {
    1049        2048 :                 assert_int_equal(1, context->visits[i]);
    1050             :         }
    1051             : 
    1052           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1053           2 :         assert_int_equal(ret, 0);
    1054             : 
    1055           2 :         TALLOC_FREE(tmp_ctx);
    1056           2 : }
    1057             : 
    1058             : /*
    1059             :  * Ensure that writes are not visible until the transaction has been
    1060             :  * committed.
    1061             :  */
    1062           2 : static void test_write_transaction_isolation(void **state)
    1063             : {
    1064           2 :         int ret;
    1065           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
    1066             :                                                           struct test_ctx);
    1067           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
    1068           2 :         struct ldb_val key;
    1069           2 :         struct ldb_val val;
    1070             : 
    1071           2 :         const char *KEY1 = "KEY01";
    1072           2 :         const char *VAL1 = "VALUE01";
    1073             : 
    1074           2 :         const char *KEY2 = "KEY02";
    1075           2 :         const char *VAL2 = "VALUE02";
    1076             : 
    1077             :         /*
    1078             :          * Pipes etc to coordinate the processes
    1079             :          */
    1080           2 :         int to_child[2];
    1081           2 :         int to_parent[2];
    1082           2 :         char buf[2];
    1083           2 :         pid_t pid, w_pid;
    1084           2 :         int wstatus;
    1085             : 
    1086           2 :         TALLOC_CTX *tmp_ctx;
    1087           2 :         tmp_ctx = talloc_new(test_ctx);
    1088           2 :         assert_non_null(tmp_ctx);
    1089             : 
    1090             : 
    1091             :         /*
    1092             :          * Add a record to the database
    1093             :          */
    1094           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1095           2 :         assert_int_equal(ret, 0);
    1096             : 
    1097           2 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1098           2 :         key.length = strlen(KEY1) + 1;
    1099             : 
    1100           2 :         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
    1101           2 :         val.length = strlen(VAL1) + 1;
    1102             : 
    1103           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
    1104           2 :         assert_int_equal(ret, 0);
    1105             : 
    1106           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1107           2 :         assert_int_equal(ret, 0);
    1108             : 
    1109             : 
    1110           2 :         ret = pipe(to_child);
    1111           2 :         assert_int_equal(ret, 0);
    1112           2 :         ret = pipe(to_parent);
    1113           2 :         assert_int_equal(ret, 0);
    1114             :         /*
    1115             :          * Now fork a new process
    1116             :          */
    1117             : 
    1118           2 :         pid = fork();
    1119           4 :         if (pid == 0) {
    1120             : 
    1121           2 :                 struct ldb_context *ldb = NULL;
    1122           2 :                 close(to_child[1]);
    1123           2 :                 close(to_parent[0]);
    1124             : 
    1125             :                 /*
    1126             :                  * Wait for the transaction to start
    1127             :                  */
    1128           2 :                 ret = read(to_child[0], buf, 2);
    1129           2 :                 if (ret != 2) {
    1130           0 :                         print_error(__location__": read returned (%d)\n",
    1131             :                                     ret);
    1132           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1133             :                 }
    1134           2 :                 ldb = ldb_init(test_ctx, test_ctx->ev);
    1135           2 :                 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
    1136           2 :                 if (ret != LDB_SUCCESS) {
    1137           0 :                         print_error(__location__": ldb_connect returned (%d)\n",
    1138             :                                     ret);
    1139           0 :                         exit(ret);
    1140             :                 }
    1141             : 
    1142           2 :                 ldb_kv = get_ldb_kv(ldb);
    1143             : 
    1144           2 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1145           2 :                 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           2 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1155           2 :                 key.length = strlen(KEY1) + 1;
    1156             : 
    1157           2 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1158           2 :                 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           2 :                 if ((strlen(VAL1) + 1) != val.length) {
    1166           0 :                         print_error(__location__": KEY1 value lengths different"
    1167             :                                     ", expected (%d) actual(%d)\n",
    1168             :                                     (int)(strlen(VAL1) + 1), (int)val.length);
    1169           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1170             :                 }
    1171           2 :                 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           2 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1180           2 :                 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           2 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1190           2 :                 key.length = strlen(KEY2 + 1);
    1191             : 
    1192           2 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1193           2 :                 if (ret != LDB_SUCCESS) {
    1194           0 :                         print_error(__location__": lock_read returned (%d)\n",
    1195             :                                     ret);
    1196           0 :                         exit(ret);
    1197             :                 }
    1198             : 
    1199           2 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1200           2 :                 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           2 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1208           2 :                 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           2 :                 ret = write(to_parent[1], "GO", 2);
    1218           2 :                 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 committed
    1226             :                  */
    1227           2 :                 ret = read(to_child[0], buf, 2);
    1228           2 :                 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           2 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1238           2 :                 if (ret != LDB_SUCCESS) {
    1239           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1240             :                                     ret);
    1241           0 :                         exit(ret);
    1242             :                 }
    1243           2 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1244           2 :                 key.length = strlen(KEY1) + 1;
    1245             : 
    1246           2 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1247           2 :                 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           2 :                 if ((strlen(VAL1) + 1) != val.length) {
    1255           0 :                         print_error(__location__": KEY1 value lengths different"
    1256             :                                     ", expected (%d) actual(%d)\n",
    1257             :                                     (int)(strlen(VAL1) + 1), (int)val.length);
    1258           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1259             :                 }
    1260           2 :                 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           2 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1269           2 :                 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           2 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1280           2 :                 if (ret != LDB_SUCCESS) {
    1281           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1282             :                                     ret);
    1283           0 :                         exit(ret);
    1284             :                 }
    1285             : 
    1286           2 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1287           2 :                 key.length = strlen(KEY2) + 1;
    1288             : 
    1289           2 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1290           2 :                 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           2 :                 if ((strlen(VAL2) + 1) != val.length) {
    1298           0 :                         print_error(__location__": KEY2 value lengths different"
    1299             :                                     ", expected (%d) actual(%d)\n",
    1300             :                                     (int)(strlen(VAL2) + 1), (int)val.length);
    1301           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1302             :                 }
    1303           2 :                 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           2 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1312           2 :                 if (ret != LDB_SUCCESS) {
    1313           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1314             :                                     ret);
    1315           0 :                         exit(ret);
    1316             :                 }
    1317             : 
    1318           2 :                 exit(0);
    1319             :         }
    1320           2 :         close(to_child[0]);
    1321           2 :         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           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1328           2 :         assert_int_equal(ret, 0);
    1329             : 
    1330           2 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1331           2 :         key.length = strlen(KEY2) + 1;
    1332             : 
    1333           2 :         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
    1334           2 :         val.length = strlen(VAL2) + 1;
    1335             : 
    1336           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
    1337           2 :         assert_int_equal(ret, 0);
    1338             : 
    1339             :         /*
    1340             :          * Signal the child process
    1341             :          */
    1342           2 :         ret = write(to_child[1], "GO", 2);
    1343           2 :         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           2 :         ret = read(to_parent[0], buf, 2);
    1350           2 :         assert_int_equal(2, ret);
    1351             : 
    1352             :         /*
    1353             :          * commit the transaction
    1354             :          */
    1355           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1356           2 :         assert_int_equal(0, ret);
    1357             : 
    1358             :         /*
    1359             :          * Signal the child process
    1360             :          */
    1361           2 :         ret = write(to_child[1], "GO", 2);
    1362           2 :         assert_int_equal(2, ret);
    1363             : 
    1364           2 :         w_pid = waitpid(pid, &wstatus, 0);
    1365           2 :         assert_int_equal(pid, w_pid);
    1366             : 
    1367           2 :         assert_true(WIFEXITED(wstatus));
    1368             : 
    1369           2 :         assert_int_equal(WEXITSTATUS(wstatus), 0);
    1370             : 
    1371             : 
    1372           2 :         TALLOC_FREE(tmp_ctx);
    1373           2 : }
    1374             : 
    1375             : /*
    1376             :  * Ensure that deletes are not visible until the transaction has been
    1377             :  * committed.
    1378             :  */
    1379           2 : static void test_delete_transaction_isolation(void **state)
    1380             : {
    1381           2 :         int ret;
    1382           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
    1383             :                                                           struct test_ctx);
    1384           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
    1385           2 :         struct ldb_val key;
    1386           2 :         struct ldb_val val;
    1387             : 
    1388           2 :         const char *KEY1 = "KEY01";
    1389           2 :         const char *VAL1 = "VALUE01";
    1390             : 
    1391           2 :         const char *KEY2 = "KEY02";
    1392           2 :         const char *VAL2 = "VALUE02";
    1393             : 
    1394             :         /*
    1395             :          * Pipes etc to coordinate the processes
    1396             :          */
    1397           2 :         int to_child[2];
    1398           2 :         int to_parent[2];
    1399           2 :         char buf[2];
    1400           2 :         pid_t pid, w_pid;
    1401           2 :         int wstatus;
    1402             : 
    1403           2 :         TALLOC_CTX *tmp_ctx;
    1404           2 :         tmp_ctx = talloc_new(test_ctx);
    1405           2 :         assert_non_null(tmp_ctx);
    1406             : 
    1407             : 
    1408             :         /*
    1409             :          * Add records to the database
    1410             :          */
    1411           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1412           2 :         assert_int_equal(ret, 0);
    1413             : 
    1414           2 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1415           2 :         key.length = strlen(KEY1) + 1;
    1416             : 
    1417           2 :         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
    1418           2 :         val.length = strlen(VAL1) + 1;
    1419             : 
    1420           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
    1421           2 :         assert_int_equal(ret, 0);
    1422             : 
    1423           2 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1424           2 :         key.length = strlen(KEY2) + 1;
    1425             : 
    1426           2 :         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
    1427           2 :         val.length = strlen(VAL2) + 1;
    1428             : 
    1429           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
    1430           2 :         assert_int_equal(ret, 0);
    1431             : 
    1432           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1433           2 :         assert_int_equal(ret, 0);
    1434             : 
    1435             : 
    1436           2 :         ret = pipe(to_child);
    1437           2 :         assert_int_equal(ret, 0);
    1438           2 :         ret = pipe(to_parent);
    1439           2 :         assert_int_equal(ret, 0);
    1440             :         /*
    1441             :          * Now fork a new process
    1442             :          */
    1443             : 
    1444           2 :         pid = fork();
    1445           4 :         if (pid == 0) {
    1446             : 
    1447           2 :                 struct ldb_context *ldb = NULL;
    1448           2 :                 close(to_child[1]);
    1449           2 :                 close(to_parent[0]);
    1450             : 
    1451             :                 /*
    1452             :                  * Wait for the transaction to be started
    1453             :                  */
    1454           2 :                 ret = read(to_child[0], buf, 2);
    1455           2 :                 if (ret != 2) {
    1456           0 :                         print_error(__location__": read returned (%d)\n",
    1457             :                                     ret);
    1458           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1459             :                 }
    1460             : 
    1461           2 :                 ldb = ldb_init(test_ctx, test_ctx->ev);
    1462           2 :                 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
    1463           2 :                 if (ret != LDB_SUCCESS) {
    1464           0 :                         print_error(__location__": ldb_connect returned (%d)\n",
    1465             :                                     ret);
    1466           0 :                         exit(ret);
    1467             :                 }
    1468             : 
    1469           2 :                 ldb_kv = get_ldb_kv(ldb);
    1470             : 
    1471           2 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1472           2 :                 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           2 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1482           2 :                 key.length = strlen(KEY1) + 1;
    1483             : 
    1484           2 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1485           2 :                 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           2 :                 if ((strlen(VAL1) + 1) != val.length) {
    1493           0 :                         print_error(__location__": KEY1 value lengths different"
    1494             :                                     ", expected (%d) actual(%d)\n",
    1495             :                                     (int)(strlen(VAL1) + 1), (int)val.length);
    1496           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1497             :                 }
    1498           2 :                 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           2 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1511           2 :                 key.length = strlen(KEY2) + 1;
    1512             : 
    1513           2 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1514           2 :                 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           2 :                 if ((strlen(VAL2) + 1) != val.length) {
    1522           0 :                         print_error(__location__": KEY2 value lengths different"
    1523             :                                     ", expected (%d) actual(%d)\n",
    1524             :                                     (int)(strlen(VAL2) + 1), (int)val.length);
    1525           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1526             :                 }
    1527           2 :                 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           2 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1536           2 :                 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           2 :                 ret = write(to_parent[1], "GO", 2);
    1546           2 :                 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 committed
    1554             :                  */
    1555           2 :                 ret = read(to_child[0], buf, 2);
    1556           2 :                 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           2 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1566           2 :                 if (ret != LDB_SUCCESS) {
    1567           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1568             :                                     ret);
    1569           0 :                         exit(ret);
    1570             :                 }
    1571           2 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
    1572           2 :                 key.length = strlen(KEY1) + 1;
    1573             : 
    1574           2 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1575           2 :                 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           2 :                 if ((strlen(VAL1) + 1) != val.length) {
    1583           0 :                         print_error(__location__": KEY1 value lengths different"
    1584             :                                     ", expected (%d) actual(%d)\n",
    1585             :                                     (int)(strlen(VAL1) + 1), (int)val.length);
    1586           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
    1587             :                 }
    1588           2 :                 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           2 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1596           2 :                 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           2 :                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1606           2 :                 key.length = strlen(KEY2 + 1);
    1607             : 
    1608           2 :                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
    1609           2 :                 if (ret != LDB_SUCCESS) {
    1610           0 :                         print_error(__location__": lock_read returned (%d)\n",
    1611             :                                     ret);
    1612           0 :                         exit(ret);
    1613             :                 }
    1614             : 
    1615           2 :                 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
    1616           2 :                 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           2 :                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
    1624           2 :                 if (ret != LDB_SUCCESS) {
    1625           0 :                         print_error(__location__": unlock_read returned (%d)\n",
    1626             :                                     ret);
    1627           0 :                         exit(ret);
    1628             :                 }
    1629           2 :                 TALLOC_FREE(tmp_ctx);
    1630           2 :                 exit(0);
    1631             :         }
    1632           2 :         close(to_child[0]);
    1633           2 :         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           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1640           2 :         assert_int_equal(ret, 0);
    1641             : 
    1642           2 :         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
    1643           2 :         key.length = strlen(KEY2) + 1;
    1644             : 
    1645           2 :         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
    1646           2 :         assert_int_equal(ret, 0);
    1647             :         /*
    1648             :          * Signal the child process
    1649             :          */
    1650           2 :         ret = write(to_child[1], "GO", 2);
    1651           2 :         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           2 :         ret = read(to_parent[0], buf, 2);
    1658           2 :         assert_int_equal(2, ret);
    1659             : 
    1660             :         /*
    1661             :          * commit the transaction
    1662             :          */
    1663           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1664           2 :         assert_int_equal(0, ret);
    1665             : 
    1666             :         /*
    1667             :          * Signal the child process
    1668             :          */
    1669           2 :         ret = write(to_child[1], "GO", 2);
    1670           2 :         assert_int_equal(2, ret);
    1671             : 
    1672           2 :         w_pid = waitpid(pid, &wstatus, 0);
    1673           2 :         assert_int_equal(pid, w_pid);
    1674             : 
    1675           2 :         assert_true(WIFEXITED(wstatus));
    1676             : 
    1677           2 :         assert_int_equal(WEXITSTATUS(wstatus), 0);
    1678             : 
    1679             : 
    1680           2 :         TALLOC_FREE(tmp_ctx);
    1681           2 : }
    1682             : 
    1683             : 
    1684             : /*
    1685             :  * Test that get_size returns a sensible estimate of the number of records
    1686             :  * in the database.
    1687             :  */
    1688           2 : static void test_get_size(void **state)
    1689             : {
    1690           2 :         int ret;
    1691           2 :         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
    1692             :                                                           struct test_ctx);
    1693           2 :         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
    1694           2 :         uint8_t key_val[] = "TheKey";
    1695           2 :         struct ldb_val key = {
    1696             :                 .data   = key_val,
    1697             :                 .length = sizeof(key_val)
    1698             :         };
    1699             : 
    1700           2 :         uint8_t value[] = "The record contents";
    1701           2 :         struct ldb_val data = {
    1702             :                 .data    = value,
    1703             :                 .length = sizeof(value)
    1704             :         };
    1705           2 :         size_t size = 0;
    1706             : 
    1707           2 :         int flags = 0;
    1708           2 :         TALLOC_CTX *tmp_ctx;
    1709             : 
    1710           2 :         tmp_ctx = talloc_new(test_ctx);
    1711           2 :         assert_non_null(tmp_ctx);
    1712             : 
    1713           2 :         size = ldb_kv->kv_ops->get_size(ldb_kv);
    1714             : #if defined(TEST_LMDB)
    1715           1 :         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           2 :         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
    1731           2 :         assert_int_equal(ret, 0);
    1732             : 
    1733             :         /*
    1734             :          * Write the record
    1735             :          */
    1736           2 :         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
    1737           2 :         assert_int_equal(ret, 0);
    1738             : 
    1739             :         /*
    1740             :          * Commit the transaction
    1741             :          */
    1742           2 :         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
    1743           2 :         assert_int_equal(ret, 0);
    1744             : 
    1745           2 :         size = ldb_kv->kv_ops->get_size(ldb_kv);
    1746             : #ifdef TEST_LMDB
    1747           1 :         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           2 :         talloc_free(tmp_ctx);
    1759           2 : }
    1760             : 
    1761           2 : int main(int argc, const char **argv)
    1762             : {
    1763           2 :         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           2 :         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
    1819             : 
    1820           2 :         return cmocka_run_group_tests(tests, NULL, NULL);
    1821             : }

Generated by: LCOV version 1.14