Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : util_strlist testing
5 :
6 : Copyright (C) Jelmer Vernooij 2005
7 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "torture/torture.h"
25 : #include "torture/local/proto.h"
26 : #include "param/param.h"
27 :
28 : struct test_list_element {
29 : const char *list_as_string;
30 : const char *separators;
31 : const char *list[5];
32 : };
33 :
34 : const struct test_list_element test_lists_strings[] = {
35 : {
36 : .list_as_string = "",
37 : .list = { NULL }
38 : },
39 : {
40 : .list_as_string = "foo",
41 : .list = { "foo", NULL }
42 : },
43 : {
44 : .list_as_string = "foo bar",
45 : .list = { "foo", "bar", NULL }
46 : },
47 : {
48 : .list_as_string = "foo bar",
49 : .list = { "foo bar", NULL },
50 : .separators = ";"
51 : },
52 : {
53 : .list_as_string = "\"foo bar\"",
54 : .list = { "\"foo", "bar\"", NULL }
55 : },
56 : {
57 : .list_as_string = "\"foo bar\",comma\ttab",
58 : .list = { "\"foo", "bar\"", "comma", "tab", NULL }
59 : },
60 : {
61 : .list_as_string = "\"foo bar\",comma;semicolon",
62 : .list = { "\"foo bar\",comma", "semicolon", NULL },
63 : .separators = ";"
64 : }
65 : };
66 :
67 : const struct test_list_element test_lists_shell_strings[] = {
68 : {
69 : .list_as_string = "",
70 : .list = { NULL }
71 : },
72 : {
73 : .list_as_string = "foo",
74 : .list = { "foo", NULL }
75 : },
76 : {
77 : .list_as_string = "foo bar",
78 : .list = { "foo", "bar", NULL }
79 : },
80 : {
81 : .list_as_string = "foo bar",
82 : .list = { "foo bar", NULL },
83 : .separators = ";"
84 : },
85 : {
86 : .list_as_string = "\"foo bar\"",
87 : .list = { "foo bar", NULL }
88 : },
89 : {
90 : .list_as_string = "foo bar \"bla \"",
91 : .list = { "foo", "bar", "bla ", NULL }
92 : },
93 : {
94 : .list_as_string = "foo \"\" bla",
95 : .list = { "foo", "", "bla", NULL },
96 : },
97 : {
98 : .list_as_string = "bla \"\"\"\" blie",
99 : .list = { "bla", "", "", "blie", NULL },
100 : }
101 : };
102 :
103 8 : static bool test_lists_shell(struct torture_context *tctx, const void *data)
104 : {
105 8 : const struct test_list_element *element = data;
106 :
107 8 : char **ret1, **ret2, *tmp;
108 8 : bool match = true;
109 8 : TALLOC_CTX *mem_ctx = tctx;
110 :
111 8 : ret1 = str_list_make_shell(mem_ctx, element->list_as_string, element->separators);
112 :
113 8 : torture_assert(tctx, ret1, "str_list_make_shell() must not return NULL");
114 8 : tmp = str_list_join_shell(mem_ctx, discard_const_p(const char *, ret1),
115 8 : element->separators ? *element->separators : ' ');
116 8 : ret2 = str_list_make_shell(mem_ctx, tmp, element->separators);
117 :
118 8 : if ((ret1 == NULL || ret2 == NULL) && ret2 != ret1) {
119 0 : match = false;
120 : } else {
121 : int j;
122 23 : for (j = 0; ret1[j] && ret2[j]; j++) {
123 15 : if (strcmp(ret1[j], ret2[j]) != 0) {
124 0 : match = false;
125 0 : break;
126 : }
127 : }
128 :
129 8 : if (ret1[j] || ret2[j])
130 0 : match = false;
131 : }
132 :
133 8 : torture_assert(tctx, match, talloc_asprintf(tctx,
134 : "str_list_{make,join}_shell: Error double parsing, first run:\n%s\nSecond run: \n%s", element->list_as_string, tmp));
135 8 : torture_assert(tctx, str_list_equal((const char * const *) ret1,
136 : element->list),
137 : talloc_asprintf(tctx,
138 : "str_list_make_shell(%s) failed to create correct list",
139 : element->list_as_string));
140 :
141 0 : return true;
142 : }
143 :
144 7 : static bool test_list_make(struct torture_context *tctx, const void *data)
145 : {
146 7 : const struct test_list_element *element = data;
147 :
148 7 : char **result;
149 7 : result = str_list_make(tctx, element->list_as_string, element->separators);
150 7 : torture_assert(tctx, result, "str_list_make() must not return NULL");
151 7 : torture_assert(tctx, str_list_equal((const char * const *) result,
152 : element->list),
153 : talloc_asprintf(tctx,
154 : "str_list_make(%s) failed to create correct list",
155 : element->list_as_string));
156 0 : return true;
157 : }
158 :
159 1 : static bool test_list_copy(struct torture_context *tctx)
160 : {
161 1 : const char **result;
162 1 : const char *list[] = { "foo", "bar", NULL };
163 1 : const char *empty_list[] = { NULL };
164 1 : const char **null_list = NULL;
165 1 : char **l;
166 :
167 1 : l = str_list_copy(tctx, list);
168 1 : result = discard_const_p(const char *, l);
169 1 : torture_assert_int_equal(tctx, str_list_length(result), 2, "list length");
170 1 : torture_assert_str_equal(tctx, result[0], "foo", "element 0");
171 1 : torture_assert_str_equal(tctx, result[1], "bar", "element 1");
172 1 : torture_assert_str_equal(tctx, result[2], NULL, "element 2");
173 :
174 1 : l = str_list_copy(tctx, empty_list);
175 1 : result = discard_const_p(const char *, l);
176 1 : torture_assert_int_equal(tctx, str_list_length(result), 0, "list length");
177 1 : torture_assert_str_equal(tctx, result[0], NULL, "element 0");
178 :
179 1 : l = str_list_copy(tctx, null_list);
180 1 : result = discard_const_p(const char *, l);
181 1 : torture_assert(tctx, result == NULL, "result NULL");
182 :
183 0 : return true;
184 : }
185 :
186 1 : static bool test_list_make_empty(struct torture_context *tctx)
187 : {
188 1 : char **result;
189 :
190 1 : result = str_list_make_empty(tctx);
191 1 : torture_assert(tctx, result, "str_list_make_empty() must not return NULL");
192 1 : torture_assert(tctx, result[0] == NULL, "first element in str_list_make_empty() result must be NULL");
193 :
194 1 : result = str_list_make(tctx, NULL, NULL);
195 1 : torture_assert(tctx, result, "str_list_make() must not return NULL");
196 1 : torture_assert(tctx, result[0] == NULL, "first element in str_list_make(ctx, NULL, NULL) result must be NULL");
197 :
198 1 : result = str_list_make(tctx, "", NULL);
199 1 : torture_assert(tctx, result, "str_list_make() must not return NULL");
200 1 : torture_assert(tctx, result[0] == NULL, "first element in str_list_make(ctx, "", NULL) result must be NULL");
201 :
202 0 : return true;
203 : }
204 :
205 1 : static bool test_list_make_single(struct torture_context *tctx)
206 : {
207 1 : char **result;
208 :
209 1 : result = str_list_make_single(tctx, "foo");
210 :
211 1 : torture_assert(tctx, result, "str_list_make_single() must not return NULL");
212 1 : torture_assert_str_equal(tctx, result[0], "foo", "element 0");
213 1 : torture_assert(tctx, result[1] == NULL, "second element in result must be NULL");
214 :
215 0 : return true;
216 : }
217 :
218 1 : static bool test_list_copy_const(struct torture_context *tctx)
219 : {
220 1 : const char **result;
221 1 : const char *list[] = {
222 : "element_0",
223 : "element_1",
224 : "element_2",
225 : "element_3",
226 : NULL
227 : };
228 1 : result = str_list_copy_const(tctx, list);
229 1 : torture_assert(tctx, result, "str_list_copy() must not return NULL");
230 1 : torture_assert(tctx, str_list_equal(result, list),
231 : "str_list_copy() failed");
232 :
233 0 : return true;
234 : }
235 :
236 1 : static bool test_list_length(struct torture_context *tctx)
237 : {
238 1 : const char *list[] = {
239 : "element_0",
240 : "element_1",
241 : "element_2",
242 : "element_3",
243 : NULL
244 : };
245 1 : const char *list2[] = {
246 : NULL
247 : };
248 1 : torture_assert_int_equal(tctx, str_list_length(list), 4,
249 : "str_list_length() failed");
250 :
251 1 : torture_assert_int_equal(tctx, str_list_length(list2), 0,
252 : "str_list_length() failed");
253 :
254 1 : torture_assert_int_equal(tctx, str_list_length(NULL), 0,
255 : "str_list_length() failed");
256 :
257 0 : return true;
258 : }
259 :
260 1 : static bool test_list_add(struct torture_context *tctx)
261 : {
262 1 : const char **result, **result2;
263 1 : const char *list[] = {
264 : "element_0",
265 : "element_1",
266 : "element_2",
267 : "element_3",
268 : NULL
269 : };
270 1 : char **l;
271 :
272 1 : l = str_list_make(tctx, "element_0, element_1, element_2", NULL);
273 1 : result = discard_const_p(const char *, l);
274 1 : torture_assert(tctx, result, "str_list_make() must not return NULL");
275 1 : result2 = str_list_add(result, "element_3");
276 1 : torture_assert(tctx, result2, "str_list_add() must not return NULL");
277 1 : torture_assert(tctx, str_list_equal(result2, list),
278 : "str_list_add() failed");
279 :
280 0 : return true;
281 : }
282 :
283 1 : static bool test_list_add_const(struct torture_context *tctx)
284 : {
285 1 : const char **result, **result2;
286 1 : const char *list[] = {
287 : "element_0",
288 : "element_1",
289 : "element_2",
290 : "element_3",
291 : NULL
292 : };
293 1 : char **l;
294 :
295 1 : l = str_list_make(tctx, "element_0, element_1, element_2", NULL);
296 1 : result = discard_const_p(const char *, l);
297 1 : torture_assert(tctx, result, "str_list_make() must not return NULL");
298 1 : result2 = str_list_add_const(result, "element_3");
299 1 : torture_assert(tctx, result2, "str_list_add_const() must not return NULL");
300 1 : torture_assert(tctx, str_list_equal(result2, list),
301 : "str_list_add() failed");
302 :
303 0 : return true;
304 : }
305 :
306 1 : static bool test_list_remove(struct torture_context *tctx)
307 : {
308 1 : const char **result;
309 1 : const char *list[] = {
310 : "element_0",
311 : "element_1",
312 : "element_3",
313 : NULL
314 : };
315 1 : char **l;
316 :
317 1 : l = str_list_make(tctx, "element_0, element_1, element_2, element_3", NULL);
318 1 : result = discard_const_p(const char *, l);
319 1 : torture_assert(tctx, result, "str_list_make() must not return NULL");
320 1 : str_list_remove(result, "element_2");
321 1 : torture_assert(tctx, str_list_equal(result, list),
322 : "str_list_remove() failed");
323 :
324 0 : return true;
325 : }
326 :
327 1 : static bool test_list_check(struct torture_context *tctx)
328 : {
329 1 : const char *list[] = {
330 : "element_0",
331 : "element_1",
332 : "element_2",
333 : NULL
334 : };
335 1 : torture_assert(tctx, str_list_check(list, "element_1"),
336 : "str_list_check() failed");
337 :
338 0 : return true;
339 : }
340 :
341 1 : static bool test_list_check_ci(struct torture_context *tctx)
342 : {
343 1 : const char *list[] = {
344 : "element_0",
345 : "element_1",
346 : "element_2",
347 : NULL
348 : };
349 1 : torture_assert(tctx, str_list_check_ci(list, "ELEMENT_1"),
350 : "str_list_check_ci() failed");
351 :
352 0 : return true;
353 : }
354 :
355 1 : static bool test_list_unique(struct torture_context *tctx)
356 : {
357 1 : const char **result;
358 1 : const char *list[] = {
359 : "element_0",
360 : "element_1",
361 : "element_2",
362 : NULL
363 : };
364 1 : const char *list_dup[] = {
365 : "element_0",
366 : "element_1",
367 : "element_2",
368 : "element_0",
369 : "element_2",
370 : "element_1",
371 : "element_1",
372 : "element_2",
373 : NULL
374 : };
375 1 : char **l;
376 :
377 1 : l = str_list_copy(tctx, list_dup);
378 1 : result = discard_const_p(const char *, l);
379 : /* We must copy the list, as str_list_unique does a talloc_realloc() on it's parameter */
380 1 : result = str_list_unique(result);
381 1 : torture_assert(tctx, result, "str_list_unique() must not return NULL");
382 :
383 1 : torture_assert(tctx, str_list_equal(list, result),
384 : "str_list_unique() failed");
385 :
386 0 : return true;
387 : }
388 :
389 1 : static bool test_list_unique_2(struct torture_context *tctx)
390 : {
391 1 : int i;
392 1 : int count, num_dups;
393 1 : const char **result;
394 1 : char **l1 = str_list_make_empty(tctx);
395 1 : char **l2 = str_list_make_empty(tctx);
396 1 : const char **list = discard_const_p(const char *, l1);
397 1 : const char **list_dup = discard_const_p(const char *, l2);
398 1 : char **l;
399 :
400 1 : count = lpcfg_parm_int(tctx->lp_ctx, NULL, "list_unique", "count", 9);
401 1 : num_dups = lpcfg_parm_int(tctx->lp_ctx, NULL, "list_unique", "dups", 7);
402 1 : torture_comment(tctx, "test_list_unique_2() with %d elements and %d dups\n", count, num_dups);
403 :
404 11 : for (i = 0; i < count; i++) {
405 9 : list = str_list_add_const(list, (const char *)talloc_asprintf(tctx, "element_%03d", i));
406 : }
407 :
408 8 : for (i = 0; i < num_dups; i++) {
409 7 : list_dup = str_list_append(list_dup, list);
410 : }
411 :
412 1 : l = str_list_copy(tctx, list_dup);
413 1 : result = discard_const_p(const char *, l);
414 : /* We must copy the list, as str_list_unique does a talloc_realloc() on it's parameter */
415 1 : result = str_list_unique(result);
416 1 : torture_assert(tctx, result, "str_list_unique() must not return NULL");
417 :
418 1 : torture_assert(tctx, str_list_equal(list, result),
419 : "str_list_unique() failed");
420 :
421 0 : return true;
422 : }
423 :
424 1 : static bool test_list_append(struct torture_context *tctx)
425 : {
426 1 : const char **result;
427 1 : const char *list[] = {
428 : "element_0",
429 : "element_1",
430 : "element_2",
431 : NULL
432 : };
433 1 : const char *list2[] = {
434 : "element_3",
435 : "element_4",
436 : "element_5",
437 : NULL
438 : };
439 1 : const char *list_combined[] = {
440 : "element_0",
441 : "element_1",
442 : "element_2",
443 : "element_3",
444 : "element_4",
445 : "element_5",
446 : NULL
447 : };
448 1 : char **l;
449 1 : l = str_list_copy(tctx, list);
450 1 : result = discard_const_p(const char *, l);
451 1 : torture_assert(tctx, result, "str_list_copy() must not return NULL");
452 1 : result = str_list_append(result, list2);
453 1 : torture_assert(tctx, result, "str_list_append() must not return NULL");
454 1 : torture_assert(tctx, str_list_equal(list_combined, result),
455 : "str_list_unique() failed");
456 :
457 0 : return true;
458 : }
459 :
460 1 : static bool test_list_append_const(struct torture_context *tctx)
461 : {
462 1 : const char **result;
463 1 : const char *list[] = {
464 : "element_0",
465 : "element_1",
466 : "element_2",
467 : NULL
468 : };
469 1 : const char *list2[] = {
470 : "element_3",
471 : "element_4",
472 : "element_5",
473 : NULL
474 : };
475 1 : const char *list_combined[] = {
476 : "element_0",
477 : "element_1",
478 : "element_2",
479 : "element_3",
480 : "element_4",
481 : "element_5",
482 : NULL
483 : };
484 1 : char **l;
485 1 : l = str_list_copy(tctx, list);
486 1 : result = discard_const_p(const char *, l);
487 1 : torture_assert(tctx, result, "str_list_copy() must not return NULL");
488 1 : result = str_list_append_const(result, list2);
489 1 : torture_assert(tctx, result, "str_list_append_const() must not return NULL");
490 1 : torture_assert(tctx, str_list_equal(list_combined, result),
491 : "str_list_unique() failed");
492 :
493 0 : return true;
494 : }
495 :
496 1 : static bool test_list_add_printf_NULL(struct torture_context *tctx)
497 : {
498 1 : char **list = NULL;
499 1 : str_list_add_printf(&list, "x=%d", 1);
500 1 : torture_assert(tctx, list==NULL, "str_list_add_printf must keep NULL");
501 0 : return true;
502 : }
503 :
504 1 : static bool test_list_add_printf(struct torture_context *tctx)
505 : {
506 1 : const char *list2[] = { "foo", "bar=baz", NULL };
507 1 : char **list = str_list_make_empty(tctx);
508 1 : str_list_add_printf(&list, "foo");
509 1 : str_list_add_printf(&list, "bar=%s", "baz");
510 1 : torture_assert(
511 : tctx,
512 : str_list_equal((const char * const *)list, list2),
513 : "str_list_add_printf failed");
514 1 : TALLOC_FREE(list);
515 0 : return true;
516 : }
517 :
518 2354 : struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx)
519 : {
520 2354 : struct torture_suite *suite = torture_suite_create(mem_ctx, "strlist");
521 125 : size_t i;
522 :
523 21311 : for (i = 0; i < ARRAY_SIZE(test_lists_shell_strings); i++) {
524 1000 : char *name;
525 19832 : name = talloc_asprintf(suite, "lists_shell(%s)",
526 18832 : test_lists_shell_strings[i].list_as_string);
527 18832 : torture_suite_add_simple_tcase_const(suite, name,
528 18832 : test_lists_shell, &test_lists_shell_strings[i]);
529 : }
530 :
531 18832 : for (i = 0; i < ARRAY_SIZE(test_lists_strings); i++) {
532 875 : char *name;
533 17353 : name = talloc_asprintf(suite, "list_make(%s)",
534 16478 : test_lists_strings[i].list_as_string);
535 16478 : torture_suite_add_simple_tcase_const(suite, name,
536 16478 : test_list_make, &test_lists_strings[i]);
537 : }
538 :
539 2354 : torture_suite_add_simple_test(suite, "list_copy", test_list_copy);
540 2354 : torture_suite_add_simple_test(suite, "make_empty", test_list_make_empty);
541 2354 : torture_suite_add_simple_test(suite, "make_single", test_list_make_single);
542 2354 : torture_suite_add_simple_test(suite, "list_copy_const", test_list_copy_const);
543 2354 : torture_suite_add_simple_test(suite, "list_length", test_list_length);
544 2354 : torture_suite_add_simple_test(suite, "list_add", test_list_add);
545 2354 : torture_suite_add_simple_test(suite, "list_add_const", test_list_add_const);
546 2354 : torture_suite_add_simple_test(suite, "list_remove", test_list_remove);
547 2354 : torture_suite_add_simple_test(suite, "list_check", test_list_check);
548 2354 : torture_suite_add_simple_test(suite, "list_check_ci", test_list_check_ci);
549 2354 : torture_suite_add_simple_test(suite, "list_unique", test_list_unique);
550 2354 : torture_suite_add_simple_test(suite, "list_unique_2", test_list_unique_2);
551 2354 : torture_suite_add_simple_test(suite, "list_append", test_list_append);
552 2354 : torture_suite_add_simple_test(suite, "list_append_const", test_list_append_const);
553 2354 : torture_suite_add_simple_test(
554 : suite, "list_add_printf_NULL", test_list_add_printf_NULL);
555 2354 : torture_suite_add_simple_test(
556 : suite, "list_add_printf", test_list_add_printf);
557 2354 : return suite;
558 : }
|