36ea3bf45d59bd06920b58a727b96127650e929b
[amitay/samba.git] / lib / ldb / tests / ldb_kv_ops_test.c
1 /*
2  * Tests exercising the ldb key value operations.
3  *
4  *  Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 /*
22  * from cmocka.c:
23  * These headers or their equivalents should be included prior to
24  * including
25  * this header file.
26  *
27  * #include <stdarg.h>
28  * #include <stddef.h>
29  * #include <setjmp.h>
30  *
31  * This allows test applications to use custom definitions of C standard
32  * library functions and types.
33  *
34  */
35
36 /*
37  * A KV module is expected to have the following behaviour
38  *
39  * - A transaction must be open to perform any read, write or delete operation
40  * - Writes and Deletes should not be visible until a transaction is 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
45  *   re-keyed.
46  */
47 #include <stdarg.h>
48 #include <stddef.h>
49 #include <setjmp.h>
50 #include <cmocka.h>
51
52 #include <errno.h>
53 #include <unistd.h>
54 #include <talloc.h>
55 #include <tevent.h>
56 #include <ldb.h>
57 #include <ldb_module.h>
58 #include <ldb_private.h>
59 #include <string.h>
60 #include <ctype.h>
61
62 #include <sys/wait.h>
63
64 #include "ldb_tdb/ldb_tdb.h"
65
66
67 #define DEFAULT_BE  "tdb"
68
69 #ifndef TEST_BE
70 #define TEST_BE DEFAULT_BE
71 #endif /* TEST_BE */
72
73 #define NUM_RECS 1024
74
75
76 struct test_ctx {
77         struct tevent_context *ev;
78         struct ldb_context *ldb;
79
80         const char *dbfile;
81         const char *lockfile;   /* lockfile is separate */
82
83         const char *dbpath;
84 };
85
86 static void unlink_old_db(struct test_ctx *test_ctx)
87 {
88         int ret;
89
90         errno = 0;
91         ret = unlink(test_ctx->lockfile);
92         if (ret == -1 && errno != ENOENT) {
93                 fail();
94         }
95
96         errno = 0;
97         ret = unlink(test_ctx->dbfile);
98         if (ret == -1 && errno != ENOENT) {
99                 fail();
100         }
101 }
102
103 static int noconn_setup(void **state)
104 {
105         struct test_ctx *test_ctx;
106
107         test_ctx = talloc_zero(NULL, struct test_ctx);
108         assert_non_null(test_ctx);
109
110         test_ctx->ev = tevent_context_init(test_ctx);
111         assert_non_null(test_ctx->ev);
112
113         test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
114         assert_non_null(test_ctx->ldb);
115
116         test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb");
117         assert_non_null(test_ctx->dbfile);
118
119         test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
120                                              test_ctx->dbfile);
121         assert_non_null(test_ctx->lockfile);
122
123         test_ctx->dbpath = talloc_asprintf(test_ctx,
124                         TEST_BE"://%s", test_ctx->dbfile);
125         assert_non_null(test_ctx->dbpath);
126
127         unlink_old_db(test_ctx);
128         *state = test_ctx;
129         return 0;
130 }
131
132 static int noconn_teardown(void **state)
133 {
134         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
135                                                           struct test_ctx);
136
137         unlink_old_db(test_ctx);
138         talloc_free(test_ctx);
139         return 0;
140 }
141
142 static int setup(void **state)
143 {
144         struct test_ctx *test_ctx;
145         int ret;
146         struct ldb_ldif *ldif;
147         const char *index_ldif =                \
148                 "dn: @INDEXLIST\n"
149                 "@IDXGUID: objectUUID\n"
150                 "@IDX_DN_GUID: GUID\n"
151                 "\n";
152
153         noconn_setup((void **) &test_ctx);
154
155         ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
156         assert_int_equal(ret, 0);
157
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);
161         }
162         *state = test_ctx;
163         return 0;
164 }
165
166 static int teardown(void **state)
167 {
168         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
169                                                           struct test_ctx);
170         noconn_teardown((void **) &test_ctx);
171         return 0;
172 }
173
174 static struct ldb_kv_private *get_ldb_kv(struct ldb_context *ldb)
175 {
176         void *data = NULL;
177         struct ldb_kv_private *ldb_kv = NULL;
178
179         data = ldb_module_get_private(ldb->modules);
180         assert_non_null(data);
181
182         ldb_kv = talloc_get_type(data, struct ldb_kv_private);
183         assert_non_null(ldb_kv);
184
185         return ldb_kv;
186 }
187
188 static int parse(struct ldb_val key,
189                  struct ldb_val data,
190                  void *private_data)
191 {
192         struct ldb_val* read = private_data;
193
194         /* Yes, we essentially leak this.  That is OK */
195         read->data = talloc_size(talloc_autofree_context(),
196                                  data.length);
197         assert_non_null(read->data);
198
199         memcpy(read->data, data.data, data.length);
200         read->length = data.length;
201         return LDB_SUCCESS;
202 }
203
204 /*
205  * Test that data can be written to the kv store and be read back.
206  */
207 static void test_add_get(void **state)
208 {
209         int ret;
210         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
211                                                           struct test_ctx);
212         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
213         uint8_t key_val[] = "TheKey";
214         struct ldb_val key = {
215                 .data   = key_val,
216                 .length = sizeof(key_val)
217         };
218
219         uint8_t value[] = "The record contents";
220         struct ldb_val data = {
221                 .data    = value,
222                 .length = sizeof(value)
223         };
224
225         struct ldb_val read;
226
227         int flags = 0;
228         TALLOC_CTX *tmp_ctx;
229
230         tmp_ctx = talloc_new(test_ctx);
231         assert_non_null(tmp_ctx);
232
233         /*
234          * Begin a transaction
235          */
236         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
237         assert_int_equal(ret, 0);
238
239         /*
240          * Write the record
241          */
242         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
243         assert_int_equal(ret, 0);
244
245         /*
246          * Commit the transaction
247          */
248         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
249         assert_int_equal(ret, 0);
250
251         /*
252          * And now read it back
253          */
254         ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
255         assert_int_equal(ret, 0);
256
257         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
258         assert_int_equal(ret, 0);
259
260         assert_int_equal(sizeof(value), read.length);
261         assert_memory_equal(value, read.data, sizeof(value));
262
263         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
264         assert_int_equal(ret, 0);
265         talloc_free(tmp_ctx);
266 }
267
268 /*
269  * Test that attempts to read data without a read transaction fail.
270  */
271 static void test_read_outside_transaction(void **state)
272 {
273         int ret;
274         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
275                                                           struct test_ctx);
276         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
277         uint8_t key_val[] = "TheKey";
278         struct ldb_val key = {
279                 .data   = key_val,
280                 .length = sizeof(key_val)
281         };
282
283         uint8_t value[] = "The record contents";
284         struct ldb_val data = {
285                 .data    = value,
286                 .length = sizeof(value)
287         };
288
289         struct ldb_val read;
290
291         int flags = 0;
292         TALLOC_CTX *tmp_ctx;
293
294         tmp_ctx = talloc_new(test_ctx);
295         assert_non_null(tmp_ctx);
296
297         /*
298          * Begin a transaction
299          */
300         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
301         assert_int_equal(ret, 0);
302
303         /*
304          * Write the record
305          */
306         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
307         assert_int_equal(ret, 0);
308
309         /*
310          * Commit the transaction
311          */
312         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
313         assert_int_equal(ret, 0);
314
315         /*
316          * And now read it back
317          * Note there is no read transaction active
318          */
319         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
320         assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
321
322         talloc_free(tmp_ctx);
323 }
324
325 /*
326  * Test that data can be deleted from the kv store
327  */
328 static void test_delete(void **state)
329 {
330         int ret;
331         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
332                                                           struct test_ctx);
333         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
334         uint8_t key_val[] = "TheKey";
335         struct ldb_val key = {
336                 .data   = key_val,
337                 .length = sizeof(key_val)
338         };
339
340         uint8_t value[] = "The record contents";
341         struct ldb_val data = {
342                 .data    = value,
343                 .length = sizeof(value)
344         };
345
346         struct ldb_val read;
347
348         int flags = 0;
349         TALLOC_CTX *tmp_ctx;
350
351         tmp_ctx = talloc_new(test_ctx);
352         assert_non_null(tmp_ctx);
353
354         /*
355          * Begin a transaction
356          */
357         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
358         assert_int_equal(ret, 0);
359
360         /*
361          * Write the record
362          */
363         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
364         assert_int_equal(ret, 0);
365
366         /*
367          * Commit the transaction
368          */
369         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
370         assert_int_equal(ret, 0);
371
372         /*
373          * And now read it back
374          */
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);
383
384         /*
385          * Begin a transaction
386          */
387         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
388         assert_int_equal(ret, 0);
389
390         /*
391          * Now delete it.
392          */
393         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
394         assert_int_equal(ret, 0);
395
396         /*
397          * Commit the transaction
398          */
399         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
400         assert_int_equal(ret, 0);
401
402         /*
403          * And now try to read it back
404          */
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);
411
412         talloc_free(tmp_ctx);
413 }
414
415 /*
416  * Check that writes are correctly rolled back when a transaction
417  * is rolled back.
418  */
419 static void test_transaction_abort_write(void **state)
420 {
421         int ret;
422         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
423                                                           struct test_ctx);
424         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
425         uint8_t key_val[] = "TheKey";
426         struct ldb_val key = {
427                 .data   = key_val,
428                 .length = sizeof(key_val)
429         };
430
431         uint8_t value[] = "The record contents";
432         struct ldb_val data = {
433                 .data    = value,
434                 .length = sizeof(value)
435         };
436
437         struct ldb_val read;
438
439         int flags = 0;
440         TALLOC_CTX *tmp_ctx;
441
442         tmp_ctx = talloc_new(test_ctx);
443         assert_non_null(tmp_ctx);
444
445         /*
446          * Begin a transaction
447          */
448         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
449         assert_int_equal(ret, 0);
450
451         /*
452          * Write the record
453          */
454         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
455         assert_int_equal(ret, 0);
456
457         /*
458          * And now read it back
459          */
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));
464
465
466         /*
467          * Now abort the transaction
468          */
469         ret = ldb_kv->kv_ops->abort_write(ldb_kv);
470         assert_int_equal(ret, 0);
471
472         /*
473          * And now read it back, should not be there
474          */
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);
481
482         talloc_free(tmp_ctx);
483 }
484
485 /*
486  * Check that deletes are correctly rolled back when a transaction is
487  * aborted.
488  */
489 static void test_transaction_abort_delete(void **state)
490 {
491         int ret;
492         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
493                                                           struct test_ctx);
494         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
495         uint8_t key_val[] = "TheKey";
496         struct ldb_val key = {
497                 .data   = key_val,
498                 .length = sizeof(key_val)
499         };
500
501         uint8_t value[] = "The record contents";
502         struct ldb_val data = {
503                 .data    = value,
504                 .length = sizeof(value)
505         };
506
507         struct ldb_val read;
508
509         int flags = 0;
510         TALLOC_CTX *tmp_ctx;
511
512         tmp_ctx = talloc_new(test_ctx);
513         assert_non_null(tmp_ctx);
514
515         /*
516          * Begin a transaction
517          */
518         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
519         assert_int_equal(ret, 0);
520
521         /*
522          * Write the record
523          */
524         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
525         assert_int_equal(ret, 0);
526
527         /*
528          * Commit the transaction
529          */
530         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
531         assert_int_equal(ret, 0);
532
533         /*
534          * And now read it back
535          */
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);
544
545         /*
546          * Begin a transaction
547          */
548         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
549         assert_int_equal(ret, 0);
550
551         /*
552          * Now delete it.
553          */
554         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
555         assert_int_equal(ret, 0);
556
557         /*
558          * And now read it back
559          */
560         ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
561         assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
562
563         /*
564          * Abort the transaction
565          */
566         ret = ldb_kv->kv_ops->abort_write(ldb_kv);
567         assert_int_equal(ret, 0);
568
569         /*
570          * And now try to read it back
571          */
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);
580
581         talloc_free(tmp_ctx);
582 }
583
584 /*
585  * Test that writes outside a transaction fail
586  */
587 static void test_write_outside_transaction(void **state)
588 {
589         int ret;
590         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
591                                                           struct test_ctx);
592         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
593         uint8_t key_val[] = "TheKey";
594         struct ldb_val key = {
595                 .data   = key_val,
596                 .length = sizeof(key_val)
597         };
598
599         uint8_t value[] = "The record contents";
600         struct ldb_val data = {
601                 .data    = value,
602                 .length = sizeof(value)
603         };
604
605
606         int flags = 0;
607         TALLOC_CTX *tmp_ctx;
608
609         tmp_ctx = talloc_new(test_ctx);
610         assert_non_null(tmp_ctx);
611
612         /*
613          * Attempt to write the record
614          */
615         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
616         assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
617
618         talloc_free(tmp_ctx);
619 }
620
621 /*
622  * Test data can not be deleted outside a transaction
623  */
624 static void test_delete_outside_transaction(void **state)
625 {
626         int ret;
627         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
628                                                           struct test_ctx);
629         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
630         uint8_t key_val[] = "TheKey";
631         struct ldb_val key = {
632                 .data   = key_val,
633                 .length = sizeof(key_val)
634         };
635
636         uint8_t value[] = "The record contents";
637         struct ldb_val data = {
638                 .data    = value,
639                 .length = sizeof(value)
640         };
641
642         struct ldb_val read;
643
644         int flags = 0;
645         TALLOC_CTX *tmp_ctx;
646
647         tmp_ctx = talloc_new(test_ctx);
648         assert_non_null(tmp_ctx);
649
650         /*
651          * Begin a transaction
652          */
653         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
654         assert_int_equal(ret, 0);
655
656         /*
657          * Write the record
658          */
659         ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
660         assert_int_equal(ret, 0);
661
662         /*
663          * Commit the transaction
664          */
665         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
666         assert_int_equal(ret, 0);
667
668         /*
669          * And now read it back
670          */
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);
679
680         /*
681          * Now attempt to delete a record
682          */
683         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
684         assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
685
686         /*
687          * And now read it back
688          */
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);
697
698         talloc_free(tmp_ctx);
699 }
700
701 static int traverse_fn(struct ldb_kv_private *ldb_kv,
702                        struct ldb_val key,
703                        struct ldb_val data,
704                        void *ctx)
705 {
706
707         int *visits = ctx;
708         int i;
709
710         if (strncmp("key ", (char *) key.data, 4) == 0) {
711                 i = strtol((char *) &key.data[4], NULL, 10);
712                 visits[i]++;
713         }
714         return LDB_SUCCESS;
715 }
716
717
718 /*
719  * Test that iterate visits all the records.
720  */
721 static void test_iterate(void **state)
722 {
723         int ret;
724         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
725                                                           struct test_ctx);
726         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
727         int i;
728         int num_recs = 1024;
729         int visits[num_recs];
730
731         TALLOC_CTX *tmp_ctx;
732
733         tmp_ctx = talloc_new(test_ctx);
734         assert_non_null(tmp_ctx);
735
736         /*
737          * Begin a transaction
738          */
739         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
740         assert_int_equal(ret, 0);
741
742         /*
743          * Write the records
744          */
745         for (i = 0; i < num_recs; i++) {
746                 struct ldb_val key;
747                 struct ldb_val rec;
748                 int flags = 0;
749
750                 visits[i] = 0;
751                 key.data   = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
752                 key.length = strlen((char *)key.data) + 1;
753
754                 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
755                                                        "data for record (%04d)",
756                                                        i);
757                 rec.length = strlen((char *)rec.data) + 1;
758
759                 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
760                 assert_int_equal(ret, 0);
761
762                 TALLOC_FREE(key.data);
763                 TALLOC_FREE(rec.data);
764         }
765
766         /*
767          * Commit the transaction
768          */
769         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
770         assert_int_equal(ret, 0);
771
772         /*
773          * Now iterate over the kv store and ensure that all the
774          * records are visited.
775          */
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]);
781         }
782         ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
783         assert_int_equal(ret, 0);
784
785         TALLOC_FREE(tmp_ctx);
786 }
787
788 struct update_context {
789         struct ldb_context* ldb;
790         int visits[NUM_RECS];
791 };
792
793 static int update_fn(struct ldb_kv_private *ldb_kv,
794                      struct ldb_val key,
795                      struct ldb_val data,
796                      void *ctx)
797 {
798
799         struct ldb_val new_key;
800         struct ldb_module *module = NULL;
801         struct update_context *context =NULL;
802         int ret = LDB_SUCCESS;
803         TALLOC_CTX *tmp_ctx;
804
805         tmp_ctx = talloc_new(ldb_kv);
806         assert_non_null(tmp_ctx);
807
808         context = talloc_get_type_abort(ctx, struct update_context);
809
810         module = talloc_zero(tmp_ctx, struct ldb_module);
811         module->ldb = context->ldb;
812
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';
819
820                 ret = ldb_kv->kv_ops->update_in_iterate(
821                     ldb_kv, key, new_key, data, &module);
822         }
823         TALLOC_FREE(tmp_ctx);
824         return ret;
825 }
826
827 /*
828  * Test that update_in_iterate behaves as expected.
829  */
830 static void test_update_in_iterate(void **state)
831 {
832         int ret;
833         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
834                                                           struct test_ctx);
835         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
836         int i;
837         struct update_context *context = NULL;
838
839
840         TALLOC_CTX *tmp_ctx;
841
842         tmp_ctx = talloc_new(test_ctx);
843         assert_non_null(tmp_ctx);
844
845         context = talloc_zero(tmp_ctx, struct update_context);
846         assert_non_null(context);
847         context->ldb = test_ctx->ldb;
848         /*
849          * Begin a transaction
850          */
851         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
852         assert_int_equal(ret, 0);
853
854         /*
855          * Write the records
856          */
857         for (i = 0; i < NUM_RECS; i++) {
858                 struct ldb_val key;
859                 struct ldb_val rec;
860                 int flags = 0;
861
862                 key.data   = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
863                 key.length = strlen((char *)key.data) + 1;
864
865                 rec.data   = (uint8_t *) talloc_asprintf(tmp_ctx,
866                                                          "data for record (%04d)",
867                                                          i);
868                 rec.length = strlen((char *)rec.data) + 1;
869
870                 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
871                 assert_int_equal(ret, 0);
872
873                 TALLOC_FREE(key.data);
874                 TALLOC_FREE(rec.data);
875         }
876
877         /*
878          * Commit the transaction
879          */
880         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
881         assert_int_equal(ret, 0);
882
883         /*
884          * Now iterate over the kv store and ensure that all the
885          * records are visited.
886          */
887
888         /*
889          * Needs to be done inside a transaction
890          */
891         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
892         assert_int_equal(ret, 0);
893
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]);
897         }
898
899         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
900         assert_int_equal(ret, 0);
901
902         TALLOC_FREE(tmp_ctx);
903 }
904
905 /*
906  * Ensure that writes are not visible until the transaction has been
907  * committed.
908  */
909 static void test_write_transaction_isolation(void **state)
910 {
911         int ret;
912         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
913                                                           struct test_ctx);
914         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
915         struct ldb_val key;
916         struct ldb_val val;
917
918         const char *KEY1 = "KEY01";
919         const char *VAL1 = "VALUE01";
920
921         const char *KEY2 = "KEY02";
922         const char *VAL2 = "VALUE02";
923
924         /*
925          * Pipes etc to co-ordinate the processes
926          */
927         int to_child[2];
928         int to_parent[2];
929         char buf[2];
930         pid_t pid, w_pid;
931         int wstatus;
932
933         TALLOC_CTX *tmp_ctx;
934         tmp_ctx = talloc_new(test_ctx);
935         assert_non_null(tmp_ctx);
936
937
938         /*
939          * Add a record to the database
940          */
941         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
942         assert_int_equal(ret, 0);
943
944         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
945         key.length = strlen(KEY1) + 1;
946
947         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
948         val.length = strlen(VAL1) + 1;
949
950         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
951         assert_int_equal(ret, 0);
952
953         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
954         assert_int_equal(ret, 0);
955
956
957         ret = pipe(to_child);
958         assert_int_equal(ret, 0);
959         ret = pipe(to_parent);
960         assert_int_equal(ret, 0);
961         /*
962          * Now fork a new process
963          */
964
965         pid = fork();
966         if (pid == 0) {
967
968                 struct ldb_context *ldb = NULL;
969                 close(to_child[1]);
970                 close(to_parent[0]);
971
972                 /*
973                  * Wait for the transaction to start
974                  */
975                 ret = read(to_child[0], buf, 2);
976                 if (ret != 2) {
977                         print_error(__location__": read returned (%d)\n",
978                                     ret);
979                         exit(LDB_ERR_OPERATIONS_ERROR);
980                 }
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",
985                                     ret);
986                         exit(ret);
987                 }
988
989                 ldb_kv = get_ldb_kv(ldb);
990
991                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
992                 if (ret != LDB_SUCCESS) {
993                         print_error(__location__": lock_read returned (%d)\n",
994                                     ret);
995                         exit(ret);
996                 }
997
998                 /*
999                  * Check that KEY1 is there
1000                  */
1001                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1002                 key.length = strlen(KEY1) + 1;
1003
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 "
1007                                     "(%d)\n",
1008                                     ret);
1009                         exit(ret);
1010                 }
1011
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);
1017                 }
1018                 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1019                         print_error(__location__": KEY1 values different, "
1020                                     "expected (%s) actual(%s)\n",
1021                                     VAL1,
1022                                     val.data);
1023                         exit(LDB_ERR_OPERATIONS_ERROR);
1024                 }
1025
1026                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1027                 if (ret != LDB_SUCCESS) {
1028                         print_error(__location__": unlock_read returned (%d)\n",
1029                                     ret);
1030                         exit(ret);
1031                 }
1032
1033                 /*
1034                  * Check that KEY2 is not there
1035                  */
1036                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1037                 key.length = strlen(KEY2 + 1);
1038
1039                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1040                 if (ret != LDB_SUCCESS) {
1041                         print_error(__location__": lock_read returned (%d)\n",
1042                                     ret);
1043                         exit(ret);
1044                 }
1045
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 "
1049                                     "(%d)\n",
1050                                     ret);
1051                         exit(ret);
1052                 }
1053
1054                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1055                 if (ret != LDB_SUCCESS) {
1056                         print_error(__location__": unlock_read returned (%d)\n",
1057                                     ret);
1058                         exit(ret);
1059                 }
1060
1061                 /*
1062                  * Signal the other process to commit the transaction
1063                  */
1064                 ret = write(to_parent[1], "GO", 2);
1065                 if (ret != 2) {
1066                         print_error(__location__": write returned (%d)\n",
1067                                     ret);
1068                         exit(LDB_ERR_OPERATIONS_ERROR);
1069                 }
1070
1071                 /*
1072                  * Wait for the transaction to be commited
1073                  */
1074                 ret = read(to_child[0], buf, 2);
1075                 if (ret != 2) {
1076                         print_error(__location__": read returned (%d)\n",
1077                                     ret);
1078                         exit(LDB_ERR_OPERATIONS_ERROR);
1079                 }
1080
1081                 /*
1082                  * Check that KEY1 is there
1083                  */
1084                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1085                 if (ret != LDB_SUCCESS) {
1086                         print_error(__location__": unlock_read returned (%d)\n",
1087                                     ret);
1088                         exit(ret);
1089                 }
1090                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1091                 key.length = strlen(KEY1) + 1;
1092
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 "
1096                                     "(%d)\n",
1097                                     ret);
1098                         exit(ret);
1099                 }
1100
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);
1106                 }
1107                 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1108                         print_error(__location__": KEY1 values different, "
1109                                     "expected (%s) actual(%s)\n",
1110                                     VAL1,
1111                                     val.data);
1112                         exit(LDB_ERR_OPERATIONS_ERROR);
1113                 }
1114
1115                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1116                 if (ret != LDB_SUCCESS) {
1117                         print_error(__location__": unlock_read returned (%d)\n",
1118                                     ret);
1119                         exit(ret);
1120                 }
1121
1122
1123                 /*
1124                  * Check that KEY2 is there
1125                  */
1126                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1127                 if (ret != LDB_SUCCESS) {
1128                         print_error(__location__": unlock_read returned (%d)\n",
1129                                     ret);
1130                         exit(ret);
1131                 }
1132
1133                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1134                 key.length = strlen(KEY2) + 1;
1135
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 "
1139                                     "(%d)\n",
1140                                     ret);
1141                         exit(ret);
1142                 }
1143
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);
1149                 }
1150                 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1151                         print_error(__location__": KEY2 values different, "
1152                                     "expected (%s) actual(%s)\n",
1153                                     VAL2,
1154                                     val.data);
1155                         exit(LDB_ERR_OPERATIONS_ERROR);
1156                 }
1157
1158                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1159                 if (ret != LDB_SUCCESS) {
1160                         print_error(__location__": unlock_read returned (%d)\n",
1161                                     ret);
1162                         exit(ret);
1163                 }
1164
1165                 exit(0);
1166         }
1167         close(to_child[0]);
1168         close(to_parent[1]);
1169
1170         /*
1171          * Begin a transaction and add a record to the database
1172          * but leave the transaction open
1173          */
1174         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1175         assert_int_equal(ret, 0);
1176
1177         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1178         key.length = strlen(KEY2) + 1;
1179
1180         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1181         val.length = strlen(VAL2) + 1;
1182
1183         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1184         assert_int_equal(ret, 0);
1185
1186         /*
1187          * Signal the child process
1188          */
1189         ret = write(to_child[1], "GO", 2);
1190         assert_int_equal(2, ret);
1191
1192         /*
1193          * Wait for the child process to check the DB state while the
1194          * transaction is active
1195          */
1196         ret = read(to_parent[0], buf, 2);
1197         assert_int_equal(2, ret);
1198
1199         /*
1200          * commit the transaction
1201          */
1202         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1203         assert_int_equal(0, ret);
1204
1205         /*
1206          * Signal the child process
1207          */
1208         ret = write(to_child[1], "GO", 2);
1209         assert_int_equal(2, ret);
1210
1211         w_pid = waitpid(pid, &wstatus, 0);
1212         assert_int_equal(pid, w_pid);
1213
1214         assert_true(WIFEXITED(wstatus));
1215
1216         assert_int_equal(WEXITSTATUS(wstatus), 0);
1217
1218
1219         TALLOC_FREE(tmp_ctx);
1220 }
1221
1222 /*
1223  * Ensure that deletes are not visible until the transaction has been
1224  * committed.
1225  */
1226 static void test_delete_transaction_isolation(void **state)
1227 {
1228         int ret;
1229         struct test_ctx *test_ctx = talloc_get_type_abort(*state,
1230                                                           struct test_ctx);
1231         struct ldb_kv_private *ldb_kv = get_ldb_kv(test_ctx->ldb);
1232         struct ldb_val key;
1233         struct ldb_val val;
1234
1235         const char *KEY1 = "KEY01";
1236         const char *VAL1 = "VALUE01";
1237
1238         const char *KEY2 = "KEY02";
1239         const char *VAL2 = "VALUE02";
1240
1241         /*
1242          * Pipes etc to co-ordinate the processes
1243          */
1244         int to_child[2];
1245         int to_parent[2];
1246         char buf[2];
1247         pid_t pid, w_pid;
1248         int wstatus;
1249
1250         TALLOC_CTX *tmp_ctx;
1251         tmp_ctx = talloc_new(test_ctx);
1252         assert_non_null(tmp_ctx);
1253
1254
1255         /*
1256          * Add records to the database
1257          */
1258         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1259         assert_int_equal(ret, 0);
1260
1261         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1262         key.length = strlen(KEY1) + 1;
1263
1264         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
1265         val.length = strlen(VAL1) + 1;
1266
1267         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1268         assert_int_equal(ret, 0);
1269
1270         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1271         key.length = strlen(KEY2) + 1;
1272
1273         val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1274         val.length = strlen(VAL2) + 1;
1275
1276         ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1277         assert_int_equal(ret, 0);
1278
1279         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1280         assert_int_equal(ret, 0);
1281
1282
1283         ret = pipe(to_child);
1284         assert_int_equal(ret, 0);
1285         ret = pipe(to_parent);
1286         assert_int_equal(ret, 0);
1287         /*
1288          * Now fork a new process
1289          */
1290
1291         pid = fork();
1292         if (pid == 0) {
1293
1294                 struct ldb_context *ldb = NULL;
1295                 close(to_child[1]);
1296                 close(to_parent[0]);
1297
1298                 /*
1299                  * Wait for the transaction to be started
1300                  */
1301                 ret = read(to_child[0], buf, 2);
1302                 if (ret != 2) {
1303                         print_error(__location__": read returned (%d)\n",
1304                                     ret);
1305                         exit(LDB_ERR_OPERATIONS_ERROR);
1306                 }
1307
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",
1312                                     ret);
1313                         exit(ret);
1314                 }
1315
1316                 ldb_kv = get_ldb_kv(ldb);
1317
1318                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1319                 if (ret != LDB_SUCCESS) {
1320                         print_error(__location__": lock_read returned (%d)\n",
1321                                     ret);
1322                         exit(ret);
1323                 }
1324
1325                 /*
1326                  * Check that KEY1 is there
1327                  */
1328                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1329                 key.length = strlen(KEY1) + 1;
1330
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 "
1334                                     "(%d)\n",
1335                                     ret);
1336                         exit(ret);
1337                 }
1338
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);
1344                 }
1345                 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1346                         print_error(__location__": KEY1 values different, "
1347                                     "expected (%s) actual(%s)\n",
1348                                     VAL1,
1349                                     val.data);
1350                         exit(LDB_ERR_OPERATIONS_ERROR);
1351                 }
1352
1353                 /*
1354                  * Check that KEY2 is there
1355                  */
1356
1357                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1358                 key.length = strlen(KEY2) + 1;
1359
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 "
1363                                     "(%d)\n",
1364                                     ret);
1365                         exit(ret);
1366                 }
1367
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);
1373                 }
1374                 if (memcmp(VAL2, val.data, strlen(VAL2)) != 0) {
1375                         print_error(__location__": KEY2 values different, "
1376                                     "expected (%s) actual(%s)\n",
1377                                     VAL2,
1378                                     val.data);
1379                         exit(LDB_ERR_OPERATIONS_ERROR);
1380                 }
1381
1382                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1383                 if (ret != LDB_SUCCESS) {
1384                         print_error(__location__": unlock_read returned (%d)\n",
1385                                     ret);
1386                         exit(ret);
1387                 }
1388
1389                 /*
1390                  * Signal the other process to commit the transaction
1391                  */
1392                 ret = write(to_parent[1], "GO", 2);
1393                 if (ret != 2) {
1394                         print_error(__location__": write returned (%d)\n",
1395                                     ret);
1396                         exit(LDB_ERR_OPERATIONS_ERROR);
1397                 }
1398
1399                 /*
1400                  * Wait for the transaction to be commited
1401                  */
1402                 ret = read(to_child[0], buf, 2);
1403                 if (ret != 2) {
1404                         print_error(__location__": read returned (%d)\n",
1405                                     ret);
1406                         exit(LDB_ERR_OPERATIONS_ERROR);
1407                 }
1408
1409                 /*
1410                  * Check that KEY1 is there
1411                  */
1412                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1413                 if (ret != LDB_SUCCESS) {
1414                         print_error(__location__": unlock_read returned (%d)\n",
1415                                     ret);
1416                         exit(ret);
1417                 }
1418                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1419                 key.length = strlen(KEY1) + 1;
1420
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 "
1424                                     "(%d)\n",
1425                                     ret);
1426                         exit(ret);
1427                 }
1428
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);
1434                 }
1435                 if (memcmp(VAL1, val.data, strlen(VAL1)) != 0) {
1436                         print_error(__location__": KEY1 values different, "
1437                                     "expected (%s) actual(%s)\n",
1438                                     VAL1,
1439                                     val.data);
1440                         exit(LDB_ERR_OPERATIONS_ERROR);
1441                 }
1442
1443                 /*
1444                  * Check that KEY2 is not there
1445                  */
1446                 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1447                 key.length = strlen(KEY2 + 1);
1448
1449                 ret = ldb_kv->kv_ops->lock_read(ldb->modules);
1450                 if (ret != LDB_SUCCESS) {
1451                         print_error(__location__": lock_read returned (%d)\n",
1452                                     ret);
1453                         exit(ret);
1454                 }
1455
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 "
1459                                     "(%d)\n",
1460                                     ret);
1461                         exit(ret);
1462                 }
1463
1464                 ret = ldb_kv->kv_ops->unlock_read(ldb->modules);
1465                 if (ret != LDB_SUCCESS) {
1466                         print_error(__location__": unlock_read returned (%d)\n",
1467                                     ret);
1468                         exit(ret);
1469                 }
1470
1471                 exit(0);
1472         }
1473         close(to_child[0]);
1474         close(to_parent[1]);
1475
1476         /*
1477          * Begin a transaction and delete a record from the database
1478          * but leave the transaction open
1479          */
1480         ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1481         assert_int_equal(ret, 0);
1482
1483         key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1484         key.length = strlen(KEY2) + 1;
1485
1486         ret = ldb_kv->kv_ops->delete (ldb_kv, key);
1487         assert_int_equal(ret, 0);
1488         /*
1489          * Signal the child process
1490          */
1491         ret = write(to_child[1], "GO", 2);
1492         assert_int_equal(2, ret);
1493
1494         /*
1495          * Wait for the child process to check the DB state while the
1496          * transaction is active
1497          */
1498         ret = read(to_parent[0], buf, 2);
1499         assert_int_equal(2, ret);
1500
1501         /*
1502          * commit the transaction
1503          */
1504         ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1505         assert_int_equal(0, ret);
1506
1507         /*
1508          * Signal the child process
1509          */
1510         ret = write(to_child[1], "GO", 2);
1511         assert_int_equal(2, ret);
1512
1513         w_pid = waitpid(pid, &wstatus, 0);
1514         assert_int_equal(pid, w_pid);
1515
1516         assert_true(WIFEXITED(wstatus));
1517
1518         assert_int_equal(WEXITSTATUS(wstatus), 0);
1519
1520
1521         TALLOC_FREE(tmp_ctx);
1522 }
1523
1524
1525 int main(int argc, const char **argv)
1526 {
1527         const struct CMUnitTest tests[] = {
1528                 cmocka_unit_test_setup_teardown(
1529                         test_add_get,
1530                         setup,
1531                         teardown),
1532                 cmocka_unit_test_setup_teardown(
1533                         test_delete,
1534                         setup,
1535                         teardown),
1536                 cmocka_unit_test_setup_teardown(
1537                         test_transaction_abort_write,
1538                         setup,
1539                         teardown),
1540                 cmocka_unit_test_setup_teardown(
1541                         test_transaction_abort_delete,
1542                         setup,
1543                         teardown),
1544                 cmocka_unit_test_setup_teardown(
1545                         test_read_outside_transaction,
1546                         setup,
1547                         teardown),
1548                 cmocka_unit_test_setup_teardown(
1549                         test_write_outside_transaction,
1550                         setup,
1551                         teardown),
1552                 cmocka_unit_test_setup_teardown(
1553                         test_delete_outside_transaction,
1554                         setup,
1555                         teardown),
1556                 cmocka_unit_test_setup_teardown(
1557                         test_iterate,
1558                         setup,
1559                         teardown),
1560                 cmocka_unit_test_setup_teardown(
1561                         test_update_in_iterate,
1562                         setup,
1563                         teardown),
1564                 cmocka_unit_test_setup_teardown(
1565                         test_write_transaction_isolation,
1566                         setup,
1567                         teardown),
1568                 cmocka_unit_test_setup_teardown(
1569                         test_delete_transaction_isolation,
1570                         setup,
1571                         teardown),
1572         };
1573
1574         return cmocka_run_group_tests(tests, NULL, NULL);
1575 }