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
;
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"));
377 assert_se(strv_length(a
) == 6);
380 static void test_strv_extend(void) {
381 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
383 a
= strv_new("test", "test1", NULL
);
385 assert_se(strv_extend(&a
, "test2") >= 0);
386 assert_se(strv_extend(&b
, "test3") >= 0);
388 assert_se(streq(a
[0], "test"));
389 assert_se(streq(a
[1], "test1"));
390 assert_se(streq(a
[2], "test2"));
391 assert_se(streq(b
[0], "test3"));
394 static void test_strv_extendf(void) {
395 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
397 a
= strv_new("test", "test1", NULL
);
399 assert_se(strv_extendf(&a
, "test2 %s %d %s", "foo", 128, "bar") >= 0);
400 assert_se(strv_extendf(&b
, "test3 %s %s %d", "bar", "foo", 128) >= 0);
402 assert_se(streq(a
[0], "test"));
403 assert_se(streq(a
[1], "test1"));
404 assert_se(streq(a
[2], "test2 foo 128 bar"));
405 assert_se(streq(b
[0], "test3 bar foo 128"));
408 static void test_strv_foreach(void) {
409 _cleanup_strv_free_
char **a
;
413 a
= strv_new("one", "two", "three", NULL
);
417 STRV_FOREACH(check
, a
) {
418 assert_se(streq(*check
, input_table_multiple
[i
++]));
422 static void test_strv_foreach_backwards(void) {
423 _cleanup_strv_free_
char **a
;
427 a
= strv_new("one", "two", "three", NULL
);
431 STRV_FOREACH_BACKWARDS(check
, a
) {
432 assert_se(streq_ptr(*check
, input_table_multiple
[i
--]));
436 static void test_strv_foreach_pair(void) {
437 _cleanup_strv_free_
char **a
= NULL
;
440 a
= strv_new("pair_one", "pair_one",
441 "pair_two", "pair_two",
442 "pair_three", "pair_three",
445 STRV_FOREACH_PAIR(x
, y
, a
) {
446 assert_se(streq(*x
, *y
));
450 static void test_strv_from_stdarg_alloca_one(char **l
, const char *first
, ...) {
454 j
= strv_from_stdarg_alloca(first
);
457 assert_se(streq_ptr(l
[i
], j
[i
]));
464 static void test_strv_from_stdarg_alloca(void) {
465 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL
);
466 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL
);
467 test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY
, NULL
);
470 static void test_strv_push_prepend(void) {
471 _cleanup_strv_free_
char **a
= NULL
;
473 a
= strv_new("foo", "bar", "three", NULL
);
475 assert_se(strv_push_prepend(&a
, strdup("first")) >= 0);
476 assert_se(streq(a
[0], "first"));
477 assert_se(streq(a
[1], "foo"));
478 assert_se(streq(a
[2], "bar"));
479 assert_se(streq(a
[3], "three"));
482 assert_se(strv_consume_prepend(&a
, strdup("first2")) >= 0);
483 assert_se(streq(a
[0], "first2"));
484 assert_se(streq(a
[1], "first"));
485 assert_se(streq(a
[2], "foo"));
486 assert_se(streq(a
[3], "bar"));
487 assert_se(streq(a
[4], "three"));
491 static void test_strv_push(void) {
492 _cleanup_strv_free_
char **a
= NULL
;
495 assert_se(i
= strdup("foo"));
496 assert_se(strv_push(&a
, i
) >= 0);
498 assert_se(i
= strdup("a"));
499 assert_se(j
= strdup("b"));
500 assert_se(strv_push_pair(&a
, i
, j
) >= 0);
502 assert_se(streq_ptr(a
[0], "foo"));
503 assert_se(streq_ptr(a
[1], "a"));
504 assert_se(streq_ptr(a
[2], "b"));
505 assert_se(streq_ptr(a
[3], NULL
));
508 static void test_strv_equal(void) {
509 _cleanup_strv_free_
char **a
= NULL
;
510 _cleanup_strv_free_
char **b
= NULL
;
511 _cleanup_strv_free_
char **c
= NULL
;
513 a
= strv_new("one", "two", "three", NULL
);
515 b
= strv_new("one", "two", "three", NULL
);
517 c
= strv_new("one", "two", "three", "four", NULL
);
520 assert_se(strv_equal(a
, a
));
521 assert_se(strv_equal(a
, b
));
522 assert_se(strv_equal(NULL
, NULL
));
524 assert_se(!strv_equal(a
, c
));
525 assert_se(!strv_equal(b
, c
));
526 assert_se(!strv_equal(b
, NULL
));
529 static void test_strv_is_uniq(void) {
530 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
532 a
= strv_new(NULL
, NULL
);
534 assert_se(strv_is_uniq(a
));
536 b
= strv_new("foo", NULL
);
538 assert_se(strv_is_uniq(b
));
540 c
= strv_new("foo", "bar", NULL
);
542 assert_se(strv_is_uniq(c
));
544 d
= strv_new("foo", "bar", "waldo", "bar", "piep", NULL
);
546 assert_se(!strv_is_uniq(d
));
549 static void test_strv_reverse(void) {
550 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
552 a
= strv_new(NULL
, NULL
);
556 assert_se(strv_isempty(a
));
558 b
= strv_new("foo", NULL
);
561 assert_se(streq_ptr(b
[0], "foo"));
562 assert_se(streq_ptr(b
[1], NULL
));
564 c
= strv_new("foo", "bar", NULL
);
567 assert_se(streq_ptr(c
[0], "bar"));
568 assert_se(streq_ptr(c
[1], "foo"));
569 assert_se(streq_ptr(c
[2], NULL
));
571 d
= strv_new("foo", "bar", "waldo", NULL
);
574 assert_se(streq_ptr(d
[0], "waldo"));
575 assert_se(streq_ptr(d
[1], "bar"));
576 assert_se(streq_ptr(d
[2], "foo"));
577 assert_se(streq_ptr(d
[3], NULL
));
580 static void test_strv_shell_escape(void) {
581 _cleanup_strv_free_
char **v
= NULL
;
583 v
= strv_new("foo:bar", "bar,baz", "wal\\do", NULL
);
585 assert_se(strv_shell_escape(v
, ",:"));
586 assert_se(streq_ptr(v
[0], "foo\\:bar"));
587 assert_se(streq_ptr(v
[1], "bar\\,baz"));
588 assert_se(streq_ptr(v
[2], "wal\\\\do"));
589 assert_se(streq_ptr(v
[3], NULL
));
592 static void test_strv_skip_one(char **a
, size_t n
, char **b
) {
594 assert_se(strv_equal(a
, b
));
597 static void test_strv_skip(void) {
598 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz"));
599 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz"));
600 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz"));
601 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 3, STRV_MAKE(NULL
));
602 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 4, STRV_MAKE(NULL
));
603 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 55, STRV_MAKE(NULL
));
605 test_strv_skip_one(STRV_MAKE("quux"), 0, STRV_MAKE("quux"));
606 test_strv_skip_one(STRV_MAKE("quux"), 1, STRV_MAKE(NULL
));
607 test_strv_skip_one(STRV_MAKE("quux"), 55, STRV_MAKE(NULL
));
609 test_strv_skip_one(STRV_MAKE(NULL
), 0, STRV_MAKE(NULL
));
610 test_strv_skip_one(STRV_MAKE(NULL
), 1, STRV_MAKE(NULL
));
611 test_strv_skip_one(STRV_MAKE(NULL
), 55, STRV_MAKE(NULL
));
614 static void test_strv_extend_n(void) {
615 _cleanup_strv_free_
char **v
= NULL
;
617 v
= strv_new("foo", "bar", NULL
);
620 assert_se(strv_extend_n(&v
, "waldo", 3) >= 0);
621 assert_se(strv_extend_n(&v
, "piep", 2) >= 0);
623 assert_se(streq(v
[0], "foo"));
624 assert_se(streq(v
[1], "bar"));
625 assert_se(streq(v
[2], "waldo"));
626 assert_se(streq(v
[3], "waldo"));
627 assert_se(streq(v
[4], "waldo"));
628 assert_se(streq(v
[5], "piep"));
629 assert_se(streq(v
[6], "piep"));
630 assert_se(v
[7] == NULL
);
634 assert_se(strv_extend_n(&v
, "foo", 1) >= 0);
635 assert_se(strv_extend_n(&v
, "bar", 0) >= 0);
637 assert_se(streq(v
[0], "foo"));
638 assert_se(v
[1] == NULL
);
641 static void test_strv_make_nulstr_one(char **l
) {
642 _cleanup_free_
char *b
= NULL
, *c
= NULL
;
643 _cleanup_strv_free_
char **q
= NULL
;
646 assert_se(strv_make_nulstr(l
, &b
, &n
) >= 0);
647 assert_se(q
= strv_parse_nulstr(b
, n
));
648 assert_se(strv_equal(l
, q
));
650 assert_se(strv_make_nulstr(q
, &c
, &m
) >= 0);
652 assert_se(memcmp(b
, c
, m
) == 0);
655 static void test_strv_make_nulstr(void) {
656 test_strv_make_nulstr_one(NULL
);
657 test_strv_make_nulstr_one(STRV_MAKE(NULL
));
658 test_strv_make_nulstr_one(STRV_MAKE("foo"));
659 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar"));
660 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux"));
663 int main(int argc
, char *argv
[]) {
664 test_specifier_printf();
666 test_strv_foreach_backwards();
667 test_strv_foreach_pair();
669 test_strv_find_prefix();
670 test_strv_find_startswith();
673 test_strv_quote_unquote(input_table_multiple
, "\"one\" \"two\" \"three\"");
674 test_strv_quote_unquote(input_table_one
, "\"one\"");
675 test_strv_quote_unquote(input_table_none
, "");
676 test_strv_quote_unquote(input_table_one_empty
, "\"\"");
677 test_strv_quote_unquote(input_table_two_empties
, "\"\" \"\"");
678 test_strv_quote_unquote(input_table_quotes
, QUOTES_STRING
);
679 test_strv_quote_unquote(input_table_spaces
, SPACES_STRING
);
681 test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
682 test_strv_unquote("", STRV_MAKE_EMPTY
);
683 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
684 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
685 test_strv_unquote(" x", STRV_MAKE("x"));
686 test_strv_unquote("x ", STRV_MAKE("x"));
687 test_strv_unquote(" x ", STRV_MAKE("x"));
688 test_strv_unquote(" \"x\" ", STRV_MAKE("x"));
689 test_strv_unquote(" 'x' ", STRV_MAKE("x"));
690 test_strv_unquote(" 'x\"' ", STRV_MAKE("x\""));
691 test_strv_unquote(" \"x'\" ", STRV_MAKE("x'"));
692 test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\""));
694 /* trailing backslashes */
695 test_strv_unquote(" x\\\\", STRV_MAKE("x\\"));
696 test_invalid_unquote(" x\\");
698 test_invalid_unquote("a --b='c \"d e\"''");
699 test_invalid_unquote("a --b='c \"d e\" '\"");
700 test_invalid_unquote("a --b='c \"d e\"garbage");
701 test_invalid_unquote("'");
702 test_invalid_unquote("\"");
703 test_invalid_unquote("'x'y'g");
706 test_strv_split_extract();
707 test_strv_split_newlines();
708 test_strv_split_nulstr();
709 test_strv_parse_nulstr();
712 test_strv_extend_strv();
713 test_strv_extend_strv_concat();
716 test_strv_from_stdarg_alloca();
717 test_strv_push_prepend();
722 test_strv_shell_escape();
724 test_strv_extend_n();
725 test_strv_make_nulstr();