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"
67 #define DEFAULT_BE "tdb"
70 #define TEST_BE DEFAULT_BE
77 struct tevent_context *ev;
78 struct ldb_context *ldb;
81 const char *lockfile; /* lockfile is separate */
86 static void unlink_old_db(struct test_ctx *test_ctx)
91 ret = unlink(test_ctx->lockfile);
92 if (ret == -1 && errno != ENOENT) {
97 ret = unlink(test_ctx->dbfile);
98 if (ret == -1 && errno != ENOENT) {
103 static int noconn_setup(void **state)
105 struct test_ctx *test_ctx;
107 test_ctx = talloc_zero(NULL, struct test_ctx);
108 assert_non_null(test_ctx);
110 test_ctx->ev = tevent_context_init(test_ctx);
111 assert_non_null(test_ctx->ev);
113 test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
114 assert_non_null(test_ctx->ldb);
116 test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb");
117 assert_non_null(test_ctx->dbfile);
119 test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
121 assert_non_null(test_ctx->lockfile);
123 test_ctx->dbpath = talloc_asprintf(test_ctx,
124 TEST_BE"://%s", test_ctx->dbfile);
125 assert_non_null(test_ctx->dbpath);
127 unlink_old_db(test_ctx);
132 static int noconn_teardown(void **state)
134 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
137 unlink_old_db(test_ctx);
138 talloc_free(test_ctx);
142 static int setup(void **state)
144 struct test_ctx *test_ctx;
146 struct ldb_ldif *ldif;
147 const char *index_ldif = \
149 "@IDXGUID: objectUUID\n"
150 "@IDX_DN_GUID: GUID\n"
153 noconn_setup((void **) &test_ctx);
155 ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
156 assert_int_equal(ret, 0);
158 while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) {
159 ret = ldb_add(test_ctx->ldb, ldif->msg);
160 assert_int_equal(ret, LDB_SUCCESS);
166 static int teardown(void **state)
168 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
170 noconn_teardown((void **) &test_ctx);
174 static struct ldb_kv_private *get_ldb_kv(struct ldb_context *ldb)
177 struct ldb_kv_private *ldb_kv = NULL;
179 data = ldb_module_get_private(ldb->modules);
180 assert_non_null(data);
182 ldb_kv = talloc_get_type(data, struct ldb_kv_private);
183 assert_non_null(ldb_kv);
188 static int parse(struct ldb_val key,
192 struct ldb_val* read = private_data;
194 /* Yes, we essentially leak this. That is OK */
195 read->data = talloc_size(talloc_autofree_context(),
197 assert_non_null(read->data);
199 memcpy(read->data, data.data, data.length);
200 read->length = data.length;
205 * Test that data can be written to the kv store and be read back.
207 static void test_add_get(void **state)
210 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
212 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
213 uint8_t key_val[] = "TheKey";
214 struct ldb_val key = {
216 .length = sizeof(key_val)
219 uint8_t value[] = "The record contents";
220 struct ldb_val data = {
222 .length = sizeof(value)
230 tmp_ctx = talloc_new(test_ctx);
231 assert_non_null(tmp_ctx);
234 * Begin a transaction
236 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
237 assert_int_equal(ret, 0);
242 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
243 assert_int_equal(ret, 0);
246 * Commit the transaction
248 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
249 assert_int_equal(ret, 0);
252 * And now read it back
254 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
255 assert_int_equal(ret, 0);
257 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
258 assert_int_equal(ret, 0);
260 assert_int_equal(sizeof(value), read.length);
261 assert_memory_equal(value, read.data, sizeof(value));
263 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
264 assert_int_equal(ret, 0);
265 talloc_free(tmp_ctx);
269 * Test that attempts to read data without a read transaction fail.
271 static void test_read_outside_transaction(void **state)
274 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
276 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
277 uint8_t key_val[] = "TheKey";
278 struct ldb_val key = {
280 .length = sizeof(key_val)
283 uint8_t value[] = "The record contents";
284 struct ldb_val data = {
286 .length = sizeof(value)
294 tmp_ctx = talloc_new(test_ctx);
295 assert_non_null(tmp_ctx);
298 * Begin a transaction
300 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
301 assert_int_equal(ret, 0);
306 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
307 assert_int_equal(ret, 0);
310 * Commit the transaction
312 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
313 assert_int_equal(ret, 0);
316 * And now read it back
317 * Note there is no read transaction active
319 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
320 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
322 talloc_free(tmp_ctx);
326 * Test that data can be deleted from the kv store
328 static void test_delete(void **state)
331 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
333 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
334 uint8_t key_val[] = "TheKey";
335 struct ldb_val key = {
337 .length = sizeof(key_val)
340 uint8_t value[] = "The record contents";
341 struct ldb_val data = {
343 .length = sizeof(value)
351 tmp_ctx = talloc_new(test_ctx);
352 assert_non_null(tmp_ctx);
355 * Begin a transaction
357 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
358 assert_int_equal(ret, 0);
363 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
364 assert_int_equal(ret, 0);
367 * Commit the transaction
369 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
370 assert_int_equal(ret, 0);
373 * And now read it back
375 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
376 assert_int_equal(ret, 0);
377 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
378 assert_int_equal(ret, 0);
379 assert_int_equal(sizeof(value), read.length);
380 assert_memory_equal(value, read.data, sizeof(value));
381 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
382 assert_int_equal(ret, 0);
385 * Begin a transaction
387 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
388 assert_int_equal(ret, 0);
393 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
394 assert_int_equal(ret, 0);
397 * Commit the transaction
399 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
400 assert_int_equal(ret, 0);
403 * And now try to read it back
405 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
406 assert_int_equal(ret, 0);
407 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
408 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
409 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
410 assert_int_equal(ret, 0);
412 talloc_free(tmp_ctx);
416 * Check that writes are correctly rolled back when a transaction
419 static void test_transaction_abort_write(void **state)
422 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
424 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
425 uint8_t key_val[] = "TheKey";
426 struct ldb_val key = {
428 .length = sizeof(key_val)
431 uint8_t value[] = "The record contents";
432 struct ldb_val data = {
434 .length = sizeof(value)
442 tmp_ctx = talloc_new(test_ctx);
443 assert_non_null(tmp_ctx);
446 * Begin a transaction
448 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
449 assert_int_equal(ret, 0);
454 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
455 assert_int_equal(ret, 0);
458 * And now read it back
460 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
461 assert_int_equal(ret, 0);
462 assert_int_equal(sizeof(value), read.length);
463 assert_memory_equal(value, read.data, sizeof(value));
467 * Now abort the transaction
469 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
470 assert_int_equal(ret, 0);
473 * And now read it back, should not be there
475 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
476 assert_int_equal(ret, 0);
477 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
478 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
479 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
480 assert_int_equal(ret, 0);
482 talloc_free(tmp_ctx);
486 * Check that deletes are correctly rolled back when a transaction is
489 static void test_transaction_abort_delete(void **state)
492 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
494 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
495 uint8_t key_val[] = "TheKey";
496 struct ldb_val key = {
498 .length = sizeof(key_val)
501 uint8_t value[] = "The record contents";
502 struct ldb_val data = {
504 .length = sizeof(value)
512 tmp_ctx = talloc_new(test_ctx);
513 assert_non_null(tmp_ctx);
516 * Begin a transaction
518 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
519 assert_int_equal(ret, 0);
524 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
525 assert_int_equal(ret, 0);
528 * Commit the transaction
530 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
531 assert_int_equal(ret, 0);
534 * And now read it back
536 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
537 assert_int_equal(ret, 0);
538 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
539 assert_int_equal(ret, 0);
540 assert_int_equal(sizeof(value), read.length);
541 assert_memory_equal(value, read.data, sizeof(value));
542 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
543 assert_int_equal(ret, 0);
546 * Begin a transaction
548 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
549 assert_int_equal(ret, 0);
554 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
555 assert_int_equal(ret, 0);
558 * And now read it back
560 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
561 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
564 * Abort the transaction
566 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
567 assert_int_equal(ret, 0);
570 * And now try to read it back
572 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
573 assert_int_equal(ret, 0);
574 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
575 assert_int_equal(ret, 0);
576 assert_int_equal(sizeof(value), read.length);
577 assert_memory_equal(value, read.data, sizeof(value));
578 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
579 assert_int_equal(ret, 0);
581 talloc_free(tmp_ctx);
585 * Test that writes outside a transaction fail
587 static void test_write_outside_transaction(void **state)
590 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
592 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
593 uint8_t key_val[] = "TheKey";
594 struct ldb_val key = {
596 .length = sizeof(key_val)
599 uint8_t value[] = "The record contents";
600 struct ldb_val data = {
602 .length = sizeof(value)
609 tmp_ctx = talloc_new(test_ctx);
610 assert_non_null(tmp_ctx);
613 * Attempt to write the record
615 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
616 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
618 talloc_free(tmp_ctx);
622 * Test data can not be deleted outside a transaction
624 static void test_delete_outside_transaction(void **state)
627 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
629 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
630 uint8_t key_val[] = "TheKey";
631 struct ldb_val key = {
633 .length = sizeof(key_val)
636 uint8_t value[] = "The record contents";
637 struct ldb_val data = {
639 .length = sizeof(value)
647 tmp_ctx = talloc_new(test_ctx);
648 assert_non_null(tmp_ctx);
651 * Begin a transaction
653 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
654 assert_int_equal(ret, 0);
659 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
660 assert_int_equal(ret, 0);
663 * Commit the transaction
665 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
666 assert_int_equal(ret, 0);
669 * And now read it back
671 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
672 assert_int_equal(ret, 0);
673 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
674 assert_int_equal(ret, 0);
675 assert_int_equal(sizeof(value), read.length);
676 assert_memory_equal(value, read.data, sizeof(value));
677 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
678 assert_int_equal(ret, 0);
681 * Now attempt to delete a record
683 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
684 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
687 * And now read it back
689 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
690 assert_int_equal(ret, 0);
691 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
692 assert_int_equal(ret, 0);
693 assert_int_equal(sizeof(value), read.length);
694 assert_memory_equal(value, read.data, sizeof(value));
695 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
696 assert_int_equal(ret, 0);
698 talloc_free(tmp_ctx);
701 static int traverse_fn(struct ldb_kv_private *ldb_kv,
710 if (strncmp("key ", (char *) key.data, 4) == 0) {
711 i = strtol((char *) &key.data[4], NULL, 10);
719 * Test that iterate visits all the records.
721 static void test_iterate(void **state)
724 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
726 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
729 int visits[num_recs];
733 tmp_ctx = talloc_new(test_ctx);
734 assert_non_null(tmp_ctx);
737 * Begin a transaction
739 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
740 assert_int_equal(ret, 0);
745 for (i = 0; i < num_recs; i++) {
751 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
752 key.length = strlen((char *)key.data) + 1;
754 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
755 "data for record (%04d)",
757 rec.length = strlen((char *)rec.data) + 1;
759 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
760 assert_int_equal(ret, 0);
762 TALLOC_FREE(key.data);
763 TALLOC_FREE(rec.data);
767 * Commit the transaction
769 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
770 assert_int_equal(ret, 0);
773 * Now iterate over the kv store and ensure that all the
774 * records are visited.
776 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
777 assert_int_equal(ret, 0);
778 ret = ldb_kv->kv_ops->iterate(ldb_kv, traverse_fn, visits);
779 for (i = 0; i <num_recs; i++) {
780 assert_int_equal(1, visits[i]);
782 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
783 assert_int_equal(ret, 0);
785 TALLOC_FREE(tmp_ctx);
788 struct update_context {
789 struct ldb_context* ldb;
790 int visits[NUM_RECS];
793 static int update_fn(struct ldb_kv_private *ldb_kv,
799 struct ldb_val new_key;
800 struct ldb_module *module = NULL;
801 struct update_context *context =NULL;
802 int ret = LDB_SUCCESS;
805 tmp_ctx = talloc_new(ldb_kv);
806 assert_non_null(tmp_ctx);
808 context = talloc_get_type_abort(ctx, struct update_context);
810 module = talloc_zero(tmp_ctx, struct ldb_module);
811 module->ldb = context->ldb;
813 if (strncmp("key ", (char *) key.data, 4) == 0) {
814 int i = strtol((char *) &key.data[4], NULL, 10);
815 context->visits[i]++;
816 new_key.data = talloc_memdup(tmp_ctx, key.data, key.length);
817 new_key.length = key.length;
818 new_key.data[0] = 'K';
820 ret = ldb_kv->kv_ops->update_in_iterate(
821 ldb_kv, key, new_key, data, &module);
823 TALLOC_FREE(tmp_ctx);
828 * Test that update_in_iterate behaves as expected.
830 static void test_update_in_iterate(void **state)
833 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
835 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
837 struct update_context *context = NULL;
842 tmp_ctx = talloc_new(test_ctx);
843 assert_non_null(tmp_ctx);
845 context = talloc_zero(tmp_ctx, struct update_context);
846 assert_non_null(context);
847 context->ldb = test_ctx->ldb;
849 * Begin a transaction
851 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
852 assert_int_equal(ret, 0);
857 for (i = 0; i < NUM_RECS; i++) {
862 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
863 key.length = strlen((char *)key.data) + 1;
865 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
866 "data for record (%04d)",
868 rec.length = strlen((char *)rec.data) + 1;
870 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
871 assert_int_equal(ret, 0);
873 TALLOC_FREE(key.data);
874 TALLOC_FREE(rec.data);
878 * Commit the transaction
880 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
881 assert_int_equal(ret, 0);
884 * Now iterate over the kv store and ensure that all the
885 * records are visited.
889 * Needs to be done inside a transaction
891 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
892 assert_int_equal(ret, 0);
894 ret = ldb_kv->kv_ops->iterate(ldb_kv, update_fn, context);
895 for (i = 0; i < NUM_RECS; i++) {
896 assert_int_equal(1, context->visits[i]);
899 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
900 assert_int_equal(ret, 0);
902 TALLOC_FREE(tmp_ctx);
906 * Ensure that writes are not visible until the transaction has been
909 static void test_write_transaction_isolation(void **state)
912 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
914 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
918 const char *KEY1 = "KEY01";
919 const char *VAL1 = "VALUE01";
921 const char *KEY2 = "KEY02";
922 const char *VAL2 = "VALUE02";
925 * Pipes etc to co-ordinate the processes
934 tmp_ctx = talloc_new(test_ctx);
935 assert_non_null(tmp_ctx);
939 * Add a record to the database
941 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
942 assert_int_equal(ret, 0);
944 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
945 key.length = strlen(KEY1) + 1;
947 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
948 val.length = strlen(VAL1) + 1;
950 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
951 assert_int_equal(ret, 0);
953 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
954 assert_int_equal(ret, 0);
957 ret = pipe(to_child);
958 assert_int_equal(ret, 0);
959 ret = pipe(to_parent);
960 assert_int_equal(ret, 0);
962 * Now fork a new process
968 struct ldb_context *ldb = NULL;
973 * Wait for the transaction to start
975 ret = read(to_child[0], buf, 2);
977 print_error(__location__": read returned (%d)\n",
979 exit(LDB_ERR_OPERATIONS_ERROR);
981 ldb = ldb_init(test_ctx, test_ctx->ev);
982 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
983 if (ret != LDB_SUCCESS) {
984 print_error(__location__": ldb_connect returned (%d)\n",
989 ldb_kv = get_ldb_kv(ldb);
991 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
992 if (ret != LDB_SUCCESS) {
993 print_error(__location__": lock_read returned (%d)\n",
999 * Check that KEY1 is there
1001 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1002 key.length = strlen(KEY1) + 1;
1004 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1005 if (ret != LDB_SUCCESS) {
1006 print_error(__location__": fetch_and_parse returned "
1012 if ((strlen(VAL1) + 1) != val.length) {
1013 print_error(__location__": KEY1 value lengths different"
1014 ", expected (%d) actual(%d)\n",
1015 (int)(strlen(VAL1) + 1), (int)val.length);
1016 exit(LDB_ERR_OPERATIONS_ERROR);
1018 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1019 print_error(__location__": KEY1 values different, "
1020 "expected (%s) actual(%s)\n",
1023 exit(LDB_ERR_OPERATIONS_ERROR);
1026 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1027 if (ret != LDB_SUCCESS) {
1028 print_error(__location__": unlock_read returned (%d)\n",
1034 * Check that KEY2 is not there
1036 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1037 key.length = strlen(KEY2 + 1);
1039 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1040 if (ret != LDB_SUCCESS) {
1041 print_error(__location__": lock_read returned (%d)\n",
1046 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1047 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
1048 print_error(__location__": fetch_and_parse returned "
1054 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1055 if (ret != LDB_SUCCESS) {
1056 print_error(__location__": unlock_read returned (%d)\n",
1062 * Signal the other process to commit the transaction
1064 ret = write(to_parent[1], "GO", 2);
1066 print_error(__location__": write returned (%d)\n",
1068 exit(LDB_ERR_OPERATIONS_ERROR);
1072 * Wait for the transaction to be commited
1074 ret = read(to_child[0], buf, 2);
1076 print_error(__location__": read returned (%d)\n",
1078 exit(LDB_ERR_OPERATIONS_ERROR);
1082 * Check that KEY1 is there
1084 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1085 if (ret != LDB_SUCCESS) {
1086 print_error(__location__": unlock_read returned (%d)\n",
1090 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1091 key.length = strlen(KEY1) + 1;
1093 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1094 if (ret != LDB_SUCCESS) {
1095 print_error(__location__": fetch_and_parse returned "
1101 if ((strlen(VAL1) + 1) != val.length) {
1102 print_error(__location__": KEY1 value lengths different"
1103 ", expected (%d) actual(%d)\n",
1104 (int)(strlen(VAL1) + 1), (int)val.length);
1105 exit(LDB_ERR_OPERATIONS_ERROR);
1107 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1108 print_error(__location__": KEY1 values different, "
1109 "expected (%s) actual(%s)\n",
1112 exit(LDB_ERR_OPERATIONS_ERROR);
1115 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1116 if (ret != LDB_SUCCESS) {
1117 print_error(__location__": unlock_read returned (%d)\n",
1124 * Check that KEY2 is there
1126 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1127 if (ret != LDB_SUCCESS) {
1128 print_error(__location__": unlock_read returned (%d)\n",
1133 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1134 key.length = strlen(KEY2) + 1;
1136 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1137 if (ret != LDB_SUCCESS) {
1138 print_error(__location__": fetch_and_parse returned "
1144 if ((strlen(VAL2) + 1) != val.length) {
1145 print_error(__location__": KEY2 value lengths different"
1146 ", expected (%d) actual(%d)\n",
1147 (int)(strlen(VAL2) + 1), (int)val.length);
1148 exit(LDB_ERR_OPERATIONS_ERROR);
1150 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1151 print_error(__location__": KEY2 values different, "
1152 "expected (%s) actual(%s)\n",
1155 exit(LDB_ERR_OPERATIONS_ERROR);
1158 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1159 if (ret != LDB_SUCCESS) {
1160 print_error(__location__": unlock_read returned (%d)\n",
1168 close(to_parent[1]);
1171 * Begin a transaction and add a record to the database
1172 * but leave the transaction open
1174 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1175 assert_int_equal(ret, 0);
1177 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1178 key.length = strlen(KEY2) + 1;
1180 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1181 val.length = strlen(VAL2) + 1;
1183 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1184 assert_int_equal(ret, 0);
1187 * Signal the child process
1189 ret = write(to_child[1], "GO", 2);
1190 assert_int_equal(2, ret);
1193 * Wait for the child process to check the DB state while the
1194 * transaction is active
1196 ret = read(to_parent[0], buf, 2);
1197 assert_int_equal(2, ret);
1200 * commit the transaction
1202 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1203 assert_int_equal(0, ret);
1206 * Signal the child process
1208 ret = write(to_child[1], "GO", 2);
1209 assert_int_equal(2, ret);
1211 w_pid = waitpid(pid, &wstatus, 0);
1212 assert_int_equal(pid, w_pid);
1214 assert_true(WIFEXITED(wstatus));
1216 assert_int_equal(WEXITSTATUS(wstatus), 0);
1219 TALLOC_FREE(tmp_ctx);
1223 * Ensure that deletes are not visible until the transaction has been
1226 static void test_delete_transaction_isolation(void **state)
1229 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
1231 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
1235 const char *KEY1 = "KEY01";
1236 const char *VAL1 = "VALUE01";
1238 const char *KEY2 = "KEY02";
1239 const char *VAL2 = "VALUE02";
1242 * Pipes etc to co-ordinate the processes
1250 TALLOC_CTX *tmp_ctx;
1251 tmp_ctx = talloc_new(test_ctx);
1252 assert_non_null(tmp_ctx);
1256 * Add records to the database
1258 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1259 assert_int_equal(ret, 0);
1261 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1262 key.length = strlen(KEY1) + 1;
1264 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
1265 val.length = strlen(VAL1) + 1;
1267 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1268 assert_int_equal(ret, 0);
1270 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1271 key.length = strlen(KEY2) + 1;
1273 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1274 val.length = strlen(VAL2) + 1;
1276 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1277 assert_int_equal(ret, 0);
1279 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1280 assert_int_equal(ret, 0);
1283 ret = pipe(to_child);
1284 assert_int_equal(ret, 0);
1285 ret = pipe(to_parent);
1286 assert_int_equal(ret, 0);
1288 * Now fork a new process
1294 struct ldb_context *ldb = NULL;
1296 close(to_parent[0]);
1299 * Wait for the transaction to be started
1301 ret = read(to_child[0], buf, 2);
1303 print_error(__location__": read returned (%d)\n",
1305 exit(LDB_ERR_OPERATIONS_ERROR);
1308 ldb = ldb_init(test_ctx, test_ctx->ev);
1309 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
1310 if (ret != LDB_SUCCESS) {
1311 print_error(__location__": ldb_connect returned (%d)\n",
1316 ldb_kv = get_ldb_kv(ldb);
1318 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1319 if (ret != LDB_SUCCESS) {
1320 print_error(__location__": lock_read returned (%d)\n",
1326 * Check that KEY1 is there
1328 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1329 key.length = strlen(KEY1) + 1;
1331 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1332 if (ret != LDB_SUCCESS) {
1333 print_error(__location__": fetch_and_parse returned "
1339 if ((strlen(VAL1) + 1) != val.length) {
1340 print_error(__location__": KEY1 value lengths different"
1341 ", expected (%d) actual(%d)\n",
1342 (int)(strlen(VAL1) + 1), (int)val.length);
1343 exit(LDB_ERR_OPERATIONS_ERROR);
1345 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1346 print_error(__location__": KEY1 values different, "
1347 "expected (%s) actual(%s)\n",
1350 exit(LDB_ERR_OPERATIONS_ERROR);
1354 * Check that KEY2 is there
1357 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1358 key.length = strlen(KEY2) + 1;
1360 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1361 if (ret != LDB_SUCCESS) {
1362 print_error(__location__": fetch_and_parse returned "
1368 if ((strlen(VAL2) + 1) != val.length) {
1369 print_error(__location__": KEY2 value lengths different"
1370 ", expected (%d) actual(%d)\n",
1371 (int)(strlen(VAL2) + 1), (int)val.length);
1372 exit(LDB_ERR_OPERATIONS_ERROR);
1374 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1375 print_error(__location__": KEY2 values different, "
1376 "expected (%s) actual(%s)\n",
1379 exit(LDB_ERR_OPERATIONS_ERROR);
1382 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1383 if (ret != LDB_SUCCESS) {
1384 print_error(__location__": unlock_read returned (%d)\n",
1390 * Signal the other process to commit the transaction
1392 ret = write(to_parent[1], "GO", 2);
1394 print_error(__location__": write returned (%d)\n",
1396 exit(LDB_ERR_OPERATIONS_ERROR);
1400 * Wait for the transaction to be commited
1402 ret = read(to_child[0], buf, 2);
1404 print_error(__location__": read returned (%d)\n",
1406 exit(LDB_ERR_OPERATIONS_ERROR);
1410 * Check that KEY1 is there
1412 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1413 if (ret != LDB_SUCCESS) {
1414 print_error(__location__": unlock_read returned (%d)\n",
1418 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1419 key.length = strlen(KEY1) + 1;
1421 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1422 if (ret != LDB_SUCCESS) {
1423 print_error(__location__": fetch_and_parse returned "
1429 if ((strlen(VAL1) + 1) != val.length) {
1430 print_error(__location__": KEY1 value lengths different"
1431 ", expected (%d) actual(%d)\n",
1432 (int)(strlen(VAL1) + 1), (int)val.length);
1433 exit(LDB_ERR_OPERATIONS_ERROR);
1435 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1436 print_error(__location__": KEY1 values different, "
1437 "expected (%s) actual(%s)\n",
1440 exit(LDB_ERR_OPERATIONS_ERROR);
1444 * Check that KEY2 is not there
1446 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1447 key.length = strlen(KEY2 + 1);
1449 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1450 if (ret != LDB_SUCCESS) {
1451 print_error(__location__": lock_read returned (%d)\n",
1456 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1457 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
1458 print_error(__location__": fetch_and_parse returned "
1464 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1465 if (ret != LDB_SUCCESS) {
1466 print_error(__location__": unlock_read returned (%d)\n",
1474 close(to_parent[1]);
1477 * Begin a transaction and delete a record from the database
1478 * but leave the transaction open
1480 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1481 assert_int_equal(ret, 0);
1483 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1484 key.length = strlen(KEY2) + 1;
1486 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
1487 assert_int_equal(ret, 0);
1489 * Signal the child process
1491 ret = write(to_child[1], "GO", 2);
1492 assert_int_equal(2, ret);
1495 * Wait for the child process to check the DB state while the
1496 * transaction is active
1498 ret = read(to_parent[0], buf, 2);
1499 assert_int_equal(2, ret);
1502 * commit the transaction
1504 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1505 assert_int_equal(0, ret);
1508 * Signal the child process
1510 ret = write(to_child[1], "GO", 2);
1511 assert_int_equal(2, ret);
1513 w_pid = waitpid(pid, &wstatus, 0);
1514 assert_int_equal(pid, w_pid);
1516 assert_true(WIFEXITED(wstatus));
1518 assert_int_equal(WEXITSTATUS(wstatus), 0);
1521 TALLOC_FREE(tmp_ctx);
1525 int main(int argc, const char **argv)
1527 const struct CMUnitTest tests[] = {
1528 cmocka_unit_test_setup_teardown(
1532 cmocka_unit_test_setup_teardown(
1536 cmocka_unit_test_setup_teardown(
1537 test_transaction_abort_write,
1540 cmocka_unit_test_setup_teardown(
1541 test_transaction_abort_delete,
1544 cmocka_unit_test_setup_teardown(
1545 test_read_outside_transaction,
1548 cmocka_unit_test_setup_teardown(
1549 test_write_outside_transaction,
1552 cmocka_unit_test_setup_teardown(
1553 test_delete_outside_transaction,
1556 cmocka_unit_test_setup_teardown(
1560 cmocka_unit_test_setup_teardown(
1561 test_update_in_iterate,
1564 cmocka_unit_test_setup_teardown(
1565 test_write_transaction_isolation,
1568 cmocka_unit_test_setup_teardown(
1569 test_delete_transaction_isolation,
1574 return cmocka_run_group_tests(tests, NULL, NULL);