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 * - 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.
49 */
50 #include <stdarg.h>
51 #include <stddef.h>
52 #include <stdint.h>
53 #include <setjmp.h>
54 #include <cmocka.h>
55
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>
65
66 #include <sys/wait.h>
67
68 #include "ldb_tdb/ldb_tdb.h"
69 #include "ldb_key_value/ldb_kv.h"
70
71
72 #define DEFAULT_BE "tdb"
73
74 #ifndef TEST_BE
75 #define TEST_BE DEFAULT_BE
76 #endif /* TEST_BE */
77
78 #define NUM_RECS 1024
79
80
81 struct test_ctx {
82 struct tevent_context *ev;
83 struct ldb_context *ldb;
84
85 const char *dbfile;
86 const char *lockfile; /* lockfile is separate */
87
88 const char *dbpath;
89 };
90
unlink_old_db(struct test_ctx * test_ctx)91 static void unlink_old_db(struct test_ctx *test_ctx)
92 {
93 int ret;
94
95 errno = 0;
96 ret = unlink(test_ctx->lockfile);
97 if (ret == -1 && errno != ENOENT) {
98 fail();
99 }
100
101 errno = 0;
102 ret = unlink(test_ctx->dbfile);
103 if (ret == -1 && errno != ENOENT) {
104 fail();
105 }
106 }
107
noconn_setup(void ** state)108 static int noconn_setup(void **state)
109 {
110 struct test_ctx *test_ctx;
111
112 test_ctx = talloc_zero(NULL, struct test_ctx);
113 assert_non_null(test_ctx);
114
115 test_ctx->ev = tevent_context_init(test_ctx);
116 assert_non_null(test_ctx->ev);
117
118 test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
119 assert_non_null(test_ctx->ldb);
120
121 test_ctx->dbfile = talloc_strdup(test_ctx, "kvopstest.ldb");
122 assert_non_null(test_ctx->dbfile);
123
124 test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
125 test_ctx->dbfile);
126 assert_non_null(test_ctx->lockfile);
127
128 test_ctx->dbpath = talloc_asprintf(test_ctx,
129 TEST_BE"://%s", test_ctx->dbfile);
130 assert_non_null(test_ctx->dbpath);
131
132 unlink_old_db(test_ctx);
133 *state = test_ctx;
134 return 0;
135 }
136
noconn_teardown(void ** state)137 static int noconn_teardown(void **state)
138 {
139 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
140 struct test_ctx);
141
142 unlink_old_db(test_ctx);
143 talloc_free(test_ctx);
144 return 0;
145 }
146
setup(void ** state)147 static int setup(void **state)
148 {
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";
157
158 noconn_setup((void **) &test_ctx);
159
160 ret = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
161 assert_int_equal(ret, 0);
162
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);
166 }
167 *state = test_ctx;
168 return 0;
169 }
170
teardown(void ** state)171 static int teardown(void **state)
172 {
173 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
174 struct test_ctx);
175 noconn_teardown((void **) &test_ctx);
176 return 0;
177 }
178
get_ldb_kv(struct ldb_context * ldb)179 static struct ldb_kv_private *get_ldb_kv(struct ldb_context *ldb)
180 {
181 void *data = NULL;
182 struct ldb_kv_private *ldb_kv = NULL;
183
184 data = ldb_module_get_private(ldb->modules);
185 assert_non_null(data);
186
187 ldb_kv = talloc_get_type(data, struct ldb_kv_private);
188 assert_non_null(ldb_kv);
189
190 return ldb_kv;
191 }
192
parse(struct ldb_val key,struct ldb_val data,void * private_data)193 static int parse(struct ldb_val key,
194 struct ldb_val data,
195 void *private_data)
196 {
197 struct ldb_val* read = private_data;
198
199 /* Yes, we leak this. That is OK */
200 read->data = talloc_size(NULL,
201 data.length);
202 assert_non_null(read->data);
203
204 memcpy(read->data, data.data, data.length);
205 read->length = data.length;
206 return LDB_SUCCESS;
207 }
208
209 /*
210 * Parse function that just returns the int we pass it.
211 */
parse_return(struct ldb_val key,struct ldb_val data,void * private_data)212 static int parse_return(struct ldb_val key,
213 struct ldb_val data,
214 void *private_data)
215 {
216 int *rcode = private_data;
217 return *rcode;
218 }
219
220 /*
221 * Test that data can be written to the kv store and be read back.
222 */
test_add_get(void ** state)223 static void test_add_get(void **state)
224 {
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)
233 };
234
235 uint8_t value[] = "The record contents";
236 struct ldb_val data = {
237 .data = value,
238 .length = sizeof(value)
239 };
240
241 struct ldb_val read;
242 int rcode;
243
244 int flags = 0;
245 TALLOC_CTX *tmp_ctx;
246
247 tmp_ctx = talloc_new(test_ctx);
248 assert_non_null(tmp_ctx);
249
250 /*
251 * Begin a transaction
252 */
253 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
254 assert_int_equal(ret, 0);
255
256 /*
257 * Write the record
258 */
259 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
260 assert_int_equal(ret, 0);
261
262 /*
263 * Commit the transaction
264 */
265 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
266 assert_int_equal(ret, 0);
267
268 /*
269 * And now read it back
270 */
271 ret = ldb_kv->kv_ops->lock_read(test_ctx->ldb->modules);
272 assert_int_equal(ret, 0);
273
274 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
275 assert_int_equal(ret, 0);
276
277 assert_int_equal(sizeof(value), read.length);
278 assert_memory_equal(value, read.data, sizeof(value));
279
280 /*
281 * Now check that the error code we return in the
282 * parse function is returned by fetch_and_parse.
283 */
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);
289 }
290
291 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
292 assert_int_equal(ret, 0);
293 talloc_free(tmp_ctx);
294 }
295
296 /*
297 * Test that attempts to read data without a read transaction fail.
298 */
test_read_outside_transaction(void ** state)299 static void test_read_outside_transaction(void **state)
300 {
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)
309 };
310
311 uint8_t value[] = "The record contents";
312 struct ldb_val data = {
313 .data = value,
314 .length = sizeof(value)
315 };
316
317 struct ldb_val read;
318
319 int flags = 0;
320 TALLOC_CTX *tmp_ctx;
321
322 tmp_ctx = talloc_new(test_ctx);
323 assert_non_null(tmp_ctx);
324
325 /*
326 * Begin a transaction
327 */
328 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
329 assert_int_equal(ret, 0);
330
331 /*
332 * Write the record
333 */
334 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
335 assert_int_equal(ret, 0);
336
337 /*
338 * Commit the transaction
339 */
340 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
341 assert_int_equal(ret, 0);
342
343 /*
344 * And now read it back
345 * Note there is no read transaction active
346 */
347 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
348 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
349
350 talloc_free(tmp_ctx);
351 }
352
353 /*
354 * Test that data can be deleted from the kv store
355 */
test_delete(void ** state)356 static void test_delete(void **state)
357 {
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)
366 };
367
368 uint8_t value[] = "The record contents";
369 struct ldb_val data = {
370 .data = value,
371 .length = sizeof(value)
372 };
373
374 struct ldb_val read;
375
376 int flags = 0;
377 TALLOC_CTX *tmp_ctx;
378
379 tmp_ctx = talloc_new(test_ctx);
380 assert_non_null(tmp_ctx);
381
382 /*
383 * Begin a transaction
384 */
385 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
386 assert_int_equal(ret, 0);
387
388 /*
389 * Write the record
390 */
391 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
392 assert_int_equal(ret, 0);
393
394 /*
395 * Commit the transaction
396 */
397 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
398 assert_int_equal(ret, 0);
399
400 /*
401 * And now read it back
402 */
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);
411
412 /*
413 * Begin a transaction
414 */
415 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
416 assert_int_equal(ret, 0);
417
418 /*
419 * Now delete it.
420 */
421 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
422 assert_int_equal(ret, 0);
423
424 /*
425 * Commit the transaction
426 */
427 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
428 assert_int_equal(ret, 0);
429
430 /*
431 * And now try to read it back
432 */
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);
439
440 talloc_free(tmp_ctx);
441 }
442
443 /*
444 * Check that writes are correctly rolled back when a transaction
445 * is rolled back.
446 */
test_transaction_abort_write(void ** state)447 static void test_transaction_abort_write(void **state)
448 {
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)
457 };
458
459 uint8_t value[] = "The record contents";
460 struct ldb_val data = {
461 .data = value,
462 .length = sizeof(value)
463 };
464
465 struct ldb_val read;
466
467 int flags = 0;
468 TALLOC_CTX *tmp_ctx;
469
470 tmp_ctx = talloc_new(test_ctx);
471 assert_non_null(tmp_ctx);
472
473 /*
474 * Begin a transaction
475 */
476 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
477 assert_int_equal(ret, 0);
478
479 /*
480 * Write the record
481 */
482 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
483 assert_int_equal(ret, 0);
484
485 /*
486 * And now read it back
487 */
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));
492
493
494 /*
495 * Now abort the transaction
496 */
497 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
498 assert_int_equal(ret, 0);
499
500 /*
501 * And now read it back, should not be there
502 */
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);
509
510 talloc_free(tmp_ctx);
511 }
512
513 /*
514 * Check that deletes are correctly rolled back when a transaction is
515 * aborted.
516 */
test_transaction_abort_delete(void ** state)517 static void test_transaction_abort_delete(void **state)
518 {
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)
527 };
528
529 uint8_t value[] = "The record contents";
530 struct ldb_val data = {
531 .data = value,
532 .length = sizeof(value)
533 };
534
535 struct ldb_val read;
536
537 int flags = 0;
538 TALLOC_CTX *tmp_ctx;
539
540 tmp_ctx = talloc_new(test_ctx);
541 assert_non_null(tmp_ctx);
542
543 /*
544 * Begin a transaction
545 */
546 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
547 assert_int_equal(ret, 0);
548
549 /*
550 * Write the record
551 */
552 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
553 assert_int_equal(ret, 0);
554
555 /*
556 * Commit the transaction
557 */
558 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
559 assert_int_equal(ret, 0);
560
561 /*
562 * And now read it back
563 */
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);
572
573 /*
574 * Begin a transaction
575 */
576 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
577 assert_int_equal(ret, 0);
578
579 /*
580 * Now delete it.
581 */
582 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
583 assert_int_equal(ret, 0);
584
585 /*
586 * And now read it back
587 */
588 ret = ldb_kv->kv_ops->fetch_and_parse(ldb_kv, key, parse, &read);
589 assert_int_equal(ret, LDB_ERR_NO_SUCH_OBJECT);
590
591 /*
592 * Abort the transaction
593 */
594 ret = ldb_kv->kv_ops->abort_write(ldb_kv);
595 assert_int_equal(ret, 0);
596
597 /*
598 * And now try to read it back
599 */
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);
608
609 talloc_free(tmp_ctx);
610 }
611
612 /*
613 * Test that writes outside a transaction fail
614 */
test_write_outside_transaction(void ** state)615 static void test_write_outside_transaction(void **state)
616 {
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)
625 };
626
627 uint8_t value[] = "The record contents";
628 struct ldb_val data = {
629 .data = value,
630 .length = sizeof(value)
631 };
632
633
634 int flags = 0;
635 TALLOC_CTX *tmp_ctx;
636
637 tmp_ctx = talloc_new(test_ctx);
638 assert_non_null(tmp_ctx);
639
640 /*
641 * Attempt to write the record
642 */
643 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
644 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
645
646 talloc_free(tmp_ctx);
647 }
648
649 /*
650 * Test data can not be deleted outside a transaction
651 */
test_delete_outside_transaction(void ** state)652 static void test_delete_outside_transaction(void **state)
653 {
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)
662 };
663
664 uint8_t value[] = "The record contents";
665 struct ldb_val data = {
666 .data = value,
667 .length = sizeof(value)
668 };
669
670 struct ldb_val read;
671
672 int flags = 0;
673 TALLOC_CTX *tmp_ctx;
674
675 tmp_ctx = talloc_new(test_ctx);
676 assert_non_null(tmp_ctx);
677
678 /*
679 * Begin a transaction
680 */
681 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
682 assert_int_equal(ret, 0);
683
684 /*
685 * Write the record
686 */
687 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
688 assert_int_equal(ret, 0);
689
690 /*
691 * Commit the transaction
692 */
693 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
694 assert_int_equal(ret, 0);
695
696 /*
697 * And now read it back
698 */
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);
707
708 /*
709 * Now attempt to delete a record
710 */
711 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
712 assert_int_equal(ret, LDB_ERR_PROTOCOL_ERROR);
713
714 /*
715 * And now read it back
716 */
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);
725
726 talloc_free(tmp_ctx);
727 }
728
traverse_fn(struct ldb_kv_private * ldb_kv,struct ldb_val key,struct ldb_val data,void * 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)
733 {
734
735 int *visits = ctx;
736 int i;
737
738 if (strncmp("key ", (char *) key.data, 4) == 0) {
739 i = strtol((char *) &key.data[4], NULL, 10);
740 visits[i]++;
741 }
742 return LDB_SUCCESS;
743 }
744
745 /*
746 * Test that iterate visits all the records.
747 */
test_iterate(void ** state)748 static void test_iterate(void **state)
749 {
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];
757
758 TALLOC_CTX *tmp_ctx;
759
760 tmp_ctx = talloc_new(test_ctx);
761 assert_non_null(tmp_ctx);
762
763 /*
764 * Begin a transaction
765 */
766 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
767 assert_int_equal(ret, 0);
768
769 /*
770 * Write the records
771 */
772 for (i = 0; i < num_recs; i++) {
773 struct ldb_val key;
774 struct ldb_val rec;
775 int flags = 0;
776
777 visits[i] = 0;
778 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
779 key.length = strlen((char *)key.data) + 1;
780
781 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
782 "data for record (%04d)",
783 i);
784 rec.length = strlen((char *)rec.data) + 1;
785
786 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
787 assert_int_equal(ret, 0);
788
789 TALLOC_FREE(key.data);
790 TALLOC_FREE(rec.data);
791 }
792
793 /*
794 * Commit the transaction
795 */
796 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
797 assert_int_equal(ret, 0);
798
799 /*
800 * Now iterate over the kv store and ensure that all the
801 * records are visited.
802 */
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]);
808 }
809 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
810 assert_int_equal(ret, 0);
811
812 TALLOC_FREE(tmp_ctx);
813 }
814
do_iterate_range_test(void ** state,int range_start,int range_end,bool fail)815 static void do_iterate_range_test(void **state, int range_start,
816 int range_end, bool fail)
817 {
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;
827
828 TALLOC_CTX *tmp_ctx;
829
830 ldb_kv = get_ldb_kv(test_ctx->ldb);
831 assert_non_null(ldb_kv);
832
833 for (i = 0; i < num_recs; i++){
834 visits[i] = 0;
835 }
836
837 /*
838 * No iterate_range on tdb
839 */
840 if (strcmp(TEST_BE, "tdb") == 0) {
841 return;
842 }
843
844 tmp_ctx = talloc_new(test_ctx);
845 assert_non_null(tmp_ctx);
846
847 /*
848 * Begin a transaction
849 */
850 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
851 assert_int_equal(ret, 0);
852
853 /*
854 * Write the records
855 */
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;
860
861 key.data = (uint8_t *)talloc_asprintf(tmp_ctx,
862 "key %04d",
863 i);
864 key.length = strlen((char *)key.data);
865
866 rec.data = (uint8_t *)talloc_asprintf(tmp_ctx,
867 "data for record (%04d)",
868 i);
869 rec.length = strlen((char *)rec.data) + 1;
870
871 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
872 assert_int_equal(ret, 0);
873
874 TALLOC_FREE(key.data);
875 TALLOC_FREE(rec.data);
876 }
877
878 /*
879 * Commit the transaction
880 */
881 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
882 assert_int_equal(ret, 0);
883
884 sk.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_start);
885 sk.length = strlen((char *)sk.data);
886
887 ek.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", range_end);
888 ek.length = strlen((char *)ek.data) + 1;
889
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);
900 }
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]);
907 }
908 }
909
910 ret = ldb_kv->kv_ops->unlock_read(test_ctx->ldb->modules);
911 assert_int_equal(ret, 0);
912
913 TALLOC_FREE(tmp_ctx);
914 }
915
916 /*
917 * Test that iterate_range visits all the records between two keys.
918 */
test_iterate_range(void ** state)919 static void test_iterate_range(void **state)
920 {
921 do_iterate_range_test(state, 300, 900, false);
922
923 /*
924 * test start_key = end_key
925 */
926 do_iterate_range_test(state, 20, 20, false);
927
928 /*
929 * test reverse range fails
930 */
931 do_iterate_range_test(state, 50, 40, true);
932
933 /*
934 * keys are between 10-1014 so test with keys outside that range
935 */
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);
939 }
940
941 struct update_context {
942 struct ldb_context* ldb;
943 int visits[NUM_RECS];
944 };
945
update_fn(struct ldb_kv_private * ldb_kv,struct ldb_val key,struct ldb_val data,void * ctx)946 static int update_fn(struct ldb_kv_private *ldb_kv,
947 struct ldb_val key,
948 struct ldb_val data,
949 void *ctx)
950 {
951
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;
957
958 tmp_ctx = talloc_new(ldb_kv);
959 assert_non_null(tmp_ctx);
960
961 context = talloc_get_type_abort(ctx, struct update_context);
962
963 module = talloc_zero(tmp_ctx, struct ldb_module);
964 module->ldb = context->ldb;
965
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';
972
973 ret = ldb_kv->kv_ops->update_in_iterate(
974 ldb_kv, key, new_key, data, &module);
975 }
976 TALLOC_FREE(tmp_ctx);
977 return ret;
978 }
979
980 /*
981 * Test that update_in_iterate behaves as expected.
982 */
test_update_in_iterate(void ** state)983 static void test_update_in_iterate(void **state)
984 {
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;
991
992
993 TALLOC_CTX *tmp_ctx;
994
995 tmp_ctx = talloc_new(test_ctx);
996 assert_non_null(tmp_ctx);
997
998 context = talloc_zero(tmp_ctx, struct update_context);
999 assert_non_null(context);
1000 context->ldb = test_ctx->ldb;
1001 /*
1002 * Begin a transaction
1003 */
1004 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1005 assert_int_equal(ret, 0);
1006
1007 /*
1008 * Write the records
1009 */
1010 for (i = 0; i < NUM_RECS; i++) {
1011 struct ldb_val key;
1012 struct ldb_val rec;
1013 int flags = 0;
1014
1015 key.data = (uint8_t *)talloc_asprintf(tmp_ctx, "key %04d", i);
1016 key.length = strlen((char *)key.data) + 1;
1017
1018 rec.data = (uint8_t *) talloc_asprintf(tmp_ctx,
1019 "data for record (%04d)",
1020 i);
1021 rec.length = strlen((char *)rec.data) + 1;
1022
1023 ret = ldb_kv->kv_ops->store(ldb_kv, key, rec, flags);
1024 assert_int_equal(ret, 0);
1025
1026 TALLOC_FREE(key.data);
1027 TALLOC_FREE(rec.data);
1028 }
1029
1030 /*
1031 * Commit the transaction
1032 */
1033 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1034 assert_int_equal(ret, 0);
1035
1036 /*
1037 * Now iterate over the kv store and ensure that all the
1038 * records are visited.
1039 */
1040
1041 /*
1042 * Needs to be done inside a transaction
1043 */
1044 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1045 assert_int_equal(ret, 0);
1046
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]);
1050 }
1051
1052 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1053 assert_int_equal(ret, 0);
1054
1055 TALLOC_FREE(tmp_ctx);
1056 }
1057
1058 /*
1059 * Ensure that writes are not visible until the transaction has been
1060 * committed.
1061 */
test_write_transaction_isolation(void ** state)1062 static void test_write_transaction_isolation(void **state)
1063 {
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;
1070
1071 const char *KEY1 = "KEY01";
1072 const char *VAL1 = "VALUE01";
1073
1074 const char *KEY2 = "KEY02";
1075 const char *VAL2 = "VALUE02";
1076
1077 /*
1078 * Pipes etc to co-ordinate the processes
1079 */
1080 int to_child[2];
1081 int to_parent[2];
1082 char buf[2];
1083 pid_t pid, w_pid;
1084 int wstatus;
1085
1086 TALLOC_CTX *tmp_ctx;
1087 tmp_ctx = talloc_new(test_ctx);
1088 assert_non_null(tmp_ctx);
1089
1090
1091 /*
1092 * Add a record to the database
1093 */
1094 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1095 assert_int_equal(ret, 0);
1096
1097 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1098 key.length = strlen(KEY1) + 1;
1099
1100 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
1101 val.length = strlen(VAL1) + 1;
1102
1103 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1104 assert_int_equal(ret, 0);
1105
1106 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1107 assert_int_equal(ret, 0);
1108
1109
1110 ret = pipe(to_child);
1111 assert_int_equal(ret, 0);
1112 ret = pipe(to_parent);
1113 assert_int_equal(ret, 0);
1114 /*
1115 * Now fork a new process
1116 */
1117
1118 pid = fork();
1119 if (pid == 0) {
1120
1121 struct ldb_context *ldb = NULL;
1122 close(to_child[1]);
1123 close(to_parent[0]);
1124
1125 /*
1126 * Wait for the transaction to start
1127 */
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);
1133 }
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);
1140 }
1141
1142 ldb_kv = get_ldb_kv(ldb);
1143
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);
1149 }
1150
1151 /*
1152 * Check that KEY1 is there
1153 */
1154 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1155 key.length = strlen(KEY1) + 1;
1156
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);
1163 }
1164
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);
1170 }
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);
1177 }
1178
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);
1184 }
1185
1186 /*
1187 * Check that KEY2 is not there
1188 */
1189 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1190 key.length = strlen(KEY2 + 1);
1191
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);
1197 }
1198
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);
1205 }
1206
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);
1212 }
1213
1214 /*
1215 * Signal the other process to commit the transaction
1216 */
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);
1222 }
1223
1224 /*
1225 * Wait for the transaction to be commited
1226 */
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);
1232 }
1233
1234 /*
1235 * Check that KEY1 is there
1236 */
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);
1242 }
1243 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1244 key.length = strlen(KEY1) + 1;
1245
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);
1252 }
1253
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);
1259 }
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);
1266 }
1267
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);
1273 }
1274
1275
1276 /*
1277 * Check that KEY2 is there
1278 */
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);
1284 }
1285
1286 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1287 key.length = strlen(KEY2) + 1;
1288
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);
1295 }
1296
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);
1302 }
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);
1309 }
1310
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);
1316 }
1317
1318 exit(0);
1319 }
1320 close(to_child[0]);
1321 close(to_parent[1]);
1322
1323 /*
1324 * Begin a transaction and add a record to the database
1325 * but leave the transaction open
1326 */
1327 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1328 assert_int_equal(ret, 0);
1329
1330 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1331 key.length = strlen(KEY2) + 1;
1332
1333 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1334 val.length = strlen(VAL2) + 1;
1335
1336 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1337 assert_int_equal(ret, 0);
1338
1339 /*
1340 * Signal the child process
1341 */
1342 ret = write(to_child[1], "GO", 2);
1343 assert_int_equal(2, ret);
1344
1345 /*
1346 * Wait for the child process to check the DB state while the
1347 * transaction is active
1348 */
1349 ret = read(to_parent[0], buf, 2);
1350 assert_int_equal(2, ret);
1351
1352 /*
1353 * commit the transaction
1354 */
1355 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1356 assert_int_equal(0, ret);
1357
1358 /*
1359 * Signal the child process
1360 */
1361 ret = write(to_child[1], "GO", 2);
1362 assert_int_equal(2, ret);
1363
1364 w_pid = waitpid(pid, &wstatus, 0);
1365 assert_int_equal(pid, w_pid);
1366
1367 assert_true(WIFEXITED(wstatus));
1368
1369 assert_int_equal(WEXITSTATUS(wstatus), 0);
1370
1371
1372 TALLOC_FREE(tmp_ctx);
1373 }
1374
1375 /*
1376 * Ensure that deletes are not visible until the transaction has been
1377 * committed.
1378 */
test_delete_transaction_isolation(void ** state)1379 static void test_delete_transaction_isolation(void **state)
1380 {
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;
1387
1388 const char *KEY1 = "KEY01";
1389 const char *VAL1 = "VALUE01";
1390
1391 const char *KEY2 = "KEY02";
1392 const char *VAL2 = "VALUE02";
1393
1394 /*
1395 * Pipes etc to co-ordinate the processes
1396 */
1397 int to_child[2];
1398 int to_parent[2];
1399 char buf[2];
1400 pid_t pid, w_pid;
1401 int wstatus;
1402
1403 TALLOC_CTX *tmp_ctx;
1404 tmp_ctx = talloc_new(test_ctx);
1405 assert_non_null(tmp_ctx);
1406
1407
1408 /*
1409 * Add records to the database
1410 */
1411 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1412 assert_int_equal(ret, 0);
1413
1414 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1415 key.length = strlen(KEY1) + 1;
1416
1417 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL1);
1418 val.length = strlen(VAL1) + 1;
1419
1420 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1421 assert_int_equal(ret, 0);
1422
1423 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1424 key.length = strlen(KEY2) + 1;
1425
1426 val.data = (uint8_t *)talloc_strdup(tmp_ctx, VAL2);
1427 val.length = strlen(VAL2) + 1;
1428
1429 ret = ldb_kv->kv_ops->store(ldb_kv, key, val, 0);
1430 assert_int_equal(ret, 0);
1431
1432 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1433 assert_int_equal(ret, 0);
1434
1435
1436 ret = pipe(to_child);
1437 assert_int_equal(ret, 0);
1438 ret = pipe(to_parent);
1439 assert_int_equal(ret, 0);
1440 /*
1441 * Now fork a new process
1442 */
1443
1444 pid = fork();
1445 if (pid == 0) {
1446
1447 struct ldb_context *ldb = NULL;
1448 close(to_child[1]);
1449 close(to_parent[0]);
1450
1451 /*
1452 * Wait for the transaction to be started
1453 */
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);
1459 }
1460
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);
1467 }
1468
1469 ldb_kv = get_ldb_kv(ldb);
1470
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);
1476 }
1477
1478 /*
1479 * Check that KEY1 is there
1480 */
1481 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1482 key.length = strlen(KEY1) + 1;
1483
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);
1490 }
1491
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);
1497 }
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);
1504 }
1505
1506 /*
1507 * Check that KEY2 is there
1508 */
1509
1510 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1511 key.length = strlen(KEY2) + 1;
1512
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);
1519 }
1520
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);
1526 }
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);
1533 }
1534
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);
1540 }
1541
1542 /*
1543 * Signal the other process to commit the transaction
1544 */
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);
1550 }
1551
1552 /*
1553 * Wait for the transaction to be commited
1554 */
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);
1560 }
1561
1562 /*
1563 * Check that KEY1 is there
1564 */
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);
1570 }
1571 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY1);
1572 key.length = strlen(KEY1) + 1;
1573
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);
1580 }
1581
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);
1587 }
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);
1594 }
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);
1600 }
1601
1602 /*
1603 * Check that KEY2 is not there
1604 */
1605 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1606 key.length = strlen(KEY2 + 1);
1607
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);
1613 }
1614
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);
1621 }
1622
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);
1628 }
1629 TALLOC_FREE(tmp_ctx);
1630 exit(0);
1631 }
1632 close(to_child[0]);
1633 close(to_parent[1]);
1634
1635 /*
1636 * Begin a transaction and delete a record from the database
1637 * but leave the transaction open
1638 */
1639 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1640 assert_int_equal(ret, 0);
1641
1642 key.data = (uint8_t *)talloc_strdup(tmp_ctx, KEY2);
1643 key.length = strlen(KEY2) + 1;
1644
1645 ret = ldb_kv->kv_ops->delete (ldb_kv, key);
1646 assert_int_equal(ret, 0);
1647 /*
1648 * Signal the child process
1649 */
1650 ret = write(to_child[1], "GO", 2);
1651 assert_int_equal(2, ret);
1652
1653 /*
1654 * Wait for the child process to check the DB state while the
1655 * transaction is active
1656 */
1657 ret = read(to_parent[0], buf, 2);
1658 assert_int_equal(2, ret);
1659
1660 /*
1661 * commit the transaction
1662 */
1663 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1664 assert_int_equal(0, ret);
1665
1666 /*
1667 * Signal the child process
1668 */
1669 ret = write(to_child[1], "GO", 2);
1670 assert_int_equal(2, ret);
1671
1672 w_pid = waitpid(pid, &wstatus, 0);
1673 assert_int_equal(pid, w_pid);
1674
1675 assert_true(WIFEXITED(wstatus));
1676
1677 assert_int_equal(WEXITSTATUS(wstatus), 0);
1678
1679
1680 TALLOC_FREE(tmp_ctx);
1681 }
1682
1683
1684 /*
1685 * Test that get_size returns a sensible estimate of the number of records
1686 * in the database.
1687 */
test_get_size(void ** state)1688 static void test_get_size(void **state)
1689 {
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)
1698 };
1699
1700 uint8_t value[] = "The record contents";
1701 struct ldb_val data = {
1702 .data = value,
1703 .length = sizeof(value)
1704 };
1705 size_t size = 0;
1706
1707 int flags = 0;
1708 TALLOC_CTX *tmp_ctx;
1709
1710 tmp_ctx = talloc_new(test_ctx);
1711 assert_non_null(tmp_ctx);
1712
1713 size = ldb_kv->kv_ops->get_size(ldb_kv);
1714 #if defined(TEST_LMDB)
1715 assert_int_equal(2, size);
1716 #else
1717 /*
1718 * The tdb implementation of get_size over estimates for sparse files
1719 * which is perfectly acceptable for it's intended use.
1720 */
1721 assert_in_range(size, 2500, 5000);
1722 #endif
1723
1724 /*
1725 * Begin a transaction
1726 */
1727 ret = ldb_kv->kv_ops->begin_write(ldb_kv);
1728 assert_int_equal(ret, 0);
1729
1730 /*
1731 * Write the record
1732 */
1733 ret = ldb_kv->kv_ops->store(ldb_kv, key, data, flags);
1734 assert_int_equal(ret, 0);
1735
1736 /*
1737 * Commit the transaction
1738 */
1739 ret = ldb_kv->kv_ops->finish_write(ldb_kv);
1740 assert_int_equal(ret, 0);
1741
1742 size = ldb_kv->kv_ops->get_size(ldb_kv);
1743 #ifdef TEST_LMDB
1744 assert_int_equal(3, size);
1745 #else
1746 /*
1747 * The tdb implementation of get_size over estimates for sparse files
1748 * which is perfectly acceptable for it's intended use.
1749 */
1750 assert_in_range(size, 2500, 5000);
1751 #endif
1752 talloc_free(tmp_ctx);
1753 }
1754
main(int argc,const char ** argv)1755 int main(int argc, const char **argv)
1756 {
1757 const struct CMUnitTest tests[] = {
1758 cmocka_unit_test_setup_teardown(
1759 test_add_get,
1760 setup,
1761 teardown),
1762 cmocka_unit_test_setup_teardown(
1763 test_delete,
1764 setup,
1765 teardown),
1766 cmocka_unit_test_setup_teardown(
1767 test_transaction_abort_write,
1768 setup,
1769 teardown),
1770 cmocka_unit_test_setup_teardown(
1771 test_transaction_abort_delete,
1772 setup,
1773 teardown),
1774 cmocka_unit_test_setup_teardown(
1775 test_read_outside_transaction,
1776 setup,
1777 teardown),
1778 cmocka_unit_test_setup_teardown(
1779 test_write_outside_transaction,
1780 setup,
1781 teardown),
1782 cmocka_unit_test_setup_teardown(
1783 test_delete_outside_transaction,
1784 setup,
1785 teardown),
1786 cmocka_unit_test_setup_teardown(
1787 test_iterate,
1788 setup,
1789 teardown),
1790 cmocka_unit_test_setup_teardown(
1791 test_iterate_range,
1792 setup,
1793 teardown),
1794 cmocka_unit_test_setup_teardown(
1795 test_update_in_iterate,
1796 setup,
1797 teardown),
1798 cmocka_unit_test_setup_teardown(
1799 test_write_transaction_isolation,
1800 setup,
1801 teardown),
1802 cmocka_unit_test_setup_teardown(
1803 test_delete_transaction_isolation,
1804 setup,
1805 teardown),
1806 cmocka_unit_test_setup_teardown(
1807 test_get_size,
1808 setup,
1809 teardown),
1810 };
1811
1812 return cmocka_run_group_tests(tests, NULL, NULL);
1813 }
1814