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