tdb: version 1.4.12
[samba4-gss.git] / lib / ldb / tests / ldb_kv_ops_test.c
blob6badff98cfb6f95b0af32a5b4ced31878ee620f6
1 /*
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/>.
22 * from cmocka.c:
23 * These headers or their equivalents should be included prior to
24 * including
25 * this header file.
27 * #include <stdarg.h>
28 * #include <stddef.h>
29 * #include <setjmp.h>
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 committed
41 * - Nested transactions are not permitted
42 * - transactions can be rolled back and committed.
43 * - supports iteration over all records in the database
44 * - supports the update_in_iterate operation allowing entries to be
45 * re-keyed.
46 * - has a get_size implementation that returns an estimate of the number of
47 * records in the database. Note that this can be an estimate rather than
48 * an accurate size.
50 #include <stdarg.h>
51 #include <stddef.h>
52 #include <stdint.h>
53 #include <setjmp.h>
54 #include <cmocka.h>
56 #include <errno.h>
57 #include <unistd.h>
58 #include <talloc.h>
59 #include <tevent.h>
60 #include <ldb.h>
61 #include <ldb_module.h>
62 #include <ldb_private.h>
63 #include <string.h>
64 #include <ctype.h>
66 #include <sys/wait.h>
68 #include "ldb_tdb/ldb_tdb.h"
69 #include "ldb_key_value/ldb_kv.h"
72 #define DEFAULT_BE "tdb"
74 #ifndef TEST_BE
75 #define TEST_BE DEFAULT_BE
76 #endif /* TEST_BE */
78 #define NUM_RECS 1024
81 struct test_ctx {
82 struct tevent_context *ev;
83 struct ldb_context *ldb;
85 const char *dbfile;
86 const char *lockfile; /* lockfile is separate */
88 const char *dbpath;
91 static void unlink_old_db(struct test_ctx *test_ctx)
93 int ret;
95 errno = 0;
96 ret = unlink(test_ctx->lockfile);
97 if (ret == -1 && errno != ENOENT) {
98 fail();
101 errno = 0;
102 ret = unlink(test_ctx->dbfile);
103 if (ret == -1 && errno != ENOENT) {
104 fail();
108 static int noconn_setup(void **state)
110 struct test_ctx *test_ctx;
112 test_ctx = talloc_zero(NULL, struct test_ctx);
113 assert_non_null(test_ctx);
115 test_ctx->ev = tevent_context_init(test_ctx);
116 assert_non_null(test_ctx->ev);
118 test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
119 assert_non_null(test_ctx->ldb);
121 test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb");
122 assert_non_null(test_ctx->dbfile);
124 test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
125 test_ctx->dbfile);
126 assert_non_null(test_ctx->lockfile);
128 test_ctx->dbpath = talloc_asprintf(test_ctx,
129 TEST_BE"://%s", test_ctx->dbfile);
130 assert_non_null(test_ctx->dbpath);
132 unlink_old_db(test_ctx);
133 *state = test_ctx;
134 return 0;
137 static int noconn_teardown(void **state)
139 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
140 struct test_ctx);
142 unlink_old_db(test_ctx);
143 talloc_free(test_ctx);
144 return 0;
147 static int setup(void **state)
149 struct test_ctx *test_ctx;
150 int ret;
151 struct ldb_ldif *ldif;
152 const char *index_ldif = \
153 "dn: @INDEXLIST\n"
154 "@IDXGUID: objectUUID\n"
155 "@IDX_DN_GUID: GUID\n"
156 "\n";
158 noconn_setup((void **) &test_ctx);
160 ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
161 assert_int_equal(ret, 0);
163 while ((ldif = ldb_ldif_read_string(test_ctx->ldb, &index_ldif))) {
164 ret = ldb_add(test_ctx->ldb, ldif->msg);
165 assert_int_equal(ret, LDB_SUCCESS);
167 *state = test_ctx;
168 return 0;
171 static int teardown(void **state)
173 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
174 struct test_ctx);
175 noconn_teardown((void **) &test_ctx);
176 return 0;
179 static struct ldb_kv_private *get_ldb_kv(struct ldb_context *ldb)
181 void *data = NULL;
182 struct ldb_kv_private *ldb_kv = NULL;
184 data = ldb_module_get_private(ldb->modules);
185 assert_non_null(data);
187 ldb_kv = talloc_get_type(data, struct ldb_kv_private);
188 assert_non_null(ldb_kv);
190 return ldb_kv;
193 static int parse(struct ldb_val key,
194 struct ldb_val data,
195 void *private_data)
197 struct ldb_val* read = private_data;
199 /* Yes, we leak this. That is OK */
200 read->data = talloc_size(NULL,
201 data.length);
202 assert_non_null(read->data);
204 memcpy(read->data, data.data, data.length);
205 read->length = data.length;
206 return LDB_SUCCESS;
210 * Parse function that just returns the int we pass it.
212 static int parse_return(struct ldb_val key,
213 struct ldb_val data,
214 void *private_data)
216 int *rcode = private_data;
217 return *rcode;
221 * Test that data can be written to the kv store and be read back.
223 static void test_add_get(void **state)
225 int ret;
226 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
227 struct test_ctx);
228 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
229 uint8_t key_val[] = "TheKey";
230 struct ldb_val key = {
231 .data = key_val,
232 .length = sizeof(key_val)
235 uint8_t value[] = "The record contents";
236 struct ldb_val data = {
237 .data = value,
238 .length = sizeof(value)
241 struct ldb_val read;
242 int rcode;
244 int flags = 0;
245 TALLOC_CTX *tmp_ctx;
247 tmp_ctx = talloc_new(test_ctx);
248 assert_non_null(tmp_ctx);
251 * Begin a transaction
253 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
254 assert_int_equal(ret, 0);
257 * Write the record
259 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
260 assert_int_equal(ret, 0);
263 * Commit the transaction
265 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
266 assert_int_equal(ret, 0);
269 * And now read it back
271 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
272 assert_int_equal(ret, 0);
274 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
275 assert_int_equal(ret, 0);
277 assert_int_equal(sizeof(value), read.length);
278 assert_memory_equal(value, read.data, sizeof(value));
281 * Now check that the error code we return in the
282 * parse function is returned by fetch_and_parse.
284 for (rcode=0; rcode<50; rcode++) {
285 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key,
286 parse_return,
287 &rcode);
288 assert_int_equal(ret, rcode);
291 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
292 assert_int_equal(ret, 0);
293 talloc_free(tmp_ctx);
297 * Test that attempts to read data without a read transaction fail.
299 static void test_read_outside_transaction(void **state)
301 int ret;
302 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
303 struct test_ctx);
304 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
305 uint8_t key_val[] = "TheKey";
306 struct ldb_val key = {
307 .data = key_val,
308 .length = sizeof(key_val)
311 uint8_t value[] = "The record contents";
312 struct ldb_val data = {
313 .data = value,
314 .length = sizeof(value)
317 struct ldb_val read;
319 int flags = 0;
320 TALLOC_CTX *tmp_ctx;
322 tmp_ctx = talloc_new(test_ctx);
323 assert_non_null(tmp_ctx);
326 * Begin a transaction
328 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
329 assert_int_equal(ret, 0);
332 * Write the record
334 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
335 assert_int_equal(ret, 0);
338 * Commit the transaction
340 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
341 assert_int_equal(ret, 0);
344 * And now read it back
345 * Note there is no read transaction active
347 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
348 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
350 talloc_free(tmp_ctx);
354 * Test that data can be deleted from the kv store
356 static void test_delete(void **state)
358 int ret;
359 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
360 struct test_ctx);
361 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
362 uint8_t key_val[] = "TheKey";
363 struct ldb_val key = {
364 .data = key_val,
365 .length = sizeof(key_val)
368 uint8_t value[] = "The record contents";
369 struct ldb_val data = {
370 .data = value,
371 .length = sizeof(value)
374 struct ldb_val read;
376 int flags = 0;
377 TALLOC_CTX *tmp_ctx;
379 tmp_ctx = talloc_new(test_ctx);
380 assert_non_null(tmp_ctx);
383 * Begin a transaction
385 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
386 assert_int_equal(ret, 0);
389 * Write the record
391 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
392 assert_int_equal(ret, 0);
395 * Commit the transaction
397 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
398 assert_int_equal(ret, 0);
401 * And now read it back
403 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
404 assert_int_equal(ret, 0);
405 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
406 assert_int_equal(ret, 0);
407 assert_int_equal(sizeof(value), read.length);
408 assert_memory_equal(value, read.data, sizeof(value));
409 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
410 assert_int_equal(ret, 0);
413 * Begin a transaction
415 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
416 assert_int_equal(ret, 0);
419 * Now delete it.
421 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
422 assert_int_equal(ret, 0);
425 * Commit the transaction
427 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
428 assert_int_equal(ret, 0);
431 * And now try to read it back
433 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
434 assert_int_equal(ret, 0);
435 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
436 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
437 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
438 assert_int_equal(ret, 0);
440 talloc_free(tmp_ctx);
444 * Check that writes are correctly rolled back when a transaction
445 * is rolled back.
447 static void test_transaction_abort_write(void **state)
449 int ret;
450 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
451 struct test_ctx);
452 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
453 uint8_t key_val[] = "TheKey";
454 struct ldb_val key = {
455 .data = key_val,
456 .length = sizeof(key_val)
459 uint8_t value[] = "The record contents";
460 struct ldb_val data = {
461 .data = value,
462 .length = sizeof(value)
465 struct ldb_val read;
467 int flags = 0;
468 TALLOC_CTX *tmp_ctx;
470 tmp_ctx = talloc_new(test_ctx);
471 assert_non_null(tmp_ctx);
474 * Begin a transaction
476 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
477 assert_int_equal(ret, 0);
480 * Write the record
482 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
483 assert_int_equal(ret, 0);
486 * And now read it back
488 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
489 assert_int_equal(ret, 0);
490 assert_int_equal(sizeof(value), read.length);
491 assert_memory_equal(value, read.data, sizeof(value));
495 * Now abort the transaction
497 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
498 assert_int_equal(ret, 0);
501 * And now read it back, should not be there
503 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
504 assert_int_equal(ret, 0);
505 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
506 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
507 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
508 assert_int_equal(ret, 0);
510 talloc_free(tmp_ctx);
514 * Check that deletes are correctly rolled back when a transaction is
515 * aborted.
517 static void test_transaction_abort_delete(void **state)
519 int ret;
520 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
521 struct test_ctx);
522 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
523 uint8_t key_val[] = "TheKey";
524 struct ldb_val key = {
525 .data = key_val,
526 .length = sizeof(key_val)
529 uint8_t value[] = "The record contents";
530 struct ldb_val data = {
531 .data = value,
532 .length = sizeof(value)
535 struct ldb_val read;
537 int flags = 0;
538 TALLOC_CTX *tmp_ctx;
540 tmp_ctx = talloc_new(test_ctx);
541 assert_non_null(tmp_ctx);
544 * Begin a transaction
546 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
547 assert_int_equal(ret, 0);
550 * Write the record
552 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
553 assert_int_equal(ret, 0);
556 * Commit the transaction
558 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
559 assert_int_equal(ret, 0);
562 * And now read it back
564 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
565 assert_int_equal(ret, 0);
566 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
567 assert_int_equal(ret, 0);
568 assert_int_equal(sizeof(value), read.length);
569 assert_memory_equal(value, read.data, sizeof(value));
570 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
571 assert_int_equal(ret, 0);
574 * Begin a transaction
576 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
577 assert_int_equal(ret, 0);
580 * Now delete it.
582 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
583 assert_int_equal(ret, 0);
586 * And now read it back
588 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
589 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
592 * Abort the transaction
594 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
595 assert_int_equal(ret, 0);
598 * And now try to read it back
600 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
601 assert_int_equal(ret, 0);
602 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
603 assert_int_equal(ret, 0);
604 assert_int_equal(sizeof(value), read.length);
605 assert_memory_equal(value, read.data, sizeof(value));
606 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
607 assert_int_equal(ret, 0);
609 talloc_free(tmp_ctx);
613 * Test that writes outside a transaction fail
615 static void test_write_outside_transaction(void **state)
617 int ret;
618 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
619 struct test_ctx);
620 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
621 uint8_t key_val[] = "TheKey";
622 struct ldb_val key = {
623 .data = key_val,
624 .length = sizeof(key_val)
627 uint8_t value[] = "The record contents";
628 struct ldb_val data = {
629 .data = value,
630 .length = sizeof(value)
634 int flags = 0;
635 TALLOC_CTX *tmp_ctx;
637 tmp_ctx = talloc_new(test_ctx);
638 assert_non_null(tmp_ctx);
641 * Attempt to write the record
643 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
644 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
646 talloc_free(tmp_ctx);
650 * Test data can not be deleted outside a transaction
652 static void test_delete_outside_transaction(void **state)
654 int ret;
655 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
656 struct test_ctx);
657 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
658 uint8_t key_val[] = "TheKey";
659 struct ldb_val key = {
660 .data = key_val,
661 .length = sizeof(key_val)
664 uint8_t value[] = "The record contents";
665 struct ldb_val data = {
666 .data = value,
667 .length = sizeof(value)
670 struct ldb_val read;
672 int flags = 0;
673 TALLOC_CTX *tmp_ctx;
675 tmp_ctx = talloc_new(test_ctx);
676 assert_non_null(tmp_ctx);
679 * Begin a transaction
681 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
682 assert_int_equal(ret, 0);
685 * Write the record
687 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
688 assert_int_equal(ret, 0);
691 * Commit the transaction
693 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
694 assert_int_equal(ret, 0);
697 * And now read it back
699 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
700 assert_int_equal(ret, 0);
701 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
702 assert_int_equal(ret, 0);
703 assert_int_equal(sizeof(value), read.length);
704 assert_memory_equal(value, read.data, sizeof(value));
705 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
706 assert_int_equal(ret, 0);
709 * Now attempt to delete a record
711 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
712 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
715 * And now read it back
717 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
718 assert_int_equal(ret, 0);
719 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
720 assert_int_equal(ret, 0);
721 assert_int_equal(sizeof(value), read.length);
722 assert_memory_equal(value, read.data, sizeof(value));
723 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
724 assert_int_equal(ret, 0);
726 talloc_free(tmp_ctx);
729 static int traverse_fn(struct ldb_kv_private *ldb_kv,
730 struct ldb_val key,
731 struct ldb_val data,
732 void *ctx)
735 int *visits = ctx;
736 int i;
738 if (strncmp("key ", (char *) key.data, 4) == 0) {
739 i = strtol((char *) &key.data[4], NULL, 10);
740 visits[i]++;
742 return LDB_SUCCESS;
746 * Test that iterate visits all the records.
748 static void test_iterate(void **state)
750 int ret;
751 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
752 struct test_ctx);
753 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
754 int i;
755 int num_recs = 1024;
756 int visits[num_recs];
758 TALLOC_CTX *tmp_ctx;
760 tmp_ctx = talloc_new(test_ctx);
761 assert_non_null(tmp_ctx);
764 * Begin a transaction
766 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
767 assert_int_equal(ret, 0);
770 * Write the records
772 for (i = 0; i < num_recs; i++) {
773 struct ldb_val key;
774 struct ldb_val rec;
775 int flags = 0;
777 visits[i] = 0;
778 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
779 key.length = strlen((char *)key.data) + 1;
781 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
782 "data for record (%04d)",
784 rec.length = strlen((char *)rec.data) + 1;
786 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
787 assert_int_equal(ret, 0);
789 TALLOC_FREE(key.data);
790 TALLOC_FREE(rec.data);
794 * Commit the transaction
796 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
797 assert_int_equal(ret, 0);
800 * Now iterate over the kv store and ensure that all the
801 * records are visited.
803 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
804 assert_int_equal(ret, 0);
805 ret = ldb_kv->kv_ops->iterate(ldb_kv, traverse_fn, visits);
806 for (i = 0; i <num_recs; i++) {
807 assert_int_equal(1, visits[i]);
809 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
810 assert_int_equal(ret, 0);
812 TALLOC_FREE(tmp_ctx);
815 static void do_iterate_range_test(void **state, int range_start,
816 int range_end, bool fail)
818 int ret;
819 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
820 struct test_ctx);
821 struct ldb_kv_private *ldb_kv = NULL;
822 int i;
823 int num_recs = 1024;
824 int skip_recs = 10;
825 int visits[num_recs];
826 struct ldb_val sk, ek;
828 TALLOC_CTX *tmp_ctx;
830 ldb_kv = get_ldb_kv(test_ctx->ldb);
831 assert_non_null(ldb_kv);
833 for (i = 0; i < num_recs; i++){
834 visits[i] = 0;
838 * No iterate_range on tdb
840 if (strcmp(TEST_BE, "tdb") == 0) {
841 return;
844 tmp_ctx = talloc_new(test_ctx);
845 assert_non_null(tmp_ctx);
848 * Begin a transaction
850 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
851 assert_int_equal(ret, 0);
854 * Write the records
856 for (i = skip_recs; i <= num_recs - skip_recs; i++) {
857 struct ldb_val key;
858 struct ldb_val rec;
859 int flags = 0;
861 key.data = (uint8_t *)talloc_asprintf(tmp_ctx,
862 "key %04d",
864 key.length = strlen((char *)key.data);
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);
884 sk.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_start);
885 sk.length = strlen((char *)sk.data);
887 ek.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_end);
888 ek.length = strlen((char *)ek.data) + 1;
890 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
891 assert_int_equal(ret, 0);
892 ret = ldb_kv->kv_ops->iterate_range(ldb_kv, sk, ek,
893 traverse_fn, visits);
894 if (fail){
895 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
896 TALLOC_FREE(tmp_ctx);
897 return;
898 } else{
899 assert_int_equal(ret, 0);
901 for (i = 0; i < num_recs; i++) {
902 if (i >= skip_recs && i <= num_recs - skip_recs &&
903 i >= range_start && i <= range_end){
904 assert_int_equal(1, visits[i]);
905 } else {
906 assert_int_equal(0, visits[i]);
910 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
911 assert_int_equal(ret, 0);
913 TALLOC_FREE(tmp_ctx);
917 * Test that iterate_range visits all the records between two keys.
919 static void test_iterate_range(void **state)
921 do_iterate_range_test(state, 300, 900, false);
924 * test start_key = end_key
926 do_iterate_range_test(state, 20, 20, false);
929 * test reverse range fails
931 do_iterate_range_test(state, 50, 40, true);
934 * keys are between 10-1014 so test with keys outside that range
936 do_iterate_range_test(state, 0, 20, false);
937 do_iterate_range_test(state, 1010, 1030, false);
938 do_iterate_range_test(state, 0, 1030, false);
941 struct update_context {
942 struct ldb_context* ldb;
943 int visits[NUM_RECS];
946 static int update_fn(struct ldb_kv_private *ldb_kv,
947 struct ldb_val key,
948 struct ldb_val data,
949 void *ctx)
952 struct ldb_val new_key;
953 struct ldb_module *module = NULL;
954 struct update_context *context =NULL;
955 int ret = LDB_SUCCESS;
956 TALLOC_CTX *tmp_ctx;
958 tmp_ctx = talloc_new(ldb_kv);
959 assert_non_null(tmp_ctx);
961 context = talloc_get_type_abort(ctx, struct update_context);
963 module = talloc_zero(tmp_ctx, struct ldb_module);
964 module->ldb = context->ldb;
966 if (strncmp("key ", (char *) key.data, 4) == 0) {
967 int i = strtol((char *) &key.data[4], NULL, 10);
968 context->visits[i]++;
969 new_key.data = talloc_memdup(tmp_ctx, key.data, key.length);
970 new_key.length = key.length;
971 new_key.data[0] = 'K';
973 ret = ldb_kv->kv_ops->update_in_iterate(
974 ldb_kv, key, new_key, data, &module);
976 TALLOC_FREE(tmp_ctx);
977 return ret;
981 * Test that update_in_iterate behaves as expected.
983 static void test_update_in_iterate(void **state)
985 int ret;
986 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
987 struct test_ctx);
988 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
989 int i;
990 struct update_context *context = NULL;
993 TALLOC_CTX *tmp_ctx;
995 tmp_ctx = talloc_new(test_ctx);
996 assert_non_null(tmp_ctx);
998 context = talloc_zero(tmp_ctx, struct update_context);
999 assert_non_null(context);
1000 context->ldb = test_ctx->ldb;
1002 * Begin a transaction
1004 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1005 assert_int_equal(ret, 0);
1008 * Write the records
1010 for (i = 0; i < NUM_RECS; i++) {
1011 struct ldb_val key;
1012 struct ldb_val rec;
1013 int flags = 0;
1015 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
1016 key.length = strlen((char *)key.data) + 1;
1018 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
1019 "data for record (%04d)",
1021 rec.length = strlen((char *)rec.data) + 1;
1023 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
1024 assert_int_equal(ret, 0);
1026 TALLOC_FREE(key.data);
1027 TALLOC_FREE(rec.data);
1031 * Commit the transaction
1033 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1034 assert_int_equal(ret, 0);
1037 * Now iterate over the kv store and ensure that all the
1038 * records are visited.
1042 * Needs to be done inside a transaction
1044 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1045 assert_int_equal(ret, 0);
1047 ret = ldb_kv->kv_ops->iterate(ldb_kv, update_fn, context);
1048 for (i = 0; i < NUM_RECS; i++) {
1049 assert_int_equal(1, context->visits[i]);
1052 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1053 assert_int_equal(ret, 0);
1055 TALLOC_FREE(tmp_ctx);
1059 * Ensure that writes are not visible until the transaction has been
1060 * committed.
1062 static void test_write_transaction_isolation(void **state)
1064 int ret;
1065 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
1066 struct test_ctx);
1067 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
1068 struct ldb_val key;
1069 struct ldb_val val;
1071 const char *KEY1 = "KEY01";
1072 const char *VAL1 = "VALUE01";
1074 const char *KEY2 = "KEY02";
1075 const char *VAL2 = "VALUE02";
1078 * Pipes etc to coordinate the processes
1080 int to_child[2];
1081 int to_parent[2];
1082 char buf[2];
1083 pid_t pid, w_pid;
1084 int wstatus;
1086 TALLOC_CTX *tmp_ctx;
1087 tmp_ctx = talloc_new(test_ctx);
1088 assert_non_null(tmp_ctx);
1092 * Add a record to the database
1094 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1095 assert_int_equal(ret, 0);
1097 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1098 key.length = strlen(KEY1) + 1;
1100 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
1101 val.length = strlen(VAL1) + 1;
1103 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1104 assert_int_equal(ret, 0);
1106 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1107 assert_int_equal(ret, 0);
1110 ret = pipe(to_child);
1111 assert_int_equal(ret, 0);
1112 ret = pipe(to_parent);
1113 assert_int_equal(ret, 0);
1115 * Now fork a new process
1118 pid = fork();
1119 if (pid == 0) {
1121 struct ldb_context *ldb = NULL;
1122 close(to_child[1]);
1123 close(to_parent[0]);
1126 * Wait for the transaction to start
1128 ret = read(to_child[0], buf, 2);
1129 if (ret != 2) {
1130 print_error(__location__": read returned (%d)\n",
1131 ret);
1132 exit(LDB_ERR_OPERATIONS_ERROR);
1134 ldb = ldb_init(test_ctx, test_ctx->ev);
1135 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
1136 if (ret != LDB_SUCCESS) {
1137 print_error(__location__": ldb_connect returned (%d)\n",
1138 ret);
1139 exit(ret);
1142 ldb_kv = get_ldb_kv(ldb);
1144 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1145 if (ret != LDB_SUCCESS) {
1146 print_error(__location__": lock_read returned (%d)\n",
1147 ret);
1148 exit(ret);
1152 * Check that KEY1 is there
1154 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1155 key.length = strlen(KEY1) + 1;
1157 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1158 if (ret != LDB_SUCCESS) {
1159 print_error(__location__": fetch_and_parse returned "
1160 "(%d)\n",
1161 ret);
1162 exit(ret);
1165 if ((strlen(VAL1) + 1) != val.length) {
1166 print_error(__location__": KEY1 value lengths different"
1167 ", expected (%d) actual(%d)\n",
1168 (int)(strlen(VAL1) + 1), (int)val.length);
1169 exit(LDB_ERR_OPERATIONS_ERROR);
1171 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1172 print_error(__location__": KEY1 values different, "
1173 "expected (%s) actual(%s)\n",
1174 VAL1,
1175 val.data);
1176 exit(LDB_ERR_OPERATIONS_ERROR);
1179 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1180 if (ret != LDB_SUCCESS) {
1181 print_error(__location__": unlock_read returned (%d)\n",
1182 ret);
1183 exit(ret);
1187 * Check that KEY2 is not there
1189 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1190 key.length = strlen(KEY2 + 1);
1192 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1193 if (ret != LDB_SUCCESS) {
1194 print_error(__location__": lock_read returned (%d)\n",
1195 ret);
1196 exit(ret);
1199 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1200 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
1201 print_error(__location__": fetch_and_parse returned "
1202 "(%d)\n",
1203 ret);
1204 exit(ret);
1207 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1208 if (ret != LDB_SUCCESS) {
1209 print_error(__location__": unlock_read returned (%d)\n",
1210 ret);
1211 exit(ret);
1215 * Signal the other process to commit the transaction
1217 ret = write(to_parent[1], "GO", 2);
1218 if (ret != 2) {
1219 print_error(__location__": write returned (%d)\n",
1220 ret);
1221 exit(LDB_ERR_OPERATIONS_ERROR);
1225 * Wait for the transaction to be committed
1227 ret = read(to_child[0], buf, 2);
1228 if (ret != 2) {
1229 print_error(__location__": read returned (%d)\n",
1230 ret);
1231 exit(LDB_ERR_OPERATIONS_ERROR);
1235 * Check that KEY1 is there
1237 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1238 if (ret != LDB_SUCCESS) {
1239 print_error(__location__": unlock_read returned (%d)\n",
1240 ret);
1241 exit(ret);
1243 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1244 key.length = strlen(KEY1) + 1;
1246 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1247 if (ret != LDB_SUCCESS) {
1248 print_error(__location__": fetch_and_parse returned "
1249 "(%d)\n",
1250 ret);
1251 exit(ret);
1254 if ((strlen(VAL1) + 1) != val.length) {
1255 print_error(__location__": KEY1 value lengths different"
1256 ", expected (%d) actual(%d)\n",
1257 (int)(strlen(VAL1) + 1), (int)val.length);
1258 exit(LDB_ERR_OPERATIONS_ERROR);
1260 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1261 print_error(__location__": KEY1 values different, "
1262 "expected (%s) actual(%s)\n",
1263 VAL1,
1264 val.data);
1265 exit(LDB_ERR_OPERATIONS_ERROR);
1268 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1269 if (ret != LDB_SUCCESS) {
1270 print_error(__location__": unlock_read returned (%d)\n",
1271 ret);
1272 exit(ret);
1277 * Check that KEY2 is there
1279 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1280 if (ret != LDB_SUCCESS) {
1281 print_error(__location__": unlock_read returned (%d)\n",
1282 ret);
1283 exit(ret);
1286 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1287 key.length = strlen(KEY2) + 1;
1289 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1290 if (ret != LDB_SUCCESS) {
1291 print_error(__location__": fetch_and_parse returned "
1292 "(%d)\n",
1293 ret);
1294 exit(ret);
1297 if ((strlen(VAL2) + 1) != val.length) {
1298 print_error(__location__": KEY2 value lengths different"
1299 ", expected (%d) actual(%d)\n",
1300 (int)(strlen(VAL2) + 1), (int)val.length);
1301 exit(LDB_ERR_OPERATIONS_ERROR);
1303 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1304 print_error(__location__": KEY2 values different, "
1305 "expected (%s) actual(%s)\n",
1306 VAL2,
1307 val.data);
1308 exit(LDB_ERR_OPERATIONS_ERROR);
1311 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1312 if (ret != LDB_SUCCESS) {
1313 print_error(__location__": unlock_read returned (%d)\n",
1314 ret);
1315 exit(ret);
1318 exit(0);
1320 close(to_child[0]);
1321 close(to_parent[1]);
1324 * Begin a transaction and add a record to the database
1325 * but leave the transaction open
1327 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1328 assert_int_equal(ret, 0);
1330 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1331 key.length = strlen(KEY2) + 1;
1333 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1334 val.length = strlen(VAL2) + 1;
1336 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1337 assert_int_equal(ret, 0);
1340 * Signal the child process
1342 ret = write(to_child[1], "GO", 2);
1343 assert_int_equal(2, ret);
1346 * Wait for the child process to check the DB state while the
1347 * transaction is active
1349 ret = read(to_parent[0], buf, 2);
1350 assert_int_equal(2, ret);
1353 * commit the transaction
1355 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1356 assert_int_equal(0, ret);
1359 * Signal the child process
1361 ret = write(to_child[1], "GO", 2);
1362 assert_int_equal(2, ret);
1364 w_pid = waitpid(pid, &wstatus, 0);
1365 assert_int_equal(pid, w_pid);
1367 assert_true(WIFEXITED(wstatus));
1369 assert_int_equal(WEXITSTATUS(wstatus), 0);
1372 TALLOC_FREE(tmp_ctx);
1376 * Ensure that deletes are not visible until the transaction has been
1377 * committed.
1379 static void test_delete_transaction_isolation(void **state)
1381 int ret;
1382 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
1383 struct test_ctx);
1384 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
1385 struct ldb_val key;
1386 struct ldb_val val;
1388 const char *KEY1 = "KEY01";
1389 const char *VAL1 = "VALUE01";
1391 const char *KEY2 = "KEY02";
1392 const char *VAL2 = "VALUE02";
1395 * Pipes etc to coordinate the processes
1397 int to_child[2];
1398 int to_parent[2];
1399 char buf[2];
1400 pid_t pid, w_pid;
1401 int wstatus;
1403 TALLOC_CTX *tmp_ctx;
1404 tmp_ctx = talloc_new(test_ctx);
1405 assert_non_null(tmp_ctx);
1409 * Add records to the database
1411 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1412 assert_int_equal(ret, 0);
1414 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1415 key.length = strlen(KEY1) + 1;
1417 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
1418 val.length = strlen(VAL1) + 1;
1420 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1421 assert_int_equal(ret, 0);
1423 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1424 key.length = strlen(KEY2) + 1;
1426 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1427 val.length = strlen(VAL2) + 1;
1429 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1430 assert_int_equal(ret, 0);
1432 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1433 assert_int_equal(ret, 0);
1436 ret = pipe(to_child);
1437 assert_int_equal(ret, 0);
1438 ret = pipe(to_parent);
1439 assert_int_equal(ret, 0);
1441 * Now fork a new process
1444 pid = fork();
1445 if (pid == 0) {
1447 struct ldb_context *ldb = NULL;
1448 close(to_child[1]);
1449 close(to_parent[0]);
1452 * Wait for the transaction to be started
1454 ret = read(to_child[0], buf, 2);
1455 if (ret != 2) {
1456 print_error(__location__": read returned (%d)\n",
1457 ret);
1458 exit(LDB_ERR_OPERATIONS_ERROR);
1461 ldb = ldb_init(test_ctx, test_ctx->ev);
1462 ret = ldb_connect(ldb, test_ctx->dbpath, 0, NULL);
1463 if (ret != LDB_SUCCESS) {
1464 print_error(__location__": ldb_connect returned (%d)\n",
1465 ret);
1466 exit(ret);
1469 ldb_kv = get_ldb_kv(ldb);
1471 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1472 if (ret != LDB_SUCCESS) {
1473 print_error(__location__": lock_read returned (%d)\n",
1474 ret);
1475 exit(ret);
1479 * Check that KEY1 is there
1481 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1482 key.length = strlen(KEY1) + 1;
1484 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1485 if (ret != LDB_SUCCESS) {
1486 print_error(__location__": fetch_and_parse returned "
1487 "(%d)\n",
1488 ret);
1489 exit(ret);
1492 if ((strlen(VAL1) + 1) != val.length) {
1493 print_error(__location__": KEY1 value lengths different"
1494 ", expected (%d) actual(%d)\n",
1495 (int)(strlen(VAL1) + 1), (int)val.length);
1496 exit(LDB_ERR_OPERATIONS_ERROR);
1498 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1499 print_error(__location__": KEY1 values different, "
1500 "expected (%s) actual(%s)\n",
1501 VAL1,
1502 val.data);
1503 exit(LDB_ERR_OPERATIONS_ERROR);
1507 * Check that KEY2 is there
1510 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1511 key.length = strlen(KEY2) + 1;
1513 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1514 if (ret != LDB_SUCCESS) {
1515 print_error(__location__": fetch_and_parse returned "
1516 "(%d)\n",
1517 ret);
1518 exit(ret);
1521 if ((strlen(VAL2) + 1) != val.length) {
1522 print_error(__location__": KEY2 value lengths different"
1523 ", expected (%d) actual(%d)\n",
1524 (int)(strlen(VAL2) + 1), (int)val.length);
1525 exit(LDB_ERR_OPERATIONS_ERROR);
1527 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1528 print_error(__location__": KEY2 values different, "
1529 "expected (%s) actual(%s)\n",
1530 VAL2,
1531 val.data);
1532 exit(LDB_ERR_OPERATIONS_ERROR);
1535 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1536 if (ret != LDB_SUCCESS) {
1537 print_error(__location__": unlock_read returned (%d)\n",
1538 ret);
1539 exit(ret);
1543 * Signal the other process to commit the transaction
1545 ret = write(to_parent[1], "GO", 2);
1546 if (ret != 2) {
1547 print_error(__location__": write returned (%d)\n",
1548 ret);
1549 exit(LDB_ERR_OPERATIONS_ERROR);
1553 * Wait for the transaction to be committed
1555 ret = read(to_child[0], buf, 2);
1556 if (ret != 2) {
1557 print_error(__location__": read returned (%d)\n",
1558 ret);
1559 exit(LDB_ERR_OPERATIONS_ERROR);
1563 * Check that KEY1 is there
1565 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1566 if (ret != LDB_SUCCESS) {
1567 print_error(__location__": unlock_read returned (%d)\n",
1568 ret);
1569 exit(ret);
1571 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1572 key.length = strlen(KEY1) + 1;
1574 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1575 if (ret != LDB_SUCCESS) {
1576 print_error(__location__": fetch_and_parse returned "
1577 "(%d)\n",
1578 ret);
1579 exit(ret);
1582 if ((strlen(VAL1) + 1) != val.length) {
1583 print_error(__location__": KEY1 value lengths different"
1584 ", expected (%d) actual(%d)\n",
1585 (int)(strlen(VAL1) + 1), (int)val.length);
1586 exit(LDB_ERR_OPERATIONS_ERROR);
1588 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1589 print_error(__location__": KEY1 values different, "
1590 "expected (%s) actual(%s)\n",
1591 VAL1,
1592 val.data);
1593 exit(LDB_ERR_OPERATIONS_ERROR);
1595 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1596 if (ret != LDB_SUCCESS) {
1597 print_error(__location__": unlock_read returned (%d)\n",
1598 ret);
1599 exit(ret);
1603 * Check that KEY2 is not there
1605 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1606 key.length = strlen(KEY2 + 1);
1608 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1609 if (ret != LDB_SUCCESS) {
1610 print_error(__location__": lock_read returned (%d)\n",
1611 ret);
1612 exit(ret);
1615 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &val);
1616 if (ret != LDB_ERR_NO_SUCH_OBJECT) {
1617 print_error(__location__": fetch_and_parse returned "
1618 "(%d)\n",
1619 ret);
1620 exit(ret);
1623 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1624 if (ret != LDB_SUCCESS) {
1625 print_error(__location__": unlock_read returned (%d)\n",
1626 ret);
1627 exit(ret);
1629 TALLOC_FREE(tmp_ctx);
1630 exit(0);
1632 close(to_child[0]);
1633 close(to_parent[1]);
1636 * Begin a transaction and delete a record from the database
1637 * but leave the transaction open
1639 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1640 assert_int_equal(ret, 0);
1642 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1643 key.length = strlen(KEY2) + 1;
1645 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
1646 assert_int_equal(ret, 0);
1648 * Signal the child process
1650 ret = write(to_child[1], "GO", 2);
1651 assert_int_equal(2, ret);
1654 * Wait for the child process to check the DB state while the
1655 * transaction is active
1657 ret = read(to_parent[0], buf, 2);
1658 assert_int_equal(2, ret);
1661 * commit the transaction
1663 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1664 assert_int_equal(0, ret);
1667 * Signal the child process
1669 ret = write(to_child[1], "GO", 2);
1670 assert_int_equal(2, ret);
1672 w_pid = waitpid(pid, &wstatus, 0);
1673 assert_int_equal(pid, w_pid);
1675 assert_true(WIFEXITED(wstatus));
1677 assert_int_equal(WEXITSTATUS(wstatus), 0);
1680 TALLOC_FREE(tmp_ctx);
1685 * Test that get_size returns a sensible estimate of the number of records
1686 * in the database.
1688 static void test_get_size(void **state)
1690 int ret;
1691 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
1692 struct test_ctx);
1693 struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
1694 uint8_t key_val[] = "TheKey";
1695 struct ldb_val key = {
1696 .data = key_val,
1697 .length = sizeof(key_val)
1700 uint8_t value[] = "The record contents";
1701 struct ldb_val data = {
1702 .data = value,
1703 .length = sizeof(value)
1705 size_t size = 0;
1707 int flags = 0;
1708 TALLOC_CTX *tmp_ctx;
1710 tmp_ctx = talloc_new(test_ctx);
1711 assert_non_null(tmp_ctx);
1713 size = ldb_kv->kv_ops->get_size(ldb_kv);
1714 #if defined(TEST_LMDB)
1715 assert_int_equal(2, size);
1716 #else
1718 * The tdb implementation of get_size over estimates for sparse files
1719 * which is perfectly acceptable for it's intended use.
1720 * mipsel, ia64: 9994
1721 * ppc64el, powerpc, ppc64: 13369
1722 * sparc64: 5046
1724 assert_in_range(size, 2500, 15000);
1725 #endif
1728 * Begin a transaction
1730 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1731 assert_int_equal(ret, 0);
1734 * Write the record
1736 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
1737 assert_int_equal(ret, 0);
1740 * Commit the transaction
1742 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1743 assert_int_equal(ret, 0);
1745 size = ldb_kv->kv_ops->get_size(ldb_kv);
1746 #ifdef TEST_LMDB
1747 assert_int_equal(3, size);
1748 #else
1750 * The tdb implementation of get_size over estimates for sparse files
1751 * which is perfectly acceptable for it's intended use.
1752 * mipsel, ia64: 9994
1753 * ppc64el, powerpc, ppc64: 13369
1754 * sparc64: 5046
1756 assert_in_range(size, 2500, 15000);
1757 #endif
1758 talloc_free(tmp_ctx);
1761 int main(int argc, const char **argv)
1763 const struct CMUnitTest tests[] = {
1764 cmocka_unit_test_setup_teardown(
1765 test_add_get,
1766 setup,
1767 teardown),
1768 cmocka_unit_test_setup_teardown(
1769 test_delete,
1770 setup,
1771 teardown),
1772 cmocka_unit_test_setup_teardown(
1773 test_transaction_abort_write,
1774 setup,
1775 teardown),
1776 cmocka_unit_test_setup_teardown(
1777 test_transaction_abort_delete,
1778 setup,
1779 teardown),
1780 cmocka_unit_test_setup_teardown(
1781 test_read_outside_transaction,
1782 setup,
1783 teardown),
1784 cmocka_unit_test_setup_teardown(
1785 test_write_outside_transaction,
1786 setup,
1787 teardown),
1788 cmocka_unit_test_setup_teardown(
1789 test_delete_outside_transaction,
1790 setup,
1791 teardown),
1792 cmocka_unit_test_setup_teardown(
1793 test_iterate,
1794 setup,
1795 teardown),
1796 cmocka_unit_test_setup_teardown(
1797 test_iterate_range,
1798 setup,
1799 teardown),
1800 cmocka_unit_test_setup_teardown(
1801 test_update_in_iterate,
1802 setup,
1803 teardown),
1804 cmocka_unit_test_setup_teardown(
1805 test_write_transaction_isolation,
1806 setup,
1807 teardown),
1808 cmocka_unit_test_setup_teardown(
1809 test_delete_transaction_isolation,
1810 setup,
1811 teardown),
1812 cmocka_unit_test_setup_teardown(
1813 test_get_size,
1814 setup,
1815 teardown),
1818 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
1820 return cmocka_run_group_tests(tests, NULL, NULL);