s3:printing: Allow to run samba-bgqd as a standalone systemd service
[Samba.git] / lib / ldb / tests / ldb_msg.c
blob207c01a3051254d941360522630306a796a754cd
1 /*
2 * from cmocka.c:
3 * These headers or their equivalents should be included prior to
4 * including
5 * this header file.
7 * #include <stdarg.h>
8 * #include <stddef.h>
9 * #include <setjmp.h>
11 * This allows test applications to use custom definitions of C standard
12 * library functions and types.
14 #include <stdarg.h>
15 #include <stddef.h>
16 #include <stdint.h>
17 #include <setjmp.h>
18 #include <cmocka.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <talloc.h>
24 #include <ldb.h>
25 #include <ldb_private.h>
26 #include <string.h>
27 #include <ctype.h>
29 struct test_ctx {
30 struct ldb_message *msg;
33 static int ldb_msg_setup(void **state)
35 struct test_ctx *test_ctx;
37 test_ctx = talloc_zero(NULL, struct test_ctx);
38 assert_non_null(test_ctx);
40 test_ctx->msg = ldb_msg_new(test_ctx);
42 *state = test_ctx;
43 return 0;
46 static int ldb_msg_teardown(void **state)
48 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
49 struct test_ctx);
51 talloc_free(test_ctx);
52 return 0;
56 static void add_uint_value(struct test_ctx *test_ctx,
57 struct ldb_message *msg,
58 const char *attr,
59 unsigned int x)
61 int ret;
62 struct ldb_val v, v_dup;
63 char s[5];
64 snprintf(s, sizeof(s), "%04x", x);
65 v.data = (uint8_t *)s;
66 v.length = 4;
67 v_dup = ldb_val_dup(test_ctx, &v);
68 assert_non_null(v_dup.data);
69 assert_ptr_not_equal(v_dup.data, v.data);
70 assert_int_equal(v_dup.length, 4);
72 ret = ldb_msg_add_value(msg, attr, &v_dup, NULL);
73 assert_int_equal(ret, LDB_SUCCESS);
77 static void test_ldb_msg_find_duplicate_val(void **state)
79 int ret;
80 unsigned int i;
81 struct test_ctx *test_ctx = talloc_get_type_abort(*state,
82 struct test_ctx);
83 struct ldb_message *msg = test_ctx->msg;
84 struct ldb_message_element *el;
85 struct ldb_val dummy;
86 struct ldb_val *dupe = &dummy; /* so we can tell it was modified to NULL, not left as NULL */
88 ret = ldb_msg_add_empty(msg, "el1", 0, &el);
89 assert_int_equal(ret, LDB_SUCCESS);
91 /* An empty message contains no duplicates */
92 ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0);
93 assert_int_equal(ret, LDB_SUCCESS);
94 assert_null(dupe);
96 for (i = 0; i < 5; i++) {
97 add_uint_value(test_ctx, msg, "el1", i);
99 /* at this point there are no duplicates, and the check uses the naive
100 quadratic path */
101 ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0);
102 assert_int_equal(ret, LDB_SUCCESS);
103 assert_null(dupe);
105 /* add a duplicate, still using quadratric path */
106 add_uint_value(test_ctx, msg, "el1", 3);
107 ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0);
108 assert_int_equal(ret, LDB_SUCCESS);
109 assert_non_null(dupe);
110 assert_int_equal(dupe->length, 4);
111 assert_memory_equal(dupe->data, "0003", 4);
113 /* add some more, triggering algorithmic jump */
114 for (i = 2; i < 11; i++) {
115 add_uint_value(test_ctx, msg, "el1", i);
117 ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0);
118 assert_int_equal(ret, LDB_SUCCESS);
119 assert_non_null(dupe);
120 assert_int_equal(dupe->length, 4);
121 /*XXX not really guaranteed by the API */
122 assert_memory_equal(dupe->data, "0002", 4);
124 /* start a new element without duplicates, for the clever algorithm */
125 ldb_msg_add_empty(msg, "el2", 0, &el);
126 for (i = 0; i < 12; i++) {
127 add_uint_value(test_ctx, msg, "el2", i);
129 ret = ldb_msg_find_duplicate_val(NULL, test_ctx, el, &dupe, 0);
130 assert_int_equal(ret, LDB_SUCCESS);
131 assert_null(dupe);
135 static struct ldb_message_element *new_msg_element(TALLOC_CTX *mem_ctx,
136 const char *name,
137 unsigned int value_offset,
138 unsigned int num_values)
140 unsigned int i, x;
141 struct ldb_message_element *el = talloc_zero(mem_ctx,
142 struct ldb_message_element);
144 el->values = talloc_array(el, struct ldb_val, num_values);
145 for (i = 0; i < num_values; i++) {
146 struct ldb_val v;
147 char s[50];
148 v.data = (uint8_t *)s;
149 /* % 3 is to ensure the values list is unsorted */
150 x = i + value_offset;
151 v.length = snprintf(s, sizeof(s), "%u %u", x % 3, x);
152 el->values[i] = ldb_val_dup(mem_ctx, &v);
154 el->name = name;
155 el->num_values = num_values;
156 return el;
159 static void _assert_element_equal(struct ldb_message_element *a,
160 struct ldb_message_element *b,
161 const char * const file,
162 const int line)
164 unsigned int i;
165 _assert_int_equal(a->num_values, b->num_values, file, line);
166 _assert_int_equal(a->flags, b->flags, file, line);
167 _assert_string_equal(a->name, b->name, file, line);
168 for (i = 0; i < a->num_values; i++) {
169 struct ldb_val *v1 = &a->values[i];
170 struct ldb_val *v2 = &b->values[i];
171 _assert_int_equal(v1->length, v2->length, file, line);
172 _assert_memory_equal(v1->data, v2->data, v1->length,
173 file, line);
177 #define assert_element_equal(a, b) \
178 _assert_element_equal((a), (b), \
179 __FILE__, __LINE__)
182 static void test_ldb_msg_find_common_values(void **state)
184 /* we only use the state as a talloc context */
185 struct ldb_message_element *el, *el2, *el3, *el4, *el2b, *empty;
186 struct ldb_message_element *orig, *orig2, *orig3, *orig4;
187 int ret;
188 const uint32_t remove_dupes = LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES;
189 el = new_msg_element(*state, "test", 0, 4);
190 el2 = new_msg_element(*state, "test", 4, 4);
191 el3 = new_msg_element(*state, "test", 6, 4);
192 empty = new_msg_element(*state, "test", 0, 0);
193 orig = new_msg_element(*state, "test", 0, 4);
194 orig2 = new_msg_element(*state, "test", 4, 4);
195 orig3 = new_msg_element(*state, "test", 6, 4);
197 /* first round is with short value arrays, using quadratic method */
198 /* we expect no collisions here */
199 ret = ldb_msg_find_common_values(NULL, *state, el, el2, 0);
200 assert_int_equal(ret, LDB_SUCCESS);
202 /*or here */
203 ret = ldb_msg_find_common_values(NULL, *state, el, el3, 0);
204 assert_int_equal(ret, LDB_SUCCESS);
206 /* the same elements in reverse order */
207 ret = ldb_msg_find_common_values(NULL, *state, el2, el, 0);
208 assert_int_equal(ret, LDB_SUCCESS);
210 ret = ldb_msg_find_common_values(NULL, *state, el3, el, 0);
211 assert_int_equal(ret, LDB_SUCCESS);
213 /* 6, 7 collide */
214 ret = ldb_msg_find_common_values(NULL, *state, el2, el3, 0);
215 assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS);
217 /* and again */
218 ret = ldb_msg_find_common_values(NULL, *state, el3, el2, 0);
219 assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS);
221 /* make sure the arrays haven't changed */
222 assert_element_equal(el, orig);
223 assert_element_equal(el2, orig2);
224 assert_element_equal(el3, orig3);
226 /* now with the control permisive flag, the first element should be
227 modified to remove the overlap.*/
229 /* 6, 7 collide, so el2 will only have 4 and 5 */
230 ret = ldb_msg_find_common_values(NULL, *state, el2, el3, remove_dupes);
231 assert_int_equal(ret, LDB_SUCCESS);
233 assert_element_equal(el3, orig3);
234 assert_int_not_equal(el2->num_values, orig2->num_values);
235 assert_int_equal(el2->num_values, 2);
236 el2b = new_msg_element(*state, "test", 4, 2);
237 assert_element_equal(el2, el2b);
239 /* now try the same things with a long and a short value list.
240 this should still trigger the quadratic path.
242 el2 = new_msg_element(*state, "test", 4, 10);
243 orig2 = new_msg_element(*state, "test", 4, 10);
245 /* no collisions */
246 ret = ldb_msg_find_common_values(NULL, *state, el, el2, 0);
247 assert_int_equal(ret, LDB_SUCCESS);
248 ret = ldb_msg_find_common_values(NULL, *state, el2, el, 0);
249 assert_int_equal(ret, LDB_SUCCESS);
251 /*collisions */
252 ret = ldb_msg_find_common_values(NULL, *state, el3, el2, 0);
253 assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS);
255 assert_element_equal(el, orig);
256 assert_element_equal(el2, orig2);
257 assert_element_equal(el3, orig3);
259 /*collisions with permissive flag*/
260 ret = ldb_msg_find_common_values(NULL, *state, el3, el2, remove_dupes);
261 assert_int_equal(ret, LDB_SUCCESS);
262 assert_element_equal(el2, orig2);
263 assert_int_equal(el3->num_values, 0);
265 /* permutations involving empty elements.
266 everything should succeed. */
267 ret = ldb_msg_find_common_values(NULL, *state, el3, el2, 0);
268 assert_int_equal(ret, LDB_SUCCESS);
269 ret = ldb_msg_find_common_values(NULL, *state, el3, el, 0);
270 assert_int_equal(ret, LDB_SUCCESS);
271 ret = ldb_msg_find_common_values(NULL, *state, el2, el3, 0);
272 assert_int_equal(ret, LDB_SUCCESS);
273 assert_int_equal(el2->num_values, orig2->num_values);
274 ret = ldb_msg_find_common_values(NULL, *state, el3, el2, remove_dupes);
275 assert_int_equal(ret, LDB_SUCCESS);
276 assert_int_equal(el2->num_values, orig2->num_values);
277 assert_int_equal(el3->num_values, 0); /* el3 is now empty */
278 ret = ldb_msg_find_common_values(NULL, *state, el2, el3, remove_dupes);
279 assert_int_equal(ret, LDB_SUCCESS);
280 ret = ldb_msg_find_common_values(NULL, *state, el3, empty, 0);
281 assert_int_equal(ret, LDB_SUCCESS);
282 ret = ldb_msg_find_common_values(NULL, *state, empty, empty, 0);
283 assert_int_equal(ret, LDB_SUCCESS);
284 ret = ldb_msg_find_common_values(NULL, *state, empty, el3, 0);
285 assert_int_equal(ret, LDB_SUCCESS);
287 assert_element_equal(el2, orig2);
288 assert_element_equal(el, orig);
289 assert_int_equal(el3->num_values, 0);
291 /* now with two large value lists */
292 el = new_msg_element(*state, "test", 0, 12);
293 orig = new_msg_element(*state, "test", 0, 12);
294 el4 = new_msg_element(*state, "test", 12, 12);
295 orig4 = new_msg_element(*state, "test", 12, 12);
297 /* no collisions */
298 ret = ldb_msg_find_common_values(NULL, *state, el, el4, 0);
299 assert_int_equal(ret, LDB_SUCCESS);
301 ret = ldb_msg_find_common_values(NULL, *state, el4, el, 0);
302 assert_int_equal(ret, LDB_SUCCESS);
304 /* collisions */
305 ret = ldb_msg_find_common_values(NULL, *state, el4, el2, 0);
306 assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS);
307 ret = ldb_msg_find_common_values(NULL, *state, el2, el4, 0);
308 assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS);
309 ret = ldb_msg_find_common_values(NULL, *state, el2, el, 0);
310 assert_int_equal(ret, LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS);
312 assert_element_equal(el, orig);
313 assert_element_equal(el2, orig2);
314 assert_element_equal(el4, orig4);
316 /* with permissive control, but no collisions */
317 ret = ldb_msg_find_common_values(NULL, *state, el, el4, remove_dupes);
318 assert_int_equal(ret, LDB_SUCCESS);
319 ret = ldb_msg_find_common_values(NULL, *state, el4, el, remove_dupes);
320 assert_int_equal(ret, LDB_SUCCESS);
322 assert_element_equal(el, orig);
323 assert_element_equal(el4, orig4);
325 /* now with collisions, thus modifications.
326 At this stage:
327 el is 0-11 (inclusive)
328 e2 is 4-13
329 el3 is empty
330 el4 is 12-23
332 ret = ldb_msg_find_common_values(NULL, *state, el4, el2, remove_dupes);
333 assert_int_equal(ret, LDB_SUCCESS);
334 assert_element_equal(el2, orig2);
335 assert_int_not_equal(el4->num_values, orig4->num_values);
336 /* 4 should start at 14 */
337 orig4 = new_msg_element(*state, "test", 14, 10);
338 assert_element_equal(el4, orig4);
340 ret = ldb_msg_find_common_values(NULL, *state, el2, el, remove_dupes);
341 assert_int_equal(ret, LDB_SUCCESS);
342 assert_element_equal(el, orig);
343 assert_int_not_equal(el2->num_values, orig2->num_values);
344 orig2 = new_msg_element(*state, "test", 12, 2);
345 assert_element_equal(el2, orig2);
347 /* test the empty el against the full elements */
348 ret = ldb_msg_find_common_values(NULL, *state, el, empty, 0);
349 assert_int_equal(ret, LDB_SUCCESS);
350 ret = ldb_msg_find_common_values(NULL, *state, empty, el, 0);
351 assert_int_equal(ret, LDB_SUCCESS);
352 ret = ldb_msg_find_common_values(NULL, *state, el, empty, remove_dupes);
353 assert_int_equal(ret, LDB_SUCCESS);
354 ret = ldb_msg_find_common_values(NULL, *state, empty, el, remove_dupes);
355 assert_int_equal(ret, LDB_SUCCESS);
356 assert_element_equal(el, orig);
357 assert_element_equal(empty, el3);
359 /* make sure an identical element with a different name is rejected */
360 el2 = new_msg_element(*state, "fish", 12, 2);
361 ret = ldb_msg_find_common_values(NULL, *state, el2, el, remove_dupes);
362 assert_int_equal(ret, LDB_ERR_INAPPROPRIATE_MATCHING);
367 int main(int argc, const char **argv)
369 const struct CMUnitTest tests[] = {
370 cmocka_unit_test_setup_teardown(test_ldb_msg_find_duplicate_val,
371 ldb_msg_setup,
372 ldb_msg_teardown),
373 cmocka_unit_test_setup_teardown(
374 test_ldb_msg_find_common_values,
375 ldb_msg_setup,
376 ldb_msg_teardown),
379 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
381 return cmocka_run_group_tests(tests, NULL, NULL);