2 * lmdb backend specific tests for ldb
4 * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 * lmdb backend specific tests for ldb
24 * Setup and tear down code copied from ldb_mod_op_test.c
29 * These headers or their equivalents should be included prior to
37 * This allows test applications to use custom definitions of C standard
38 * library functions and types.
52 #include <ldb_module.h>
53 #include <ldb_private.h>
59 #include "../ldb_tdb/ldb_tdb.h"
60 #include "../ldb_mdb/ldb_mdb.h"
61 #include "../ldb_key_value/ldb_kv.h"
65 #define LMDB_MAX_KEY_SIZE 511
68 struct tevent_context
*ev
;
69 struct ldb_context
*ldb
;
72 const char *lockfile
; /* lockfile is separate */
77 static void unlink_old_db(struct ldbtest_ctx
*test_ctx
)
82 ret
= unlink(test_ctx
->lockfile
);
83 if (ret
== -1 && errno
!= ENOENT
) {
88 ret
= unlink(test_ctx
->dbfile
);
89 if (ret
== -1 && errno
!= ENOENT
) {
94 static int ldbtest_noconn_setup(void **state
)
96 struct ldbtest_ctx
*test_ctx
;
98 test_ctx
= talloc_zero(NULL
, struct ldbtest_ctx
);
99 assert_non_null(test_ctx
);
101 test_ctx
->ev
= tevent_context_init(test_ctx
);
102 assert_non_null(test_ctx
->ev
);
104 test_ctx
->ldb
= ldb_init(test_ctx
, test_ctx
->ev
);
105 assert_non_null(test_ctx
->ldb
);
107 test_ctx
->dbfile
= talloc_strdup(test_ctx
, "apitest.ldb");
108 assert_non_null(test_ctx
->dbfile
);
110 test_ctx
->lockfile
= talloc_asprintf(test_ctx
, "%s-lock",
112 assert_non_null(test_ctx
->lockfile
);
114 test_ctx
->dbpath
= talloc_asprintf(test_ctx
,
115 TEST_BE
"://%s", test_ctx
->dbfile
);
116 assert_non_null(test_ctx
->dbpath
);
118 unlink_old_db(test_ctx
);
123 static int ldbtest_noconn_teardown(void **state
)
125 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
128 unlink_old_db(test_ctx
);
129 talloc_free(test_ctx
);
133 static int ldbtest_setup(void **state
)
135 struct ldbtest_ctx
*test_ctx
;
137 struct ldb_ldif
*ldif
;
138 const char *index_ldif
= \
140 "@IDXGUID: objectUUID\n"
141 "@IDX_DN_GUID: GUID\n"
144 ldbtest_noconn_setup((void **) &test_ctx
);
146 ret
= ldb_connect(test_ctx
->ldb
, test_ctx
->dbpath
, 0, NULL
);
147 assert_int_equal(ret
, 0);
149 while ((ldif
= ldb_ldif_read_string(test_ctx
->ldb
, &index_ldif
))) {
150 ret
= ldb_add(test_ctx
->ldb
, ldif
->msg
);
151 assert_int_equal(ret
, LDB_SUCCESS
);
157 static int ldbtest_teardown(void **state
)
159 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
161 ldbtest_noconn_teardown((void **) &test_ctx
);
165 static void test_ldb_add_key_len_gt_max(void **state
)
169 struct ldb_message
*msg
;
170 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
175 tmp_ctx
= talloc_new(test_ctx
);
176 assert_non_null(tmp_ctx
);
178 msg
= ldb_msg_new(tmp_ctx
);
179 assert_non_null(msg
);
182 * The zero terminator is part of the key if we were not in
186 xs_size
= LMDB_MAX_KEY_SIZE
- 7; /* "dn=dc=" and the zero terminator */
187 xs_size
+= 1; /* want key on char too long */
188 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
189 memset(xs
, 'x', xs_size
);
191 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "dc=%s", xs
);
192 assert_non_null(msg
->dn
);
194 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
195 assert_int_equal(ret
, 0);
197 ret
= ldb_msg_add_string(msg
, "objectUUID", "0123456789abcdef");
198 assert_int_equal(ret
, 0);
200 ret
= ldb_add(test_ctx
->ldb
, msg
);
201 assert_int_equal(ret
, LDB_SUCCESS
);
203 talloc_free(tmp_ctx
);
206 static void test_ldb_add_key_len_2x_gt_max(void **state
)
210 struct ldb_message
*msg
;
211 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
216 tmp_ctx
= talloc_new(test_ctx
);
217 assert_non_null(tmp_ctx
);
219 msg
= ldb_msg_new(tmp_ctx
);
220 assert_non_null(msg
);
223 * The zero terminator is part of the key if we were not in
227 xs_size
= 2 * LMDB_MAX_KEY_SIZE
;
228 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
229 memset(xs
, 'x', xs_size
);
231 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "dc=%s", xs
);
232 assert_non_null(msg
->dn
);
234 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
235 assert_int_equal(ret
, 0);
237 ret
= ldb_msg_add_string(msg
, "objectUUID", "0123456789abcdef");
238 assert_int_equal(ret
, 0);
240 ret
= ldb_add(test_ctx
->ldb
, msg
);
241 assert_int_equal(ret
, LDB_SUCCESS
);
243 talloc_free(tmp_ctx
);
246 static void test_ldb_add_key_len_eq_max(void **state
)
250 struct ldb_message
*msg
;
251 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
256 tmp_ctx
= talloc_new(test_ctx
);
257 assert_non_null(tmp_ctx
);
259 msg
= ldb_msg_new(tmp_ctx
);
260 assert_non_null(msg
);
263 * The zero terminator is part of the key if we were not in
267 xs_size
= LMDB_MAX_KEY_SIZE
- 7; /* "dn=dc=" and the zero terminator */
268 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
269 memset(xs
, 'x', xs_size
);
271 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "dc=%s", xs
);
272 assert_non_null(msg
->dn
);
274 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
275 assert_int_equal(ret
, 0);
277 ret
= ldb_msg_add_string(msg
, "objectUUID", "0123456789abcdef");
278 assert_int_equal(ret
, 0);
280 ret
= ldb_add(test_ctx
->ldb
, msg
);
281 assert_int_equal(ret
, 0);
283 talloc_free(tmp_ctx
);
286 static int ldbtest_setup_noguid(void **state
)
288 struct ldbtest_ctx
*test_ctx
;
291 ldbtest_noconn_setup((void **) &test_ctx
);
293 ret
= ldb_connect(test_ctx
->ldb
, test_ctx
->dbpath
, 0, NULL
);
294 assert_int_equal(ret
, 0);
300 static void test_ldb_add_special_key_len_gt_max(void **state
)
304 struct ldb_message
*msg
;
305 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
310 tmp_ctx
= talloc_new(test_ctx
);
311 assert_non_null(tmp_ctx
);
313 msg
= ldb_msg_new(tmp_ctx
);
314 assert_non_null(msg
);
317 * The zero terminator is part of the key if we were not in
321 xs_size
= LMDB_MAX_KEY_SIZE
- 5; /* "dn=@" and the zero terminator */
322 xs_size
+= 1; /* want key on char too long */
323 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
324 memset(xs
, 'x', xs_size
);
326 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "@%s", xs
);
327 assert_non_null(msg
->dn
);
329 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
330 assert_int_equal(ret
, 0);
332 ret
= ldb_add(test_ctx
->ldb
, msg
);
333 assert_int_equal(ret
, LDB_ERR_PROTOCOL_ERROR
);
335 talloc_free(tmp_ctx
);
338 static void test_ldb_add_special_key_len_eq_max(void **state
)
342 struct ldb_message
*msg
;
343 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
348 tmp_ctx
= talloc_new(test_ctx
);
349 assert_non_null(tmp_ctx
);
351 msg
= ldb_msg_new(tmp_ctx
);
352 assert_non_null(msg
);
355 * The zero terminator is part of the key if we were not in
359 xs_size
= LMDB_MAX_KEY_SIZE
- 5; /* "dn=@" and the zero terminator */
360 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
361 memset(xs
, 'x', xs_size
);
363 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "@%s", xs
);
364 assert_non_null(msg
->dn
);
366 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
367 assert_int_equal(ret
, 0);
369 ret
= ldb_add(test_ctx
->ldb
, msg
);
370 assert_int_equal(ret
, LDB_SUCCESS
);
372 talloc_free(tmp_ctx
);
375 static void test_ldb_add_dn_no_guid_mode(void **state
)
379 struct ldb_message
*msg
;
380 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
385 tmp_ctx
= talloc_new(test_ctx
);
386 assert_non_null(tmp_ctx
);
388 msg
= ldb_msg_new(tmp_ctx
);
389 assert_non_null(msg
);
392 * The zero terminator is part of the key if we were not in
396 xs_size
= LMDB_MAX_KEY_SIZE
- 7; /* "dn=dc=" and the zero terminator */
397 xs_size
+= 1; /* want key on char too long */
398 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
399 memset(xs
, 'x', xs_size
);
401 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "dc=%s", xs
);
402 assert_non_null(msg
->dn
);
404 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
405 assert_int_equal(ret
, 0);
407 ret
= ldb_msg_add_string(msg
, "objectUUID", "0123456789abcdef");
408 assert_int_equal(ret
, 0);
410 ret
= ldb_add(test_ctx
->ldb
, msg
);
411 assert_int_equal(ret
, LDB_ERR_UNWILLING_TO_PERFORM
);
413 talloc_free(tmp_ctx
);
416 static struct MDB_env
*get_mdb_env(struct ldb_context
*ldb
)
419 struct ldb_kv_private
*ldb_kv
= NULL
;
420 struct lmdb_private
*lmdb
= NULL
;
421 struct MDB_env
*env
= NULL
;
423 data
= ldb_module_get_private(ldb
->modules
);
424 assert_non_null(data
);
426 ldb_kv
= talloc_get_type(data
, struct ldb_kv_private
);
427 assert_non_null(ldb_kv
);
429 lmdb
= ldb_kv
->lmdb_private
;
430 assert_non_null(lmdb
);
433 assert_non_null(env
);
438 static void test_multiple_opens(void **state
)
440 struct ldb_context
*ldb1
= NULL
;
441 struct ldb_context
*ldb2
= NULL
;
442 struct ldb_context
*ldb3
= NULL
;
443 struct MDB_env
*env1
= NULL
;
444 struct MDB_env
*env2
= NULL
;
445 struct MDB_env
*env3
= NULL
;
447 struct ldbtest_ctx
*test_ctx
= NULL
;
449 test_ctx
= talloc_get_type_abort(*state
, struct ldbtest_ctx
);
452 * Open the database again
454 ldb1
= ldb_init(test_ctx
, test_ctx
->ev
);
455 ret
= ldb_connect(ldb1
, test_ctx
->dbpath
, LDB_FLG_RDONLY
, NULL
);
456 assert_int_equal(ret
, 0);
458 ldb2
= ldb_init(test_ctx
, test_ctx
->ev
);
459 ret
= ldb_connect(ldb2
, test_ctx
->dbpath
, LDB_FLG_RDONLY
, NULL
);
460 assert_int_equal(ret
, 0);
462 ldb3
= ldb_init(test_ctx
, test_ctx
->ev
);
463 ret
= ldb_connect(ldb3
, test_ctx
->dbpath
, 0, NULL
);
464 assert_int_equal(ret
, 0);
466 * We now have 3 ldb's open pointing to the same on disk database
467 * they should all share the same MDB_env
469 env1
= get_mdb_env(ldb1
);
470 env2
= get_mdb_env(ldb2
);
471 env3
= get_mdb_env(ldb3
);
473 assert_ptr_equal(env1
, env2
);
474 assert_ptr_equal(env1
, env3
);
477 static void test_multiple_opens_across_fork(void **state
)
479 struct ldb_context
*ldb1
= NULL
;
480 struct ldb_context
*ldb2
= NULL
;
481 struct MDB_env
*env1
= NULL
;
482 struct MDB_env
*env2
= NULL
;
484 struct ldbtest_ctx
*test_ctx
= NULL
;
488 pid_t pid
, child_pid
;
490 test_ctx
= talloc_get_type_abort(*state
, struct ldbtest_ctx
);
493 * Open the database again
495 ldb1
= ldb_init(test_ctx
, test_ctx
->ev
);
496 ret
= ldb_connect(ldb1
, test_ctx
->dbpath
, LDB_FLG_RDONLY
, NULL
);
497 assert_int_equal(ret
, 0);
499 ldb2
= ldb_init(test_ctx
, test_ctx
->ev
);
500 ret
= ldb_connect(ldb2
, test_ctx
->dbpath
, LDB_FLG_RDONLY
, NULL
);
501 assert_int_equal(ret
, 0);
503 env1
= get_mdb_env(ldb1
);
504 env2
= get_mdb_env(ldb2
);
507 assert_int_equal(ret
, 0);
510 if (child_pid
== 0) {
511 struct ldb_context
*ldb3
= NULL
;
512 struct MDB_env
*env3
= NULL
;
515 ldb3
= ldb_init(test_ctx
, test_ctx
->ev
);
516 ret
= ldb_connect(ldb3
, test_ctx
->dbpath
, 0, NULL
);
518 print_error(__location__
": ldb_connect returned (%d)\n",
522 env3
= get_mdb_env(ldb3
);
524 print_error(__location__
": env1 != env2\n");
525 exit(LDB_ERR_OPERATIONS_ERROR
);
528 print_error(__location__
": env1 == env3\n");
529 exit(LDB_ERR_OPERATIONS_ERROR
);
531 ret
= write(pipes
[1], "GO", 2);
533 print_error(__location__
534 " write returned (%d)",
536 exit(LDB_ERR_OPERATIONS_ERROR
);
541 ret
= read(pipes
[0], buf
, 2);
542 assert_int_equal(ret
, 2);
544 pid
= waitpid(child_pid
, &wstatus
, 0);
545 assert_int_equal(pid
, child_pid
);
547 assert_true(WIFEXITED(wstatus
));
549 assert_int_equal(WEXITSTATUS(wstatus
), 0);
552 int main(int argc
, const char **argv
)
554 const struct CMUnitTest tests
[] = {
555 cmocka_unit_test_setup_teardown(
556 test_ldb_add_key_len_eq_max
,
559 cmocka_unit_test_setup_teardown(
560 test_ldb_add_key_len_gt_max
,
563 cmocka_unit_test_setup_teardown(
564 test_ldb_add_key_len_2x_gt_max
,
567 cmocka_unit_test_setup_teardown(
568 test_ldb_add_special_key_len_eq_max
,
569 ldbtest_setup_noguid
,
571 cmocka_unit_test_setup_teardown(
572 test_ldb_add_special_key_len_gt_max
,
573 ldbtest_setup_noguid
,
575 cmocka_unit_test_setup_teardown(
576 test_ldb_add_dn_no_guid_mode
,
577 ldbtest_setup_noguid
,
579 cmocka_unit_test_setup_teardown(
583 cmocka_unit_test_setup_teardown(
584 test_multiple_opens_across_fork
,
589 return cmocka_run_group_tests(tests
, NULL
, NULL
);