2 * Tests exercising the ldb match operations.
5 * Copyright (C) Catalyst.NET Ltd 2017
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * These headers or their equivalents should be included prior to
32 * This allows test applications to use custom definitions of C standard
33 * library functions and types.
41 #include "../common/ldb_match.c"
43 #include "../include/ldb.h"
46 struct tevent_context
*ev
;
47 struct ldb_context
*ldb
;
50 static int ldb_test_canonicalise(
51 struct ldb_context
*ldb
,
53 const struct ldb_val
*in
,
56 out
->length
= in
->length
;
61 static int setup(void **state
)
63 struct ldbtest_ctx
*test_ctx
;
64 struct ldb_schema_syntax
*syntax
= NULL
;
67 test_ctx
= talloc_zero(NULL
, struct ldbtest_ctx
);
68 assert_non_null(test_ctx
);
70 test_ctx
->ev
= tevent_context_init(test_ctx
);
71 assert_non_null(test_ctx
->ev
);
73 test_ctx
->ldb
= ldb_init(test_ctx
, test_ctx
->ev
);
74 assert_non_null(test_ctx
->ldb
);
76 syntax
= talloc_zero(test_ctx
, struct ldb_schema_syntax
);
77 assert_non_null(syntax
);
78 syntax
->canonicalise_fn
= ldb_test_canonicalise
;
80 ret
= ldb_schema_attribute_add_with_syntax(
81 test_ctx
->ldb
, "a", LDB_ATTR_FLAG_FIXED
, syntax
);
82 assert_int_equal(LDB_SUCCESS
, ret
);
88 static int teardown(void **state
)
94 static void escape_string(uint8_t *buf
, size_t buflen
,
95 const uint8_t *s
, size_t len
)
99 for (i
= 0; i
< len
; i
++) {
100 if (j
== buflen
- 1) {
107 if (j
>= buflen
- 4) {
110 /* utf-8 control char representation */
113 buf
[j
+ 2] = 0x80 + s
[i
];
123 * The wild card pattern "attribute=*" is parsed as an LDB_OP_PRESENT operation
124 * rather than a LDB_OP_????
126 * This test serves to document that behaviour, and to confirm that
127 * ldb_wildcard_compare handles this case appropriately.
129 static void test_wildcard_match_star(void **state
)
131 struct ldbtest_ctx
*ctx
= *state
;
132 bool matched
= false;
135 uint8_t value
[] = "The value.......end";
136 struct ldb_val val
= {
138 .length
= (sizeof(value
))
140 struct ldb_parse_tree
*tree
= ldb_parse_tree(ctx
, "a=*");
141 assert_non_null(tree
);
143 ret
= ldb_wildcard_compare(ctx
->ldb
, tree
, val
, &matched
);
144 assert_false(matched
);
145 assert_int_equal(LDB_ERR_INAPPROPRIATE_MATCHING
, ret
);
149 * Test basic wild card matching
152 struct wildcard_test
{
161 * Q: Why this macro rather than plain struct values?
162 * A: So we can get the size of the const char[] value while it is still a
163 * true array, not a pointer.
165 * Q: but why not just use strlen?
166 * A: so values can contain '\0', which we supposedly allow.
169 #define TEST_ENTRY(val, search, should_match, fold) \
171 (uint8_t*)discard_const(val), \
178 static void test_wildcard_match(void **state
)
180 struct ldbtest_ctx
*ctx
= *state
;
183 struct wildcard_test tests
[] = {
184 TEST_ENTRY(" 1 0", "1*0*", true, true),
185 TEST_ENTRY(" 1 0", "1 *0", true, true),
186 TEST_ENTRY(" 1 0", "*1 0", true, true),
187 TEST_ENTRY("1 0", "*1 0", true, true),
188 TEST_ENTRY("The value.......end", "*end", true, true),
189 TEST_ENTRY("The value.......end", "*fend", false, true),
190 TEST_ENTRY("The value.......end", "*eel", false, true),
191 TEST_ENTRY("The value.......end", "*d", true, true),
192 TEST_ENTRY("The value.......end", "*D*", true, true),
193 TEST_ENTRY("The value.......end", "*e*d*", true, true),
194 TEST_ENTRY("end", "*e*d*", true, true),
195 TEST_ENTRY("end", " *e*d*", true, true),
196 TEST_ENTRY("1.0.0.0.0.0.0.0aaaaaaaaaaaa", "*aaaaa", true, true),
197 TEST_ENTRY("1.0..0.0.0.0.0.0.0aAaaaAAAAAAA", "*a", true, true),
198 TEST_ENTRY("1.0.0.0.0.0.0.0.0.0.0aaaa", "*aaaaa", false, true),
199 TEST_ENTRY("1.0.0.0.0.0.0.0.0.0.0", "*0.0", true, true),
200 TEST_ENTRY("1.0.0.0.0.0.0.0.0.0.0", "*0.0.0", true, true),
201 TEST_ENTRY("1.0.0.0.0.0.0.0.0.0", "1*0*0*0*0*0*0*0*0*0", true,
203 TEST_ENTRY("1.0.0.0.0.0.0.0.0", "1*0*0*0*0*0*0*0*0*0", false,
205 TEST_ENTRY("1.0.0.0.000.0.0.0.0", "1*0*0*0*0*0*0*0*0*0", true,
207 TEST_ENTRY("1\n0\r0\t000.0.0.0.0", "1*0*0*0*0*0*0*0*0", true,
210 * We allow NUL bytes and redundant spaces in non-casefolding
213 TEST_ENTRY(" 1 0", "*1 0", true, false),
214 TEST_ENTRY(" 1 0", "*1 0", true, false),
215 TEST_ENTRY("1 0", "*1 0", false, false),
216 TEST_ENTRY("1\x00 x", "1*x", true, false),
217 TEST_ENTRY("1\x00 x", "*x", true, false),
218 TEST_ENTRY("1\x00 x", "*x*", true, false),
219 TEST_ENTRY("1\x00 x", "* *", true, false),
220 TEST_ENTRY("1\x00 x", "1*", true, false),
221 TEST_ENTRY("1\x00 b* x", "1*b*", true, false),
222 TEST_ENTRY("1.0..0.0.0.0.0.0.0aAaaaAAAAAAA", "*a", false, false),
225 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
228 struct ldb_val val
= {
229 .data
= (uint8_t *)tests
[i
].val
,
230 .length
= tests
[i
].val_size
232 const char *attr
= tests
[i
].fold
? "objectclass" : "birthLocation";
233 const char *s
= talloc_asprintf(ctx
, "%s=%s",
234 attr
, tests
[i
].search
);
235 struct ldb_parse_tree
*tree
= ldb_parse_tree(ctx
, s
);
236 assert_non_null(tree
);
237 ret
= ldb_wildcard_compare(ctx
->ldb
, tree
, val
, &matched
);
238 if (ret
!= LDB_SUCCESS
) {
240 escape_string(buf
, sizeof(buf
),
241 tests
[i
].val
, tests
[i
].val_size
);
242 print_error("%zu val: «%s», search «%s» FAILED with %d\n",
243 i
, buf
, tests
[i
].search
, ret
);
246 if (matched
!= tests
[i
].should_match
) {
248 escape_string(buf
, sizeof(buf
),
249 tests
[i
].val
, tests
[i
].val_size
);
250 print_error("%zu val: «%s», search «%s» should %s\n",
251 i
, buf
, tests
[i
].search
,
252 matched
? "not match" : "match");
257 fail_msg("wrong results for %zu/%zu wildcard searches\n",
258 failed
, ARRAY_SIZE(tests
));
266 * ldb_handler_copy and ldb_val_dup over allocate by one and add a trailing '\0'
267 * to the data, to make them safe to use the C string functions on.
269 * However testing for the trailing '\0' is not the correct way to test for
270 * the end of a value, the length should be checked instead.
272 static void test_wildcard_match_end_condition(void **state
)
274 struct ldbtest_ctx
*ctx
= *state
;
275 bool matched
= false;
277 uint8_t value
[] = "hellomynameisbobx";
278 struct ldb_val val
= {
279 .data
= talloc_memdup(NULL
, value
, sizeof(value
)),
280 .length
= (sizeof(value
) - 2)
282 struct ldb_parse_tree
*tree
= ldb_parse_tree(ctx
, "a=*hello*mynameis*bob");
283 assert_non_null(tree
);
285 ldb_wildcard_compare(ctx
->ldb
, tree
, val
, &matched
);
286 assert_true(matched
);
290 * Note: to run under valgrind use:
292 * --suppressions=lib/ldb/tests/ldb_match_test.valgrind \
295 int main(int argc
, const char **argv
)
297 const struct CMUnitTest tests
[] = {
298 cmocka_unit_test_setup_teardown(
299 test_wildcard_match_star
,
302 cmocka_unit_test_setup_teardown(
306 cmocka_unit_test_setup_teardown(
307 test_wildcard_match_end_condition
,
312 cmocka_set_message_output(CM_OUTPUT_SUBUNIT
);
314 return cmocka_run_group_tests(tests
, NULL
, NULL
);