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/>.
26 #include "specifier.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_quotes
[] = {
81 #define QUOTES_STRING \
88 static const char * const input_table_spaces
[] = {
96 #define SPACES_STRING \
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"));
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"));
116 static void test_strv_find_startswith(void) {
119 r
= strv_find_startswith((char **)input_table_multiple
, "o");
120 assert_se(r
&& streq(r
, "ne"));
122 r
= strv_find_startswith((char **)input_table_multiple
, "one");
123 assert_se(r
&& streq(r
, ""));
125 r
= strv_find_startswith((char **)input_table_multiple
, "");
126 assert_se(r
&& streq(r
, "one"));
128 assert_se(!strv_find_startswith((char **)input_table_multiple
, "xxx"));
129 assert_se(!strv_find_startswith((char **)input_table_multiple
, "onee"));
132 static void test_strv_join(void) {
133 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *r
= NULL
, *s
= NULL
, *t
= NULL
;
135 p
= strv_join((char **)input_table_multiple
, ", ");
137 assert_se(streq(p
, "one, two, three"));
139 q
= strv_join((char **)input_table_multiple
, ";");
141 assert_se(streq(q
, "one;two;three"));
143 r
= strv_join((char **)input_table_multiple
, NULL
);
145 assert_se(streq(r
, "one two three"));
147 s
= strv_join((char **)input_table_one
, ", ");
149 assert_se(streq(s
, "one"));
151 t
= strv_join((char **)input_table_none
, ", ");
153 assert_se(streq(t
, ""));
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
;
162 p
= strv_join_quoted((char **)split
);
164 printf("-%s- --- -%s-\n", p
, quoted
); /* fprintf deals with NULL, puts does not */
166 assert_se(streq(p
, quoted
));
168 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
173 assert_se(streq(*t
, *split
));
178 static void test_strv_unquote(const char *quoted
, char **list
) {
179 _cleanup_strv_free_
char **s
;
180 _cleanup_free_
char *j
;
185 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
188 j
= strv_join(s
, " | ");
193 assert_se(streq(list
[i
++], *t
));
195 assert_se(list
[i
] == NULL
);
198 static void test_invalid_unquote(const char *quoted
) {
202 r
= strv_split_extract(&s
, quoted
, WHITESPACE
, EXTRACT_QUOTES
);
203 assert_se(s
== NULL
);
204 assert_se(r
== -EINVAL
);
207 static void test_strv_split(void) {
210 _cleanup_strv_free_
char **l
= NULL
;
211 const char str
[] = "one,two,three";
213 l
= strv_split(str
, ",");
218 assert_se(streq(*s
, input_table_multiple
[i
++]));
222 static void test_strv_split_extract(void) {
223 _cleanup_strv_free_
char **l
= NULL
;
224 const char *str
= ":foo\\:bar::waldo:";
227 r
= strv_split_extract(&l
, str
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
229 assert_se(streq_ptr(l
[0], ""));
230 assert_se(streq_ptr(l
[1], "foo:bar"));
231 assert_se(streq_ptr(l
[2], ""));
232 assert_se(streq_ptr(l
[3], "waldo"));
233 assert_se(streq_ptr(l
[4], ""));
234 assert_se(streq_ptr(l
[5], NULL
));
237 static void test_strv_split_newlines(void) {
240 _cleanup_strv_free_
char **l
= NULL
;
241 const char str
[] = "one\ntwo\nthree";
243 l
= strv_split_newlines(str
);
248 assert_se(streq(*s
, input_table_multiple
[i
++]));
252 static void test_strv_split_nulstr(void) {
253 _cleanup_strv_free_
char **l
= NULL
;
254 const char nulstr
[] = "str0\0str1\0str2\0str3\0";
256 l
= strv_split_nulstr (nulstr
);
259 assert_se(streq(l
[0], "str0"));
260 assert_se(streq(l
[1], "str1"));
261 assert_se(streq(l
[2], "str2"));
262 assert_se(streq(l
[3], "str3"));
265 static void test_strv_parse_nulstr(void) {
266 _cleanup_strv_free_
char **l
= NULL
;
267 const char nulstr
[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx";
269 l
= strv_parse_nulstr(nulstr
, sizeof(nulstr
)-1);
271 puts("Parse nulstr:");
274 assert_se(streq(l
[0], "fuck"));
275 assert_se(streq(l
[1], "fuck2"));
276 assert_se(streq(l
[2], "fuck3"));
277 assert_se(streq(l
[3], ""));
278 assert_se(streq(l
[4], "fuck5"));
279 assert_se(streq(l
[5], ""));
280 assert_se(streq(l
[6], "xxx"));
283 static void test_strv_overlap(void) {
284 const char * const input_table
[] = {
290 const char * const input_table_overlap
[] = {
294 const char * const input_table_unique
[] = {
301 assert_se(strv_overlap((char **)input_table
, (char**)input_table_overlap
));
302 assert_se(!strv_overlap((char **)input_table
, (char**)input_table_unique
));
305 static void test_strv_sort(void) {
306 const char* input_table
[] = {
310 "CAPITAL LETTERS FIRST",
315 strv_sort((char **)input_table
);
317 assert_se(streq(input_table
[0], "CAPITAL LETTERS FIRST"));
318 assert_se(streq(input_table
[1], "apple"));
319 assert_se(streq(input_table
[2], "banana"));
320 assert_se(streq(input_table
[3], "citrus"));
321 assert_se(streq(input_table
[4], "durian"));
324 static void test_strv_extend_strv_concat(void) {
325 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
327 a
= strv_new("without", "suffix", NULL
);
328 b
= strv_new("with", "suffix", NULL
);
332 assert_se(strv_extend_strv_concat(&a
, b
, "_suffix") >= 0);
334 assert_se(streq(a
[0], "without"));
335 assert_se(streq(a
[1], "suffix"));
336 assert_se(streq(a
[2], "with_suffix"));
337 assert_se(streq(a
[3], "suffix_suffix"));
340 static void test_strv_extend_strv(void) {
341 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
343 a
= strv_new("abc", "def", "ghi", NULL
);
344 b
= strv_new("jkl", "mno", "pqr", NULL
);
348 assert_se(strv_extend_strv(&a
, b
) >= 0);
350 assert_se(streq(a
[0], "abc"));
351 assert_se(streq(a
[1], "def"));
352 assert_se(streq(a
[2], "ghi"));
353 assert_se(streq(a
[3], "jkl"));
354 assert_se(streq(a
[4], "mno"));
355 assert_se(streq(a
[5], "pqr"));
357 assert_se(strv_length(a
) == 6);
360 static void test_strv_extend(void) {
361 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
363 a
= strv_new("test", "test1", NULL
);
365 assert_se(strv_extend(&a
, "test2") >= 0);
366 assert_se(strv_extend(&b
, "test3") >= 0);
368 assert_se(streq(a
[0], "test"));
369 assert_se(streq(a
[1], "test1"));
370 assert_se(streq(a
[2], "test2"));
371 assert_se(streq(b
[0], "test3"));
374 static void test_strv_extendf(void) {
375 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
;
377 a
= strv_new("test", "test1", NULL
);
379 assert_se(strv_extendf(&a
, "test2 %s %d %s", "foo", 128, "bar") >= 0);
380 assert_se(strv_extendf(&b
, "test3 %s %s %d", "bar", "foo", 128) >= 0);
382 assert_se(streq(a
[0], "test"));
383 assert_se(streq(a
[1], "test1"));
384 assert_se(streq(a
[2], "test2 foo 128 bar"));
385 assert_se(streq(b
[0], "test3 bar foo 128"));
388 static void test_strv_foreach(void) {
389 _cleanup_strv_free_
char **a
;
393 a
= strv_new("one", "two", "three", NULL
);
397 STRV_FOREACH(check
, a
) {
398 assert_se(streq(*check
, input_table_multiple
[i
++]));
402 static void test_strv_foreach_backwards(void) {
403 _cleanup_strv_free_
char **a
;
407 a
= strv_new("one", "two", "three", NULL
);
411 STRV_FOREACH_BACKWARDS(check
, a
) {
412 assert_se(streq_ptr(*check
, input_table_multiple
[i
--]));
416 static void test_strv_foreach_pair(void) {
417 _cleanup_strv_free_
char **a
= NULL
;
420 a
= strv_new("pair_one", "pair_one",
421 "pair_two", "pair_two",
422 "pair_three", "pair_three",
425 STRV_FOREACH_PAIR(x
, y
, a
) {
426 assert_se(streq(*x
, *y
));
430 static void test_strv_from_stdarg_alloca_one(char **l
, const char *first
, ...) {
434 j
= strv_from_stdarg_alloca(first
);
437 assert_se(streq_ptr(l
[i
], j
[i
]));
444 static void test_strv_from_stdarg_alloca(void) {
445 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL
);
446 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL
);
447 test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY
, NULL
);
450 static void test_strv_push_prepend(void) {
451 _cleanup_strv_free_
char **a
= NULL
;
453 a
= strv_new("foo", "bar", "three", NULL
);
455 assert_se(strv_push_prepend(&a
, strdup("first")) >= 0);
456 assert_se(streq(a
[0], "first"));
457 assert_se(streq(a
[1], "foo"));
458 assert_se(streq(a
[2], "bar"));
459 assert_se(streq(a
[3], "three"));
462 assert_se(strv_consume_prepend(&a
, strdup("first2")) >= 0);
463 assert_se(streq(a
[0], "first2"));
464 assert_se(streq(a
[1], "first"));
465 assert_se(streq(a
[2], "foo"));
466 assert_se(streq(a
[3], "bar"));
467 assert_se(streq(a
[4], "three"));
471 static void test_strv_push(void) {
472 _cleanup_strv_free_
char **a
= NULL
;
475 assert_se(i
= strdup("foo"));
476 assert_se(strv_push(&a
, i
) >= 0);
478 assert_se(i
= strdup("a"));
479 assert_se(j
= strdup("b"));
480 assert_se(strv_push_pair(&a
, i
, j
) >= 0);
482 assert_se(streq_ptr(a
[0], "foo"));
483 assert_se(streq_ptr(a
[1], "a"));
484 assert_se(streq_ptr(a
[2], "b"));
485 assert_se(streq_ptr(a
[3], NULL
));
488 static void test_strv_equal(void) {
489 _cleanup_strv_free_
char **a
= NULL
;
490 _cleanup_strv_free_
char **b
= NULL
;
491 _cleanup_strv_free_
char **c
= NULL
;
493 a
= strv_new("one", "two", "three", NULL
);
495 b
= strv_new("one", "two", "three", NULL
);
497 c
= strv_new("one", "two", "three", "four", NULL
);
500 assert_se(strv_equal(a
, a
));
501 assert_se(strv_equal(a
, b
));
502 assert_se(strv_equal(NULL
, NULL
));
504 assert_se(!strv_equal(a
, c
));
505 assert_se(!strv_equal(b
, c
));
506 assert_se(!strv_equal(b
, NULL
));
509 static void test_strv_is_uniq(void) {
510 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
512 a
= strv_new(NULL
, NULL
);
514 assert_se(strv_is_uniq(a
));
516 b
= strv_new("foo", NULL
);
518 assert_se(strv_is_uniq(b
));
520 c
= strv_new("foo", "bar", NULL
);
522 assert_se(strv_is_uniq(c
));
524 d
= strv_new("foo", "bar", "waldo", "bar", "piep", NULL
);
526 assert_se(!strv_is_uniq(d
));
529 static void test_strv_reverse(void) {
530 _cleanup_strv_free_
char **a
= NULL
, **b
= NULL
, **c
= NULL
, **d
= NULL
;
532 a
= strv_new(NULL
, NULL
);
536 assert_se(strv_isempty(a
));
538 b
= strv_new("foo", NULL
);
541 assert_se(streq_ptr(b
[0], "foo"));
542 assert_se(streq_ptr(b
[1], NULL
));
544 c
= strv_new("foo", "bar", NULL
);
547 assert_se(streq_ptr(c
[0], "bar"));
548 assert_se(streq_ptr(c
[1], "foo"));
549 assert_se(streq_ptr(c
[2], NULL
));
551 d
= strv_new("foo", "bar", "waldo", NULL
);
554 assert_se(streq_ptr(d
[0], "waldo"));
555 assert_se(streq_ptr(d
[1], "bar"));
556 assert_se(streq_ptr(d
[2], "foo"));
557 assert_se(streq_ptr(d
[3], NULL
));
560 static void test_strv_shell_escape(void) {
561 _cleanup_strv_free_
char **v
= NULL
;
563 v
= strv_new("foo:bar", "bar,baz", "wal\\do", NULL
);
565 assert_se(strv_shell_escape(v
, ",:"));
566 assert_se(streq_ptr(v
[0], "foo\\:bar"));
567 assert_se(streq_ptr(v
[1], "bar\\,baz"));
568 assert_se(streq_ptr(v
[2], "wal\\\\do"));
569 assert_se(streq_ptr(v
[3], NULL
));
572 int main(int argc
, char *argv
[]) {
573 test_specifier_printf();
575 test_strv_foreach_backwards();
576 test_strv_foreach_pair();
578 test_strv_find_prefix();
579 test_strv_find_startswith();
582 test_strv_quote_unquote(input_table_multiple
, "\"one\" \"two\" \"three\"");
583 test_strv_quote_unquote(input_table_one
, "\"one\"");
584 test_strv_quote_unquote(input_table_none
, "");
585 test_strv_quote_unquote(input_table_quotes
, QUOTES_STRING
);
586 test_strv_quote_unquote(input_table_spaces
, SPACES_STRING
);
588 test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
589 test_strv_unquote("", STRV_MAKE_EMPTY
);
590 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
591 test_strv_unquote(" ", STRV_MAKE_EMPTY
);
592 test_strv_unquote(" x", STRV_MAKE("x"));
593 test_strv_unquote("x ", STRV_MAKE("x"));
594 test_strv_unquote(" x ", STRV_MAKE("x"));
595 test_strv_unquote(" \"x\" ", STRV_MAKE("x"));
596 test_strv_unquote(" 'x' ", STRV_MAKE("x"));
597 test_strv_unquote(" 'x\"' ", STRV_MAKE("x\""));
598 test_strv_unquote(" \"x'\" ", STRV_MAKE("x'"));
599 test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\""));
601 /* trailing backslashes */
602 test_strv_unquote(" x\\\\", STRV_MAKE("x\\"));
603 test_invalid_unquote(" x\\");
605 test_invalid_unquote("a --b='c \"d e\"''");
606 test_invalid_unquote("a --b='c \"d e\" '\"");
607 test_invalid_unquote("a --b='c \"d e\"garbage");
608 test_invalid_unquote("'");
609 test_invalid_unquote("\"");
610 test_invalid_unquote("'x'y'g");
613 test_strv_split_extract();
614 test_strv_split_newlines();
615 test_strv_split_nulstr();
616 test_strv_parse_nulstr();
619 test_strv_extend_strv();
620 test_strv_extend_strv_concat();
623 test_strv_from_stdarg_alloca();
624 test_strv_push_prepend();
629 test_strv_shell_escape();