chiark / gitweb /
370219121bc9a3b4b26b9df9eb2c6fb65737b255
[elogind.git] / src / test / test-strv.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7   Copyright 2013 Thomas H.P. Andersen
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <string.h>
24
25 #include "util.h"
26 #include "specifier.h"
27 #include "strv.h"
28
29 static void test_specifier_printf(void) {
30         static const Specifier table[] = {
31                 { 'a', specifier_string, (char*) "AAAA" },
32                 { 'b', specifier_string, (char*) "BBBB" },
33                 { 'm', specifier_machine_id, NULL },
34                 { 'B', specifier_boot_id, NULL },
35                 { 'H', specifier_host_name, NULL },
36                 { 'v', specifier_kernel_release, NULL },
37                 {}
38         };
39
40         _cleanup_free_ char *w = NULL;
41         int r;
42
43         r = specifier_printf("xxx a=%a b=%b yyy", table, NULL, &w);
44         assert_se(r >= 0);
45         assert_se(w);
46
47         puts(w);
48         assert_se(streq(w, "xxx a=AAAA b=BBBB yyy"));
49
50         free(w);
51         r = specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table, NULL, &w);
52         assert_se(r >= 0);
53         assert_se(w);
54         puts(w);
55 }
56
57 static const char* const input_table_multiple[] = {
58         "one",
59         "two",
60         "three",
61         NULL,
62 };
63
64 static const char* const input_table_one[] = {
65         "one",
66         NULL,
67 };
68
69 static const char* const input_table_none[] = {
70         NULL,
71 };
72
73 static const char* const input_table_quotes[] = {
74         "\"",
75         "'",
76         "\"\"",
77         "\\",
78         "\\\\",
79         NULL,
80 };
81 #define QUOTES_STRING                            \
82         "\"\\\"\" "                              \
83         "\"\\\'\" "                              \
84         "\"\\\"\\\"\" "                          \
85         "\"\\\\\" "                              \
86         "\"\\\\\\\\\""
87
88 static const char * const input_table_spaces[] = {
89         " ",
90         "' '",
91         "\" ",
92         " \"",
93         " \\\\ ",
94         NULL,
95 };
96 #define SPACES_STRING                           \
97         "\" \" "                                \
98         "\"\\' \\'\" "                          \
99         "\"\\\" \" "                            \
100         "\" \\\"\" "                            \
101         "\" \\\\\\\\ \""
102
103 static void test_strv_find(void) {
104         assert_se(strv_find((char **)input_table_multiple, "three"));
105         assert_se(!strv_find((char **)input_table_multiple, "four"));
106 }
107
108 static void test_strv_find_prefix(void) {
109         assert_se(strv_find_prefix((char **)input_table_multiple, "o"));
110         assert_se(strv_find_prefix((char **)input_table_multiple, "one"));
111         assert_se(strv_find_prefix((char **)input_table_multiple, ""));
112         assert_se(!strv_find_prefix((char **)input_table_multiple, "xxx"));
113         assert_se(!strv_find_prefix((char **)input_table_multiple, "onee"));
114 }
115
116 static void test_strv_join(void) {
117         _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL;
118
119         p = strv_join((char **)input_table_multiple, ", ");
120         assert_se(p);
121         assert_se(streq(p, "one, two, three"));
122
123         q = strv_join((char **)input_table_multiple, ";");
124         assert_se(q);
125         assert_se(streq(q, "one;two;three"));
126
127         r = strv_join((char **)input_table_multiple, NULL);
128         assert_se(r);
129         assert_se(streq(r, "one two three"));
130
131         s = strv_join((char **)input_table_one, ", ");
132         assert_se(s);
133         assert_se(streq(s, "one"));
134
135         t = strv_join((char **)input_table_none, ", ");
136         assert_se(t);
137         assert_se(streq(t, ""));
138 }
139
140 static void test_strv_quote_unquote(const char* const *split, const char *quoted) {
141         _cleanup_free_ char *p;
142         _cleanup_strv_free_ char **s;
143         char **t;
144
145         p = strv_join_quoted((char **)split);
146         assert_se(p);
147         printf("-%s- --- -%s-\n", p, quoted); /* fprintf deals with NULL, puts does not */
148         assert_se(p);
149         assert_se(streq(p, quoted));
150
151         s = strv_split_quoted(quoted);
152         assert_se(s);
153         STRV_FOREACH(t, s) {
154                 assert_se(*t);
155                 assert_se(streq(*t, *split));
156                 split++;
157         }
158 }
159
160 static void test_strv_unquote(const char *quoted, const char **list) {
161         _cleanup_strv_free_ char **s;
162         unsigned i = 0;
163         char **t;
164
165         s = strv_split_quoted(quoted);
166         assert_se(s);
167         strv_print(s);
168
169         STRV_FOREACH(t, s)
170                 assert_se(streq(list[i++], *t));
171
172         assert_se(list[i] == NULL);
173 }
174
175 static void test_strv_split(void) {
176         char **s;
177         unsigned i = 0;
178         _cleanup_strv_free_ char **l = NULL;
179         const char str[] = "one,two,three";
180
181         l = strv_split(str, ",");
182
183         assert(l);
184
185         STRV_FOREACH(s, l) {
186                 assert_se(streq(*s, input_table_multiple[i++]));
187         }
188 }
189
190 static void test_strv_split_newlines(void) {
191         unsigned i = 0;
192         char **s;
193         _cleanup_strv_free_ char **l = NULL;
194         const char str[] = "one\ntwo\nthree";
195
196         l = strv_split_newlines(str);
197
198         assert(l);
199
200         STRV_FOREACH(s, l) {
201                 assert_se(streq(*s, input_table_multiple[i++]));
202         }
203 }
204
205 static void test_strv_split_nulstr(void) {
206         _cleanup_strv_free_ char **l = NULL;
207         const char nulstr[] = "str0\0str1\0str2\0str3\0";
208
209         l = strv_split_nulstr (nulstr);
210         assert_se(l);
211
212         assert_se(streq(l[0], "str0"));
213         assert_se(streq(l[1], "str1"));
214         assert_se(streq(l[2], "str2"));
215         assert_se(streq(l[3], "str3"));
216 }
217
218 static void test_strv_parse_nulstr(void) {
219         _cleanup_strv_free_ char **l = NULL;
220         const char nulstr[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
221
222         l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1);
223         assert_se(l);
224         puts("Parse nulstr:");
225         strv_print(l);
226
227         assert_se(streq(l[0], "fuck"));
228         assert_se(streq(l[1], "fuck2"));
229         assert_se(streq(l[2], "fuck3"));
230         assert_se(streq(l[3], ""));
231         assert_se(streq(l[4], "fuck5"));
232         assert_se(streq(l[5], ""));
233         assert_se(streq(l[6], "xxx"));
234 }
235
236 static void test_strv_overlap(void) {
237         const char * const input_table[] = {
238                 "one",
239                 "two",
240                 "three",
241                 NULL
242         };
243         const char * const input_table_overlap[] = {
244                 "two",
245                 NULL
246         };
247         const char * const input_table_unique[] = {
248                 "four",
249                 "five",
250                 "six",
251                 NULL
252         };
253
254         assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap));
255         assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique));
256 }
257
258 static void test_strv_sort(void) {
259         const char* input_table[] = {
260                 "durian",
261                 "apple",
262                 "citrus",
263                  "CAPITAL LETTERS FIRST",
264                 "banana",
265                 NULL
266         };
267
268         strv_sort((char **)input_table);
269
270         assert_se(streq(input_table[0], "CAPITAL LETTERS FIRST"));
271         assert_se(streq(input_table[1], "apple"));
272         assert_se(streq(input_table[2], "banana"));
273         assert_se(streq(input_table[3], "citrus"));
274         assert_se(streq(input_table[4], "durian"));
275 }
276
277 static void test_strv_extend_strv_concat(void) {
278          _cleanup_strv_free_ char **a = NULL, **b = NULL;
279
280         a = strv_new("without", "suffix", NULL);
281         b = strv_new("with", "suffix", NULL);
282         assert_se(a);
283         assert_se(b);
284
285         assert_se(strv_extend_strv_concat(&a, b, "_suffix") >= 0);
286
287         assert_se(streq(a[0], "without"));
288         assert_se(streq(a[1], "suffix"));
289         assert_se(streq(a[2], "with_suffix"));
290         assert_se(streq(a[3], "suffix_suffix"));
291 }
292
293 static void test_strv_extend_strv(void) {
294          _cleanup_strv_free_ char **a = NULL, **b = NULL;
295
296         a = strv_new("abc", "def", "ghi", NULL);
297         b = strv_new("jkl", "mno", "pqr", NULL);
298         assert_se(a);
299         assert_se(b);
300
301         assert_se(strv_extend_strv(&a, b) >= 0);
302
303         assert_se(streq(a[0], "abc"));
304         assert_se(streq(a[1], "def"));
305         assert_se(streq(a[2], "ghi"));
306         assert_se(streq(a[3], "jkl"));
307         assert_se(streq(a[4], "mno"));
308         assert_se(streq(a[5], "pqr"));
309
310         assert_se(strv_length(a) == 6);
311 }
312
313 static void test_strv_extend(void) {
314         _cleanup_strv_free_ char **a = NULL, **b = NULL;
315
316         a = strv_new("test", "test1", NULL);
317         assert_se(a);
318         assert_se(strv_extend(&a, "test2") >= 0);
319         assert_se(strv_extend(&b, "test3") >= 0);
320
321         assert_se(streq(a[0], "test"));
322         assert_se(streq(a[1], "test1"));
323         assert_se(streq(a[2], "test2"));
324         assert_se(streq(b[0], "test3"));
325 }
326
327 static void test_strv_extendf(void) {
328         _cleanup_strv_free_ char **a = NULL, **b = NULL;
329
330         a = strv_new("test", "test1", NULL);
331         assert_se(a);
332         assert_se(strv_extendf(&a, "test2 %s %d %s", "foo", 128, "bar") >= 0);
333         assert_se(strv_extendf(&b, "test3 %s %s %d", "bar", "foo", 128) >= 0);
334
335         assert_se(streq(a[0], "test"));
336         assert_se(streq(a[1], "test1"));
337         assert_se(streq(a[2], "test2 foo 128 bar"));
338         assert_se(streq(b[0], "test3 bar foo 128"));
339 }
340
341 static void test_strv_foreach(void) {
342         _cleanup_strv_free_ char **a;
343         unsigned i = 0;
344         char **check;
345
346         a = strv_new("one", "two", "three", NULL);
347
348         assert_se(a);
349
350         STRV_FOREACH(check, a) {
351                 assert_se(streq(*check, input_table_multiple[i++]));
352         }
353 }
354
355 static void test_strv_foreach_backwards(void) {
356         _cleanup_strv_free_ char **a;
357         unsigned i = 2;
358         char **check;
359
360         a = strv_new("one", "two", "three", NULL);
361
362         assert_se(a);
363
364         STRV_FOREACH_BACKWARDS(check, a) {
365                 assert_se(streq_ptr(*check, input_table_multiple[i--]));
366         }
367 }
368
369 static void test_strv_foreach_pair(void) {
370         _cleanup_strv_free_ char **a = NULL;
371         char **x, **y;
372
373         a = strv_new("pair_one",   "pair_one",
374                      "pair_two",   "pair_two",
375                      "pair_three", "pair_three",
376                      NULL);
377
378         STRV_FOREACH_PAIR(x, y, a) {
379                 assert_se(streq(*x, *y));
380         }
381 }
382
383 static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) {
384         char **j;
385         unsigned i;
386
387         j = strv_from_stdarg_alloca(first);
388
389         for (i = 0;; i++) {
390                 assert_se(streq_ptr(l[i], j[i]));
391
392                 if (!l[i])
393                         break;
394         }
395 }
396
397 static void test_strv_from_stdarg_alloca(void) {
398         test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL);
399         test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL);
400         test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY, NULL);
401 }
402
403 int main(int argc, char *argv[]) {
404         test_specifier_printf();
405         test_strv_foreach();
406         test_strv_foreach_backwards();
407         test_strv_foreach_pair();
408         test_strv_find();
409         test_strv_find_prefix();
410         test_strv_join();
411
412         test_strv_quote_unquote(input_table_multiple, "\"one\" \"two\" \"three\"");
413         test_strv_quote_unquote(input_table_one, "\"one\"");
414         test_strv_quote_unquote(input_table_none, "");
415         test_strv_quote_unquote(input_table_quotes, QUOTES_STRING);
416         test_strv_quote_unquote(input_table_spaces, SPACES_STRING);
417
418         test_strv_unquote("    foo=bar     \"waldo\"    zzz    ", (const char*[]) { "foo=bar", "waldo", "zzz", NULL });
419         test_strv_unquote("", (const char*[]) { NULL });
420         test_strv_unquote(" ", (const char*[]) { NULL });
421         test_strv_unquote("   ", (const char*[]) { NULL });
422         test_strv_unquote("   x", (const char*[]) { "x", NULL });
423         test_strv_unquote("x   ", (const char*[]) { "x", NULL });
424         test_strv_unquote("  x   ", (const char*[]) { "x", NULL });
425         test_strv_unquote("  \"x\"   ", (const char*[]) { "x", NULL });
426         test_strv_unquote("  'x'   ", (const char*[]) { "x", NULL });
427         test_strv_unquote("  'x\"'   ", (const char*[]) { "x\"", NULL });
428         test_strv_unquote("  \"x'\"   ", (const char*[]) { "x'", NULL });
429         test_strv_unquote("a  '--b=c \"d e\"'", (const char*[]) { "a", "--b=c \"d e\"", NULL });
430
431         test_strv_unquote("a  --b='c \"d e\"'", (const char*[]) { "a", "--b='c", "\"d", "e\"'", NULL });
432
433         test_strv_split();
434         test_strv_split_newlines();
435         test_strv_split_nulstr();
436         test_strv_parse_nulstr();
437         test_strv_overlap();
438         test_strv_sort();
439         test_strv_extend_strv();
440         test_strv_extend_strv_concat();
441         test_strv_extend();
442         test_strv_extendf();
443         test_strv_from_stdarg_alloca();
444
445         return 0;
446 }