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