2 * Tests exercising the ldb key value operations.
4 * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
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.
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.
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/>.
23 * These headers or their equivalents should be included prior to
31 * This allows test applications to use custom definitions of C standard
32 * library functions and types.
37 * A KV module is expected to have the following behaviour
39 * - A transaction must be open to perform any read, write or delete operation
40 * - Writes and Deletes should not be visible until a transaction is commited
41 * - Nested transactions are not permitted
42 * - transactions can be rolled back and commited.
43 * - supports iteration over all records in the database
44 * - supports the update_in_iterate operation allowing entries to be
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
60 #include <ldb_module.h>
61 #include <ldb_private.h>
67 #include "ldb_tdb/ldb_tdb.h"
68 #include "ldb_key_value/ldb_kv.h"
71 #define DEFAULT_BE "tdb"
74 #define TEST_BE DEFAULT_BE
81 struct tevent_context *ev;
82 struct ldb_context *ldb;
85 const char *lockfile; /* lockfile is separate */
90 static void unlink_old_db(struct test_ctx *test_ctx)
95 ret = unlink(test_ctx->lockfile);
96 if (ret == -1 && errno != ENOENT) {
101 ret = unlink(test_ctx->dbfile);
102 if (ret == -1 && errno != ENOENT) {
107 static int noconn_setup(void **state)
109 struct test_ctx *test_ctx;
111 test_ctx = talloc_zero(NULL, struct test_ctx);
112 assert_non_null(test_ctx);
114 test_ctx->ev = tevent_context_init(test_ctx);
115 assert_non_null(test_ctx->ev);
117 test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
118 assert_non_null(test_ctx->ldb);
120 test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb");
121 assert_non_null(test_ctx->dbfile);
123 test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
125 assert_non_null(test_ctx->lockfile);
127 test_ctx->dbpath = talloc_asprintf(test_ctx,
128 TEST_BE"://%s", test_ctx->dbfile);
129 assert_non_null(test_ctx->dbpath);
131 unlink_old_db(test_ctx);
136 static int noconn_teardown(void **state)
138 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
141 unlink_old_db(test_ctx);
142 talloc_free(test_ctx);
146 static int setup(void **state)
148 struct test_ctx *test_ctx;
150 struct ldb_ldif *ldif;
151 const char *index_ldif = \
153 "@IDXGUID: objectUUID\n"
154 "@IDX_DN_GUID: GUID\n"
157 noconn_setup((void **) &test_ctx);
159 ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
160 assert_int_equal(ret, 0);
162 while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) {
163 ret = ldb_add(test_ctx->ldb, ldif->msg);
164 assert_int_equal(ret, LDB_SUCCESS);
170 static int teardown(void **state)
172 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
174 noconn_teardown((void **) &test_ctx);
178 static struct ldb_kv_private *get_ldb_kv(struct ldb_context *ldb)
181 struct ldb_kv_private *ldb_kv = NULL;
183 data = ldb_module_get_private(ldb->modules);
184 assert_non_null(data);
186 ldb_kv = talloc_get_type(data, struct ldb_kv_private);
187 assert_non_null(ldb_kv);
192 static int parse(struct ldb_val key,
196 struct ldb_val* read = private_data;
198 /* Yes, we leak this. That is OK */
199 read->data = talloc_size(NULL,
201 assert_non_null(read->data);
203 memcpy(read->data, data.data, data.length);
204 read->length = data.length;
209 * Test that data can be written to the kv store and be read back.
211 static void test_add_get(void **state)
214 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
216 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
217 uint8_t key_val[] = "TheKey";
218 struct ldb_val key = {
220 .length = sizeof(key_val)
223 uint8_t value[] = "The record contents";
224 struct ldb_val data = {
226 .length = sizeof(value)
234 tmp_ctx = talloc_new(test_ctx);
235 assert_non_null(tmp_ctx);
238 * Begin a transaction
240 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
241 assert_int_equal(ret, 0);
246 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
247 assert_int_equal(ret, 0);
250 * Commit the transaction
252 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
253 assert_int_equal(ret, 0);
256 * And now read it back
258 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
259 assert_int_equal(ret, 0);
261 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
262 assert_int_equal(ret, 0);
264 assert_int_equal(sizeof(value), read.length);
265 assert_memory_equal(value, read.data, sizeof(value));
267 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
268 assert_int_equal(ret, 0);
269 talloc_free(tmp_ctx);
273 * Test that attempts to read data without a read transaction fail.
275 static void test_read_outside_transaction(void **state)
278 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
280 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
281 uint8_t key_val[] = "TheKey";
282 struct ldb_val key = {
284 .length = sizeof(key_val)
287 uint8_t value[] = "The record contents";
288 struct ldb_val data = {
290 .length = sizeof(value)
298 tmp_ctx = talloc_new(test_ctx);
299 assert_non_null(tmp_ctx);
302 * Begin a transaction
304 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
305 assert_int_equal(ret, 0);
310 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
311 assert_int_equal(ret, 0);
314 * Commit the transaction
316 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
317 assert_int_equal(ret, 0);
320 * And now read it back
321 * Note there is no read transaction active
323 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
324 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
326 talloc_free(tmp_ctx);
330 * Test that data can be deleted from the kv store
332 static void test_delete(void **state)
335 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
337 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
338 uint8_t key_val[] = "TheKey";
339 struct ldb_val key = {
341 .length = sizeof(key_val)
344 uint8_t value[] = "The record contents";
345 struct ldb_val data = {
347 .length = sizeof(value)
355 tmp_ctx = talloc_new(test_ctx);
356 assert_non_null(tmp_ctx);
359 * Begin a transaction
361 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
362 assert_int_equal(ret, 0);
367 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
368 assert_int_equal(ret, 0);
371 * Commit the transaction
373 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
374 assert_int_equal(ret, 0);
377 * And now read it back
379 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
380 assert_int_equal(ret, 0);
381 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
382 assert_int_equal(ret, 0);
383 assert_int_equal(sizeof(value), read.length);
384 assert_memory_equal(value, read.data, sizeof(value));
385 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
386 assert_int_equal(ret, 0);
389 * Begin a transaction
391 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
392 assert_int_equal(ret, 0);
397 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
398 assert_int_equal(ret, 0);
401 * Commit the transaction
403 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
404 assert_int_equal(ret, 0);
407 * And now try to read it back
409 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
410 assert_int_equal(ret, 0);
411 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
412 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
413 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
414 assert_int_equal(ret, 0);
416 talloc_free(tmp_ctx);
420 * Check that writes are correctly rolled back when a transaction
423 static void test_transaction_abort_write(void **state)
426 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
428 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
429 uint8_t key_val[] = "TheKey";
430 struct ldb_val key = {
432 .length = sizeof(key_val)
435 uint8_t value[] = "The record contents";
436 struct ldb_val data = {
438 .length = sizeof(value)
446 tmp_ctx = talloc_new(test_ctx);
447 assert_non_null(tmp_ctx);
450 * Begin a transaction
452 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
453 assert_int_equal(ret, 0);
458 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
459 assert_int_equal(ret, 0);
462 * And now read it back
464 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
465 assert_int_equal(ret, 0);
466 assert_int_equal(sizeof(value), read.length);
467 assert_memory_equal(value, read.data, sizeof(value));
471 * Now abort the transaction
473 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
474 assert_int_equal(ret, 0);
477 * And now read it back, should not be there
479 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
480 assert_int_equal(ret, 0);
481 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
482 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
483 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
484 assert_int_equal(ret, 0);
486 talloc_free(tmp_ctx);
490 * Check that deletes are correctly rolled back when a transaction is
493 static void test_transaction_abort_delete(void **state)
496 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
498 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
499 uint8_t key_val[] = "TheKey";
500 struct ldb_val key = {
502 .length = sizeof(key_val)
505 uint8_t value[] = "The record contents";
506 struct ldb_val data = {
508 .length = sizeof(value)
516 tmp_ctx = talloc_new(test_ctx);
517 assert_non_null(tmp_ctx);
520 * Begin a transaction
522 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
523 assert_int_equal(ret, 0);
528 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
529 assert_int_equal(ret, 0);
532 * Commit the transaction
534 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
535 assert_int_equal(ret, 0);
538 * And now read it back
540 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
541 assert_int_equal(ret, 0);
542 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
543 assert_int_equal(ret, 0);
544 assert_int_equal(sizeof(value), read.length);
545 assert_memory_equal(value, read.data, sizeof(value));
546 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
547 assert_int_equal(ret, 0);
550 * Begin a transaction
552 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
553 assert_int_equal(ret, 0);
558 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
559 assert_int_equal(ret, 0);
562 * And now read it back
564 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
565 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
568 * Abort the transaction
570 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
571 assert_int_equal(ret, 0);
574 * And now try to read it back
576 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
577 assert_int_equal(ret, 0);
578 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
579 assert_int_equal(ret, 0);
580 assert_int_equal(sizeof(value), read.length);
581 assert_memory_equal(value, read.data, sizeof(value));
582 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
583 assert_int_equal(ret, 0);
585 talloc_free(tmp_ctx);
589 * Test that writes outside a transaction fail
591 static void test_write_outside_transaction(void **state)
594 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
596 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
597 uint8_t key_val[] = "TheKey";
598 struct ldb_val key = {
600 .length = sizeof(key_val)
603 uint8_t value[] = "The record contents";
604 struct ldb_val data = {
606 .length = sizeof(value)
613 tmp_ctx = talloc_new(test_ctx);
614 assert_non_null(tmp_ctx);
617 * Attempt to write the record
619 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
620 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
622 talloc_free(tmp_ctx);
626 * Test data can not be deleted outside a transaction
628 static void test_delete_outside_transaction(void **state)
631 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
633 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
634 uint8_t key_val[] = "TheKey";
635 struct ldb_val key = {
637 .length = sizeof(key_val)
640 uint8_t value[] = "The record contents";
641 struct ldb_val data = {
643 .length = sizeof(value)
651 tmp_ctx = talloc_new(test_ctx);
652 assert_non_null(tmp_ctx);
655 * Begin a transaction
657 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
658 assert_int_equal(ret, 0);
663 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
664 assert_int_equal(ret, 0);
667 * Commit the transaction
669 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
670 assert_int_equal(ret, 0);
673 * And now read it back
675 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
676 assert_int_equal(ret, 0);
677 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
678 assert_int_equal(ret, 0);
679 assert_int_equal(sizeof(value), read.length);
680 assert_memory_equal(value, read.data, sizeof(value));
681 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
682 assert_int_equal(ret, 0);
685 * Now attempt to delete a record
687 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
688 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
691 * And now read it back
693 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
694 assert_int_equal(ret, 0);
695 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
696 assert_int_equal(ret, 0);
697 assert_int_equal(sizeof(value), read.length);
698 assert_memory_equal(value, read.data, sizeof(value));
699 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
700 assert_int_equal(ret, 0);
702 talloc_free(tmp_ctx);
705 static int traverse_fn(struct ldb_kv_private *ldb_kv,
714 if (strncmp("key ", (char *) key.data, 4) == 0) {
715 i = strtol((char *) &key.data[4], NULL, 10);
722 * Test that iterate visits all the records.
724 static void test_iterate(void **state)
727 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
729 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
732 int visits[num_recs];
736 tmp_ctx = talloc_new(test_ctx);
737 assert_non_null(tmp_ctx);
740 * Begin a transaction
742 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
743 assert_int_equal(ret, 0);
748 for (i = 0; i < num_recs; i++) {
754 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
755 key.length = strlen((char *)key.data) + 1;
757 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
758 "data for record (%04d)",
760 rec.length = strlen((char *)rec.data) + 1;
762 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
763 assert_int_equal(ret, 0);
765 TALLOC_FREE(key.data);
766 TALLOC_FREE(rec.data);
770 * Commit the transaction
772 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
773 assert_int_equal(ret, 0);
776 * Now iterate over the kv store and ensure that all the
777 * records are visited.
779 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
780 assert_int_equal(ret, 0);
781 ret = ldb_kv->kv_ops->iterate(ldb_kv, traverse_fn, visits);
782 for (i = 0; i <num_recs; i++) {
783 assert_int_equal(1, visits[i]);
785 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
786 assert_int_equal(ret, 0);
788 TALLOC_FREE(tmp_ctx);
791 static void do_iterate_range_test(void **state, int range_start,
792 int range_end, bool fail)
795 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
797 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
801 int visits[num_recs];
802 struct ldb_val sk, ek;
806 for (i = 0; i < num_recs; i++){
811 * No iterate_range on tdb
813 if (strcmp(TEST_BE, "tdb") == 0) {
817 tmp_ctx = talloc_new(test_ctx);
818 assert_non_null(tmp_ctx);
821 * Begin a transaction
823 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
824 assert_int_equal(ret, 0);
829 for (i = skip_recs; i <= num_recs - skip_recs; i++) {
834 key.data = (uint8_t *)talloc_asprintf(tmp_ctx,
837 key.length = strlen((char *)key.data);
839 rec.data = (uint8_t *)talloc_asprintf(tmp_ctx,
840 "data for record (%04d)",
842 rec.length = strlen((char *)rec.data) + 1;
844 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
845 assert_int_equal(ret, 0);
847 TALLOC_FREE(key.data);
848 TALLOC_FREE(rec.data);
852 * Commit the transaction
854 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
855 assert_int_equal(ret, 0);
857 sk.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_start);
858 sk.length = strlen((char *)sk.data);
860 ek.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_end);
861 ek.length = strlen((char *)ek.data) + 1;
863 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
864 assert_int_equal(ret, 0);
865 ret = ldb_kv->kv_ops->iterate_range(ldb_kv, sk, ek,
866 traverse_fn, visits);
868 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
869 TALLOC_FREE(tmp_ctx);
872 assert_int_equal(ret, 0);
874 for (i = 0; i < num_recs; i++) {
875 if (i >= skip_recs && i <= num_recs - skip_recs &&
876 i >= range_start && i <= range_end){
877 assert_int_equal(1, visits[i]);
879 assert_int_equal(0, visits[i]);
883 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
884 assert_int_equal(ret, 0);
886 TALLOC_FREE(tmp_ctx);
890 * Test that iterate_range visits all the records between two keys.
892 static void test_iterate_range(void **state)
894 do_iterate_range_test(state, 300, 900, false);
897 * test start_key = end_key
899 do_iterate_range_test(state, 20, 20, false);
902 * test reverse range fails
904 do_iterate_range_test(state, 50, 40, true);
907 * keys are between 10-1014 so test with keys outside that range
909 do_iterate_range_test(state, 0, 20, false);
910 do_iterate_range_test(state, 1010, 1030, false);
911 do_iterate_range_test(state, 0, 1030, false);
914 struct update_context {
915 struct ldb_context* ldb;
916 int visits[NUM_RECS];
919 static int update_fn(struct ldb_kv_private *ldb_kv,
925 struct ldb_val new_key;
926 struct ldb_module *module = NULL;
927 struct update_context *context =NULL;
928 int ret = LDB_SUCCESS;
931 tmp_ctx = talloc_new(ldb_kv);
932 assert_non_null(tmp_ctx);
934 context = talloc_get_type_abort(ctx, struct update_context);
936 module = talloc_zero(tmp_ctx, struct ldb_module);
937 module->ldb = context->ldb;
939 if (strncmp("key ", (char *) key.data, 4) == 0) {
940 int i = strtol((char *) &key.data[4], NULL, 10);
941 context->visits[i]++;
942 new_key.data = talloc_memdup(tmp_ctx, key.data, key.length);
943 new_key.length = key.length;
944 new_key.data[0] = 'K';
946 ret = ldb_kv->kv_ops->update_in_iterate(
947 ldb_kv, key, new_key, data, &module);
949 TALLOC_FREE(tmp_ctx);
954 * Test that update_in_iterate behaves as expected.
956 static void test_update_in_iterate(void **state)
959 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
961 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
963 struct update_context *context = NULL;
968 tmp_ctx = talloc_new(test_ctx);
969 assert_non_null(tmp_ctx);
971 context = talloc_zero(tmp_ctx, struct update_context);
972 assert_non_null(context);
973 context->ldb = test_ctx->ldb;
975 * Begin a transaction
977 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
978 assert_int_equal(ret, 0);
983 for (i = 0; i < NUM_RECS; i++) {
988 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
989 key.length = strlen((char *)key.data) + 1;
991 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
992 "data for record (%04d)",
994 rec.length = strlen((char *)rec.data) + 1;
996 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
997 assert_int_equal(ret, 0);
999 TALLOC_FREE(key.data);
1000 TALLOC_FREE(rec.data);
1004 * Commit the transaction
1006 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1007 assert_int_equal(ret, 0);
1010 * Now iterate over the kv store and ensure that all the
1011 * records are visited.
1015 * Needs to be done inside a transaction
1017 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1018 assert_int_equal(ret, 0);
1020 ret = ldb_kv->kv_ops->iterate(ldb_kv, update_fn, context);
1021 for (i = 0; i < NUM_RECS; i++) {
1022 assert_int_equal(1, context->visits[i]);
1025 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1026 assert_int_equal(ret, 0);
1028 TALLOC_FREE(tmp_ctx);
1032 * Ensure that writes are not visible until the transaction has been
1035 static void test_write_transaction_isolation(void **state)
1038 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
1040 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
1044 const char *KEY1 = "KEY01";
1045 const char *VAL1 = "VALUE01";
1047 const char *KEY2 = "KEY02";
1048 const char *VAL2 = "VALUE02";
1051 * Pipes etc to co-ordinate the processes
1059 TALLOC_CTX *tmp_ctx;
1060 tmp_ctx = talloc_new(test_ctx);
1061 assert_non_null(tmp_ctx);
1065 * Add a record to the database
1067 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1068 assert_int_equal(ret, 0);
1070 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1071 key.length = strlen(KEY1) + 1;
1073 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
1074 val.length = strlen(VAL1) + 1;
1076 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1077 assert_int_equal(ret, 0);
1079 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1080 assert_int_equal(ret, 0);
1083 ret = pipe(to_child);
1084 assert_int_equal(ret, 0);
1085 ret = pipe(to_parent);
1086 assert_int_equal(ret, 0);
1088 * Now fork a new process
1094 struct ldb_context *ldb = NULL;
1096 close(to_parent[0]);
1099 * Wait for the transaction to start
1101 ret = read(to_child[0], buf, 2);
1103 print_error(__location__": read returned (%d)\n",
1105 exit(LDB_ERR_OPERATIONS_ERROR);
1107 ldb = ldb_init(test_ctx, test_ctx->ev);
1108 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
1109 if (ret != LDB_SUCCESS) {
1110 print_error(__location__": ldb_connect returned (%d)\n",
1115 ldb_kv = get_ldb_kv(ldb);
1117 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1118 if (ret != LDB_SUCCESS) {
1119 print_error(__location__": lock_read returned (%d)\n",
1125 * Check that KEY1 is there
1127 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1128 key.length = strlen(KEY1) + 1;
1130 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1131 if (ret != LDB_SUCCESS) {
1132 print_error(__location__": fetch_and_parse returned "
1138 if ((strlen(VAL1) + 1) != val.length) {
1139 print_error(__location__": KEY1 value lengths different"
1140 ", expected (%d) actual(%d)\n",
1141 (int)(strlen(VAL1) + 1), (int)val.length);
1142 exit(LDB_ERR_OPERATIONS_ERROR);
1144 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1145 print_error(__location__": KEY1 values different, "
1146 "expected (%s) actual(%s)\n",
1149 exit(LDB_ERR_OPERATIONS_ERROR);
1152 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1153 if (ret != LDB_SUCCESS) {
1154 print_error(__location__": unlock_read returned (%d)\n",
1160 * Check that KEY2 is not there
1162 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1163 key.length = strlen(KEY2 + 1);
1165 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1166 if (ret != LDB_SUCCESS) {
1167 print_error(__location__": lock_read returned (%d)\n",
1172 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1173 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
1174 print_error(__location__": fetch_and_parse returned "
1180 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1181 if (ret != LDB_SUCCESS) {
1182 print_error(__location__": unlock_read returned (%d)\n",
1188 * Signal the other process to commit the transaction
1190 ret = write(to_parent[1], "GO", 2);
1192 print_error(__location__": write returned (%d)\n",
1194 exit(LDB_ERR_OPERATIONS_ERROR);
1198 * Wait for the transaction to be commited
1200 ret = read(to_child[0], buf, 2);
1202 print_error(__location__": read returned (%d)\n",
1204 exit(LDB_ERR_OPERATIONS_ERROR);
1208 * Check that KEY1 is there
1210 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1211 if (ret != LDB_SUCCESS) {
1212 print_error(__location__": unlock_read returned (%d)\n",
1216 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1217 key.length = strlen(KEY1) + 1;
1219 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1220 if (ret != LDB_SUCCESS) {
1221 print_error(__location__": fetch_and_parse returned "
1227 if ((strlen(VAL1) + 1) != val.length) {
1228 print_error(__location__": KEY1 value lengths different"
1229 ", expected (%d) actual(%d)\n",
1230 (int)(strlen(VAL1) + 1), (int)val.length);
1231 exit(LDB_ERR_OPERATIONS_ERROR);
1233 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1234 print_error(__location__": KEY1 values different, "
1235 "expected (%s) actual(%s)\n",
1238 exit(LDB_ERR_OPERATIONS_ERROR);
1241 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1242 if (ret != LDB_SUCCESS) {
1243 print_error(__location__": unlock_read returned (%d)\n",
1250 * Check that KEY2 is there
1252 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1253 if (ret != LDB_SUCCESS) {
1254 print_error(__location__": unlock_read returned (%d)\n",
1259 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1260 key.length = strlen(KEY2) + 1;
1262 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1263 if (ret != LDB_SUCCESS) {
1264 print_error(__location__": fetch_and_parse returned "
1270 if ((strlen(VAL2) + 1) != val.length) {
1271 print_error(__location__": KEY2 value lengths different"
1272 ", expected (%d) actual(%d)\n",
1273 (int)(strlen(VAL2) + 1), (int)val.length);
1274 exit(LDB_ERR_OPERATIONS_ERROR);
1276 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1277 print_error(__location__": KEY2 values different, "
1278 "expected (%s) actual(%s)\n",
1281 exit(LDB_ERR_OPERATIONS_ERROR);
1284 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1285 if (ret != LDB_SUCCESS) {
1286 print_error(__location__": unlock_read returned (%d)\n",
1294 close(to_parent[1]);
1297 * Begin a transaction and add a record to the database
1298 * but leave the transaction open
1300 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1301 assert_int_equal(ret, 0);
1303 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1304 key.length = strlen(KEY2) + 1;
1306 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1307 val.length = strlen(VAL2) + 1;
1309 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1310 assert_int_equal(ret, 0);
1313 * Signal the child process
1315 ret = write(to_child[1], "GO", 2);
1316 assert_int_equal(2, ret);
1319 * Wait for the child process to check the DB state while the
1320 * transaction is active
1322 ret = read(to_parent[0], buf, 2);
1323 assert_int_equal(2, ret);
1326 * commit the transaction
1328 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1329 assert_int_equal(0, ret);
1332 * Signal the child process
1334 ret = write(to_child[1], "GO", 2);
1335 assert_int_equal(2, ret);
1337 w_pid = waitpid(pid, &wstatus, 0);
1338 assert_int_equal(pid, w_pid);
1340 assert_true(WIFEXITED(wstatus));
1342 assert_int_equal(WEXITSTATUS(wstatus), 0);
1345 TALLOC_FREE(tmp_ctx);
1349 * Ensure that deletes are not visible until the transaction has been
1352 static void test_delete_transaction_isolation(void **state)
1355 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
1357 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
1361 const char *KEY1 = "KEY01";
1362 const char *VAL1 = "VALUE01";
1364 const char *KEY2 = "KEY02";
1365 const char *VAL2 = "VALUE02";
1368 * Pipes etc to co-ordinate the processes
1376 TALLOC_CTX *tmp_ctx;
1377 tmp_ctx = talloc_new(test_ctx);
1378 assert_non_null(tmp_ctx);
1382 * Add records to the database
1384 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1385 assert_int_equal(ret, 0);
1387 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1388 key.length = strlen(KEY1) + 1;
1390 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
1391 val.length = strlen(VAL1) + 1;
1393 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1394 assert_int_equal(ret, 0);
1396 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1397 key.length = strlen(KEY2) + 1;
1399 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1400 val.length = strlen(VAL2) + 1;
1402 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1403 assert_int_equal(ret, 0);
1405 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1406 assert_int_equal(ret, 0);
1409 ret = pipe(to_child);
1410 assert_int_equal(ret, 0);
1411 ret = pipe(to_parent);
1412 assert_int_equal(ret, 0);
1414 * Now fork a new process
1420 struct ldb_context *ldb = NULL;
1422 close(to_parent[0]);
1425 * Wait for the transaction to be started
1427 ret = read(to_child[0], buf, 2);
1429 print_error(__location__": read returned (%d)\n",
1431 exit(LDB_ERR_OPERATIONS_ERROR);
1434 ldb = ldb_init(test_ctx, test_ctx->ev);
1435 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
1436 if (ret != LDB_SUCCESS) {
1437 print_error(__location__": ldb_connect returned (%d)\n",
1442 ldb_kv = get_ldb_kv(ldb);
1444 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1445 if (ret != LDB_SUCCESS) {
1446 print_error(__location__": lock_read returned (%d)\n",
1452 * Check that KEY1 is there
1454 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1455 key.length = strlen(KEY1) + 1;
1457 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1458 if (ret != LDB_SUCCESS) {
1459 print_error(__location__": fetch_and_parse returned "
1465 if ((strlen(VAL1) + 1) != val.length) {
1466 print_error(__location__": KEY1 value lengths different"
1467 ", expected (%d) actual(%d)\n",
1468 (int)(strlen(VAL1) + 1), (int)val.length);
1469 exit(LDB_ERR_OPERATIONS_ERROR);
1471 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1472 print_error(__location__": KEY1 values different, "
1473 "expected (%s) actual(%s)\n",
1476 exit(LDB_ERR_OPERATIONS_ERROR);
1480 * Check that KEY2 is there
1483 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1484 key.length = strlen(KEY2) + 1;
1486 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1487 if (ret != LDB_SUCCESS) {
1488 print_error(__location__": fetch_and_parse returned "
1494 if ((strlen(VAL2) + 1) != val.length) {
1495 print_error(__location__": KEY2 value lengths different"
1496 ", expected (%d) actual(%d)\n",
1497 (int)(strlen(VAL2) + 1), (int)val.length);
1498 exit(LDB_ERR_OPERATIONS_ERROR);
1500 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1501 print_error(__location__": KEY2 values different, "
1502 "expected (%s) actual(%s)\n",
1505 exit(LDB_ERR_OPERATIONS_ERROR);
1508 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1509 if (ret != LDB_SUCCESS) {
1510 print_error(__location__": unlock_read returned (%d)\n",
1516 * Signal the other process to commit the transaction
1518 ret = write(to_parent[1], "GO", 2);
1520 print_error(__location__": write returned (%d)\n",
1522 exit(LDB_ERR_OPERATIONS_ERROR);
1526 * Wait for the transaction to be commited
1528 ret = read(to_child[0], buf, 2);
1530 print_error(__location__": read returned (%d)\n",
1532 exit(LDB_ERR_OPERATIONS_ERROR);
1536 * Check that KEY1 is there
1538 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1539 if (ret != LDB_SUCCESS) {
1540 print_error(__location__": unlock_read returned (%d)\n",
1544 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1545 key.length = strlen(KEY1) + 1;
1547 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1548 if (ret != LDB_SUCCESS) {
1549 print_error(__location__": fetch_and_parse returned "
1555 if ((strlen(VAL1) + 1) != val.length) {
1556 print_error(__location__": KEY1 value lengths different"
1557 ", expected (%d) actual(%d)\n",
1558 (int)(strlen(VAL1) + 1), (int)val.length);
1559 exit(LDB_ERR_OPERATIONS_ERROR);
1561 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1562 print_error(__location__": KEY1 values different, "
1563 "expected (%s) actual(%s)\n",
1566 exit(LDB_ERR_OPERATIONS_ERROR);
1570 * Check that KEY2 is not there
1572 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1573 key.length = strlen(KEY2 + 1);
1575 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1576 if (ret != LDB_SUCCESS) {
1577 print_error(__location__": lock_read returned (%d)\n",
1582 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1583 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
1584 print_error(__location__": fetch_and_parse returned "
1590 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1591 if (ret != LDB_SUCCESS) {
1592 print_error(__location__": unlock_read returned (%d)\n",
1600 close(to_parent[1]);
1603 * Begin a transaction and delete a record from the database
1604 * but leave the transaction open
1606 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1607 assert_int_equal(ret, 0);
1609 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1610 key.length = strlen(KEY2) + 1;
1612 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
1613 assert_int_equal(ret, 0);
1615 * Signal the child process
1617 ret = write(to_child[1], "GO", 2);
1618 assert_int_equal(2, ret);
1621 * Wait for the child process to check the DB state while the
1622 * transaction is active
1624 ret = read(to_parent[0], buf, 2);
1625 assert_int_equal(2, ret);
1628 * commit the transaction
1630 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1631 assert_int_equal(0, ret);
1634 * Signal the child process
1636 ret = write(to_child[1], "GO", 2);
1637 assert_int_equal(2, ret);
1639 w_pid = waitpid(pid, &wstatus, 0);
1640 assert_int_equal(pid, w_pid);
1642 assert_true(WIFEXITED(wstatus));
1644 assert_int_equal(WEXITSTATUS(wstatus), 0);
1647 TALLOC_FREE(tmp_ctx);
1652 * Test that get_size returns a sensible estimate of the number of records
1655 static void test_get_size(void **state)
1658 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
1660 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
1661 uint8_t key_val[] = "TheKey";
1662 struct ldb_val key = {
1664 .length = sizeof(key_val)
1667 uint8_t value[] = "The record contents";
1668 struct ldb_val data = {
1670 .length = sizeof(value)
1675 TALLOC_CTX *tmp_ctx;
1677 tmp_ctx = talloc_new(test_ctx);
1678 assert_non_null(tmp_ctx);
1680 size = ldb_kv->kv_ops->get_size(ldb_kv);
1681 #if defined(TEST_LMDB)
1682 assert_int_equal(2, size);
1685 * The tdb implementation of get_size over estimates for sparse files
1686 * which is perfectly acceptable for it's intended use.
1688 assert_true( size > 2500);
1692 * Begin a transaction
1694 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1695 assert_int_equal(ret, 0);
1700 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
1701 assert_int_equal(ret, 0);
1704 * Commit the transaction
1706 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1707 assert_int_equal(ret, 0);
1709 size = ldb_kv->kv_ops->get_size(ldb_kv);
1711 assert_int_equal(3, size);
1713 talloc_free(tmp_ctx);
1716 int main(int argc, const char **argv)
1718 const struct CMUnitTest tests[] = {
1719 cmocka_unit_test_setup_teardown(
1723 cmocka_unit_test_setup_teardown(
1727 cmocka_unit_test_setup_teardown(
1728 test_transaction_abort_write,
1731 cmocka_unit_test_setup_teardown(
1732 test_transaction_abort_delete,
1735 cmocka_unit_test_setup_teardown(
1736 test_read_outside_transaction,
1739 cmocka_unit_test_setup_teardown(
1740 test_write_outside_transaction,
1743 cmocka_unit_test_setup_teardown(
1744 test_delete_outside_transaction,
1747 cmocka_unit_test_setup_teardown(
1751 cmocka_unit_test_setup_teardown(
1755 cmocka_unit_test_setup_teardown(
1756 test_update_in_iterate,
1759 cmocka_unit_test_setup_teardown(
1760 test_write_transaction_isolation,
1763 cmocka_unit_test_setup_teardown(
1764 test_delete_transaction_isolation,
1767 cmocka_unit_test_setup_teardown(
1773 return cmocka_run_group_tests(tests, NULL, NULL);