8940dab4156462a59aa0db4b3125682c29fef7e1
[ira/wip.git] / lib / util / tests / strlist.c
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 "param/param.h"
26
27 struct test_list_element {
28         const char *list_as_string;
29         const char *seperators;
30         const char *list[5];
31 };
32
33 const struct test_list_element test_lists_strings[] = {
34         {
35                 .list_as_string = "",
36                 .list = { NULL }
37         },
38         {
39                 .list_as_string = "foo",
40                 .list = { "foo", NULL }
41         },
42         {
43                 .list_as_string = "foo bar",
44                 .list = { "foo", "bar", NULL }
45         },
46         {
47                 .list_as_string = "foo bar",
48                 .list = { "foo bar", NULL },
49                 .seperators = ";"
50         },
51         {
52                 .list_as_string = "\"foo bar\"",
53                 .list = { "\"foo", "bar\"", NULL }
54         },
55         {
56                 .list_as_string = "\"foo bar\",comma\ttab",
57                 .list = { "\"foo", "bar\"", "comma", "tab", NULL }
58         },
59         {
60                 .list_as_string = "\"foo bar\",comma;semicolon",
61                 .list = { "\"foo bar\",comma", "semicolon", NULL },
62                 .seperators = ";"
63         }
64 };
65
66 const struct test_list_element test_lists_shell_strings[] = {
67         {
68                 .list_as_string = "",
69                 .list = { NULL }
70         },
71         {
72                 .list_as_string = "foo",
73                 .list = { "foo", NULL }
74         },
75         {
76                 .list_as_string = "foo bar",
77                 .list = { "foo", "bar", NULL }
78         },
79         {
80                 .list_as_string = "foo bar",
81                 .list = { "foo bar", NULL },
82                 .seperators = ";"
83         },
84         {
85                 .list_as_string = "\"foo bar\"",
86                 .list = { "foo bar", NULL }
87         },
88         {
89                 .list_as_string = "foo bar \"bla \"",
90                 .list = { "foo", "bar", "bla ", NULL }
91         },
92         {
93                 .list_as_string = "foo \"\" bla",
94                 .list = { "foo", "", "bla", NULL },
95         },
96         {
97                 .list_as_string = "bla \"\"\"\" blie",
98                 .list = { "bla", "", "", "blie", NULL },
99         }
100 };
101
102 static bool test_lists_shell(struct torture_context *tctx, const void *data)
103 {
104         const struct test_list_element *element = data;
105
106         char **ret1, **ret2, *tmp;
107         bool match = true;
108         TALLOC_CTX *mem_ctx = tctx;
109
110         ret1 = str_list_make_shell(mem_ctx, element->list_as_string, element->seperators);
111         
112         torture_assert(tctx, ret1, "str_list_make_shell() must not return NULL");
113         tmp = str_list_join_shell(mem_ctx, (const char **) ret1, element->seperators ? *element->seperators : ' ');
114         ret2 = str_list_make_shell(mem_ctx, tmp, element->seperators);
115
116         if ((ret1 == NULL || ret2 == NULL) && ret2 != ret1) {
117                 match = false;
118         } else {
119                 int j;
120                 for (j = 0; ret1[j] && ret2[j]; j++) {
121                         if (strcmp(ret1[j], ret2[j]) != 0) {
122                                 match = false;
123                                 break;
124                         }
125                 }
126
127                 if (ret1[j] || ret2[j])
128                         match = false;
129         }
130
131         torture_assert(tctx, match, talloc_asprintf(tctx, 
132                 "str_list_{make,join}_shell: Error double parsing, first run:\n%s\nSecond run: \n%s", element->list_as_string, tmp));
133         torture_assert(tctx, str_list_equal((const char * const *) ret1,
134                                             element->list),
135                        talloc_asprintf(tctx, 
136                                        "str_list_make_shell(%s) failed to create correct list", 
137                                        element->list_as_string));
138
139         return true;
140 }
141
142 static bool test_list_make(struct torture_context *tctx, const void *data)
143 {
144         const struct test_list_element *element = data;
145
146         char **result;
147         result = str_list_make(tctx, element->list_as_string, element->seperators);
148         torture_assert(tctx, result, "str_list_make() must not return NULL");
149         torture_assert(tctx, str_list_equal((const char * const *) result,
150                                             element->list),
151                        talloc_asprintf(tctx, 
152                                        "str_list_make(%s) failed to create correct list", 
153                                        element->list_as_string));
154         return true;
155 }
156
157 static bool test_list_copy(struct torture_context *tctx)
158 {
159         const char **result;
160         const char *list[] = { "foo", "bar", NULL };
161         const char *empty_list[] = { NULL };
162         const char **null_list = NULL;
163
164         result = (const char **)str_list_copy(tctx, list);
165         torture_assert_int_equal(tctx, str_list_length(result), 2, "list length");
166         torture_assert_str_equal(tctx, result[0], "foo", "element 0");
167         torture_assert_str_equal(tctx, result[1], "bar", "element 1");
168         torture_assert_str_equal(tctx, result[2], NULL, "element 2");
169
170         result = (const char **)str_list_copy(tctx, empty_list);
171         torture_assert_int_equal(tctx, str_list_length(result), 0, "list length");
172         torture_assert_str_equal(tctx, result[0], NULL, "element 0");
173
174         result = (const char **)str_list_copy(tctx, null_list);
175         torture_assert(tctx, result == NULL, "result NULL");
176         
177         return true;
178 }
179
180 static bool test_list_make_empty(struct torture_context *tctx)
181 {
182         char **result;
183
184         result = str_list_make_empty(tctx);
185         torture_assert(tctx, result, "str_list_make_empty() must not return NULL");
186         torture_assert(tctx, result[0] == NULL, "first element in str_list_make_empty() result must be NULL");
187
188         result = str_list_make(tctx, NULL, NULL);
189         torture_assert(tctx, result, "str_list_make() must not return NULL");
190         torture_assert(tctx, result[0] == NULL, "first element in str_list_make(ctx, NULL, NULL) result must be NULL");
191         
192         result = str_list_make(tctx, "", NULL);
193         torture_assert(tctx, result, "str_list_make() must not return NULL");
194         torture_assert(tctx, result[0] == NULL, "first element in str_list_make(ctx, "", NULL) result must be NULL");
195         
196         return true;
197 }
198
199 static bool test_list_make_single(struct torture_context *tctx)
200 {
201         char **result;
202
203         result = str_list_make_single(tctx, "foo");
204
205         torture_assert(tctx, result, "str_list_make_single() must not return NULL");
206         torture_assert_str_equal(tctx, result[0], "foo", "element 0");
207         torture_assert(tctx, result[1] == NULL, "second element in result must be NULL");
208         
209         return true;
210 }
211
212 static bool test_list_copy_const(struct torture_context *tctx)
213 {
214         const char **result;
215         const char *list[] = {
216                 "element_0", 
217                 "element_1",
218                 "element_2",
219                 "element_3",
220                 NULL
221         };
222         result = str_list_copy_const(tctx, list);
223         torture_assert(tctx, result, "str_list_copy() must not return NULL");
224         torture_assert(tctx, str_list_equal(result, list), 
225                        "str_list_copy() failed");
226
227         return true;
228 }
229
230 static bool test_list_length(struct torture_context *tctx)
231 {
232         const char *list[] = {
233                 "element_0", 
234                 "element_1",
235                 "element_2",
236                 "element_3",
237                 NULL
238         };
239         const char *list2[] = {
240                 NULL
241         };
242         torture_assert_int_equal(tctx, str_list_length(list), 4, 
243                        "str_list_length() failed");
244
245         torture_assert_int_equal(tctx, str_list_length(list2), 0, 
246                        "str_list_length() failed");
247
248         torture_assert_int_equal(tctx, str_list_length(NULL), 0, 
249                        "str_list_length() failed");
250
251         return true;
252 }
253
254 static bool test_list_add(struct torture_context *tctx)
255 {
256         const char **result, **result2;
257         const char *list[] = {
258                 "element_0", 
259                 "element_1",
260                 "element_2",
261                 "element_3",
262                 NULL
263         };
264         result = (const char **) str_list_make(tctx, "element_0, element_1, element_2", NULL);
265         torture_assert(tctx, result, "str_list_make() must not return NULL");
266         result2 = str_list_add((const char **) result, "element_3");
267         torture_assert(tctx, result2, "str_list_add() must not return NULL");
268         torture_assert(tctx, str_list_equal(result2, list), 
269                        "str_list_add() failed");
270
271         return true;
272 }
273
274 static bool test_list_add_const(struct torture_context *tctx)
275 {
276         const char **result, **result2;
277         const char *list[] = {
278                 "element_0", 
279                 "element_1",
280                 "element_2",
281                 "element_3",
282                 NULL
283         };
284         result = (const char **) str_list_make(tctx, "element_0, element_1, element_2", NULL);
285         torture_assert(tctx, result, "str_list_make() must not return NULL");
286         result2 = str_list_add_const(result, "element_3");
287         torture_assert(tctx, result2, "str_list_add_const() must not return NULL");
288         torture_assert(tctx, str_list_equal(result2, list), 
289                        "str_list_add() failed");
290
291         return true;
292 }
293
294 static bool test_list_remove(struct torture_context *tctx)
295 {
296         const char **result;
297         const char *list[] = {
298                 "element_0", 
299                 "element_1",
300                 "element_3",
301                 NULL
302         };
303         result = (const char **) str_list_make(tctx, "element_0, element_1, element_2, element_3", NULL);
304         torture_assert(tctx, result, "str_list_make() must not return NULL");
305         str_list_remove(result, "element_2");
306         torture_assert(tctx, str_list_equal(result, list), 
307                        "str_list_remove() failed");
308
309         return true;
310 }
311
312 static bool test_list_check(struct torture_context *tctx)
313 {
314         const char *list[] = {
315                 "element_0", 
316                 "element_1",
317                 "element_2",
318                 NULL
319         };
320         torture_assert(tctx, str_list_check(list, "element_1"), 
321                        "str_list_check() failed");
322
323         return true;
324 }
325
326 static bool test_list_check_ci(struct torture_context *tctx)
327 {
328         const char *list[] = {
329                 "element_0", 
330                 "element_1",
331                 "element_2",
332                 NULL
333         };
334         torture_assert(tctx, str_list_check_ci(list, "ELEMENT_1"), 
335                        "str_list_check_ci() failed");
336
337         return true;
338 }
339
340 static bool test_list_unique(struct torture_context *tctx)
341 {
342         const char **result;
343         const char *list[] = {
344                 "element_0", 
345                 "element_1",
346                 "element_2",
347                 NULL
348         };
349         const char *list_dup[] = {
350                 "element_0", 
351                 "element_1",
352                 "element_2",
353                 "element_0", 
354                 "element_2",
355                 "element_1",
356                 "element_1",
357                 "element_2",
358                 NULL
359         };
360         result = (const char **) str_list_copy(tctx, list_dup);
361         /* We must copy the list, as str_list_unique does a talloc_realloc() on it's parameter */
362         result = str_list_unique(result);
363         torture_assert(tctx, result, "str_list_unique() must not return NULL");
364         
365         torture_assert(tctx, str_list_equal(list, result), 
366                        "str_list_unique() failed");
367
368         return true;
369 }
370
371 static bool test_list_unique_2(struct torture_context *tctx)
372 {
373         int i;
374         int count, num_dups;
375         const char **result;
376         const char **list = (const char **)str_list_make_empty(tctx);
377         const char **list_dup = (const char **)str_list_make_empty(tctx);
378
379         count = lp_parm_int(tctx->lp_ctx, NULL, "list_unique", "count", 9);
380         num_dups = lp_parm_int(tctx->lp_ctx, NULL, "list_unique", "dups", 7);
381         torture_comment(tctx, "test_list_unique_2() with %d elements and %d dups\n", count, num_dups);
382
383         for (i = 0; i < count; i++) {
384                 list = str_list_add_const(list, (const char *)talloc_asprintf(tctx, "element_%03d", i));
385         }
386
387         for (i = 0; i < num_dups; i++) {
388                 list_dup = str_list_append(list_dup, list);
389         }
390
391         result = (const char **)str_list_copy(tctx, list_dup);
392         /* We must copy the list, as str_list_unique does a talloc_realloc() on it's parameter */
393         result = str_list_unique(result);
394         torture_assert(tctx, result, "str_list_unique() must not return NULL");
395
396         torture_assert(tctx, str_list_equal(list, result),
397                        "str_list_unique() failed");
398
399         return true;
400 }
401
402 static bool test_list_append(struct torture_context *tctx)
403 {
404         const char **result;
405         const char *list[] = {
406                 "element_0", 
407                 "element_1",
408                 "element_2",
409                 NULL
410         };
411         const char *list2[] = {
412                 "element_3", 
413                 "element_4",
414                 "element_5",
415                 NULL
416         };
417         const char *list_combined[] = {
418                 "element_0", 
419                 "element_1",
420                 "element_2",
421                 "element_3", 
422                 "element_4",
423                 "element_5",
424                 NULL
425         };
426         result = (const char **) str_list_copy(tctx, list);
427         torture_assert(tctx, result, "str_list_copy() must not return NULL");
428         result = str_list_append(result, list2);
429         torture_assert(tctx, result, "str_list_append() must not return NULL");
430         torture_assert(tctx, str_list_equal(list_combined, result), 
431                        "str_list_unique() failed");
432
433         return true;
434 }
435
436 static bool test_list_append_const(struct torture_context *tctx)
437 {
438         const char **result;
439         const char *list[] = {
440                 "element_0", 
441                 "element_1",
442                 "element_2",
443                 NULL
444         };
445         const char *list2[] = {
446                 "element_3", 
447                 "element_4",
448                 "element_5",
449                 NULL
450         };
451         const char *list_combined[] = {
452                 "element_0", 
453                 "element_1",
454                 "element_2",
455                 "element_3", 
456                 "element_4",
457                 "element_5",
458                 NULL
459         };
460         result = (const char **) str_list_copy(tctx, list);
461         torture_assert(tctx, result, "str_list_copy() must not return NULL");
462         result = str_list_append_const(result, list2);
463         torture_assert(tctx, result, "str_list_append_const() must not return NULL");
464         torture_assert(tctx, str_list_equal(list_combined, result), 
465                        "str_list_unique() failed");
466
467         return true;
468 }
469
470 struct torture_suite *torture_local_util_strlist(TALLOC_CTX *mem_ctx)
471 {
472         struct torture_suite *suite = torture_suite_create(mem_ctx, "STRLIST");
473         int i;
474
475         for (i = 0; i < ARRAY_SIZE(test_lists_shell_strings); i++) {
476                 torture_suite_add_simple_tcase_const(suite, "lists_shell",
477                         test_lists_shell,  &test_lists_shell_strings[i]);
478         }
479
480         for (i = 0; i < ARRAY_SIZE(test_lists_strings); i++) {
481                 torture_suite_add_simple_tcase_const(suite, "list_make",
482                         test_list_make, &test_lists_strings[i]);
483         }
484
485         torture_suite_add_simple_test(suite, "list_copy", test_list_copy);
486         torture_suite_add_simple_test(suite, "make_empty", test_list_make_empty);
487         torture_suite_add_simple_test(suite, "make_single", test_list_make_single);
488         torture_suite_add_simple_test(suite, "list_copy_const", test_list_copy_const);
489         torture_suite_add_simple_test(suite, "list_length", test_list_length);
490         torture_suite_add_simple_test(suite, "list_add", test_list_add);
491         torture_suite_add_simple_test(suite, "list_add_const", test_list_add_const);
492         torture_suite_add_simple_test(suite, "list_remove", test_list_remove);
493         torture_suite_add_simple_test(suite, "list_check", test_list_check);
494         torture_suite_add_simple_test(suite, "list_check_ci", test_list_check_ci);
495         torture_suite_add_simple_test(suite, "list_unique", test_list_unique);
496         torture_suite_add_simple_test(suite, "list_unique_2", test_list_unique_2);
497         torture_suite_add_simple_test(suite, "list_append", test_list_append);
498         torture_suite_add_simple_test(suite, "list_append_const", test_list_append_const);
499
500         return suite;
501 }