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