]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-strv.c
Merge pull request #882 from phomes/indentation
[thirdparty/systemd.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_find_startswith(void) {
117 char *r;
118
119 r = strv_find_startswith((char **)input_table_multiple, "o");
120 assert_se(r && streq(r, "ne"));
121
122 r = strv_find_startswith((char **)input_table_multiple, "one");
123 assert_se(r && streq(r, ""));
124
125 r = strv_find_startswith((char **)input_table_multiple, "");
126 assert_se(r && streq(r, "one"));
127
128 assert_se(!strv_find_startswith((char **)input_table_multiple, "xxx"));
129 assert_se(!strv_find_startswith((char **)input_table_multiple, "onee"));
130 }
131
132 static void test_strv_join(void) {
133 _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL;
134
135 p = strv_join((char **)input_table_multiple, ", ");
136 assert_se(p);
137 assert_se(streq(p, "one, two, three"));
138
139 q = strv_join((char **)input_table_multiple, ";");
140 assert_se(q);
141 assert_se(streq(q, "one;two;three"));
142
143 r = strv_join((char **)input_table_multiple, NULL);
144 assert_se(r);
145 assert_se(streq(r, "one two three"));
146
147 s = strv_join((char **)input_table_one, ", ");
148 assert_se(s);
149 assert_se(streq(s, "one"));
150
151 t = strv_join((char **)input_table_none, ", ");
152 assert_se(t);
153 assert_se(streq(t, ""));
154 }
155
156 static void test_strv_quote_unquote(const char* const *split, const char *quoted) {
157 _cleanup_free_ char *p;
158 _cleanup_strv_free_ char **s;
159 char **t;
160 int r;
161
162 p = strv_join_quoted((char **)split);
163 assert_se(p);
164 printf("-%s- --- -%s-\n", p, quoted); /* fprintf deals with NULL, puts does not */
165 assert_se(p);
166 assert_se(streq(p, quoted));
167
168 r = strv_split_quoted(&s, quoted, 0);
169 assert_se(r == 0);
170 assert_se(s);
171 STRV_FOREACH(t, s) {
172 assert_se(*t);
173 assert_se(streq(*t, *split));
174 split++;
175 }
176 }
177
178 static void test_strv_unquote(const char *quoted, char **list) {
179 _cleanup_strv_free_ char **s;
180 _cleanup_free_ char *j;
181 unsigned i = 0;
182 char **t;
183 int r;
184
185 r = strv_split_quoted(&s, quoted, 0);
186 assert_se(r == 0);
187 assert_se(s);
188 j = strv_join(s, " | ");
189 assert_se(j);
190 puts(j);
191
192 STRV_FOREACH(t, s)
193 assert_se(streq(list[i++], *t));
194
195 assert_se(list[i] == NULL);
196 }
197
198 static void test_invalid_unquote(const char *quoted) {
199 char **s = NULL;
200 int r;
201
202 r = strv_split_quoted(&s, quoted, 0);
203 assert_se(s == NULL);
204 assert_se(r == -EINVAL);
205 }
206
207 static void test_strv_split(void) {
208 char **s;
209 unsigned i = 0;
210 _cleanup_strv_free_ char **l = NULL;
211 const char str[] = "one,two,three";
212
213 l = strv_split(str, ",");
214
215 assert_se(l);
216
217 STRV_FOREACH(s, l) {
218 assert_se(streq(*s, input_table_multiple[i++]));
219 }
220 }
221
222 static void test_strv_split_newlines(void) {
223 unsigned i = 0;
224 char **s;
225 _cleanup_strv_free_ char **l = NULL;
226 const char str[] = "one\ntwo\nthree";
227
228 l = strv_split_newlines(str);
229
230 assert_se(l);
231
232 STRV_FOREACH(s, l) {
233 assert_se(streq(*s, input_table_multiple[i++]));
234 }
235 }
236
237 static void test_strv_split_nulstr(void) {
238 _cleanup_strv_free_ char **l = NULL;
239 const char nulstr[] = "str0\0str1\0str2\0str3\0";
240
241 l = strv_split_nulstr (nulstr);
242 assert_se(l);
243
244 assert_se(streq(l[0], "str0"));
245 assert_se(streq(l[1], "str1"));
246 assert_se(streq(l[2], "str2"));
247 assert_se(streq(l[3], "str3"));
248 }
249
250 static void test_strv_parse_nulstr(void) {
251 _cleanup_strv_free_ char **l = NULL;
252 const char nulstr[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
253
254 l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1);
255 assert_se(l);
256 puts("Parse nulstr:");
257 strv_print(l);
258
259 assert_se(streq(l[0], "fuck"));
260 assert_se(streq(l[1], "fuck2"));
261 assert_se(streq(l[2], "fuck3"));
262 assert_se(streq(l[3], ""));
263 assert_se(streq(l[4], "fuck5"));
264 assert_se(streq(l[5], ""));
265 assert_se(streq(l[6], "xxx"));
266 }
267
268 static void test_strv_overlap(void) {
269 const char * const input_table[] = {
270 "one",
271 "two",
272 "three",
273 NULL
274 };
275 const char * const input_table_overlap[] = {
276 "two",
277 NULL
278 };
279 const char * const input_table_unique[] = {
280 "four",
281 "five",
282 "six",
283 NULL
284 };
285
286 assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap));
287 assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique));
288 }
289
290 static void test_strv_sort(void) {
291 const char* input_table[] = {
292 "durian",
293 "apple",
294 "citrus",
295 "CAPITAL LETTERS FIRST",
296 "banana",
297 NULL
298 };
299
300 strv_sort((char **)input_table);
301
302 assert_se(streq(input_table[0], "CAPITAL LETTERS FIRST"));
303 assert_se(streq(input_table[1], "apple"));
304 assert_se(streq(input_table[2], "banana"));
305 assert_se(streq(input_table[3], "citrus"));
306 assert_se(streq(input_table[4], "durian"));
307 }
308
309 static void test_strv_extend_strv_concat(void) {
310 _cleanup_strv_free_ char **a = NULL, **b = NULL;
311
312 a = strv_new("without", "suffix", NULL);
313 b = strv_new("with", "suffix", NULL);
314 assert_se(a);
315 assert_se(b);
316
317 assert_se(strv_extend_strv_concat(&a, b, "_suffix") >= 0);
318
319 assert_se(streq(a[0], "without"));
320 assert_se(streq(a[1], "suffix"));
321 assert_se(streq(a[2], "with_suffix"));
322 assert_se(streq(a[3], "suffix_suffix"));
323 }
324
325 static void test_strv_extend_strv(void) {
326 _cleanup_strv_free_ char **a = NULL, **b = NULL;
327
328 a = strv_new("abc", "def", "ghi", NULL);
329 b = strv_new("jkl", "mno", "pqr", NULL);
330 assert_se(a);
331 assert_se(b);
332
333 assert_se(strv_extend_strv(&a, b) >= 0);
334
335 assert_se(streq(a[0], "abc"));
336 assert_se(streq(a[1], "def"));
337 assert_se(streq(a[2], "ghi"));
338 assert_se(streq(a[3], "jkl"));
339 assert_se(streq(a[4], "mno"));
340 assert_se(streq(a[5], "pqr"));
341
342 assert_se(strv_length(a) == 6);
343 }
344
345 static void test_strv_extend(void) {
346 _cleanup_strv_free_ char **a = NULL, **b = NULL;
347
348 a = strv_new("test", "test1", NULL);
349 assert_se(a);
350 assert_se(strv_extend(&a, "test2") >= 0);
351 assert_se(strv_extend(&b, "test3") >= 0);
352
353 assert_se(streq(a[0], "test"));
354 assert_se(streq(a[1], "test1"));
355 assert_se(streq(a[2], "test2"));
356 assert_se(streq(b[0], "test3"));
357 }
358
359 static void test_strv_extendf(void) {
360 _cleanup_strv_free_ char **a = NULL, **b = NULL;
361
362 a = strv_new("test", "test1", NULL);
363 assert_se(a);
364 assert_se(strv_extendf(&a, "test2 %s %d %s", "foo", 128, "bar") >= 0);
365 assert_se(strv_extendf(&b, "test3 %s %s %d", "bar", "foo", 128) >= 0);
366
367 assert_se(streq(a[0], "test"));
368 assert_se(streq(a[1], "test1"));
369 assert_se(streq(a[2], "test2 foo 128 bar"));
370 assert_se(streq(b[0], "test3 bar foo 128"));
371 }
372
373 static void test_strv_foreach(void) {
374 _cleanup_strv_free_ char **a;
375 unsigned i = 0;
376 char **check;
377
378 a = strv_new("one", "two", "three", NULL);
379
380 assert_se(a);
381
382 STRV_FOREACH(check, a) {
383 assert_se(streq(*check, input_table_multiple[i++]));
384 }
385 }
386
387 static void test_strv_foreach_backwards(void) {
388 _cleanup_strv_free_ char **a;
389 unsigned i = 2;
390 char **check;
391
392 a = strv_new("one", "two", "three", NULL);
393
394 assert_se(a);
395
396 STRV_FOREACH_BACKWARDS(check, a) {
397 assert_se(streq_ptr(*check, input_table_multiple[i--]));
398 }
399 }
400
401 static void test_strv_foreach_pair(void) {
402 _cleanup_strv_free_ char **a = NULL;
403 char **x, **y;
404
405 a = strv_new("pair_one", "pair_one",
406 "pair_two", "pair_two",
407 "pair_three", "pair_three",
408 NULL);
409
410 STRV_FOREACH_PAIR(x, y, a) {
411 assert_se(streq(*x, *y));
412 }
413 }
414
415 static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) {
416 char **j;
417 unsigned i;
418
419 j = strv_from_stdarg_alloca(first);
420
421 for (i = 0;; i++) {
422 assert_se(streq_ptr(l[i], j[i]));
423
424 if (!l[i])
425 break;
426 }
427 }
428
429 static void test_strv_from_stdarg_alloca(void) {
430 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL);
431 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL);
432 test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY, NULL);
433 }
434
435 static void test_strv_push_prepend(void) {
436 _cleanup_strv_free_ char **a = NULL;
437
438 a = strv_new("foo", "bar", "three", NULL);
439
440 assert_se(strv_push_prepend(&a, strdup("first")) >= 0);
441 assert_se(streq(a[0], "first"));
442 assert_se(streq(a[1], "foo"));
443 assert_se(streq(a[2], "bar"));
444 assert_se(streq(a[3], "three"));
445 assert_se(!a[4]);
446
447 assert_se(strv_consume_prepend(&a, strdup("first2")) >= 0);
448 assert_se(streq(a[0], "first2"));
449 assert_se(streq(a[1], "first"));
450 assert_se(streq(a[2], "foo"));
451 assert_se(streq(a[3], "bar"));
452 assert_se(streq(a[4], "three"));
453 assert_se(!a[5]);
454 }
455
456 static void test_strv_push(void) {
457 _cleanup_strv_free_ char **a = NULL;
458 char *i, *j;
459
460 assert_se(i = strdup("foo"));
461 assert_se(strv_push(&a, i) >= 0);
462
463 assert_se(i = strdup("a"));
464 assert_se(j = strdup("b"));
465 assert_se(strv_push_pair(&a, i, j) >= 0);
466
467 assert_se(streq_ptr(a[0], "foo"));
468 assert_se(streq_ptr(a[1], "a"));
469 assert_se(streq_ptr(a[2], "b"));
470 assert_se(streq_ptr(a[3], NULL));
471 }
472
473 static void test_strv_equal(void) {
474 _cleanup_strv_free_ char **a = NULL;
475 _cleanup_strv_free_ char **b = NULL;
476 _cleanup_strv_free_ char **c = NULL;
477
478 a = strv_new("one", "two", "three", NULL);
479 assert_se(a);
480 b = strv_new("one", "two", "three", NULL);
481 assert_se(a);
482 c = strv_new("one", "two", "three", "four", NULL);
483 assert_se(a);
484
485 assert_se(strv_equal(a, a));
486 assert_se(strv_equal(a, b));
487 assert_se(strv_equal(NULL, NULL));
488
489 assert_se(!strv_equal(a, c));
490 assert_se(!strv_equal(b, c));
491 assert_se(!strv_equal(b, NULL));
492 }
493
494 static void test_strv_is_uniq(void) {
495 _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
496
497 a = strv_new(NULL, NULL);
498 assert_se(a);
499 assert_se(strv_is_uniq(a));
500
501 b = strv_new("foo", NULL);
502 assert_se(b);
503 assert_se(strv_is_uniq(b));
504
505 c = strv_new("foo", "bar", NULL);
506 assert_se(c);
507 assert_se(strv_is_uniq(c));
508
509 d = strv_new("foo", "bar", "waldo", "bar", "piep", NULL);
510 assert_se(d);
511 assert_se(!strv_is_uniq(d));
512 }
513
514 static void test_strv_reverse(void) {
515 _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
516
517 a = strv_new(NULL, NULL);
518 assert_se(a);
519
520 strv_reverse(a);
521 assert_se(strv_isempty(a));
522
523 b = strv_new("foo", NULL);
524 assert_se(b);
525 strv_reverse(b);
526 assert_se(streq_ptr(b[0], "foo"));
527 assert_se(streq_ptr(b[1], NULL));
528
529 c = strv_new("foo", "bar", NULL);
530 assert_se(c);
531 strv_reverse(c);
532 assert_se(streq_ptr(c[0], "bar"));
533 assert_se(streq_ptr(c[1], "foo"));
534 assert_se(streq_ptr(c[2], NULL));
535
536 d = strv_new("foo", "bar", "waldo", NULL);
537 assert_se(d);
538 strv_reverse(d);
539 assert_se(streq_ptr(d[0], "waldo"));
540 assert_se(streq_ptr(d[1], "bar"));
541 assert_se(streq_ptr(d[2], "foo"));
542 assert_se(streq_ptr(d[3], NULL));
543 }
544
545 int main(int argc, char *argv[]) {
546 test_specifier_printf();
547 test_strv_foreach();
548 test_strv_foreach_backwards();
549 test_strv_foreach_pair();
550 test_strv_find();
551 test_strv_find_prefix();
552 test_strv_find_startswith();
553 test_strv_join();
554
555 test_strv_quote_unquote(input_table_multiple, "\"one\" \"two\" \"three\"");
556 test_strv_quote_unquote(input_table_one, "\"one\"");
557 test_strv_quote_unquote(input_table_none, "");
558 test_strv_quote_unquote(input_table_quotes, QUOTES_STRING);
559 test_strv_quote_unquote(input_table_spaces, SPACES_STRING);
560
561 test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
562 test_strv_unquote("", STRV_MAKE_EMPTY);
563 test_strv_unquote(" ", STRV_MAKE_EMPTY);
564 test_strv_unquote(" ", STRV_MAKE_EMPTY);
565 test_strv_unquote(" x", STRV_MAKE("x"));
566 test_strv_unquote("x ", STRV_MAKE("x"));
567 test_strv_unquote(" x ", STRV_MAKE("x"));
568 test_strv_unquote(" \"x\" ", STRV_MAKE("x"));
569 test_strv_unquote(" 'x' ", STRV_MAKE("x"));
570 test_strv_unquote(" 'x\"' ", STRV_MAKE("x\""));
571 test_strv_unquote(" \"x'\" ", STRV_MAKE("x'"));
572 test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\""));
573
574 /* trailing backslashes */
575 test_strv_unquote(" x\\\\", STRV_MAKE("x\\"));
576 test_invalid_unquote(" x\\");
577
578 test_invalid_unquote("a --b='c \"d e\"''");
579 test_invalid_unquote("a --b='c \"d e\" '\"");
580 test_invalid_unquote("a --b='c \"d e\"garbage");
581 test_invalid_unquote("'");
582 test_invalid_unquote("\"");
583 test_invalid_unquote("'x'y'g");
584
585 test_strv_split();
586 test_strv_split_newlines();
587 test_strv_split_nulstr();
588 test_strv_parse_nulstr();
589 test_strv_overlap();
590 test_strv_sort();
591 test_strv_extend_strv();
592 test_strv_extend_strv_concat();
593 test_strv_extend();
594 test_strv_extendf();
595 test_strv_from_stdarg_alloca();
596 test_strv_push_prepend();
597 test_strv_push();
598 test_strv_equal();
599 test_strv_is_uniq();
600 test_strv_reverse();
601
602 return 0;
603 }