]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-strv.c
Merge pull request #13365 from keszybz/fix-commits-from-pr-13246
[thirdparty/systemd.git] / src / test / test-strv.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <string.h>
4
5 #include "alloc-util.h"
6 #include "escape.h"
7 #include "nulstr-util.h"
8 #include "specifier.h"
9 #include "string-util.h"
10 #include "strv.h"
11
12 static void test_specifier_printf(void) {
13 static const Specifier table[] = {
14 { 'a', specifier_string, (char*) "AAAA" },
15 { 'b', specifier_string, (char*) "BBBB" },
16 { 'm', specifier_machine_id, NULL },
17 { 'B', specifier_boot_id, NULL },
18 { 'H', specifier_host_name, NULL },
19 { 'v', specifier_kernel_release, NULL },
20 {}
21 };
22
23 _cleanup_free_ char *w = NULL;
24 int r;
25
26 log_info("/* %s */", __func__);
27
28 r = specifier_printf("xxx a=%a b=%b yyy", table, NULL, &w);
29 assert_se(r >= 0);
30 assert_se(w);
31
32 puts(w);
33 assert_se(streq(w, "xxx a=AAAA b=BBBB yyy"));
34
35 free(w);
36 r = specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table, NULL, &w);
37 assert_se(r >= 0);
38 assert_se(w);
39 puts(w);
40 }
41
42 static void test_str_in_set(void) {
43 log_info("/* %s */", __func__);
44
45 assert_se(STR_IN_SET("x", "x", "y", "z"));
46 assert_se(!STR_IN_SET("X", "x", "y", "z"));
47 assert_se(!STR_IN_SET("", "x", "y", "z"));
48 assert_se(STR_IN_SET("x", "w", "x"));
49 }
50
51 static void test_strptr_in_set(void) {
52 log_info("/* %s */", __func__);
53
54 assert_se(STRPTR_IN_SET("x", "x", "y", "z"));
55 assert_se(!STRPTR_IN_SET("X", "x", "y", "z"));
56 assert_se(!STRPTR_IN_SET("", "x", "y", "z"));
57 assert_se(STRPTR_IN_SET("x", "w", "x"));
58
59 assert_se(!STRPTR_IN_SET(NULL, "x", "y", "z"));
60 assert_se(!STRPTR_IN_SET(NULL, ""));
61 /* strv cannot contain a null, hence the result below */
62 assert_se(!STRPTR_IN_SET(NULL, NULL));
63 }
64
65 static void test_startswith_set(void) {
66 log_info("/* %s */", __func__);
67
68 assert_se(!STARTSWITH_SET("foo", "bar", "baz", "waldo"));
69 assert_se(!STARTSWITH_SET("foo", "bar"));
70
71 assert_se(STARTSWITH_SET("abc", "a", "ab", "abc"));
72 assert_se(STARTSWITH_SET("abc", "ax", "ab", "abc"));
73 assert_se(STARTSWITH_SET("abc", "ax", "abx", "abc"));
74 assert_se(!STARTSWITH_SET("abc", "ax", "abx", "abcx"));
75
76 assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "foo", "zzz"), "bar"));
77 assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "", "zzz"), "foobar"));
78 assert_se(streq_ptr(STARTSWITH_SET("", "hhh", "kkk", "zzz", ""), ""));
79 }
80
81 static const char* const input_table_multiple[] = {
82 "one",
83 "two",
84 "three",
85 NULL,
86 };
87
88 static const char* const input_table_quoted[] = {
89 "one",
90 " two\t three ",
91 " four five",
92 NULL,
93 };
94
95 static const char* const input_table_one[] = {
96 "one",
97 NULL,
98 };
99
100 static const char* const input_table_none[] = {
101 NULL,
102 };
103
104 static const char* const input_table_two_empties[] = {
105 "",
106 "",
107 NULL,
108 };
109
110 static const char* const input_table_one_empty[] = {
111 "",
112 NULL,
113 };
114
115 static void test_strv_find(void) {
116 log_info("/* %s */", __func__);
117
118 assert_se(strv_find((char **)input_table_multiple, "three"));
119 assert_se(!strv_find((char **)input_table_multiple, "four"));
120 }
121
122 static void test_strv_find_prefix(void) {
123 log_info("/* %s */", __func__);
124
125 assert_se(strv_find_prefix((char **)input_table_multiple, "o"));
126 assert_se(strv_find_prefix((char **)input_table_multiple, "one"));
127 assert_se(strv_find_prefix((char **)input_table_multiple, ""));
128 assert_se(!strv_find_prefix((char **)input_table_multiple, "xxx"));
129 assert_se(!strv_find_prefix((char **)input_table_multiple, "onee"));
130 }
131
132 static void test_strv_find_startswith(void) {
133 char *r;
134
135 log_info("/* %s */", __func__);
136
137 r = strv_find_startswith((char **)input_table_multiple, "o");
138 assert_se(r && streq(r, "ne"));
139
140 r = strv_find_startswith((char **)input_table_multiple, "one");
141 assert_se(r && streq(r, ""));
142
143 r = strv_find_startswith((char **)input_table_multiple, "");
144 assert_se(r && streq(r, "one"));
145
146 assert_se(!strv_find_startswith((char **)input_table_multiple, "xxx"));
147 assert_se(!strv_find_startswith((char **)input_table_multiple, "onee"));
148 }
149
150 static void test_strv_join(void) {
151 _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL;
152
153 log_info("/* %s */", __func__);
154
155 p = strv_join((char **)input_table_multiple, ", ");
156 assert_se(p);
157 assert_se(streq(p, "one, two, three"));
158
159 q = strv_join((char **)input_table_multiple, ";");
160 assert_se(q);
161 assert_se(streq(q, "one;two;three"));
162
163 r = strv_join((char **)input_table_multiple, NULL);
164 assert_se(r);
165 assert_se(streq(r, "one two three"));
166
167 s = strv_join((char **)input_table_one, ", ");
168 assert_se(s);
169 assert_se(streq(s, "one"));
170
171 t = strv_join((char **)input_table_none, ", ");
172 assert_se(t);
173 assert_se(streq(t, ""));
174
175 v = strv_join((char **)input_table_two_empties, ", ");
176 assert_se(v);
177 assert_se(streq(v, ", "));
178
179 w = strv_join((char **)input_table_one_empty, ", ");
180 assert_se(w);
181 assert_se(streq(w, ""));
182 }
183
184 static void test_strv_join_prefix(void) {
185 _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL;
186
187 log_info("/* %s */", __func__);
188
189 p = strv_join_prefix((char **)input_table_multiple, ", ", "foo");
190 assert_se(p);
191 assert_se(streq(p, "fooone, footwo, foothree"));
192
193 q = strv_join_prefix((char **)input_table_multiple, ";", "foo");
194 assert_se(q);
195 assert_se(streq(q, "fooone;footwo;foothree"));
196
197 r = strv_join_prefix((char **)input_table_multiple, NULL, "foo");
198 assert_se(r);
199 assert_se(streq(r, "fooone footwo foothree"));
200
201 s = strv_join_prefix((char **)input_table_one, ", ", "foo");
202 assert_se(s);
203 assert_se(streq(s, "fooone"));
204
205 t = strv_join_prefix((char **)input_table_none, ", ", "foo");
206 assert_se(t);
207 assert_se(streq(t, ""));
208
209 v = strv_join_prefix((char **)input_table_two_empties, ", ", "foo");
210 assert_se(v);
211 assert_se(streq(v, "foo, foo"));
212
213 w = strv_join_prefix((char **)input_table_one_empty, ", ", "foo");
214 assert_se(w);
215 assert_se(streq(w, "foo"));
216 }
217
218 static void test_strv_unquote(const char *quoted, char **list) {
219 _cleanup_strv_free_ char **s;
220 _cleanup_free_ char *j;
221 unsigned i = 0;
222 char **t;
223 int r;
224
225 log_info("/* %s */", __func__);
226
227 r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE);
228 assert_se(r == (int) strv_length(list));
229 assert_se(s);
230 j = strv_join(s, " | ");
231 assert_se(j);
232 puts(j);
233
234 STRV_FOREACH(t, s)
235 assert_se(streq(list[i++], *t));
236
237 assert_se(list[i] == NULL);
238 }
239
240 static void test_invalid_unquote(const char *quoted) {
241 char **s = NULL;
242 int r;
243
244 log_info("/* %s */", __func__);
245
246 r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE);
247 assert_se(s == NULL);
248 assert_se(r == -EINVAL);
249 }
250
251 static void test_strv_split(void) {
252 _cleanup_(strv_free_erasep) char **l = NULL;
253 const char str[] = "one,two,three";
254
255 log_info("/* %s */", __func__);
256
257 l = strv_split(str, ",");
258 assert_se(l);
259 assert_se(strv_equal(l, (char**) input_table_multiple));
260
261 strv_free_erase(l);
262
263 l = strv_split(" one two\t three", WHITESPACE);
264 assert_se(l);
265 assert_se(strv_equal(l, (char**) input_table_multiple));
266
267 strv_free_erase(l);
268
269 /* Setting NULL for separator is equivalent to WHITESPACE */
270 l = strv_split(" one two\t three", NULL);
271 assert_se(l);
272 assert_se(strv_equal(l, (char**) input_table_multiple));
273
274 strv_free_erase(l);
275
276 l = strv_split_full(" one two\t three", NULL, 0);
277 assert_se(l);
278 assert_se(strv_equal(l, (char**) input_table_multiple));
279
280 strv_free_erase(l);
281
282 l = strv_split_full(" 'one' \" two\t three \" ' four five'", NULL, SPLIT_QUOTES);
283 assert_se(l);
284 assert_se(strv_equal(l, (char**) input_table_quoted));
285
286 strv_free_erase(l);
287
288 /* missing last quote ignores the last element. */
289 l = strv_split_full(" 'one' \" two\t three \" ' four five' ' ignored element ", NULL, SPLIT_QUOTES);
290 assert_se(l);
291 assert_se(strv_equal(l, (char**) input_table_quoted));
292
293 strv_free_erase(l);
294
295 /* missing last quote, but the last element is _not_ ignored with SPLIT_RELAX. */
296 l = strv_split_full(" 'one' \" two\t three \" ' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
297 assert_se(l);
298 assert_se(strv_equal(l, (char**) input_table_quoted));
299
300 strv_free_erase(l);
301
302 /* missing separator between */
303 l = strv_split_full(" 'one' \" two\t three \"' four five'", NULL, SPLIT_QUOTES | SPLIT_RELAX);
304 assert_se(l);
305 assert_se(strv_equal(l, (char**) input_table_quoted));
306
307 strv_free_erase(l);
308
309 l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX);
310 assert_se(l);
311 assert_se(strv_equal(l, (char**) input_table_quoted));
312 }
313
314 static void test_strv_split_empty(void) {
315 _cleanup_strv_free_ char **l = NULL;
316
317 log_info("/* %s */", __func__);
318
319 l = strv_split("", WHITESPACE);
320 assert_se(l);
321 assert_se(strv_isempty(l));
322
323 strv_free(l);
324 l = strv_split("", NULL);
325 assert_se(l);
326 assert_se(strv_isempty(l));
327
328 strv_free(l);
329 l = strv_split_full("", NULL, 0);
330 assert_se(l);
331 assert_se(strv_isempty(l));
332
333 strv_free(l);
334 l = strv_split_full("", NULL, SPLIT_QUOTES);
335 assert_se(l);
336 assert_se(strv_isempty(l));
337
338 strv_free(l);
339 l = strv_split_full("", WHITESPACE, SPLIT_QUOTES);
340 assert_se(l);
341 assert_se(strv_isempty(l));
342
343 strv_free(l);
344 l = strv_split_full("", WHITESPACE, SPLIT_QUOTES | SPLIT_RELAX);
345 assert_se(l);
346 assert_se(strv_isempty(l));
347
348 strv_free(l);
349 l = strv_split(" ", WHITESPACE);
350 assert_se(l);
351 assert_se(strv_isempty(l));
352
353 strv_free(l);
354 l = strv_split(" ", NULL);
355 assert_se(l);
356 assert_se(strv_isempty(l));
357
358 strv_free(l);
359 l = strv_split_full(" ", NULL, 0);
360 assert_se(l);
361 assert_se(strv_isempty(l));
362
363 strv_free(l);
364 l = strv_split_full(" ", WHITESPACE, SPLIT_QUOTES);
365 assert_se(l);
366 assert_se(strv_isempty(l));
367
368 strv_free(l);
369 l = strv_split_full(" ", NULL, SPLIT_QUOTES);
370 assert_se(l);
371 assert_se(strv_isempty(l));
372
373 strv_free(l);
374 l = strv_split_full(" ", NULL, SPLIT_QUOTES | SPLIT_RELAX);
375 assert_se(l);
376 assert_se(strv_isempty(l));
377 }
378
379 static void test_strv_split_extract(void) {
380 _cleanup_strv_free_ char **l = NULL;
381 const char *str = ":foo\\:bar::waldo:";
382 int r;
383
384 log_info("/* %s */", __func__);
385
386 r = strv_split_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
387 assert_se(r == (int) strv_length(l));
388 assert_se(streq_ptr(l[0], ""));
389 assert_se(streq_ptr(l[1], "foo:bar"));
390 assert_se(streq_ptr(l[2], ""));
391 assert_se(streq_ptr(l[3], "waldo"));
392 assert_se(streq_ptr(l[4], ""));
393 assert_se(streq_ptr(l[5], NULL));
394 }
395
396 static void test_strv_split_newlines(void) {
397 unsigned i = 0;
398 char **s;
399 _cleanup_strv_free_ char **l = NULL;
400 const char str[] = "one\ntwo\nthree";
401
402 log_info("/* %s */", __func__);
403
404 l = strv_split_newlines(str);
405 assert_se(l);
406
407 STRV_FOREACH(s, l) {
408 assert_se(streq(*s, input_table_multiple[i++]));
409 }
410 }
411
412 static void test_strv_split_nulstr(void) {
413 _cleanup_strv_free_ char **l = NULL;
414 const char nulstr[] = "str0\0str1\0str2\0str3\0";
415
416 log_info("/* %s */", __func__);
417
418 l = strv_split_nulstr (nulstr);
419 assert_se(l);
420
421 assert_se(streq(l[0], "str0"));
422 assert_se(streq(l[1], "str1"));
423 assert_se(streq(l[2], "str2"));
424 assert_se(streq(l[3], "str3"));
425 }
426
427 static void test_strv_parse_nulstr(void) {
428 _cleanup_strv_free_ char **l = NULL;
429 const char nulstr[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx";
430
431 log_info("/* %s */", __func__);
432
433 l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1);
434 assert_se(l);
435 puts("Parse nulstr:");
436 strv_print(l);
437
438 assert_se(streq(l[0], "hoge"));
439 assert_se(streq(l[1], "hoge2"));
440 assert_se(streq(l[2], "hoge3"));
441 assert_se(streq(l[3], ""));
442 assert_se(streq(l[4], "hoge5"));
443 assert_se(streq(l[5], ""));
444 assert_se(streq(l[6], "xxx"));
445 }
446
447 static void test_strv_overlap(void) {
448 const char * const input_table[] = {
449 "one",
450 "two",
451 "three",
452 NULL
453 };
454 const char * const input_table_overlap[] = {
455 "two",
456 NULL
457 };
458 const char * const input_table_unique[] = {
459 "four",
460 "five",
461 "six",
462 NULL
463 };
464
465 log_info("/* %s */", __func__);
466
467 assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap));
468 assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique));
469 }
470
471 static void test_strv_sort(void) {
472 const char* input_table[] = {
473 "durian",
474 "apple",
475 "citrus",
476 "CAPITAL LETTERS FIRST",
477 "banana",
478 NULL
479 };
480
481 log_info("/* %s */", __func__);
482
483 strv_sort((char **)input_table);
484
485 assert_se(streq(input_table[0], "CAPITAL LETTERS FIRST"));
486 assert_se(streq(input_table[1], "apple"));
487 assert_se(streq(input_table[2], "banana"));
488 assert_se(streq(input_table[3], "citrus"));
489 assert_se(streq(input_table[4], "durian"));
490 }
491
492 static void test_strv_extend_strv_concat(void) {
493 _cleanup_strv_free_ char **a = NULL, **b = NULL;
494
495 log_info("/* %s */", __func__);
496
497 a = strv_new("without", "suffix");
498 b = strv_new("with", "suffix");
499 assert_se(a);
500 assert_se(b);
501
502 assert_se(strv_extend_strv_concat(&a, b, "_suffix") >= 0);
503
504 assert_se(streq(a[0], "without"));
505 assert_se(streq(a[1], "suffix"));
506 assert_se(streq(a[2], "with_suffix"));
507 assert_se(streq(a[3], "suffix_suffix"));
508 }
509
510 static void test_strv_extend_strv(void) {
511 _cleanup_strv_free_ char **a = NULL, **b = NULL, **n = NULL;
512
513 log_info("/* %s */", __func__);
514
515 a = strv_new("abc", "def", "ghi");
516 b = strv_new("jkl", "mno", "abc", "pqr");
517 assert_se(a);
518 assert_se(b);
519
520 assert_se(strv_extend_strv(&a, b, true) == 3);
521
522 assert_se(streq(a[0], "abc"));
523 assert_se(streq(a[1], "def"));
524 assert_se(streq(a[2], "ghi"));
525 assert_se(streq(a[3], "jkl"));
526 assert_se(streq(a[4], "mno"));
527 assert_se(streq(a[5], "pqr"));
528 assert_se(strv_length(a) == 6);
529
530 assert_se(strv_extend_strv(&n, b, false) >= 0);
531 assert_se(streq(n[0], "jkl"));
532 assert_se(streq(n[1], "mno"));
533 assert_se(streq(n[2], "abc"));
534 assert_se(streq(n[3], "pqr"));
535 assert_se(strv_length(n) == 4);
536 }
537
538 static void test_strv_extend(void) {
539 _cleanup_strv_free_ char **a = NULL, **b = NULL;
540
541 log_info("/* %s */", __func__);
542
543 a = strv_new("test", "test1");
544 assert_se(a);
545 assert_se(strv_extend(&a, "test2") >= 0);
546 assert_se(strv_extend(&b, "test3") >= 0);
547
548 assert_se(streq(a[0], "test"));
549 assert_se(streq(a[1], "test1"));
550 assert_se(streq(a[2], "test2"));
551 assert_se(streq(b[0], "test3"));
552 }
553
554 static void test_strv_extendf(void) {
555 _cleanup_strv_free_ char **a = NULL, **b = NULL;
556
557 log_info("/* %s */", __func__);
558
559 a = strv_new("test", "test1");
560 assert_se(a);
561 assert_se(strv_extendf(&a, "test2 %s %d %s", "foo", 128, "bar") >= 0);
562 assert_se(strv_extendf(&b, "test3 %s %s %d", "bar", "foo", 128) >= 0);
563
564 assert_se(streq(a[0], "test"));
565 assert_se(streq(a[1], "test1"));
566 assert_se(streq(a[2], "test2 foo 128 bar"));
567 assert_se(streq(b[0], "test3 bar foo 128"));
568 }
569
570 static void test_strv_foreach(void) {
571 _cleanup_strv_free_ char **a;
572 unsigned i = 0;
573 char **check;
574
575 log_info("/* %s */", __func__);
576
577 a = strv_new("one", "two", "three");
578 assert_se(a);
579
580 STRV_FOREACH(check, a)
581 assert_se(streq(*check, input_table_multiple[i++]));
582 }
583
584 static void test_strv_foreach_backwards(void) {
585 _cleanup_strv_free_ char **a;
586 unsigned i = 2;
587 char **check;
588
589 log_info("/* %s */", __func__);
590
591 a = strv_new("one", "two", "three");
592
593 assert_se(a);
594
595 STRV_FOREACH_BACKWARDS(check, a)
596 assert_se(streq_ptr(*check, input_table_multiple[i--]));
597
598 STRV_FOREACH_BACKWARDS(check, (char**) NULL)
599 assert_not_reached("Let's see that we check empty strv right, too.");
600
601 STRV_FOREACH_BACKWARDS(check, (char**) { NULL })
602 assert_not_reached("Let's see that we check empty strv right, too.");
603 }
604
605 static void test_strv_foreach_pair(void) {
606 _cleanup_strv_free_ char **a = NULL;
607 char **x, **y;
608
609 log_info("/* %s */", __func__);
610
611 a = strv_new("pair_one", "pair_one",
612 "pair_two", "pair_two",
613 "pair_three", "pair_three");
614 STRV_FOREACH_PAIR(x, y, a)
615 assert_se(streq(*x, *y));
616 }
617
618 static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) {
619 char **j;
620 unsigned i;
621
622 log_info("/* %s */", __func__);
623
624 j = strv_from_stdarg_alloca(first);
625
626 for (i = 0;; i++) {
627 assert_se(streq_ptr(l[i], j[i]));
628
629 if (!l[i])
630 break;
631 }
632 }
633
634 static void test_strv_from_stdarg_alloca(void) {
635 log_info("/* %s */", __func__);
636
637 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL);
638 test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL);
639 test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY, NULL);
640 }
641
642 static void test_strv_insert(void) {
643 _cleanup_strv_free_ char **a = NULL;
644
645 log_info("/* %s */", __func__);
646
647 assert_se(strv_insert(&a, 0, strdup("first")) == 0);
648 assert_se(streq(a[0], "first"));
649 assert_se(!a[1]);
650
651 assert_se(strv_insert(&a, 0, NULL) == 0);
652 assert_se(streq(a[0], "first"));
653 assert_se(!a[1]);
654
655 assert_se(strv_insert(&a, 1, strdup("two")) == 0);
656 assert_se(streq(a[0], "first"));
657 assert_se(streq(a[1], "two"));
658 assert_se(!a[2]);
659
660 assert_se(strv_insert(&a, 4, strdup("tri")) == 0);
661 assert_se(streq(a[0], "first"));
662 assert_se(streq(a[1], "two"));
663 assert_se(streq(a[2], "tri"));
664 assert_se(!a[3]);
665
666 assert_se(strv_insert(&a, 1, strdup("duo")) == 0);
667 assert_se(streq(a[0], "first"));
668 assert_se(streq(a[1], "duo"));
669 assert_se(streq(a[2], "two"));
670 assert_se(streq(a[3], "tri"));
671 assert_se(!a[4]);
672 }
673
674 static void test_strv_push_prepend(void) {
675 _cleanup_strv_free_ char **a = NULL;
676
677 log_info("/* %s */", __func__);
678
679 a = strv_new("foo", "bar", "three");
680
681 assert_se(strv_push_prepend(&a, strdup("first")) >= 0);
682 assert_se(streq(a[0], "first"));
683 assert_se(streq(a[1], "foo"));
684 assert_se(streq(a[2], "bar"));
685 assert_se(streq(a[3], "three"));
686 assert_se(!a[4]);
687
688 assert_se(strv_consume_prepend(&a, strdup("first2")) >= 0);
689 assert_se(streq(a[0], "first2"));
690 assert_se(streq(a[1], "first"));
691 assert_se(streq(a[2], "foo"));
692 assert_se(streq(a[3], "bar"));
693 assert_se(streq(a[4], "three"));
694 assert_se(!a[5]);
695 }
696
697 static void test_strv_push(void) {
698 _cleanup_strv_free_ char **a = NULL;
699 char *i, *j;
700
701 log_info("/* %s */", __func__);
702
703 assert_se(i = strdup("foo"));
704 assert_se(strv_push(&a, i) >= 0);
705
706 assert_se(i = strdup("a"));
707 assert_se(j = strdup("b"));
708 assert_se(strv_push_pair(&a, i, j) >= 0);
709
710 assert_se(streq_ptr(a[0], "foo"));
711 assert_se(streq_ptr(a[1], "a"));
712 assert_se(streq_ptr(a[2], "b"));
713 assert_se(streq_ptr(a[3], NULL));
714 }
715
716 static void test_strv_equal(void) {
717 _cleanup_strv_free_ char **a = NULL;
718 _cleanup_strv_free_ char **b = NULL;
719 _cleanup_strv_free_ char **c = NULL;
720
721 log_info("/* %s */", __func__);
722
723 a = strv_new("one", "two", "three");
724 assert_se(a);
725 b = strv_new("one", "two", "three");
726 assert_se(a);
727 c = strv_new("one", "two", "three", "four");
728 assert_se(a);
729
730 assert_se(strv_equal(a, a));
731 assert_se(strv_equal(a, b));
732 assert_se(strv_equal(NULL, NULL));
733
734 assert_se(!strv_equal(a, c));
735 assert_se(!strv_equal(b, c));
736 assert_se(!strv_equal(b, NULL));
737 }
738
739 static void test_strv_is_uniq(void) {
740 _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
741
742 log_info("/* %s */", __func__);
743
744 a = strv_new(NULL);
745 assert_se(a);
746 assert_se(strv_is_uniq(a));
747
748 b = strv_new("foo");
749 assert_se(b);
750 assert_se(strv_is_uniq(b));
751
752 c = strv_new("foo", "bar");
753 assert_se(c);
754 assert_se(strv_is_uniq(c));
755
756 d = strv_new("foo", "bar", "waldo", "bar", "piep");
757 assert_se(d);
758 assert_se(!strv_is_uniq(d));
759 }
760
761 static void test_strv_reverse(void) {
762 _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL;
763
764 log_info("/* %s */", __func__);
765
766 a = strv_new(NULL);
767 assert_se(a);
768
769 strv_reverse(a);
770 assert_se(strv_isempty(a));
771
772 b = strv_new("foo");
773 assert_se(b);
774 strv_reverse(b);
775 assert_se(streq_ptr(b[0], "foo"));
776 assert_se(streq_ptr(b[1], NULL));
777
778 c = strv_new("foo", "bar");
779 assert_se(c);
780 strv_reverse(c);
781 assert_se(streq_ptr(c[0], "bar"));
782 assert_se(streq_ptr(c[1], "foo"));
783 assert_se(streq_ptr(c[2], NULL));
784
785 d = strv_new("foo", "bar", "waldo");
786 assert_se(d);
787 strv_reverse(d);
788 assert_se(streq_ptr(d[0], "waldo"));
789 assert_se(streq_ptr(d[1], "bar"));
790 assert_se(streq_ptr(d[2], "foo"));
791 assert_se(streq_ptr(d[3], NULL));
792 }
793
794 static void test_strv_shell_escape(void) {
795 _cleanup_strv_free_ char **v = NULL;
796
797 log_info("/* %s */", __func__);
798
799 v = strv_new("foo:bar", "bar,baz", "wal\\do");
800 assert_se(v);
801 assert_se(strv_shell_escape(v, ",:"));
802 assert_se(streq_ptr(v[0], "foo\\:bar"));
803 assert_se(streq_ptr(v[1], "bar\\,baz"));
804 assert_se(streq_ptr(v[2], "wal\\\\do"));
805 assert_se(streq_ptr(v[3], NULL));
806 }
807
808 static void test_strv_skip_one(char **a, size_t n, char **b) {
809 a = strv_skip(a, n);
810 assert_se(strv_equal(a, b));
811 }
812
813 static void test_strv_skip(void) {
814 log_info("/* %s */", __func__);
815
816 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz"));
817 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz"));
818 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz"));
819 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 3, STRV_MAKE(NULL));
820 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 4, STRV_MAKE(NULL));
821 test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 55, STRV_MAKE(NULL));
822
823 test_strv_skip_one(STRV_MAKE("quux"), 0, STRV_MAKE("quux"));
824 test_strv_skip_one(STRV_MAKE("quux"), 1, STRV_MAKE(NULL));
825 test_strv_skip_one(STRV_MAKE("quux"), 55, STRV_MAKE(NULL));
826
827 test_strv_skip_one(STRV_MAKE(NULL), 0, STRV_MAKE(NULL));
828 test_strv_skip_one(STRV_MAKE(NULL), 1, STRV_MAKE(NULL));
829 test_strv_skip_one(STRV_MAKE(NULL), 55, STRV_MAKE(NULL));
830 }
831
832 static void test_strv_extend_n(void) {
833 _cleanup_strv_free_ char **v = NULL;
834
835 log_info("/* %s */", __func__);
836
837 v = strv_new("foo", "bar");
838 assert_se(v);
839
840 assert_se(strv_extend_n(&v, "waldo", 3) >= 0);
841 assert_se(strv_extend_n(&v, "piep", 2) >= 0);
842
843 assert_se(streq(v[0], "foo"));
844 assert_se(streq(v[1], "bar"));
845 assert_se(streq(v[2], "waldo"));
846 assert_se(streq(v[3], "waldo"));
847 assert_se(streq(v[4], "waldo"));
848 assert_se(streq(v[5], "piep"));
849 assert_se(streq(v[6], "piep"));
850 assert_se(v[7] == NULL);
851
852 v = strv_free(v);
853
854 assert_se(strv_extend_n(&v, "foo", 1) >= 0);
855 assert_se(strv_extend_n(&v, "bar", 0) >= 0);
856
857 assert_se(streq(v[0], "foo"));
858 assert_se(v[1] == NULL);
859 }
860
861 static void test_strv_make_nulstr_one(char **l) {
862 _cleanup_free_ char *b = NULL, *c = NULL;
863 _cleanup_strv_free_ char **q = NULL;
864 const char *s = NULL;
865 size_t n, m;
866 unsigned i = 0;
867
868 log_info("/* %s */", __func__);
869
870 assert_se(strv_make_nulstr(l, &b, &n) >= 0);
871 assert_se(q = strv_parse_nulstr(b, n));
872 assert_se(strv_equal(l, q));
873
874 assert_se(strv_make_nulstr(q, &c, &m) >= 0);
875 assert_se(m == n);
876 assert_se(memcmp(b, c, m) == 0);
877
878 NULSTR_FOREACH(s, b)
879 assert_se(streq(s, l[i++]));
880 assert_se(i == strv_length(l));
881 }
882
883 static void test_strv_make_nulstr(void) {
884 log_info("/* %s */", __func__);
885
886 test_strv_make_nulstr_one(NULL);
887 test_strv_make_nulstr_one(STRV_MAKE(NULL));
888 test_strv_make_nulstr_one(STRV_MAKE("foo"));
889 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar"));
890 test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux"));
891 }
892
893 static void test_strv_free_free(void) {
894 char ***t;
895
896 log_info("/* %s */", __func__);
897
898 assert_se(t = new(char**, 3));
899 assert_se(t[0] = strv_new("a", "b"));
900 assert_se(t[1] = strv_new("c", "d", "e"));
901 t[2] = NULL;
902
903 t = strv_free_free(t);
904 }
905
906 static void test_foreach_string(void) {
907 const char * const t[] = {
908 "foo",
909 "bar",
910 "waldo",
911 NULL
912 };
913 const char *x;
914 unsigned i = 0;
915
916 log_info("/* %s */", __func__);
917
918 FOREACH_STRING(x, "foo", "bar", "waldo")
919 assert_se(streq_ptr(t[i++], x));
920
921 assert_se(i == 3);
922
923 FOREACH_STRING(x, "zzz")
924 assert_se(streq(x, "zzz"));
925 }
926
927 static void test_strv_fnmatch(void) {
928 _cleanup_strv_free_ char **v = NULL;
929
930 log_info("/* %s */", __func__);
931
932 assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a", 0));
933
934 v = strv_new("*\\*");
935 assert_se(!strv_fnmatch(v, "\\", 0));
936 assert_se(strv_fnmatch(v, "\\", FNM_NOESCAPE));
937 }
938
939 int main(int argc, char *argv[]) {
940 test_specifier_printf();
941 test_str_in_set();
942 test_strptr_in_set();
943 test_startswith_set();
944 test_strv_foreach();
945 test_strv_foreach_backwards();
946 test_strv_foreach_pair();
947 test_strv_find();
948 test_strv_find_prefix();
949 test_strv_find_startswith();
950 test_strv_join();
951 test_strv_join_prefix();
952
953 test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz"));
954 test_strv_unquote("", STRV_MAKE_EMPTY);
955 test_strv_unquote(" ", STRV_MAKE_EMPTY);
956 test_strv_unquote(" ", STRV_MAKE_EMPTY);
957 test_strv_unquote(" x", STRV_MAKE("x"));
958 test_strv_unquote("x ", STRV_MAKE("x"));
959 test_strv_unquote(" x ", STRV_MAKE("x"));
960 test_strv_unquote(" \"x\" ", STRV_MAKE("x"));
961 test_strv_unquote(" 'x' ", STRV_MAKE("x"));
962 test_strv_unquote(" 'x\"' ", STRV_MAKE("x\""));
963 test_strv_unquote(" \"x'\" ", STRV_MAKE("x'"));
964 test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\""));
965
966 /* trailing backslashes */
967 test_strv_unquote(" x\\\\", STRV_MAKE("x\\"));
968 test_invalid_unquote(" x\\");
969
970 test_invalid_unquote("a --b='c \"d e\"''");
971 test_invalid_unquote("a --b='c \"d e\" '\"");
972 test_invalid_unquote("a --b='c \"d e\"garbage");
973 test_invalid_unquote("'");
974 test_invalid_unquote("\"");
975 test_invalid_unquote("'x'y'g");
976
977 test_strv_split();
978 test_strv_split_empty();
979 test_strv_split_extract();
980 test_strv_split_newlines();
981 test_strv_split_nulstr();
982 test_strv_parse_nulstr();
983 test_strv_overlap();
984 test_strv_sort();
985 test_strv_extend_strv();
986 test_strv_extend_strv_concat();
987 test_strv_extend();
988 test_strv_extendf();
989 test_strv_from_stdarg_alloca();
990 test_strv_insert();
991 test_strv_push_prepend();
992 test_strv_push();
993 test_strv_equal();
994 test_strv_is_uniq();
995 test_strv_reverse();
996 test_strv_shell_escape();
997 test_strv_skip();
998 test_strv_extend_n();
999 test_strv_make_nulstr();
1000 test_strv_free_free();
1001
1002 test_foreach_string();
1003 test_strv_fnmatch();
1004
1005 return 0;
1006 }