1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Thomas H.P. Andersen
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.
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.
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/>.
25 #include "specifier.h"
26 #include "string-util.h"
30 static void test_specifier_printf(void) {
31 static const Specifier table
[] = {
32 { 'a', specifier_string
, (char*) "AAAA" },
33 { 'b', specifier_string
, (char*) "BBBB" },
34 { 'm', specifier_machine_id
, NULL
},
35 { 'B', specifier_boot_id
, NULL
},
36 { 'H', specifier_host_name
, NULL
},
37 { 'v', specifier_kernel_release
, NULL
},
41 _cleanup_free_
char *w
= NULL
;
44 r
= specifier_printf("xxx a=%a b=%b yyy", table
, NULL
, &w
);
49 assert_se(streq(w
, "xxx a=AAAA b=BBBB yyy"));
52 r
= specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table
, NULL
, &w
);
58 static const char* const input_table_multiple
[] = {
65 static const char* const input_table_one
[] = {
70 static const char* const input_table_none
[] = {
74 static const char* const input_table_quotes
[] = {
82 #define QUOTES_STRING \
89 static const char * const input_table_spaces
[] = {
97 #define SPACES_STRING \
104 static void test_strv_find(void) {
105 assert_se(strv_find((char **)input_table_multiple
, "three"));
106 assert_se(!strv_find((char **)input_table_multiple
, "four"));
109 static void test_strv_find_prefix(void) {
110 assert_se(strv_find_prefix((char **)input_table_multiple
, "o"));
111 assert_se(strv_find_prefix((char **)input_table_multiple
, "one"));
112 assert_se(strv_find_prefix((char **)input_table_multiple
, ""));
113 assert_se(!strv_find_prefix((char **)input_table_multiple
, "xxx"));
114 assert_se(!strv_find_prefix((char **)input_table_multiple
, "onee"));
117 static void test_strv_find_startswith(void) {
120 r
= strv_find_startswith((char **)input_table_multiple
, "o");
121 assert_se(r
&& streq(r
, "ne"));
123 r
= strv_find_startswith((char **)input_table_multiple
, "one");
124 assert_se(r
&& streq(r
, ""));
126 r
= strv_find_startswith((char **)input_table_multiple
, "");
127 assert_se(r
&& streq(r
, "one"));
129 assert_se(!strv_find_startswith((char **)input_table_multiple
, "xxx"));
130 assert_se(!strv_find_startswith((char **)input_table_multiple
, "onee"));
133 static void test_strv_join(void) {
134 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *r
= NULL
, *s
= NULL
, *t
= NULL
;
136 p
= strv_join((char **)input_table_multiple
, ", ");
138 assert_se(streq(p
, "one, two, three"));
140 q
= strv_join((char **)input_table_multiple
, ";");
142 assert_se(streq(q
, "one;two;three"));
144 r
= strv_join((char **)input_table_multiple
, NULL
);
146 assert_se(streq(r
, "one two three"));
148 s
= strv_join((char **)input_table_one
, ", ");
150 assert_se(streq(s
, "one"));
152 t
= strv_join((char **)input_table_none
, ", ");
154 assert_se(streq(t
, ""));
157 static void test_strv_quote_unquote(const char* const *split
, const char *quoted
) {
158 _cleanup_free_
char *p
;
159 _cleanup_strv_free_
char **s
= NULL
;
163 p
= strv_join_quoted((char **)split
);
165 printf("-%s- --- -%s-\n", p
, quoted
); /* fprintf deals with NULL, puts does not */
167 assert_se(streq(p
, quoted
));
169 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
170 assert_se(r
== (int) strv_length(s
));
174 assert_se(streq(*t
, *split
));
179 static void test_strv_unquote(const char *quoted
, char **list
) {
180 _cleanup_strv_free_
char **s
;
181 _cleanup_free_
char *j
;
186 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
187 assert_se(r
== (int) strv_length(list
));
189 j
= strv_join(s
, " | ");
194 assert_se(streq(list
[i
++], *t
));
196 assert_se(list
[i
] == NULL
);
199 static void test_invalid_unquote(const char *quoted
) {
203 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
204 assert_se(s
== NULL
);
205 assert_se(r
== -EINVAL
);
208 static void test_strv_split(void) {
211 _cleanup_strv_free_
char **l
= NULL
;
212 const char str
[] = "one,two,three";
214 l
= strv_split(str
, ",");
219 assert_se(streq(*s
, input_table_multiple
[i
++]));
223 static void test_strv_split_extract(void) {
224 _cleanup_strv_free_
char **l
= NULL
;
225 const char *str
= ":foo\\:bar::waldo:";
228 r
= strv_split_extract(&l
, str
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
229 assert_se(r
== (int) strv_length(l
));
230 assert_se(streq_ptr(l
[0], ""));
231 assert_se(streq_ptr(l
[1], "foo:bar"));
232 assert_se(streq_ptr(l
[2], ""));
233 assert_se(streq_ptr(l
[3], "waldo"));
234 assert_se(streq_ptr(l
[4], ""));
235 assert_se(streq_ptr(l
[5], NULL
));
238 static void test_strv_split_newlines(void) {
241 _cleanup_strv_free_
char **l
= NULL
;
242 const char str
[] = "one\ntwo\nthree";
244 l
= strv_split_newlines(str
);
249 assert_se(streq(*s
, input_table_multiple
[i
++]));
253 static void test_strv_split_nulstr(void) {
254 _cleanup_strv_free_
char **l
= NULL
;
255 const char nulstr
[] = "str0\0str1\0str2\0str3\0";
257 l
= strv_split_nulstr (nulstr
);
260 assert_se(streq(l
[0], "str0"));
261 assert_se(streq(l
[1], "str1"));
262 assert_se(streq(l
[2], "str2"));
263 assert_se(streq(l
[3], "str3"));
266 static void test_strv_parse_nulstr(void) {
267 _cleanup_strv_free_
char **l
= NULL
;
268 const char nulstr
[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
270 l
= strv_parse_nulstr(nulstr
, sizeof(nulstr
)-1);
272 puts("Parse nulstr:");
275 assert_se(streq(l
[0], "fuck"));
276 assert_se(streq(l
[1], "fuck2"));
277 assert_se(streq(l
[2], "fuck3"));
278 assert_se(streq(l
[3], ""));
279 assert_se(streq(l
[4], "fuck5"));
280 assert_se(streq(l
[5], ""));
281 assert_se(streq(l
[6], "xxx"));
284 static void test_strv_overlap(void) {
285 const char * const input_table
[] = {
291 const char * const input_table_overlap
[] = {
295 const char * const input_table_unique
[] = {
302 assert_se(strv_overlap((char **)input_table
, (char**)input_table_overlap
));
303 assert_se(!strv_overlap((char **)input_table
, (char**)input_table_unique
));
306 static void test_strv_sort(void) {
307 const char* input_table
[] = {
311 "CAPITAL LETTERS FIRST",
316 strv_sort((char **)input_table
);
318 assert_se(streq(input_table
[0], "CAPITAL LETTERS FIRST"));
319 assert_se(streq(input_table
[1], "apple"));
320 assert_se(streq(input_table
[2], "banana"));
321 assert_se(streq(input_table
[3], "citrus"));
322 assert_se(streq(input_table
[4], "durian"));
325 static void test_strv_extend_strv_concat(void) {
326 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
328 a
= strv_new("without", "suffix", NULL
);
329 b
= strv_new("with", "suffix", NULL
);
333 assert_se(strv_extend_strv_concat(&a
, b
, "_suffix") >= 0);
335 assert_se(streq(a
[0], "without"));
336 assert_se(streq(a
[1], "suffix"));
337 assert_se(streq(a
[2], "with_suffix"));
338 assert_se(streq(a
[3], "suffix_suffix"));
341 static void test_strv_extend_strv(void) {
342 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
344 a
= strv_new("abc", "def", "ghi", NULL
);
345 b
= strv_new("jkl", "mno", "abc", "pqr", NULL
);
349 assert_se(strv_extend_strv(&a
, b
, true) == 3);
351 assert_se(streq(a
[0], "abc"));
352 assert_se(streq(a
[1], "def"));
353 assert_se(streq(a
[2], "ghi"));
354 assert_se(streq(a
[3], "jkl"));
355 assert_se(streq(a
[4], "mno"));
356 assert_se(streq(a
[5], "pqr"));
358 assert_se(strv_length(a
) == 6);
361 static void test_strv_extend(void) {
362 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
364 a
= strv_new("test", "test1", NULL
);
366 assert_se(strv_extend(&a
, "test2") >= 0);
367 assert_se(strv_extend(&b
, "test3") >= 0);
369 assert_se(streq(a
[0], "test"));
370 assert_se(streq(a
[1], "test1"));
371 assert_se(streq(a
[2], "test2"));
372 assert_se(streq(b
[0], "test3"));
375 static void test_strv_extendf(void) {
376 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
378 a
= strv_new("test", "test1", NULL
);
380 assert_se(strv_extendf(&a
, "test2 %s %d %s", "foo", 128, "bar") >= 0);
381 assert_se(strv_extendf(&b
, "test3 %s %s %d", "bar", "foo", 128) >= 0);
383 assert_se(streq(a
[0], "test"));
384 assert_se(streq(a
[1], "test1"));
385 assert_se(streq(a
[2], "test2 foo 128 bar"));
386 assert_se(streq(b
[0], "test3 bar foo 128"));
389 static void test_strv_foreach(void) {
390 _cleanup_strv_free_
char **a
;
394 a
= strv_new("one", "two", "three", NULL
);
398 STRV_FOREACH(check
, a
) {
399 assert_se(streq(*check
, input_table_multiple
[i
++]));
403 static void test_strv_foreach_backwards(void) {
404 _cleanup_strv_free_
char **a
;
408 a
= strv_new("one", "two", "three", NULL
);
412 STRV_FOREACH_BACKWARDS(check
, a
) {
413 assert_se(streq_ptr(*check
, input_table_multiple
[i
--]));
417 static void test_strv_foreach_pair(void) {
418 _cleanup_strv_free_
char **a
= NULL
;
421 a
= strv_new("pair_one", "pair_one",
422 "pair_two", "pair_two",
423 "pair_three", "pair_three",
426 STRV_FOREACH_PAIR(x
, y
, a
) {
427 assert_se(streq(*x
, *y
));
431 static void test_strv_from_stdarg_alloca_one(char **l
, const char *first
, ...) {
435 j
= strv_from_stdarg_alloca(first
);
438 assert_se(streq_ptr(l
[i
], j
[i
]));
445 static void test_strv_from_stdarg_alloca(void) {
446 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL
);
447 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL
);
448 test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY
, NULL
);
451 static void test_strv_push_prepend(void) {
452 _cleanup_strv_free_
char **a
= NULL
;
454 a
= strv_new("foo", "bar", "three", NULL
);
456 assert_se(strv_push_prepend(&a
, strdup("first")) >= 0);
457 assert_se(streq(a
[0], "first"));
458 assert_se(streq(a
[1], "foo"));
459 assert_se(streq(a
[2], "bar"));
460 assert_se(streq(a
[3], "three"));
463 assert_se(strv_consume_prepend(&a
, strdup("first2")) >= 0);
464 assert_se(streq(a
[0], "first2"));
465 assert_se(streq(a
[1], "first"));
466 assert_se(streq(a
[2], "foo"));
467 assert_se(streq(a
[3], "bar"));
468 assert_se(streq(a
[4], "three"));
472 static void test_strv_push(void) {
473 _cleanup_strv_free_
char **a
= NULL
;
476 assert_se(i
= strdup("foo"));
477 assert_se(strv_push(&a
, i
) >= 0);
479 assert_se(i
= strdup("a"));
480 assert_se(j
= strdup("b"));
481 assert_se(strv_push_pair(&a
, i
, j
) >= 0);
483 assert_se(streq_ptr(a
[0], "foo"));
484 assert_se(streq_ptr(a
[1], "a"));
485 assert_se(streq_ptr(a
[2], "b"));
486 assert_se(streq_ptr(a
[3], NULL
));
489 static void test_strv_equal(void) {
490 _cleanup_strv_free_
char **a
= NULL
;
491 _cleanup_strv_free_
char **b
= NULL
;
492 _cleanup_strv_free_
char **c
= NULL
;
494 a
= strv_new("one", "two", "three", NULL
);
496 b
= strv_new("one", "two", "three", NULL
);
498 c
= strv_new("one", "two", "three", "four", NULL
);
501 assert_se(strv_equal(a
, a
));
502 assert_se(strv_equal(a
, b
));
503 assert_se(strv_equal(NULL
, NULL
));
505 assert_se(!strv_equal(a
, c
));
506 assert_se(!strv_equal(b
, c
));
507 assert_se(!strv_equal(b
, NULL
));
510 static void test_strv_is_uniq(void) {
511 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
513 a
= strv_new(NULL
, NULL
);
515 assert_se(strv_is_uniq(a
));
517 b
= strv_new("foo", NULL
);
519 assert_se(strv_is_uniq(b
));
521 c
= strv_new("foo", "bar", NULL
);
523 assert_se(strv_is_uniq(c
));
525 d
= strv_new("foo", "bar", "waldo", "bar", "piep", NULL
);
527 assert_se(!strv_is_uniq(d
));
530 static void test_strv_reverse(void) {
531 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
533 a
= strv_new(NULL
, NULL
);
537 assert_se(strv_isempty(a
));
539 b
= strv_new("foo", NULL
);
542 assert_se(streq_ptr(b
[0], "foo"));
543 assert_se(streq_ptr(b
[1], NULL
));
545 c
= strv_new("foo", "bar", NULL
);
548 assert_se(streq_ptr(c
[0], "bar"));
549 assert_se(streq_ptr(c
[1], "foo"));
550 assert_se(streq_ptr(c
[2], NULL
));
552 d
= strv_new("foo", "bar", "waldo", NULL
);
555 assert_se(streq_ptr(d
[0], "waldo"));
556 assert_se(streq_ptr(d
[1], "bar"));
557 assert_se(streq_ptr(d
[2], "foo"));
558 assert_se(streq_ptr(d
[3], NULL
));
561 static void test_strv_shell_escape(void) {
562 _cleanup_strv_free_
char **v
= NULL
;
564 v
= strv_new("foo:bar", "bar,baz", "wal\\do", NULL
);
566 assert_se(strv_shell_escape(v
, ",:"));
567 assert_se(streq_ptr(v
[0], "foo\\:bar"));
568 assert_se(streq_ptr(v
[1], "bar\\,baz"));
569 assert_se(streq_ptr(v
[2], "wal\\\\do"));
570 assert_se(streq_ptr(v
[3], NULL
));
573 static void test_strv_skip_one(char **a
, size_t n
, char **b
) {
575 assert_se(strv_equal(a
, b
));
578 static void test_strv_skip(void) {
579 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz"));
580 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz"));
581 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz"));
582 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 3, STRV_MAKE(NULL
));
583 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 4, STRV_MAKE(NULL
));
584 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 55, STRV_MAKE(NULL
));
586 test_strv_skip_one(STRV_MAKE("quux"), 0, STRV_MAKE("quux"));
587 test_strv_skip_one(STRV_MAKE("quux"), 1, STRV_MAKE(NULL
));
588 test_strv_skip_one(STRV_MAKE("quux"), 55, STRV_MAKE(NULL
));
590 test_strv_skip_one(STRV_MAKE(NULL
), 0, STRV_MAKE(NULL
));
591 test_strv_skip_one(STRV_MAKE(NULL
), 1, STRV_MAKE(NULL
));
592 test_strv_skip_one(STRV_MAKE(NULL
), 55, STRV_MAKE(NULL
));
595 static void test_strv_extend_n(void) {
596 _cleanup_strv_free_
char **v
= NULL
;
598 v
= strv_new("foo", "bar", NULL
);
601 assert_se(strv_extend_n(&v
, "waldo", 3) >= 0);
602 assert_se(strv_extend_n(&v
, "piep", 2) >= 0);
604 assert_se(streq(v
[0], "foo"));
605 assert_se(streq(v
[1], "bar"));
606 assert_se(streq(v
[2], "waldo"));
607 assert_se(streq(v
[3], "waldo"));
608 assert_se(streq(v
[4], "waldo"));
609 assert_se(streq(v
[5], "piep"));
610 assert_se(streq(v
[6], "piep"));
611 assert_se(v
[7] == NULL
);
615 assert_se(strv_extend_n(&v
, "foo", 1) >= 0);
616 assert_se(strv_extend_n(&v
, "bar", 0) >= 0);
618 assert_se(streq(v
[0], "foo"));
619 assert_se(v
[1] == NULL
);
622 static void test_strv_make_nulstr_one(char **l
) {
623 _cleanup_free_
char *b
= NULL
, *c
= NULL
;
624 _cleanup_strv_free_
char **q
= NULL
;
627 assert_se(strv_make_nulstr(l
, &b
, &n
) >= 0);
628 assert_se(q
= strv_parse_nulstr(b
, n
));
629 assert_se(strv_equal(l
, q
));
631 assert_se(strv_make_nulstr(q
, &c
, &m
) >= 0);
633 assert_se(memcmp(b
, c
, m
) == 0);
636 static void test_strv_make_nulstr(void) {
637 test_strv_make_nulstr_one(NULL
);
638 test_strv_make_nulstr_one(STRV_MAKE(NULL
));
639 test_strv_make_nulstr_one(STRV_MAKE("foo"));
640 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar"));
641 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux"));
644 int main(int argc
, char *argv
[]) {
645 test_specifier_printf();
647 test_strv_foreach_backwards();
648 test_strv_foreach_pair();
650 test_strv_find_prefix();
651 test_strv_find_startswith();
654 test_strv_quote_unquote(input_table_multiple
, "\"one\" \"two\" \"three\"");
655 test_strv_quote_unquote(input_table_one
, "\"one\"");
656 test_strv_quote_unquote(input_table_none
, "");
657 test_strv_quote_unquote(input_table_quotes
, QUOTES_STRING
);
658 test_strv_quote_unquote(input_table_spaces
, SPACES_STRING
);
660 test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
661 test_strv_unquote("", STRV_MAKE_EMPTY
);
662 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
663 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
664 test_strv_unquote(" x", STRV_MAKE("x"));
665 test_strv_unquote("x ", STRV_MAKE("x"));
666 test_strv_unquote(" x ", STRV_MAKE("x"));
667 test_strv_unquote(" \"x\" ", STRV_MAKE("x"));
668 test_strv_unquote(" 'x' ", STRV_MAKE("x"));
669 test_strv_unquote(" 'x\"' ", STRV_MAKE("x\""));
670 test_strv_unquote(" \"x'\" ", STRV_MAKE("x'"));
671 test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\""));
673 /* trailing backslashes */
674 test_strv_unquote(" x\\\\", STRV_MAKE("x\\"));
675 test_invalid_unquote(" x\\");
677 test_invalid_unquote("a --b='c \"d e\"''");
678 test_invalid_unquote("a --b='c \"d e\" '\"");
679 test_invalid_unquote("a --b='c \"d e\"garbage");
680 test_invalid_unquote("'");
681 test_invalid_unquote("\"");
682 test_invalid_unquote("'x'y'g");
685 test_strv_split_extract();
686 test_strv_split_newlines();
687 test_strv_split_nulstr();
688 test_strv_parse_nulstr();
691 test_strv_extend_strv();
692 test_strv_extend_strv_concat();
695 test_strv_from_stdarg_alloca();
696 test_strv_push_prepend();
701 test_strv_shell_escape();
703 test_strv_extend_n();
704 test_strv_make_nulstr();