2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Thomas H.P. Andersen
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include "alloc-util.h"
24 #include "specifier.h"
25 #include "string-util.h"
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
},
40 _cleanup_free_
char *w
= NULL
;
43 r
= specifier_printf("xxx a=%a b=%b yyy", table
, NULL
, &w
);
48 assert_se(streq(w
, "xxx a=AAAA b=BBBB yyy"));
51 r
= specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table
, NULL
, &w
);
57 static const char* const input_table_multiple
[] = {
64 static const char* const input_table_one
[] = {
69 static const char* const input_table_none
[] = {
73 static const char* const input_table_two_empties
[] = {
79 static const char* const input_table_one_empty
[] = {
85 static const char* const input_table_quotes
[] = {
93 #define QUOTES_STRING \
100 static const char * const input_table_spaces
[] = {
108 #define SPACES_STRING \
115 static void test_strv_find(void) {
116 assert_se(strv_find((char **)input_table_multiple
, "three"));
117 assert_se(!strv_find((char **)input_table_multiple
, "four"));
120 static void test_strv_find_prefix(void) {
121 assert_se(strv_find_prefix((char **)input_table_multiple
, "o"));
122 assert_se(strv_find_prefix((char **)input_table_multiple
, "one"));
123 assert_se(strv_find_prefix((char **)input_table_multiple
, ""));
124 assert_se(!strv_find_prefix((char **)input_table_multiple
, "xxx"));
125 assert_se(!strv_find_prefix((char **)input_table_multiple
, "onee"));
128 static void test_strv_find_startswith(void) {
131 r
= strv_find_startswith((char **)input_table_multiple
, "o");
132 assert_se(r
&& streq(r
, "ne"));
134 r
= strv_find_startswith((char **)input_table_multiple
, "one");
135 assert_se(r
&& streq(r
, ""));
137 r
= strv_find_startswith((char **)input_table_multiple
, "");
138 assert_se(r
&& streq(r
, "one"));
140 assert_se(!strv_find_startswith((char **)input_table_multiple
, "xxx"));
141 assert_se(!strv_find_startswith((char **)input_table_multiple
, "onee"));
144 static void test_strv_join(void) {
145 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *r
= NULL
, *s
= NULL
, *t
= NULL
, *v
= NULL
, *w
= NULL
;
147 p
= strv_join((char **)input_table_multiple
, ", ");
149 assert_se(streq(p
, "one, two, three"));
151 q
= strv_join((char **)input_table_multiple
, ";");
153 assert_se(streq(q
, "one;two;three"));
155 r
= strv_join((char **)input_table_multiple
, NULL
);
157 assert_se(streq(r
, "one two three"));
159 s
= strv_join((char **)input_table_one
, ", ");
161 assert_se(streq(s
, "one"));
163 t
= strv_join((char **)input_table_none
, ", ");
165 assert_se(streq(t
, ""));
167 v
= strv_join((char **)input_table_two_empties
, ", ");
169 assert_se(streq(v
, ", "));
171 w
= strv_join((char **)input_table_one_empty
, ", ");
173 assert_se(streq(w
, ""));
176 static void test_strv_quote_unquote(const char* const *split
, const char *quoted
) {
177 _cleanup_free_
char *p
;
178 _cleanup_strv_free_
char **s
= NULL
;
182 p
= strv_join_quoted((char **)split
);
184 printf("-%s- --- -%s-\n", p
, quoted
); /* fprintf deals with NULL, puts does not */
186 assert_se(streq(p
, quoted
));
188 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
189 assert_se(r
== (int) strv_length(s
));
193 assert_se(streq(*t
, *split
));
198 static void test_strv_unquote(const char *quoted
, char **list
) {
199 _cleanup_strv_free_
char **s
;
200 _cleanup_free_
char *j
;
205 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
206 assert_se(r
== (int) strv_length(list
));
208 j
= strv_join(s
, " | ");
213 assert_se(streq(list
[i
++], *t
));
215 assert_se(list
[i
] == NULL
);
218 static void test_invalid_unquote(const char *quoted
) {
222 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
223 assert_se(s
== NULL
);
224 assert_se(r
== -EINVAL
);
227 static void test_strv_split(void) {
230 _cleanup_strv_free_
char **l
= NULL
;
231 const char str
[] = "one,two,three";
233 l
= strv_split(str
, ",");
238 assert_se(streq(*s
, input_table_multiple
[i
++]));
242 static void test_strv_split_extract(void) {
243 _cleanup_strv_free_
char **l
= NULL
;
244 const char *str
= ":foo\\:bar::waldo:";
247 r
= strv_split_extract(&l
, str
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
248 assert_se(r
== (int) strv_length(l
));
249 assert_se(streq_ptr(l
[0], ""));
250 assert_se(streq_ptr(l
[1], "foo:bar"));
251 assert_se(streq_ptr(l
[2], ""));
252 assert_se(streq_ptr(l
[3], "waldo"));
253 assert_se(streq_ptr(l
[4], ""));
254 assert_se(streq_ptr(l
[5], NULL
));
257 static void test_strv_split_newlines(void) {
260 _cleanup_strv_free_
char **l
= NULL
;
261 const char str
[] = "one\ntwo\nthree";
263 l
= strv_split_newlines(str
);
268 assert_se(streq(*s
, input_table_multiple
[i
++]));
272 static void test_strv_split_nulstr(void) {
273 _cleanup_strv_free_
char **l
= NULL
;
274 const char nulstr
[] = "str0\0str1\0str2\0str3\0";
276 l
= strv_split_nulstr (nulstr
);
279 assert_se(streq(l
[0], "str0"));
280 assert_se(streq(l
[1], "str1"));
281 assert_se(streq(l
[2], "str2"));
282 assert_se(streq(l
[3], "str3"));
285 static void test_strv_parse_nulstr(void) {
286 _cleanup_strv_free_
char **l
= NULL
;
287 const char nulstr
[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
289 l
= strv_parse_nulstr(nulstr
, sizeof(nulstr
)-1);
291 puts("Parse nulstr:");
294 assert_se(streq(l
[0], "fuck"));
295 assert_se(streq(l
[1], "fuck2"));
296 assert_se(streq(l
[2], "fuck3"));
297 assert_se(streq(l
[3], ""));
298 assert_se(streq(l
[4], "fuck5"));
299 assert_se(streq(l
[5], ""));
300 assert_se(streq(l
[6], "xxx"));
303 static void test_strv_overlap(void) {
304 const char * const input_table
[] = {
310 const char * const input_table_overlap
[] = {
314 const char * const input_table_unique
[] = {
321 assert_se(strv_overlap((char **)input_table
, (char**)input_table_overlap
));
322 assert_se(!strv_overlap((char **)input_table
, (char**)input_table_unique
));
325 static void test_strv_sort(void) {
326 const char* input_table
[] = {
330 "CAPITAL LETTERS FIRST",
335 strv_sort((char **)input_table
);
337 assert_se(streq(input_table
[0], "CAPITAL LETTERS FIRST"));
338 assert_se(streq(input_table
[1], "apple"));
339 assert_se(streq(input_table
[2], "banana"));
340 assert_se(streq(input_table
[3], "citrus"));
341 assert_se(streq(input_table
[4], "durian"));
344 static void test_strv_extend_strv_concat(void) {
345 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
347 a
= strv_new("without", "suffix", NULL
);
348 b
= strv_new("with", "suffix", NULL
);
352 assert_se(strv_extend_strv_concat(&a
, b
, "_suffix") >= 0);
354 assert_se(streq(a
[0], "without"));
355 assert_se(streq(a
[1], "suffix"));
356 assert_se(streq(a
[2], "with_suffix"));
357 assert_se(streq(a
[3], "suffix_suffix"));
360 static void test_strv_extend_strv(void) {
361 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **n
= NULL
;
363 a
= strv_new("abc", "def", "ghi", NULL
);
364 b
= strv_new("jkl", "mno", "abc", "pqr", NULL
);
368 assert_se(strv_extend_strv(&a
, b
, true) == 3);
370 assert_se(streq(a
[0], "abc"));
371 assert_se(streq(a
[1], "def"));
372 assert_se(streq(a
[2], "ghi"));
373 assert_se(streq(a
[3], "jkl"));
374 assert_se(streq(a
[4], "mno"));
375 assert_se(streq(a
[5], "pqr"));
376 assert_se(strv_length(a
) == 6);
378 assert_se(strv_extend_strv(&n
, b
, false) >= 0);
379 assert_se(streq(n
[0], "jkl"));
380 assert_se(streq(n
[1], "mno"));
381 assert_se(streq(n
[2], "abc"));
382 assert_se(streq(n
[3], "pqr"));
383 assert_se(strv_length(n
) == 4);
386 static void test_strv_extend(void) {
387 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
389 a
= strv_new("test", "test1", NULL
);
391 assert_se(strv_extend(&a
, "test2") >= 0);
392 assert_se(strv_extend(&b
, "test3") >= 0);
394 assert_se(streq(a
[0], "test"));
395 assert_se(streq(a
[1], "test1"));
396 assert_se(streq(a
[2], "test2"));
397 assert_se(streq(b
[0], "test3"));
400 static void test_strv_extendf(void) {
401 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
403 a
= strv_new("test", "test1", NULL
);
405 assert_se(strv_extendf(&a
, "test2 %s %d %s", "foo", 128, "bar") >= 0);
406 assert_se(strv_extendf(&b
, "test3 %s %s %d", "bar", "foo", 128) >= 0);
408 assert_se(streq(a
[0], "test"));
409 assert_se(streq(a
[1], "test1"));
410 assert_se(streq(a
[2], "test2 foo 128 bar"));
411 assert_se(streq(b
[0], "test3 bar foo 128"));
414 static void test_strv_foreach(void) {
415 _cleanup_strv_free_
char **a
;
419 a
= strv_new("one", "two", "three", NULL
);
423 STRV_FOREACH(check
, a
) {
424 assert_se(streq(*check
, input_table_multiple
[i
++]));
428 static void test_strv_foreach_backwards(void) {
429 _cleanup_strv_free_
char **a
;
433 a
= strv_new("one", "two", "three", NULL
);
437 STRV_FOREACH_BACKWARDS(check
, a
) {
438 assert_se(streq_ptr(*check
, input_table_multiple
[i
--]));
442 static void test_strv_foreach_pair(void) {
443 _cleanup_strv_free_
char **a
= NULL
;
446 a
= strv_new("pair_one", "pair_one",
447 "pair_two", "pair_two",
448 "pair_three", "pair_three",
451 STRV_FOREACH_PAIR(x
, y
, a
) {
452 assert_se(streq(*x
, *y
));
456 static void test_strv_from_stdarg_alloca_one(char **l
, const char *first
, ...) {
460 j
= strv_from_stdarg_alloca(first
);
463 assert_se(streq_ptr(l
[i
], j
[i
]));
470 static void test_strv_from_stdarg_alloca(void) {
471 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL
);
472 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL
);
473 test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY
, NULL
);
476 static void test_strv_push_prepend(void) {
477 _cleanup_strv_free_
char **a
= NULL
;
479 a
= strv_new("foo", "bar", "three", NULL
);
481 assert_se(strv_push_prepend(&a
, strdup("first")) >= 0);
482 assert_se(streq(a
[0], "first"));
483 assert_se(streq(a
[1], "foo"));
484 assert_se(streq(a
[2], "bar"));
485 assert_se(streq(a
[3], "three"));
488 assert_se(strv_consume_prepend(&a
, strdup("first2")) >= 0);
489 assert_se(streq(a
[0], "first2"));
490 assert_se(streq(a
[1], "first"));
491 assert_se(streq(a
[2], "foo"));
492 assert_se(streq(a
[3], "bar"));
493 assert_se(streq(a
[4], "three"));
497 static void test_strv_push(void) {
498 _cleanup_strv_free_
char **a
= NULL
;
501 assert_se(i
= strdup("foo"));
502 assert_se(strv_push(&a
, i
) >= 0);
504 assert_se(i
= strdup("a"));
505 assert_se(j
= strdup("b"));
506 assert_se(strv_push_pair(&a
, i
, j
) >= 0);
508 assert_se(streq_ptr(a
[0], "foo"));
509 assert_se(streq_ptr(a
[1], "a"));
510 assert_se(streq_ptr(a
[2], "b"));
511 assert_se(streq_ptr(a
[3], NULL
));
514 static void test_strv_equal(void) {
515 _cleanup_strv_free_
char **a
= NULL
;
516 _cleanup_strv_free_
char **b
= NULL
;
517 _cleanup_strv_free_
char **c
= NULL
;
519 a
= strv_new("one", "two", "three", NULL
);
521 b
= strv_new("one", "two", "three", NULL
);
523 c
= strv_new("one", "two", "three", "four", NULL
);
526 assert_se(strv_equal(a
, a
));
527 assert_se(strv_equal(a
, b
));
528 assert_se(strv_equal(NULL
, NULL
));
530 assert_se(!strv_equal(a
, c
));
531 assert_se(!strv_equal(b
, c
));
532 assert_se(!strv_equal(b
, NULL
));
535 static void test_strv_is_uniq(void) {
536 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
538 a
= strv_new(NULL
, NULL
);
540 assert_se(strv_is_uniq(a
));
542 b
= strv_new("foo", NULL
);
544 assert_se(strv_is_uniq(b
));
546 c
= strv_new("foo", "bar", NULL
);
548 assert_se(strv_is_uniq(c
));
550 d
= strv_new("foo", "bar", "waldo", "bar", "piep", NULL
);
552 assert_se(!strv_is_uniq(d
));
555 static void test_strv_reverse(void) {
556 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
558 a
= strv_new(NULL
, NULL
);
562 assert_se(strv_isempty(a
));
564 b
= strv_new("foo", NULL
);
567 assert_se(streq_ptr(b
[0], "foo"));
568 assert_se(streq_ptr(b
[1], NULL
));
570 c
= strv_new("foo", "bar", NULL
);
573 assert_se(streq_ptr(c
[0], "bar"));
574 assert_se(streq_ptr(c
[1], "foo"));
575 assert_se(streq_ptr(c
[2], NULL
));
577 d
= strv_new("foo", "bar", "waldo", NULL
);
580 assert_se(streq_ptr(d
[0], "waldo"));
581 assert_se(streq_ptr(d
[1], "bar"));
582 assert_se(streq_ptr(d
[2], "foo"));
583 assert_se(streq_ptr(d
[3], NULL
));
586 static void test_strv_shell_escape(void) {
587 _cleanup_strv_free_
char **v
= NULL
;
589 v
= strv_new("foo:bar", "bar,baz", "wal\\do", NULL
);
591 assert_se(strv_shell_escape(v
, ",:"));
592 assert_se(streq_ptr(v
[0], "foo\\:bar"));
593 assert_se(streq_ptr(v
[1], "bar\\,baz"));
594 assert_se(streq_ptr(v
[2], "wal\\\\do"));
595 assert_se(streq_ptr(v
[3], NULL
));
598 static void test_strv_skip_one(char **a
, size_t n
, char **b
) {
600 assert_se(strv_equal(a
, b
));
603 static void test_strv_skip(void) {
604 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz"));
605 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz"));
606 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz"));
607 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 3, STRV_MAKE(NULL
));
608 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 4, STRV_MAKE(NULL
));
609 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 55, STRV_MAKE(NULL
));
611 test_strv_skip_one(STRV_MAKE("quux"), 0, STRV_MAKE("quux"));
612 test_strv_skip_one(STRV_MAKE("quux"), 1, STRV_MAKE(NULL
));
613 test_strv_skip_one(STRV_MAKE("quux"), 55, STRV_MAKE(NULL
));
615 test_strv_skip_one(STRV_MAKE(NULL
), 0, STRV_MAKE(NULL
));
616 test_strv_skip_one(STRV_MAKE(NULL
), 1, STRV_MAKE(NULL
));
617 test_strv_skip_one(STRV_MAKE(NULL
), 55, STRV_MAKE(NULL
));
620 static void test_strv_extend_n(void) {
621 _cleanup_strv_free_
char **v
= NULL
;
623 v
= strv_new("foo", "bar", NULL
);
626 assert_se(strv_extend_n(&v
, "waldo", 3) >= 0);
627 assert_se(strv_extend_n(&v
, "piep", 2) >= 0);
629 assert_se(streq(v
[0], "foo"));
630 assert_se(streq(v
[1], "bar"));
631 assert_se(streq(v
[2], "waldo"));
632 assert_se(streq(v
[3], "waldo"));
633 assert_se(streq(v
[4], "waldo"));
634 assert_se(streq(v
[5], "piep"));
635 assert_se(streq(v
[6], "piep"));
636 assert_se(v
[7] == NULL
);
640 assert_se(strv_extend_n(&v
, "foo", 1) >= 0);
641 assert_se(strv_extend_n(&v
, "bar", 0) >= 0);
643 assert_se(streq(v
[0], "foo"));
644 assert_se(v
[1] == NULL
);
647 static void test_strv_make_nulstr_one(char **l
) {
648 _cleanup_free_
char *b
= NULL
, *c
= NULL
;
649 _cleanup_strv_free_
char **q
= NULL
;
652 assert_se(strv_make_nulstr(l
, &b
, &n
) >= 0);
653 assert_se(q
= strv_parse_nulstr(b
, n
));
654 assert_se(strv_equal(l
, q
));
656 assert_se(strv_make_nulstr(q
, &c
, &m
) >= 0);
658 assert_se(memcmp(b
, c
, m
) == 0);
661 static void test_strv_make_nulstr(void) {
662 test_strv_make_nulstr_one(NULL
);
663 test_strv_make_nulstr_one(STRV_MAKE(NULL
));
664 test_strv_make_nulstr_one(STRV_MAKE("foo"));
665 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar"));
666 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux"));
669 static void test_foreach_string(void) {
670 const char * const t
[] = {
679 FOREACH_STRING(x
, "foo", "bar", "waldo")
680 assert_se(streq_ptr(t
[i
++], x
));
684 FOREACH_STRING(x
, "zzz")
685 assert_se(streq(x
, "zzz"));
688 static void test_strv_fnmatch(void) {
689 _cleanup_strv_free_
char **v
= NULL
;
691 assert_se(!strv_fnmatch(STRV_MAKE_EMPTY
, "a", 0));
693 v
= strv_new("*\\*", NULL
);
694 assert_se(!strv_fnmatch(v
, "\\", 0));
695 assert_se(strv_fnmatch(v
, "\\", FNM_NOESCAPE
));
698 int main(int argc
, char *argv
[]) {
699 test_specifier_printf();
701 test_strv_foreach_backwards();
702 test_strv_foreach_pair();
704 test_strv_find_prefix();
705 test_strv_find_startswith();
708 test_strv_quote_unquote(input_table_multiple
, "\"one\" \"two\" \"three\"");
709 test_strv_quote_unquote(input_table_one
, "\"one\"");
710 test_strv_quote_unquote(input_table_none
, "");
711 test_strv_quote_unquote(input_table_one_empty
, "\"\"");
712 test_strv_quote_unquote(input_table_two_empties
, "\"\" \"\"");
713 test_strv_quote_unquote(input_table_quotes
, QUOTES_STRING
);
714 test_strv_quote_unquote(input_table_spaces
, SPACES_STRING
);
716 test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
717 test_strv_unquote("", STRV_MAKE_EMPTY
);
718 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
719 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
720 test_strv_unquote(" x", STRV_MAKE("x"));
721 test_strv_unquote("x ", STRV_MAKE("x"));
722 test_strv_unquote(" x ", STRV_MAKE("x"));
723 test_strv_unquote(" \"x\" ", STRV_MAKE("x"));
724 test_strv_unquote(" 'x' ", STRV_MAKE("x"));
725 test_strv_unquote(" 'x\"' ", STRV_MAKE("x\""));
726 test_strv_unquote(" \"x'\" ", STRV_MAKE("x'"));
727 test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\""));
729 /* trailing backslashes */
730 test_strv_unquote(" x\\\\", STRV_MAKE("x\\"));
731 test_invalid_unquote(" x\\");
733 test_invalid_unquote("a --b='c \"d e\"''");
734 test_invalid_unquote("a --b='c \"d e\" '\"");
735 test_invalid_unquote("a --b='c \"d e\"garbage");
736 test_invalid_unquote("'");
737 test_invalid_unquote("\"");
738 test_invalid_unquote("'x'y'g");
741 test_strv_split_extract();
742 test_strv_split_newlines();
743 test_strv_split_nulstr();
744 test_strv_parse_nulstr();
747 test_strv_extend_strv();
748 test_strv_extend_strv_concat();
751 test_strv_from_stdarg_alloca();
752 test_strv_push_prepend();
757 test_strv_shell_escape();
759 test_strv_extend_n();
760 test_strv_make_nulstr();
762 test_foreach_string();