chiark / gitweb /
tests: add tests for strv_extendf
[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_parse_nulstr(void) {
218         _cleanup_strv_free_ char **l = NULL;
219         const char nulstr[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
220
221         l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1);
222         assert_se(l);
223         puts("Parse nulstr:");
224         strv_print(l);
225
226         assert_se(streq(l[0], "fuck"));
227         assert_se(streq(l[1], "fuck2"));
228         assert_se(streq(l[2], "fuck3"));
229         assert_se(streq(l[3], ""));
230         assert_se(streq(l[4], "fuck5"));
231         assert_se(streq(l[5], ""));
232         assert_se(streq(l[6], "xxx"));
233 }
234
235 static void test_strv_overlap(void) {
236         const char * const input_table[] = {
237                 "one",
238                 "two",
239                 "three",
240                 NULL
241         };
242         const char * const input_table_overlap[] = {
243                 "two",
244                 NULL
245         };
246         const char * const input_table_unique[] = {
247                 "four",
248                 "five",
249                 "six",
250                 NULL
251         };
252
253         assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap));
254         assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique));
255 }
256
257 static void test_strv_sort(void) {
258         const char* input_table[] = {
259                 "durian",
260                 "apple",
261                 "citrus",
262                  "CAPITAL LETTERS FIRST",
263                 "banana",
264                 NULL
265         };
266
267         strv_sort((char **)input_table);
268
269         assert_se(streq(input_table[0], "CAPITAL LETTERS FIRST"));
270         assert_se(streq(input_table[1], "apple"));
271         assert_se(streq(input_table[2], "banana"));
272         assert_se(streq(input_table[3], "citrus"));
273         assert_se(streq(input_table[4], "durian"));
274 }
275
276 static void test_strv_extend_strv_concat(void) {
277          _cleanup_strv_free_ char **a = NULL, **b = NULL;
278
279         a = strv_new("without", "suffix", NULL);
280         b = strv_new("with", "suffix", NULL);
281         assert_se(a);
282         assert_se(b);
283
284         assert_se(strv_extend_strv_concat(&a, b, "_suffix") >= 0);
285
286         assert_se(streq(a[0], "without"));
287         assert_se(streq(a[1], "suffix"));
288         assert_se(streq(a[2], "with_suffix"));
289         assert_se(streq(a[3], "suffix_suffix"));
290 }
291
292 static void test_strv_extend_strv(void) {
293          _cleanup_strv_free_ char **a = NULL, **b = NULL;
294
295         a = strv_new("abc", "def", "ghi", NULL);
296         b = strv_new("jkl", "mno", "pqr", NULL);
297         assert_se(a);
298         assert_se(b);
299
300         assert_se(strv_extend_strv(&a, b) >= 0);
301
302         assert_se(streq(a[0], "abc"));
303         assert_se(streq(a[1], "def"));
304         assert_se(streq(a[2], "ghi"));
305         assert_se(streq(a[3], "jkl"));
306         assert_se(streq(a[4], "mno"));
307         assert_se(streq(a[5], "pqr"));
308
309         assert_se(strv_length(a) == 6);
310 }
311
312 static void test_strv_extend(void) {
313         _cleanup_strv_free_ char **a = NULL, **b = NULL;
314
315         a = strv_new("test", "test1", NULL);
316         assert_se(a);
317         assert_se(strv_extend(&a, "test2") >= 0);
318         assert_se(strv_extend(&b, "test3") >= 0);
319
320         assert_se(streq(a[0], "test"));
321         assert_se(streq(a[1], "test1"));
322         assert_se(streq(a[2], "test2"));
323         assert_se(streq(b[0], "test3"));
324 }
325
326 static void test_strv_extendf(void) {
327         _cleanup_strv_free_ char **a = NULL, **b = NULL;
328
329         a = strv_new("test", "test1", NULL);
330         assert_se(a);
331         assert_se(strv_extendf(&a, "test2 %s %d %s", "foo", 128, "bar") >= 0);
332         assert_se(strv_extendf(&b, "test3 %s %s %d", "bar", "foo", 128) >= 0);
333
334         assert_se(streq(a[0], "test"));
335         assert_se(streq(a[1], "test1"));
336         assert_se(streq(a[2], "test2 foo 128 bar"));
337         assert_se(streq(b[0], "test3 bar foo 128"));
338 }
339
340 static void test_strv_foreach(void) {
341         _cleanup_strv_free_ char **a;
342         unsigned i = 0;
343         char **check;
344
345         a = strv_new("one", "two", "three", NULL);
346
347         assert_se(a);
348
349         STRV_FOREACH(check, a) {
350                 assert_se(streq(*check, input_table_multiple[i++]));
351         }
352 }
353
354 static void test_strv_foreach_backwards(void) {
355         _cleanup_strv_free_ char **a;
356         unsigned i = 2;
357         char **check;
358
359         a = strv_new("one", "two", "three", NULL);
360
361         assert_se(a);
362
363         STRV_FOREACH_BACKWARDS(check, a) {
364                 assert_se(streq_ptr(*check, input_table_multiple[i--]));
365         }
366 }
367
368 static void test_strv_foreach_pair(void) {
369         _cleanup_strv_free_ char **a = NULL;
370         char **x, **y;
371
372         a = strv_new("pair_one",   "pair_one",
373                      "pair_two",   "pair_two",
374                      "pair_three", "pair_three",
375                      NULL);
376
377         STRV_FOREACH_PAIR(x, y, a) {
378                 assert_se(streq(*x, *y));
379         }
380 }
381
382 static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) {
383         char **j;
384         unsigned i;
385
386         j = strv_from_stdarg_alloca(first);
387
388         for (i = 0;; i++) {
389                 assert_se(streq_ptr(l[i], j[i]));
390
391                 if (!l[i])
392                         break;
393         }
394 }
395
396 static void test_strv_from_stdarg_alloca(void) {
397         test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL);
398         test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL);
399         test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY, NULL);
400 }
401
402 int main(int argc, char *argv[]) {
403         test_specifier_printf();
404         test_strv_foreach();
405         test_strv_foreach_backwards();
406         test_strv_foreach_pair();
407         test_strv_find();
408         test_strv_find_prefix();
409         test_strv_join();
410
411         test_strv_quote_unquote(input_table_multiple, "\"one\" \"two\" \"three\"");
412         test_strv_quote_unquote(input_table_one, "\"one\"");
413         test_strv_quote_unquote(input_table_none, "");
414         test_strv_quote_unquote(input_table_quotes, QUOTES_STRING);
415         test_strv_quote_unquote(input_table_spaces, SPACES_STRING);
416
417         test_strv_quote_unquote2("    foo=bar     \"waldo\"    zzz    ", (const char*[]) { "foo=bar", "waldo", "zzz", NULL });
418         test_strv_quote_unquote2("", (const char*[]) { NULL });
419         test_strv_quote_unquote2(" ", (const char*[]) { NULL });
420         test_strv_quote_unquote2("   ", (const char*[]) { NULL });
421         test_strv_quote_unquote2("   x", (const char*[]) { "x", NULL });
422         test_strv_quote_unquote2("x   ", (const char*[]) { "x", NULL });
423         test_strv_quote_unquote2("  x   ", (const char*[]) { "x", NULL });
424         test_strv_quote_unquote2("  \"x\"   ", (const char*[]) { "x", NULL });
425         test_strv_quote_unquote2("  \'x\'   ", (const char*[]) { "x", NULL });
426         test_strv_quote_unquote2("  \'x\"\'   ", (const char*[]) { "x\"", NULL });
427         test_strv_quote_unquote2("  \"x\'\"   ", (const char*[]) { "x\'", NULL });
428
429         test_strv_split();
430         test_strv_split_newlines();
431         test_strv_split_nulstr();
432         test_strv_parse_nulstr();
433         test_strv_overlap();
434         test_strv_sort();
435         test_strv_extend_strv();
436         test_strv_extend_strv_concat();
437         test_strv_extend();
438         test_strv_extendf();
439         test_strv_from_stdarg_alloca();
440
441         return 0;
442 }