chiark / gitweb /
d58d99c99fe8ac07e4b71e38c53bd83b3dd097b6
[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_quote_unquote2(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
168         STRV_FOREACH(t, s)
169                 assert_se(streq(list[i++], *t));
170
171         assert_se(list[i] == NULL);
172 }
173
174 static void test_strv_split(void) {
175         char **s;
176         unsigned i = 0;
177         _cleanup_strv_free_ char **l = NULL;
178         const char str[] = "one,two,three";
179
180         l = strv_split(str, ",");
181
182         assert(l);
183
184         STRV_FOREACH(s, l) {
185                 assert_se(streq(*s, input_table_multiple[i++]));
186         }
187 }
188
189 static void test_strv_split_newlines(void) {
190         unsigned i = 0;
191         char **s;
192         _cleanup_strv_free_ char **l = NULL;
193         const char str[] = "one\ntwo\nthree";
194
195         l = strv_split_newlines(str);
196
197         assert(l);
198
199         STRV_FOREACH(s, l) {
200                 assert_se(streq(*s, input_table_multiple[i++]));
201         }
202 }
203
204 static void test_strv_split_nulstr(void) {
205         _cleanup_strv_free_ char **l = NULL;
206         const char nulstr[] = "str0\0str1\0str2\0str3\0";
207
208         l = strv_split_nulstr (nulstr);
209         assert_se(l);
210
211         assert_se(streq(l[0], "str0"));
212         assert_se(streq(l[1], "str1"));
213         assert_se(streq(l[2], "str2"));
214         assert_se(streq(l[3], "str3"));
215 }
216
217 static void test_strv_remove_prefix(void) {
218         unsigned i = 0;
219         char **s;
220         _cleanup_strv_free_ char **l = NULL;
221
222         l = strv_new("_one", "_two", "_three", NULL);
223         assert(l);
224
225         l = strv_remove_prefix(l, "_");
226         assert(l);
227
228         STRV_FOREACH(s, l) {
229                 assert_se(streq(*s, input_table_multiple[i++]));
230         }
231 }
232
233 static void test_strv_parse_nulstr(void) {
234         _cleanup_strv_free_ char **l = NULL;
235         const char nulstr[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
236
237         l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1);
238         assert_se(l);
239         puts("Parse nulstr:");
240         strv_print(l);
241
242         assert_se(streq(l[0], "fuck"));
243         assert_se(streq(l[1], "fuck2"));
244         assert_se(streq(l[2], "fuck3"));
245         assert_se(streq(l[3], ""));
246         assert_se(streq(l[4], "fuck5"));
247         assert_se(streq(l[5], ""));
248         assert_se(streq(l[6], "xxx"));
249 }
250
251 static void test_strv_overlap(void) {
252         const char * const input_table[] = {
253                 "one",
254                 "two",
255                 "three",
256                 NULL
257         };
258         const char * const input_table_overlap[] = {
259                 "two",
260                 NULL
261         };
262         const char * const input_table_unique[] = {
263                 "four",
264                 "five",
265                 "six",
266                 NULL
267         };
268
269         assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap));
270         assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique));
271 }
272
273 static void test_strv_sort(void) {
274         const char* input_table[] = {
275                 "durian",
276                 "apple",
277                 "citrus",
278                  "CAPITAL LETTERS FIRST",
279                 "banana",
280                 NULL
281         };
282
283         strv_sort((char **)input_table);
284
285         assert_se(streq(input_table[0], "CAPITAL LETTERS FIRST"));
286         assert_se(streq(input_table[1], "apple"));
287         assert_se(streq(input_table[2], "banana"));
288         assert_se(streq(input_table[3], "citrus"));
289         assert_se(streq(input_table[4], "durian"));
290 }
291
292 static void test_strv_merge_concat(void) {
293          _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL;
294
295         a = strv_new("without", "suffix", NULL);
296         b = strv_new("with", "suffix", NULL);
297         assert_se(a);
298         assert_se(b);
299
300         c = strv_merge_concat(a, b, "_suffix");
301         assert_se(c);
302
303         assert_se(streq(c[0], "without"));
304         assert_se(streq(c[1], "suffix"));
305         assert_se(streq(c[2], "with_suffix"));
306         assert_se(streq(c[3], "suffix_suffix"));
307 }
308
309 static void test_strv_merge(void) {
310          _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL;
311
312         a = strv_new("abc", "def", "ghi", NULL);
313         b = strv_new("jkl", "mno", "pqr", NULL);
314         assert_se(a);
315         assert_se(b);
316
317         c = strv_merge(a, b);
318         assert_se(c);
319
320         assert_se(streq(c[0], "abc"));
321         assert_se(streq(c[1], "def"));
322         assert_se(streq(c[2], "ghi"));
323         assert_se(streq(c[3], "jkl"));
324         assert_se(streq(c[4], "mno"));
325         assert_se(streq(c[5], "pqr"));
326
327         assert_se(strv_length(c) == 6);
328 }
329
330 static void test_strv_append(void) {
331         _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL;
332
333         a = strv_new("test", "test1", NULL);
334         assert_se(a);
335         b = strv_append(a, "test2");
336         c = strv_append(NULL, "test3");
337         assert_se(b);
338         assert_se(c);
339
340         assert_se(streq(b[0], "test"));
341         assert_se(streq(b[1], "test1"));
342         assert_se(streq(b[2], "test2"));
343         assert_se(streq(c[0], "test3"));
344 }
345
346 static void test_strv_foreach(void) {
347         _cleanup_strv_free_ char **a;
348         unsigned i = 0;
349         char **check;
350
351         a = strv_new("one", "two", "three", NULL);
352
353         assert_se(a);
354
355         STRV_FOREACH(check, a) {
356                 assert_se(streq(*check, input_table_multiple[i++]));
357         }
358 }
359
360 static void test_strv_foreach_backwards(void) {
361         _cleanup_strv_free_ char **a;
362         unsigned i = 2;
363         char **check;
364
365         a = strv_new("one", "two", "three", NULL);
366
367         assert_se(a);
368
369         STRV_FOREACH_BACKWARDS(check, a) {
370                 assert_se(streq_ptr(*check, input_table_multiple[i--]));
371         }
372 }
373
374 static void test_strv_foreach_pair(void) {
375         _cleanup_strv_free_ char **a = NULL;
376         char **x, **y;
377
378         a = strv_new("pair_one",   "pair_one",
379                      "pair_two",   "pair_two",
380                      "pair_three", "pair_three",
381                      NULL);
382
383         STRV_FOREACH_PAIR(x, y, a) {
384                 assert_se(streq(*x, *y));
385         }
386 }
387
388 static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) {
389         char **j;
390         unsigned i;
391
392         j = strv_from_stdarg_alloca(first);
393
394         for (i = 0;; i++) {
395                 assert_se(streq_ptr(l[i], j[i]));
396
397                 if (!l[i])
398                         break;
399         }
400 }
401
402 static void test_strv_from_stdarg_alloca(void) {
403         test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL);
404         test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL);
405         test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY, NULL);
406 }
407
408 int main(int argc, char *argv[]) {
409         test_specifier_printf();
410         test_strv_foreach();
411         test_strv_foreach_backwards();
412         test_strv_foreach_pair();
413         test_strv_find();
414         test_strv_find_prefix();
415         test_strv_join();
416
417         test_strv_quote_unquote(input_table_multiple, "\"one\" \"two\" \"three\"");
418         test_strv_quote_unquote(input_table_one, "\"one\"");
419         test_strv_quote_unquote(input_table_none, "");
420         test_strv_quote_unquote(input_table_quotes, QUOTES_STRING);
421         test_strv_quote_unquote(input_table_spaces, SPACES_STRING);
422
423         test_strv_quote_unquote2("    foo=bar     \"waldo\"    zzz    ", (const char*[]) { "foo=bar", "waldo", "zzz", NULL });
424         test_strv_quote_unquote2("", (const char*[]) { NULL });
425         test_strv_quote_unquote2(" ", (const char*[]) { NULL });
426         test_strv_quote_unquote2("   ", (const char*[]) { NULL });
427         test_strv_quote_unquote2("   x", (const char*[]) { "x", NULL });
428         test_strv_quote_unquote2("x   ", (const char*[]) { "x", NULL });
429         test_strv_quote_unquote2("  x   ", (const char*[]) { "x", NULL });
430         test_strv_quote_unquote2("  \"x\"   ", (const char*[]) { "x", NULL });
431         test_strv_quote_unquote2("  \'x\'   ", (const char*[]) { "x", NULL });
432         test_strv_quote_unquote2("  \'x\"\'   ", (const char*[]) { "x\"", NULL });
433         test_strv_quote_unquote2("  \"x\'\"   ", (const char*[]) { "x\'", NULL });
434
435         test_strv_split();
436         test_strv_split_newlines();
437         test_strv_split_nulstr();
438         test_strv_parse_nulstr();
439         test_strv_remove_prefix();
440         test_strv_overlap();
441         test_strv_sort();
442         test_strv_merge();
443         test_strv_merge_concat();
444         test_strv_append();
445         test_strv_from_stdarg_alloca();
446
447         return 0;
448 }