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.
51 #include <ldb_module.h>
52 #include <ldb_private.h>
58 #include "../ldb_tdb/ldb_tdb.h"
59 #include "../ldb_mdb/ldb_mdb.h"
63 #define LMDB_MAX_KEY_SIZE 511
66 struct tevent_context
*ev
;
67 struct ldb_context
*ldb
;
70 const char *lockfile
; /* lockfile is separate */
75 static void unlink_old_db(struct ldbtest_ctx
*test_ctx
)
80 ret
= unlink(test_ctx
->lockfile
);
81 if (ret
== -1 && errno
!= ENOENT
) {
86 ret
= unlink(test_ctx
->dbfile
);
87 if (ret
== -1 && errno
!= ENOENT
) {
92 static int ldbtest_noconn_setup(void **state
)
94 struct ldbtest_ctx
*test_ctx
;
96 test_ctx
= talloc_zero(NULL
, struct ldbtest_ctx
);
97 assert_non_null(test_ctx
);
99 test_ctx
->ev
= tevent_context_init(test_ctx
);
100 assert_non_null(test_ctx
->ev
);
102 test_ctx
->ldb
= ldb_init(test_ctx
, test_ctx
->ev
);
103 assert_non_null(test_ctx
->ldb
);
105 test_ctx
->dbfile
= talloc_strdup(test_ctx
, "apitest.ldb");
106 assert_non_null(test_ctx
->dbfile
);
108 test_ctx
->lockfile
= talloc_asprintf(test_ctx
, "%s-lock",
110 assert_non_null(test_ctx
->lockfile
);
112 test_ctx
->dbpath
= talloc_asprintf(test_ctx
,
113 TEST_BE
"://%s", test_ctx
->dbfile
);
114 assert_non_null(test_ctx
->dbpath
);
116 unlink_old_db(test_ctx
);
121 static int ldbtest_noconn_teardown(void **state
)
123 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
126 unlink_old_db(test_ctx
);
127 talloc_free(test_ctx
);
131 static int ldbtest_setup(void **state
)
133 struct ldbtest_ctx
*test_ctx
;
135 struct ldb_ldif
*ldif
;
136 const char *index_ldif
= \
138 "@IDXGUID: objectUUID\n"
139 "@IDX_DN_GUID: GUID\n"
142 ldbtest_noconn_setup((void **) &test_ctx
);
144 ret
= ldb_connect(test_ctx
->ldb
, test_ctx
->dbpath
, 0, NULL
);
145 assert_int_equal(ret
, 0);
147 while ((ldif
= ldb_ldif_read_string(test_ctx
->ldb
, &index_ldif
))) {
148 ret
= ldb_add(test_ctx
->ldb
, ldif
->msg
);
149 assert_int_equal(ret
, LDB_SUCCESS
);
155 static int ldbtest_teardown(void **state
)
157 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
159 ldbtest_noconn_teardown((void **) &test_ctx
);
163 static void test_ldb_add_key_len_gt_max(void **state
)
167 struct ldb_message
*msg
;
168 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
173 tmp_ctx
= talloc_new(test_ctx
);
174 assert_non_null(tmp_ctx
);
176 msg
= ldb_msg_new(tmp_ctx
);
177 assert_non_null(msg
);
180 * The zero terminator is part of the key if we were not in
184 xs_size
= LMDB_MAX_KEY_SIZE
- 7; /* "dn=dc=" and the zero terminator */
185 xs_size
+= 1; /* want key on char too long */
186 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
187 memset(xs
, 'x', xs_size
);
189 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "dc=%s", xs
);
190 assert_non_null(msg
->dn
);
192 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
193 assert_int_equal(ret
, 0);
195 ret
= ldb_msg_add_string(msg
, "objectUUID", "0123456789abcdef");
196 assert_int_equal(ret
, 0);
198 ret
= ldb_add(test_ctx
->ldb
, msg
);
199 assert_int_equal(ret
, LDB_SUCCESS
);
201 talloc_free(tmp_ctx
);
204 static void test_ldb_add_key_len_eq_max(void **state
)
208 struct ldb_message
*msg
;
209 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
214 tmp_ctx
= talloc_new(test_ctx
);
215 assert_non_null(tmp_ctx
);
217 msg
= ldb_msg_new(tmp_ctx
);
218 assert_non_null(msg
);
221 * The zero terminator is part of the key if we were not in
225 xs_size
= LMDB_MAX_KEY_SIZE
- 7; /* "dn=dc=" and the zero terminator */
226 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
227 memset(xs
, 'x', xs_size
);
229 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "dc=%s", xs
);
230 assert_non_null(msg
->dn
);
232 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
233 assert_int_equal(ret
, 0);
235 ret
= ldb_msg_add_string(msg
, "objectUUID", "0123456789abcdef");
236 assert_int_equal(ret
, 0);
238 ret
= ldb_add(test_ctx
->ldb
, msg
);
239 assert_int_equal(ret
, 0);
241 talloc_free(tmp_ctx
);
244 static int ldbtest_setup_noguid(void **state
)
246 struct ldbtest_ctx
*test_ctx
;
249 ldbtest_noconn_setup((void **) &test_ctx
);
251 ret
= ldb_connect(test_ctx
->ldb
, test_ctx
->dbpath
, 0, NULL
);
252 assert_int_equal(ret
, 0);
258 static void test_ldb_add_special_key_len_gt_max(void **state
)
262 struct ldb_message
*msg
;
263 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
268 tmp_ctx
= talloc_new(test_ctx
);
269 assert_non_null(tmp_ctx
);
271 msg
= ldb_msg_new(tmp_ctx
);
272 assert_non_null(msg
);
275 * The zero terminator is part of the key if we were not in
279 xs_size
= LMDB_MAX_KEY_SIZE
- 5; /* "dn=@" and the zero terminator */
280 xs_size
+= 1; /* want key on char too long */
281 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
282 memset(xs
, 'x', xs_size
);
284 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "@%s", xs
);
285 assert_non_null(msg
->dn
);
287 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
288 assert_int_equal(ret
, 0);
290 ret
= ldb_add(test_ctx
->ldb
, msg
);
291 assert_int_equal(ret
, LDB_ERR_PROTOCOL_ERROR
);
293 talloc_free(tmp_ctx
);
296 static void test_ldb_add_special_key_len_eq_max(void **state
)
300 struct ldb_message
*msg
;
301 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
306 tmp_ctx
= talloc_new(test_ctx
);
307 assert_non_null(tmp_ctx
);
309 msg
= ldb_msg_new(tmp_ctx
);
310 assert_non_null(msg
);
313 * The zero terminator is part of the key if we were not in
317 xs_size
= LMDB_MAX_KEY_SIZE
- 5; /* "dn=@" and the zero terminator */
318 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
319 memset(xs
, 'x', xs_size
);
321 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "@%s", xs
);
322 assert_non_null(msg
->dn
);
324 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
325 assert_int_equal(ret
, 0);
327 ret
= ldb_add(test_ctx
->ldb
, msg
);
328 assert_int_equal(ret
, LDB_SUCCESS
);
330 talloc_free(tmp_ctx
);
333 static void test_ldb_add_dn_no_guid_mode(void **state
)
337 struct ldb_message
*msg
;
338 struct ldbtest_ctx
*test_ctx
= talloc_get_type_abort(*state
,
343 tmp_ctx
= talloc_new(test_ctx
);
344 assert_non_null(tmp_ctx
);
346 msg
= ldb_msg_new(tmp_ctx
);
347 assert_non_null(msg
);
350 * The zero terminator is part of the key if we were not in
354 xs_size
= LMDB_MAX_KEY_SIZE
- 7; /* "dn=dc=" and the zero terminator */
355 xs_size
+= 1; /* want key on char too long */
356 xs
= talloc_zero_size(tmp_ctx
, (xs_size
+ 1));
357 memset(xs
, 'x', xs_size
);
359 msg
->dn
= ldb_dn_new_fmt(msg
, test_ctx
->ldb
, "dc=%s", xs
);
360 assert_non_null(msg
->dn
);
362 ret
= ldb_msg_add_string(msg
, "cn", "test_cn_val");
363 assert_int_equal(ret
, 0);
365 ret
= ldb_msg_add_string(msg
, "objectUUID", "0123456789abcdef");
366 assert_int_equal(ret
, 0);
368 ret
= ldb_add(test_ctx
->ldb
, msg
);
369 assert_int_equal(ret
, LDB_ERR_UNWILLING_TO_PERFORM
);
371 talloc_free(tmp_ctx
);
374 static struct MDB_env
*get_mdb_env(struct ldb_context
*ldb
)
377 struct ltdb_private
*ltdb
= NULL
;
378 struct lmdb_private
*lmdb
= NULL
;
379 struct MDB_env
*env
= NULL
;
381 data
= ldb_module_get_private(ldb
->modules
);
382 assert_non_null(data
);
384 ltdb
= talloc_get_type(data
, struct ltdb_private
);
385 assert_non_null(ltdb
);
387 lmdb
= ltdb
->lmdb_private
;
388 assert_non_null(lmdb
);
391 assert_non_null(env
);
396 static void test_multiple_opens(void **state
)
398 struct ldb_context
*ldb1
= NULL
;
399 struct ldb_context
*ldb2
= NULL
;
400 struct ldb_context
*ldb3
= NULL
;
401 struct MDB_env
*env1
= NULL
;
402 struct MDB_env
*env2
= NULL
;
403 struct MDB_env
*env3
= NULL
;
405 struct ldbtest_ctx
*test_ctx
= NULL
;
407 test_ctx
= talloc_get_type_abort(*state
, struct ldbtest_ctx
);
410 * Open the database again
412 ldb1
= ldb_init(test_ctx
, test_ctx
->ev
);
413 ret
= ldb_connect(ldb1
, test_ctx
->dbpath
, LDB_FLG_RDONLY
, NULL
);
414 assert_int_equal(ret
, 0);
416 ldb2
= ldb_init(test_ctx
, test_ctx
->ev
);
417 ret
= ldb_connect(ldb2
, test_ctx
->dbpath
, LDB_FLG_RDONLY
, NULL
);
418 assert_int_equal(ret
, 0);
420 ldb3
= ldb_init(test_ctx
, test_ctx
->ev
);
421 ret
= ldb_connect(ldb3
, test_ctx
->dbpath
, 0, NULL
);
422 assert_int_equal(ret
, 0);
424 * We now have 3 ldb's open pointing to the same on disk database
425 * they should all share the same MDB_env
427 env1
= get_mdb_env(ldb1
);
428 env2
= get_mdb_env(ldb2
);
429 env3
= get_mdb_env(ldb3
);
431 assert_ptr_equal(env1
, env2
);
432 assert_ptr_equal(env1
, env3
);
435 int main(int argc
, const char **argv
)
437 const struct CMUnitTest tests
[] = {
438 cmocka_unit_test_setup_teardown(
439 test_ldb_add_key_len_eq_max
,
442 cmocka_unit_test_setup_teardown(
443 test_ldb_add_key_len_gt_max
,
446 cmocka_unit_test_setup_teardown(
447 test_ldb_add_special_key_len_eq_max
,
448 ldbtest_setup_noguid
,
450 cmocka_unit_test_setup_teardown(
451 test_ldb_add_special_key_len_gt_max
,
452 ldbtest_setup_noguid
,
454 cmocka_unit_test_setup_teardown(
455 test_ldb_add_dn_no_guid_mode
,
456 ldbtest_setup_noguid
,
458 cmocka_unit_test_setup_teardown(
464 return cmocka_run_group_tests(tests
, NULL
, NULL
);