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
57 #include <ldb_module.h>
58 #include <ldb_private.h>
64 #include "ldb_tdb/ldb_tdb.h"
65 #include "ldb_key_value/ldb_kv.h"
68 #define DEFAULT_BE "tdb"
71 #define TEST_BE DEFAULT_BE
78 struct tevent_context *ev;
79 struct ldb_context *ldb;
82 const char *lockfile; /* lockfile is separate */
87 static void unlink_old_db(struct test_ctx *test_ctx)
92 ret = unlink(test_ctx->lockfile);
93 if (ret == -1 && errno != ENOENT) {
98 ret = unlink(test_ctx->dbfile);
99 if (ret == -1 && errno != ENOENT) {
104 static int noconn_setup(void **state)
106 struct test_ctx *test_ctx;
108 test_ctx = talloc_zero(NULL, struct test_ctx);
109 assert_non_null(test_ctx);
111 test_ctx->ev = tevent_context_init(test_ctx);
112 assert_non_null(test_ctx->ev);
114 test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
115 assert_non_null(test_ctx->ldb);
117 test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb");
118 assert_non_null(test_ctx->dbfile);
120 test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
122 assert_non_null(test_ctx->lockfile);
124 test_ctx->dbpath = talloc_asprintf(test_ctx,
125 TEST_BE"://%s", test_ctx->dbfile);
126 assert_non_null(test_ctx->dbpath);
128 unlink_old_db(test_ctx);
133 static int noconn_teardown(void **state)
135 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
138 unlink_old_db(test_ctx);
139 talloc_free(test_ctx);
143 static int setup(void **state)
145 struct test_ctx *test_ctx;
147 struct ldb_ldif *ldif;
148 const char *index_ldif = \
150 "@IDXGUID: objectUUID\n"
151 "@IDX_DN_GUID: GUID\n"
154 noconn_setup((void **) &test_ctx);
156 ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
157 assert_int_equal(ret, 0);
159 while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) {
160 ret = ldb_add(test_ctx->ldb, ldif->msg);
161 assert_int_equal(ret, LDB_SUCCESS);
167 static int teardown(void **state)
169 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
171 noconn_teardown((void **) &test_ctx);
175 static struct ldb_kv_private *get_ldb_kv(struct ldb_context *ldb)
178 struct ldb_kv_private *ldb_kv = NULL;
180 data = ldb_module_get_private(ldb->modules);
181 assert_non_null(data);
183 ldb_kv = talloc_get_type(data, struct ldb_kv_private);
184 assert_non_null(ldb_kv);
189 static int parse(struct ldb_val key,
193 struct ldb_val* read = private_data;
195 /* Yes, we essentially leak this. That is OK */
196 read->data = talloc_size(talloc_autofree_context(),
198 assert_non_null(read->data);
200 memcpy(read->data, data.data, data.length);
201 read->length = data.length;
206 * Test that data can be written to the kv store and be read back.
208 static void test_add_get(void **state)
211 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
213 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
214 uint8_t key_val[] = "TheKey";
215 struct ldb_val key = {
217 .length = sizeof(key_val)
220 uint8_t value[] = "The record contents";
221 struct ldb_val data = {
223 .length = sizeof(value)
231 tmp_ctx = talloc_new(test_ctx);
232 assert_non_null(tmp_ctx);
235 * Begin a transaction
237 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
238 assert_int_equal(ret, 0);
243 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
244 assert_int_equal(ret, 0);
247 * Commit the transaction
249 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
250 assert_int_equal(ret, 0);
253 * And now read it back
255 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
256 assert_int_equal(ret, 0);
258 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
259 assert_int_equal(ret, 0);
261 assert_int_equal(sizeof(value), read.length);
262 assert_memory_equal(value, read.data, sizeof(value));
264 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
265 assert_int_equal(ret, 0);
266 talloc_free(tmp_ctx);
270 * Test that attempts to read data without a read transaction fail.
272 static void test_read_outside_transaction(void **state)
275 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
277 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
278 uint8_t key_val[] = "TheKey";
279 struct ldb_val key = {
281 .length = sizeof(key_val)
284 uint8_t value[] = "The record contents";
285 struct ldb_val data = {
287 .length = sizeof(value)
295 tmp_ctx = talloc_new(test_ctx);
296 assert_non_null(tmp_ctx);
299 * Begin a transaction
301 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
302 assert_int_equal(ret, 0);
307 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
308 assert_int_equal(ret, 0);
311 * Commit the transaction
313 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
314 assert_int_equal(ret, 0);
317 * And now read it back
318 * Note there is no read transaction active
320 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
321 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
323 talloc_free(tmp_ctx);
327 * Test that data can be deleted from the kv store
329 static void test_delete(void **state)
332 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
334 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
335 uint8_t key_val[] = "TheKey";
336 struct ldb_val key = {
338 .length = sizeof(key_val)
341 uint8_t value[] = "The record contents";
342 struct ldb_val data = {
344 .length = sizeof(value)
352 tmp_ctx = talloc_new(test_ctx);
353 assert_non_null(tmp_ctx);
356 * Begin a transaction
358 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
359 assert_int_equal(ret, 0);
364 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
365 assert_int_equal(ret, 0);
368 * Commit the transaction
370 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
371 assert_int_equal(ret, 0);
374 * And now read it back
376 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
377 assert_int_equal(ret, 0);
378 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
379 assert_int_equal(ret, 0);
380 assert_int_equal(sizeof(value), read.length);
381 assert_memory_equal(value, read.data, sizeof(value));
382 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
383 assert_int_equal(ret, 0);
386 * Begin a transaction
388 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
389 assert_int_equal(ret, 0);
394 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
395 assert_int_equal(ret, 0);
398 * Commit the transaction
400 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
401 assert_int_equal(ret, 0);
404 * And now try to read it back
406 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
407 assert_int_equal(ret, 0);
408 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
409 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
410 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
411 assert_int_equal(ret, 0);
413 talloc_free(tmp_ctx);
417 * Check that writes are correctly rolled back when a transaction
420 static void test_transaction_abort_write(void **state)
423 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
425 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
426 uint8_t key_val[] = "TheKey";
427 struct ldb_val key = {
429 .length = sizeof(key_val)
432 uint8_t value[] = "The record contents";
433 struct ldb_val data = {
435 .length = sizeof(value)
443 tmp_ctx = talloc_new(test_ctx);
444 assert_non_null(tmp_ctx);
447 * Begin a transaction
449 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
450 assert_int_equal(ret, 0);
455 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
456 assert_int_equal(ret, 0);
459 * And now read it back
461 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
462 assert_int_equal(ret, 0);
463 assert_int_equal(sizeof(value), read.length);
464 assert_memory_equal(value, read.data, sizeof(value));
468 * Now abort the transaction
470 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
471 assert_int_equal(ret, 0);
474 * And now read it back, should not be there
476 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
477 assert_int_equal(ret, 0);
478 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
479 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
480 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
481 assert_int_equal(ret, 0);
483 talloc_free(tmp_ctx);
487 * Check that deletes are correctly rolled back when a transaction is
490 static void test_transaction_abort_delete(void **state)
493 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
495 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
496 uint8_t key_val[] = "TheKey";
497 struct ldb_val key = {
499 .length = sizeof(key_val)
502 uint8_t value[] = "The record contents";
503 struct ldb_val data = {
505 .length = sizeof(value)
513 tmp_ctx = talloc_new(test_ctx);
514 assert_non_null(tmp_ctx);
517 * Begin a transaction
519 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
520 assert_int_equal(ret, 0);
525 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
526 assert_int_equal(ret, 0);
529 * Commit the transaction
531 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
532 assert_int_equal(ret, 0);
535 * And now read it back
537 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
538 assert_int_equal(ret, 0);
539 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
540 assert_int_equal(ret, 0);
541 assert_int_equal(sizeof(value), read.length);
542 assert_memory_equal(value, read.data, sizeof(value));
543 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
544 assert_int_equal(ret, 0);
547 * Begin a transaction
549 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
550 assert_int_equal(ret, 0);
555 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
556 assert_int_equal(ret, 0);
559 * And now read it back
561 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
562 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
565 * Abort the transaction
567 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
568 assert_int_equal(ret, 0);
571 * And now try to read it back
573 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
574 assert_int_equal(ret, 0);
575 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
576 assert_int_equal(ret, 0);
577 assert_int_equal(sizeof(value), read.length);
578 assert_memory_equal(value, read.data, sizeof(value));
579 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
580 assert_int_equal(ret, 0);
582 talloc_free(tmp_ctx);
586 * Test that writes outside a transaction fail
588 static void test_write_outside_transaction(void **state)
591 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
593 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
594 uint8_t key_val[] = "TheKey";
595 struct ldb_val key = {
597 .length = sizeof(key_val)
600 uint8_t value[] = "The record contents";
601 struct ldb_val data = {
603 .length = sizeof(value)
610 tmp_ctx = talloc_new(test_ctx);
611 assert_non_null(tmp_ctx);
614 * Attempt to write the record
616 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
617 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
619 talloc_free(tmp_ctx);
623 * Test data can not be deleted outside a transaction
625 static void test_delete_outside_transaction(void **state)
628 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
630 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
631 uint8_t key_val[] = "TheKey";
632 struct ldb_val key = {
634 .length = sizeof(key_val)
637 uint8_t value[] = "The record contents";
638 struct ldb_val data = {
640 .length = sizeof(value)
648 tmp_ctx = talloc_new(test_ctx);
649 assert_non_null(tmp_ctx);
652 * Begin a transaction
654 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
655 assert_int_equal(ret, 0);
660 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
661 assert_int_equal(ret, 0);
664 * Commit the transaction
666 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
667 assert_int_equal(ret, 0);
670 * And now read it back
672 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
673 assert_int_equal(ret, 0);
674 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
675 assert_int_equal(ret, 0);
676 assert_int_equal(sizeof(value), read.length);
677 assert_memory_equal(value, read.data, sizeof(value));
678 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
679 assert_int_equal(ret, 0);
682 * Now attempt to delete a record
684 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
685 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
688 * And now read it back
690 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
691 assert_int_equal(ret, 0);
692 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
693 assert_int_equal(ret, 0);
694 assert_int_equal(sizeof(value), read.length);
695 assert_memory_equal(value, read.data, sizeof(value));
696 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
697 assert_int_equal(ret, 0);
699 talloc_free(tmp_ctx);
702 static int traverse_fn(struct ldb_kv_private *ldb_kv,
711 if (strncmp("key ", (char *) key.data, 4) == 0) {
712 i = strtol((char *) &key.data[4], NULL, 10);
720 * Test that iterate visits all the records.
722 static void test_iterate(void **state)
725 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
727 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
730 int visits[num_recs];
734 tmp_ctx = talloc_new(test_ctx);
735 assert_non_null(tmp_ctx);
738 * Begin a transaction
740 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
741 assert_int_equal(ret, 0);
746 for (i = 0; i < num_recs; i++) {
752 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
753 key.length = strlen((char *)key.data) + 1;
755 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
756 "data for record (%04d)",
758 rec.length = strlen((char *)rec.data) + 1;
760 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
761 assert_int_equal(ret, 0);
763 TALLOC_FREE(key.data);
764 TALLOC_FREE(rec.data);
768 * Commit the transaction
770 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
771 assert_int_equal(ret, 0);
774 * Now iterate over the kv store and ensure that all the
775 * records are visited.
777 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
778 assert_int_equal(ret, 0);
779 ret = ldb_kv->kv_ops->iterate(ldb_kv, traverse_fn, visits);
780 for (i = 0; i <num_recs; i++) {
781 assert_int_equal(1, visits[i]);
783 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
784 assert_int_equal(ret, 0);
786 TALLOC_FREE(tmp_ctx);
789 struct update_context {
790 struct ldb_context* ldb;
791 int visits[NUM_RECS];
794 static int update_fn(struct ldb_kv_private *ldb_kv,
800 struct ldb_val new_key;
801 struct ldb_module *module = NULL;
802 struct update_context *context =NULL;
803 int ret = LDB_SUCCESS;
806 tmp_ctx = talloc_new(ldb_kv);
807 assert_non_null(tmp_ctx);
809 context = talloc_get_type_abort(ctx, struct update_context);
811 module = talloc_zero(tmp_ctx, struct ldb_module);
812 module->ldb = context->ldb;
814 if (strncmp("key ", (char *) key.data, 4) == 0) {
815 int i = strtol((char *) &key.data[4], NULL, 10);
816 context->visits[i]++;
817 new_key.data = talloc_memdup(tmp_ctx, key.data, key.length);
818 new_key.length = key.length;
819 new_key.data[0] = 'K';
821 ret = ldb_kv->kv_ops->update_in_iterate(
822 ldb_kv, key, new_key, data, &module);
824 TALLOC_FREE(tmp_ctx);
829 * Test that update_in_iterate behaves as expected.
831 static void test_update_in_iterate(void **state)
834 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
836 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
838 struct update_context *context = NULL;
843 tmp_ctx = talloc_new(test_ctx);
844 assert_non_null(tmp_ctx);
846 context = talloc_zero(tmp_ctx, struct update_context);
847 assert_non_null(context);
848 context->ldb = test_ctx->ldb;
850 * Begin a transaction
852 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
853 assert_int_equal(ret, 0);
858 for (i = 0; i < NUM_RECS; i++) {
863 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
864 key.length = strlen((char *)key.data) + 1;
866 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
867 "data for record (%04d)",
869 rec.length = strlen((char *)rec.data) + 1;
871 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
872 assert_int_equal(ret, 0);
874 TALLOC_FREE(key.data);
875 TALLOC_FREE(rec.data);
879 * Commit the transaction
881 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
882 assert_int_equal(ret, 0);
885 * Now iterate over the kv store and ensure that all the
886 * records are visited.
890 * Needs to be done inside a transaction
892 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
893 assert_int_equal(ret, 0);
895 ret = ldb_kv->kv_ops->iterate(ldb_kv, update_fn, context);
896 for (i = 0; i < NUM_RECS; i++) {
897 assert_int_equal(1, context->visits[i]);
900 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
901 assert_int_equal(ret, 0);
903 TALLOC_FREE(tmp_ctx);
907 * Ensure that writes are not visible until the transaction has been
910 static void test_write_transaction_isolation(void **state)
913 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
915 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
919 const char *KEY1 = "KEY01";
920 const char *VAL1 = "VALUE01";
922 const char *KEY2 = "KEY02";
923 const char *VAL2 = "VALUE02";
926 * Pipes etc to co-ordinate the processes
935 tmp_ctx = talloc_new(test_ctx);
936 assert_non_null(tmp_ctx);
940 * Add a record to the database
942 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
943 assert_int_equal(ret, 0);
945 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
946 key.length = strlen(KEY1) + 1;
948 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
949 val.length = strlen(VAL1) + 1;
951 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
952 assert_int_equal(ret, 0);
954 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
955 assert_int_equal(ret, 0);
958 ret = pipe(to_child);
959 assert_int_equal(ret, 0);
960 ret = pipe(to_parent);
961 assert_int_equal(ret, 0);
963 * Now fork a new process
969 struct ldb_context *ldb = NULL;
974 * Wait for the transaction to start
976 ret = read(to_child[0], buf, 2);
978 print_error(__location__": read returned (%d)\n",
980 exit(LDB_ERR_OPERATIONS_ERROR);
982 ldb = ldb_init(test_ctx, test_ctx->ev);
983 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
984 if (ret != LDB_SUCCESS) {
985 print_error(__location__": ldb_connect returned (%d)\n",
990 ldb_kv = get_ldb_kv(ldb);
992 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
993 if (ret != LDB_SUCCESS) {
994 print_error(__location__": lock_read returned (%d)\n",
1000 * Check that KEY1 is there
1002 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1003 key.length = strlen(KEY1) + 1;
1005 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1006 if (ret != LDB_SUCCESS) {
1007 print_error(__location__": fetch_and_parse returned "
1013 if ((strlen(VAL1) + 1) != val.length) {
1014 print_error(__location__": KEY1 value lengths different"
1015 ", expected (%d) actual(%d)\n",
1016 (int)(strlen(VAL1) + 1), (int)val.length);
1017 exit(LDB_ERR_OPERATIONS_ERROR);
1019 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1020 print_error(__location__": KEY1 values different, "
1021 "expected (%s) actual(%s)\n",
1024 exit(LDB_ERR_OPERATIONS_ERROR);
1027 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1028 if (ret != LDB_SUCCESS) {
1029 print_error(__location__": unlock_read returned (%d)\n",
1035 * Check that KEY2 is not there
1037 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1038 key.length = strlen(KEY2 + 1);
1040 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1041 if (ret != LDB_SUCCESS) {
1042 print_error(__location__": lock_read returned (%d)\n",
1047 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1048 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
1049 print_error(__location__": fetch_and_parse returned "
1055 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1056 if (ret != LDB_SUCCESS) {
1057 print_error(__location__": unlock_read returned (%d)\n",
1063 * Signal the other process to commit the transaction
1065 ret = write(to_parent[1], "GO", 2);
1067 print_error(__location__": write returned (%d)\n",
1069 exit(LDB_ERR_OPERATIONS_ERROR);
1073 * Wait for the transaction to be commited
1075 ret = read(to_child[0], buf, 2);
1077 print_error(__location__": read returned (%d)\n",
1079 exit(LDB_ERR_OPERATIONS_ERROR);
1083 * Check that KEY1 is there
1085 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1086 if (ret != LDB_SUCCESS) {
1087 print_error(__location__": unlock_read returned (%d)\n",
1091 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1092 key.length = strlen(KEY1) + 1;
1094 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1095 if (ret != LDB_SUCCESS) {
1096 print_error(__location__": fetch_and_parse returned "
1102 if ((strlen(VAL1) + 1) != val.length) {
1103 print_error(__location__": KEY1 value lengths different"
1104 ", expected (%d) actual(%d)\n",
1105 (int)(strlen(VAL1) + 1), (int)val.length);
1106 exit(LDB_ERR_OPERATIONS_ERROR);
1108 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1109 print_error(__location__": KEY1 values different, "
1110 "expected (%s) actual(%s)\n",
1113 exit(LDB_ERR_OPERATIONS_ERROR);
1116 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1117 if (ret != LDB_SUCCESS) {
1118 print_error(__location__": unlock_read returned (%d)\n",
1125 * Check that KEY2 is there
1127 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1128 if (ret != LDB_SUCCESS) {
1129 print_error(__location__": unlock_read returned (%d)\n",
1134 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1135 key.length = strlen(KEY2) + 1;
1137 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1138 if (ret != LDB_SUCCESS) {
1139 print_error(__location__": fetch_and_parse returned "
1145 if ((strlen(VAL2) + 1) != val.length) {
1146 print_error(__location__": KEY2 value lengths different"
1147 ", expected (%d) actual(%d)\n",
1148 (int)(strlen(VAL2) + 1), (int)val.length);
1149 exit(LDB_ERR_OPERATIONS_ERROR);
1151 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1152 print_error(__location__": KEY2 values different, "
1153 "expected (%s) actual(%s)\n",
1156 exit(LDB_ERR_OPERATIONS_ERROR);
1159 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1160 if (ret != LDB_SUCCESS) {
1161 print_error(__location__": unlock_read returned (%d)\n",
1169 close(to_parent[1]);
1172 * Begin a transaction and add a record to the database
1173 * but leave the transaction open
1175 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1176 assert_int_equal(ret, 0);
1178 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1179 key.length = strlen(KEY2) + 1;
1181 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1182 val.length = strlen(VAL2) + 1;
1184 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1185 assert_int_equal(ret, 0);
1188 * Signal the child process
1190 ret = write(to_child[1], "GO", 2);
1191 assert_int_equal(2, ret);
1194 * Wait for the child process to check the DB state while the
1195 * transaction is active
1197 ret = read(to_parent[0], buf, 2);
1198 assert_int_equal(2, ret);
1201 * commit the transaction
1203 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1204 assert_int_equal(0, ret);
1207 * Signal the child process
1209 ret = write(to_child[1], "GO", 2);
1210 assert_int_equal(2, ret);
1212 w_pid = waitpid(pid, &wstatus, 0);
1213 assert_int_equal(pid, w_pid);
1215 assert_true(WIFEXITED(wstatus));
1217 assert_int_equal(WEXITSTATUS(wstatus), 0);
1220 TALLOC_FREE(tmp_ctx);
1224 * Ensure that deletes are not visible until the transaction has been
1227 static void test_delete_transaction_isolation(void **state)
1230 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
1232 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
1236 const char *KEY1 = "KEY01";
1237 const char *VAL1 = "VALUE01";
1239 const char *KEY2 = "KEY02";
1240 const char *VAL2 = "VALUE02";
1243 * Pipes etc to co-ordinate the processes
1251 TALLOC_CTX *tmp_ctx;
1252 tmp_ctx = talloc_new(test_ctx);
1253 assert_non_null(tmp_ctx);
1257 * Add records to the database
1259 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1260 assert_int_equal(ret, 0);
1262 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1263 key.length = strlen(KEY1) + 1;
1265 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
1266 val.length = strlen(VAL1) + 1;
1268 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1269 assert_int_equal(ret, 0);
1271 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1272 key.length = strlen(KEY2) + 1;
1274 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1275 val.length = strlen(VAL2) + 1;
1277 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1278 assert_int_equal(ret, 0);
1280 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1281 assert_int_equal(ret, 0);
1284 ret = pipe(to_child);
1285 assert_int_equal(ret, 0);
1286 ret = pipe(to_parent);
1287 assert_int_equal(ret, 0);
1289 * Now fork a new process
1295 struct ldb_context *ldb = NULL;
1297 close(to_parent[0]);
1300 * Wait for the transaction to be started
1302 ret = read(to_child[0], buf, 2);
1304 print_error(__location__": read returned (%d)\n",
1306 exit(LDB_ERR_OPERATIONS_ERROR);
1309 ldb = ldb_init(test_ctx, test_ctx->ev);
1310 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
1311 if (ret != LDB_SUCCESS) {
1312 print_error(__location__": ldb_connect returned (%d)\n",
1317 ldb_kv = get_ldb_kv(ldb);
1319 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1320 if (ret != LDB_SUCCESS) {
1321 print_error(__location__": lock_read returned (%d)\n",
1327 * Check that KEY1 is there
1329 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1330 key.length = strlen(KEY1) + 1;
1332 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1333 if (ret != LDB_SUCCESS) {
1334 print_error(__location__": fetch_and_parse returned "
1340 if ((strlen(VAL1) + 1) != val.length) {
1341 print_error(__location__": KEY1 value lengths different"
1342 ", expected (%d) actual(%d)\n",
1343 (int)(strlen(VAL1) + 1), (int)val.length);
1344 exit(LDB_ERR_OPERATIONS_ERROR);
1346 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1347 print_error(__location__": KEY1 values different, "
1348 "expected (%s) actual(%s)\n",
1351 exit(LDB_ERR_OPERATIONS_ERROR);
1355 * Check that KEY2 is there
1358 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1359 key.length = strlen(KEY2) + 1;
1361 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1362 if (ret != LDB_SUCCESS) {
1363 print_error(__location__": fetch_and_parse returned "
1369 if ((strlen(VAL2) + 1) != val.length) {
1370 print_error(__location__": KEY2 value lengths different"
1371 ", expected (%d) actual(%d)\n",
1372 (int)(strlen(VAL2) + 1), (int)val.length);
1373 exit(LDB_ERR_OPERATIONS_ERROR);
1375 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1376 print_error(__location__": KEY2 values different, "
1377 "expected (%s) actual(%s)\n",
1380 exit(LDB_ERR_OPERATIONS_ERROR);
1383 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1384 if (ret != LDB_SUCCESS) {
1385 print_error(__location__": unlock_read returned (%d)\n",
1391 * Signal the other process to commit the transaction
1393 ret = write(to_parent[1], "GO", 2);
1395 print_error(__location__": write returned (%d)\n",
1397 exit(LDB_ERR_OPERATIONS_ERROR);
1401 * Wait for the transaction to be commited
1403 ret = read(to_child[0], buf, 2);
1405 print_error(__location__": read returned (%d)\n",
1407 exit(LDB_ERR_OPERATIONS_ERROR);
1411 * Check that KEY1 is there
1413 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1414 if (ret != LDB_SUCCESS) {
1415 print_error(__location__": unlock_read returned (%d)\n",
1419 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1420 key.length = strlen(KEY1) + 1;
1422 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1423 if (ret != LDB_SUCCESS) {
1424 print_error(__location__": fetch_and_parse returned "
1430 if ((strlen(VAL1) + 1) != val.length) {
1431 print_error(__location__": KEY1 value lengths different"
1432 ", expected (%d) actual(%d)\n",
1433 (int)(strlen(VAL1) + 1), (int)val.length);
1434 exit(LDB_ERR_OPERATIONS_ERROR);
1436 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1437 print_error(__location__": KEY1 values different, "
1438 "expected (%s) actual(%s)\n",
1441 exit(LDB_ERR_OPERATIONS_ERROR);
1445 * Check that KEY2 is not there
1447 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1448 key.length = strlen(KEY2 + 1);
1450 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1451 if (ret != LDB_SUCCESS) {
1452 print_error(__location__": lock_read returned (%d)\n",
1457 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1458 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
1459 print_error(__location__": fetch_and_parse returned "
1465 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1466 if (ret != LDB_SUCCESS) {
1467 print_error(__location__": unlock_read returned (%d)\n",
1475 close(to_parent[1]);
1478 * Begin a transaction and delete a record from the database
1479 * but leave the transaction open
1481 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1482 assert_int_equal(ret, 0);
1484 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1485 key.length = strlen(KEY2) + 1;
1487 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
1488 assert_int_equal(ret, 0);
1490 * Signal the child process
1492 ret = write(to_child[1], "GO", 2);
1493 assert_int_equal(2, ret);
1496 * Wait for the child process to check the DB state while the
1497 * transaction is active
1499 ret = read(to_parent[0], buf, 2);
1500 assert_int_equal(2, ret);
1503 * commit the transaction
1505 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1506 assert_int_equal(0, ret);
1509 * Signal the child process
1511 ret = write(to_child[1], "GO", 2);
1512 assert_int_equal(2, ret);
1514 w_pid = waitpid(pid, &wstatus, 0);
1515 assert_int_equal(pid, w_pid);
1517 assert_true(WIFEXITED(wstatus));
1519 assert_int_equal(WEXITSTATUS(wstatus), 0);
1522 TALLOC_FREE(tmp_ctx);
1526 int main(int argc, const char **argv)
1528 const struct CMUnitTest tests[] = {
1529 cmocka_unit_test_setup_teardown(
1533 cmocka_unit_test_setup_teardown(
1537 cmocka_unit_test_setup_teardown(
1538 test_transaction_abort_write,
1541 cmocka_unit_test_setup_teardown(
1542 test_transaction_abort_delete,
1545 cmocka_unit_test_setup_teardown(
1546 test_read_outside_transaction,
1549 cmocka_unit_test_setup_teardown(
1550 test_write_outside_transaction,
1553 cmocka_unit_test_setup_teardown(
1554 test_delete_outside_transaction,
1557 cmocka_unit_test_setup_teardown(
1561 cmocka_unit_test_setup_teardown(
1562 test_update_in_iterate,
1565 cmocka_unit_test_setup_teardown(
1566 test_write_transaction_isolation,
1569 cmocka_unit_test_setup_teardown(
1570 test_delete_transaction_isolation,
1575 return cmocka_run_group_tests(tests, NULL, NULL);