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 "alloc-util.h"
26 #include "specifier.h"
27 #include "string-util.h"
31 static void test_specifier_printf(void) {
32 static const Specifier table
[] = {
33 { 'a', specifier_string
, (char*) "AAAA" },
34 { 'b', specifier_string
, (char*) "BBBB" },
35 { 'm', specifier_machine_id
, NULL
},
36 { 'B', specifier_boot_id
, NULL
},
37 { 'H', specifier_host_name
, NULL
},
38 { 'v', specifier_kernel_release
, NULL
},
42 _cleanup_free_
char *w
= NULL
;
45 r
= specifier_printf("xxx a=%a b=%b yyy", table
, NULL
, &w
);
50 assert_se(streq(w
, "xxx a=AAAA b=BBBB yyy"));
53 r
= specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table
, NULL
, &w
);
59 static const char* const input_table_multiple
[] = {
66 static const char* const input_table_one
[] = {
71 static const char* const input_table_none
[] = {
75 static const char* const input_table_quotes
[] = {
83 #define QUOTES_STRING \
90 static const char * const input_table_spaces
[] = {
98 #define SPACES_STRING \
105 static void test_strv_find(void) {
106 assert_se(strv_find((char **)input_table_multiple
, "three"));
107 assert_se(!strv_find((char **)input_table_multiple
, "four"));
110 static void test_strv_find_prefix(void) {
111 assert_se(strv_find_prefix((char **)input_table_multiple
, "o"));
112 assert_se(strv_find_prefix((char **)input_table_multiple
, "one"));
113 assert_se(strv_find_prefix((char **)input_table_multiple
, ""));
114 assert_se(!strv_find_prefix((char **)input_table_multiple
, "xxx"));
115 assert_se(!strv_find_prefix((char **)input_table_multiple
, "onee"));
118 static void test_strv_find_startswith(void) {
121 r
= strv_find_startswith((char **)input_table_multiple
, "o");
122 assert_se(r
&& streq(r
, "ne"));
124 r
= strv_find_startswith((char **)input_table_multiple
, "one");
125 assert_se(r
&& streq(r
, ""));
127 r
= strv_find_startswith((char **)input_table_multiple
, "");
128 assert_se(r
&& streq(r
, "one"));
130 assert_se(!strv_find_startswith((char **)input_table_multiple
, "xxx"));
131 assert_se(!strv_find_startswith((char **)input_table_multiple
, "onee"));
134 static void test_strv_join(void) {
135 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *r
= NULL
, *s
= NULL
, *t
= NULL
;
137 p
= strv_join((char **)input_table_multiple
, ", ");
139 assert_se(streq(p
, "one, two, three"));
141 q
= strv_join((char **)input_table_multiple
, ";");
143 assert_se(streq(q
, "one;two;three"));
145 r
= strv_join((char **)input_table_multiple
, NULL
);
147 assert_se(streq(r
, "one two three"));
149 s
= strv_join((char **)input_table_one
, ", ");
151 assert_se(streq(s
, "one"));
153 t
= strv_join((char **)input_table_none
, ", ");
155 assert_se(streq(t
, ""));
158 static void test_strv_quote_unquote(const char* const *split
, const char *quoted
) {
159 _cleanup_free_
char *p
;
160 _cleanup_strv_free_
char **s
= NULL
;
164 p
= strv_join_quoted((char **)split
);
166 printf("-%s- --- -%s-\n", p
, quoted
); /* fprintf deals with NULL, puts does not */
168 assert_se(streq(p
, quoted
));
170 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
171 assert_se(r
== (int) strv_length(s
));
175 assert_se(streq(*t
, *split
));
180 static void test_strv_unquote(const char *quoted
, char **list
) {
181 _cleanup_strv_free_
char **s
;
182 _cleanup_free_
char *j
;
187 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
188 assert_se(r
== (int) strv_length(list
));
190 j
= strv_join(s
, " | ");
195 assert_se(streq(list
[i
++], *t
));
197 assert_se(list
[i
] == NULL
);
200 static void test_invalid_unquote(const char *quoted
) {
204 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
205 assert_se(s
== NULL
);
206 assert_se(r
== -EINVAL
);
209 static void test_strv_split(void) {
212 _cleanup_strv_free_
char **l
= NULL
;
213 const char str
[] = "one,two,three";
215 l
= strv_split(str
, ",");
220 assert_se(streq(*s
, input_table_multiple
[i
++]));
224 static void test_strv_split_extract(void) {
225 _cleanup_strv_free_
char **l
= NULL
;
226 const char *str
= ":foo\\:bar::waldo:";
229 r
= strv_split_extract(&l
, str
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
230 assert_se(r
== (int) strv_length(l
));
231 assert_se(streq_ptr(l
[0], ""));
232 assert_se(streq_ptr(l
[1], "foo:bar"));
233 assert_se(streq_ptr(l
[2], ""));
234 assert_se(streq_ptr(l
[3], "waldo"));
235 assert_se(streq_ptr(l
[4], ""));
236 assert_se(streq_ptr(l
[5], NULL
));
239 static void test_strv_split_newlines(void) {
242 _cleanup_strv_free_
char **l
= NULL
;
243 const char str
[] = "one\ntwo\nthree";
245 l
= strv_split_newlines(str
);
250 assert_se(streq(*s
, input_table_multiple
[i
++]));
254 static void test_strv_split_nulstr(void) {
255 _cleanup_strv_free_
char **l
= NULL
;
256 const char nulstr
[] = "str0\0str1\0str2\0str3\0";
258 l
= strv_split_nulstr (nulstr
);
261 assert_se(streq(l
[0], "str0"));
262 assert_se(streq(l
[1], "str1"));
263 assert_se(streq(l
[2], "str2"));
264 assert_se(streq(l
[3], "str3"));
267 static void test_strv_parse_nulstr(void) {
268 _cleanup_strv_free_
char **l
= NULL
;
269 const char nulstr
[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
271 l
= strv_parse_nulstr(nulstr
, sizeof(nulstr
)-1);
273 puts("Parse nulstr:");
276 assert_se(streq(l
[0], "fuck"));
277 assert_se(streq(l
[1], "fuck2"));
278 assert_se(streq(l
[2], "fuck3"));
279 assert_se(streq(l
[3], ""));
280 assert_se(streq(l
[4], "fuck5"));
281 assert_se(streq(l
[5], ""));
282 assert_se(streq(l
[6], "xxx"));
285 static void test_strv_overlap(void) {
286 const char * const input_table
[] = {
292 const char * const input_table_overlap
[] = {
296 const char * const input_table_unique
[] = {
303 assert_se(strv_overlap((char **)input_table
, (char**)input_table_overlap
));
304 assert_se(!strv_overlap((char **)input_table
, (char**)input_table_unique
));
307 static void test_strv_sort(void) {
308 const char* input_table
[] = {
312 "CAPITAL LETTERS FIRST",
317 strv_sort((char **)input_table
);
319 assert_se(streq(input_table
[0], "CAPITAL LETTERS FIRST"));
320 assert_se(streq(input_table
[1], "apple"));
321 assert_se(streq(input_table
[2], "banana"));
322 assert_se(streq(input_table
[3], "citrus"));
323 assert_se(streq(input_table
[4], "durian"));
326 static void test_strv_extend_strv_concat(void) {
327 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
329 a
= strv_new("without", "suffix", NULL
);
330 b
= strv_new("with", "suffix", NULL
);
334 assert_se(strv_extend_strv_concat(&a
, b
, "_suffix") >= 0);
336 assert_se(streq(a
[0], "without"));
337 assert_se(streq(a
[1], "suffix"));
338 assert_se(streq(a
[2], "with_suffix"));
339 assert_se(streq(a
[3], "suffix_suffix"));
342 static void test_strv_extend_strv(void) {
343 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
345 a
= strv_new("abc", "def", "ghi", NULL
);
346 b
= strv_new("jkl", "mno", "abc", "pqr", NULL
);
350 assert_se(strv_extend_strv(&a
, b
, true) == 3);
352 assert_se(streq(a
[0], "abc"));
353 assert_se(streq(a
[1], "def"));
354 assert_se(streq(a
[2], "ghi"));
355 assert_se(streq(a
[3], "jkl"));
356 assert_se(streq(a
[4], "mno"));
357 assert_se(streq(a
[5], "pqr"));
359 assert_se(strv_length(a
) == 6);
362 static void test_strv_extend(void) {
363 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
365 a
= strv_new("test", "test1", NULL
);
367 assert_se(strv_extend(&a
, "test2") >= 0);
368 assert_se(strv_extend(&b
, "test3") >= 0);
370 assert_se(streq(a
[0], "test"));
371 assert_se(streq(a
[1], "test1"));
372 assert_se(streq(a
[2], "test2"));
373 assert_se(streq(b
[0], "test3"));
376 static void test_strv_extendf(void) {
377 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
379 a
= strv_new("test", "test1", NULL
);
381 assert_se(strv_extendf(&a
, "test2 %s %d %s", "foo", 128, "bar") >= 0);
382 assert_se(strv_extendf(&b
, "test3 %s %s %d", "bar", "foo", 128) >= 0);
384 assert_se(streq(a
[0], "test"));
385 assert_se(streq(a
[1], "test1"));
386 assert_se(streq(a
[2], "test2 foo 128 bar"));
387 assert_se(streq(b
[0], "test3 bar foo 128"));
390 static void test_strv_foreach(void) {
391 _cleanup_strv_free_
char **a
;
395 a
= strv_new("one", "two", "three", NULL
);
399 STRV_FOREACH(check
, a
) {
400 assert_se(streq(*check
, input_table_multiple
[i
++]));
404 static void test_strv_foreach_backwards(void) {
405 _cleanup_strv_free_
char **a
;
409 a
= strv_new("one", "two", "three", NULL
);
413 STRV_FOREACH_BACKWARDS(check
, a
) {
414 assert_se(streq_ptr(*check
, input_table_multiple
[i
--]));
418 static void test_strv_foreach_pair(void) {
419 _cleanup_strv_free_
char **a
= NULL
;
422 a
= strv_new("pair_one", "pair_one",
423 "pair_two", "pair_two",
424 "pair_three", "pair_three",
427 STRV_FOREACH_PAIR(x
, y
, a
) {
428 assert_se(streq(*x
, *y
));
432 static void test_strv_from_stdarg_alloca_one(char **l
, const char *first
, ...) {
436 j
= strv_from_stdarg_alloca(first
);
439 assert_se(streq_ptr(l
[i
], j
[i
]));
446 static void test_strv_from_stdarg_alloca(void) {
447 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL
);
448 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL
);
449 test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY
, NULL
);
452 static void test_strv_push_prepend(void) {
453 _cleanup_strv_free_
char **a
= NULL
;
455 a
= strv_new("foo", "bar", "three", NULL
);
457 assert_se(strv_push_prepend(&a
, strdup("first")) >= 0);
458 assert_se(streq(a
[0], "first"));
459 assert_se(streq(a
[1], "foo"));
460 assert_se(streq(a
[2], "bar"));
461 assert_se(streq(a
[3], "three"));
464 assert_se(strv_consume_prepend(&a
, strdup("first2")) >= 0);
465 assert_se(streq(a
[0], "first2"));
466 assert_se(streq(a
[1], "first"));
467 assert_se(streq(a
[2], "foo"));
468 assert_se(streq(a
[3], "bar"));
469 assert_se(streq(a
[4], "three"));
473 static void test_strv_push(void) {
474 _cleanup_strv_free_
char **a
= NULL
;
477 assert_se(i
= strdup("foo"));
478 assert_se(strv_push(&a
, i
) >= 0);
480 assert_se(i
= strdup("a"));
481 assert_se(j
= strdup("b"));
482 assert_se(strv_push_pair(&a
, i
, j
) >= 0);
484 assert_se(streq_ptr(a
[0], "foo"));
485 assert_se(streq_ptr(a
[1], "a"));
486 assert_se(streq_ptr(a
[2], "b"));
487 assert_se(streq_ptr(a
[3], NULL
));
490 static void test_strv_equal(void) {
491 _cleanup_strv_free_
char **a
= NULL
;
492 _cleanup_strv_free_
char **b
= NULL
;
493 _cleanup_strv_free_
char **c
= NULL
;
495 a
= strv_new("one", "two", "three", NULL
);
497 b
= strv_new("one", "two", "three", NULL
);
499 c
= strv_new("one", "two", "three", "four", NULL
);
502 assert_se(strv_equal(a
, a
));
503 assert_se(strv_equal(a
, b
));
504 assert_se(strv_equal(NULL
, NULL
));
506 assert_se(!strv_equal(a
, c
));
507 assert_se(!strv_equal(b
, c
));
508 assert_se(!strv_equal(b
, NULL
));
511 static void test_strv_is_uniq(void) {
512 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
514 a
= strv_new(NULL
, NULL
);
516 assert_se(strv_is_uniq(a
));
518 b
= strv_new("foo", NULL
);
520 assert_se(strv_is_uniq(b
));
522 c
= strv_new("foo", "bar", NULL
);
524 assert_se(strv_is_uniq(c
));
526 d
= strv_new("foo", "bar", "waldo", "bar", "piep", NULL
);
528 assert_se(!strv_is_uniq(d
));
531 static void test_strv_reverse(void) {
532 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
534 a
= strv_new(NULL
, NULL
);
538 assert_se(strv_isempty(a
));
540 b
= strv_new("foo", NULL
);
543 assert_se(streq_ptr(b
[0], "foo"));
544 assert_se(streq_ptr(b
[1], NULL
));
546 c
= strv_new("foo", "bar", NULL
);
549 assert_se(streq_ptr(c
[0], "bar"));
550 assert_se(streq_ptr(c
[1], "foo"));
551 assert_se(streq_ptr(c
[2], NULL
));
553 d
= strv_new("foo", "bar", "waldo", NULL
);
556 assert_se(streq_ptr(d
[0], "waldo"));
557 assert_se(streq_ptr(d
[1], "bar"));
558 assert_se(streq_ptr(d
[2], "foo"));
559 assert_se(streq_ptr(d
[3], NULL
));
562 static void test_strv_shell_escape(void) {
563 _cleanup_strv_free_
char **v
= NULL
;
565 v
= strv_new("foo:bar", "bar,baz", "wal\\do", NULL
);
567 assert_se(strv_shell_escape(v
, ",:"));
568 assert_se(streq_ptr(v
[0], "foo\\:bar"));
569 assert_se(streq_ptr(v
[1], "bar\\,baz"));
570 assert_se(streq_ptr(v
[2], "wal\\\\do"));
571 assert_se(streq_ptr(v
[3], NULL
));
574 static void test_strv_skip_one(char **a
, size_t n
, char **b
) {
576 assert_se(strv_equal(a
, b
));
579 static void test_strv_skip(void) {
580 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz"));
581 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz"));
582 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz"));
583 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 3, STRV_MAKE(NULL
));
584 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 4, STRV_MAKE(NULL
));
585 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 55, STRV_MAKE(NULL
));
587 test_strv_skip_one(STRV_MAKE("quux"), 0, STRV_MAKE("quux"));
588 test_strv_skip_one(STRV_MAKE("quux"), 1, STRV_MAKE(NULL
));
589 test_strv_skip_one(STRV_MAKE("quux"), 55, STRV_MAKE(NULL
));
591 test_strv_skip_one(STRV_MAKE(NULL
), 0, STRV_MAKE(NULL
));
592 test_strv_skip_one(STRV_MAKE(NULL
), 1, STRV_MAKE(NULL
));
593 test_strv_skip_one(STRV_MAKE(NULL
), 55, STRV_MAKE(NULL
));
596 static void test_strv_extend_n(void) {
597 _cleanup_strv_free_
char **v
= NULL
;
599 v
= strv_new("foo", "bar", NULL
);
602 assert_se(strv_extend_n(&v
, "waldo", 3) >= 0);
603 assert_se(strv_extend_n(&v
, "piep", 2) >= 0);
605 assert_se(streq(v
[0], "foo"));
606 assert_se(streq(v
[1], "bar"));
607 assert_se(streq(v
[2], "waldo"));
608 assert_se(streq(v
[3], "waldo"));
609 assert_se(streq(v
[4], "waldo"));
610 assert_se(streq(v
[5], "piep"));
611 assert_se(streq(v
[6], "piep"));
612 assert_se(v
[7] == NULL
);
616 assert_se(strv_extend_n(&v
, "foo", 1) >= 0);
617 assert_se(strv_extend_n(&v
, "bar", 0) >= 0);
619 assert_se(streq(v
[0], "foo"));
620 assert_se(v
[1] == NULL
);
623 static void test_strv_make_nulstr_one(char **l
) {
624 _cleanup_free_
char *b
= NULL
, *c
= NULL
;
625 _cleanup_strv_free_
char **q
= NULL
;
628 assert_se(strv_make_nulstr(l
, &b
, &n
) >= 0);
629 assert_se(q
= strv_parse_nulstr(b
, n
));
630 assert_se(strv_equal(l
, q
));
632 assert_se(strv_make_nulstr(q
, &c
, &m
) >= 0);
634 assert_se(memcmp(b
, c
, m
) == 0);
637 static void test_strv_make_nulstr(void) {
638 test_strv_make_nulstr_one(NULL
);
639 test_strv_make_nulstr_one(STRV_MAKE(NULL
));
640 test_strv_make_nulstr_one(STRV_MAKE("foo"));
641 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar"));
642 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux"));
645 int main(int argc
, char *argv
[]) {
646 test_specifier_printf();
648 test_strv_foreach_backwards();
649 test_strv_foreach_pair();
651 test_strv_find_prefix();
652 test_strv_find_startswith();
655 test_strv_quote_unquote(input_table_multiple
, "\"one\" \"two\" \"three\"");
656 test_strv_quote_unquote(input_table_one
, "\"one\"");
657 test_strv_quote_unquote(input_table_none
, "");
658 test_strv_quote_unquote(input_table_quotes
, QUOTES_STRING
);
659 test_strv_quote_unquote(input_table_spaces
, SPACES_STRING
);
661 test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
662 test_strv_unquote("", STRV_MAKE_EMPTY
);
663 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
664 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
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(" \"x'\" ", STRV_MAKE("x'"));
672 test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\""));
674 /* trailing backslashes */
675 test_strv_unquote(" x\\\\", STRV_MAKE("x\\"));
676 test_invalid_unquote(" x\\");
678 test_invalid_unquote("a --b='c \"d e\"''");
679 test_invalid_unquote("a --b='c \"d e\" '\"");
680 test_invalid_unquote("a --b='c \"d e\"garbage");
681 test_invalid_unquote("'");
682 test_invalid_unquote("\"");
683 test_invalid_unquote("'x'y'g");
686 test_strv_split_extract();
687 test_strv_split_newlines();
688 test_strv_split_nulstr();
689 test_strv_parse_nulstr();
692 test_strv_extend_strv();
693 test_strv_extend_strv_concat();
696 test_strv_from_stdarg_alloca();
697 test_strv_push_prepend();
702 test_strv_shell_escape();
704 test_strv_extend_n();
705 test_strv_make_nulstr();