]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
f90cf44c LP |
2 | |
3 | #include <string.h> | |
2c4b304e | 4 | |
b5efdb8a | 5 | #include "alloc-util.h" |
e7b2ea7c | 6 | #include "escape.h" |
d8b4d14d | 7 | #include "nulstr-util.h" |
2c4b304e | 8 | #include "specifier.h" |
07630cea | 9 | #include "string-util.h" |
682cfdff | 10 | #include "strv.h" |
f90cf44c | 11 | |
3a7719d3 | 12 | static void test_specifier_printf(void) { |
1731e34a | 13 | static const Specifier table[] = { |
2c4b304e LP |
14 | { 'a', specifier_string, (char*) "AAAA" }, |
15 | { 'b', specifier_string, (char*) "BBBB" }, | |
19f6d710 LP |
16 | { 'm', specifier_machine_id, NULL }, |
17 | { 'B', specifier_boot_id, NULL }, | |
18 | { 'H', specifier_host_name, NULL }, | |
19 | { 'v', specifier_kernel_release, NULL }, | |
1731e34a | 20 | {} |
2c4b304e LP |
21 | }; |
22 | ||
1731e34a LP |
23 | _cleanup_free_ char *w = NULL; |
24 | int r; | |
25 | ||
19f6d710 LP |
26 | r = specifier_printf("xxx a=%a b=%b yyy", table, NULL, &w); |
27 | assert_se(r >= 0); | |
28 | assert_se(w); | |
29 | ||
9f316366 | 30 | puts(w); |
19f6d710 | 31 | assert_se(streq(w, "xxx a=AAAA b=BBBB yyy")); |
9f316366 | 32 | |
19f6d710 LP |
33 | free(w); |
34 | r = specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table, NULL, &w); | |
35 | assert_se(r >= 0); | |
9f316366 | 36 | assert_se(w); |
19f6d710 | 37 | puts(w); |
3a7719d3 DB |
38 | } |
39 | ||
c7bf9d51 ZJS |
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 | ||
52f15520 LP |
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 | ||
a6fde353 ZJS |
73 | static const char* const input_table_multiple[] = { |
74 | "one", | |
75 | "two", | |
76 | "three", | |
77 | NULL, | |
78 | }; | |
79 | ||
1f938af8 YW |
80 | static const char* const input_table_quoted[] = { |
81 | "one", | |
82 | " two\t three ", | |
83 | " four five", | |
84 | NULL, | |
85 | }; | |
86 | ||
a6fde353 ZJS |
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 | ||
afe773b0 ZJS |
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 | ||
a6fde353 ZJS |
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")); | |
539ad707 TA |
110 | } |
111 | ||
112 | static void test_strv_find_prefix(void) { | |
a6fde353 ZJS |
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")); | |
3a7719d3 | 118 | } |
f90cf44c | 119 | |
7bd57a87 RC |
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 | ||
682cfdff | 136 | static void test_strv_join(void) { |
afe773b0 | 137 | _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL; |
682cfdff | 138 | |
539ad707 | 139 | p = strv_join((char **)input_table_multiple, ", "); |
04045d84 | 140 | assert_se(p); |
7b68d618 | 141 | assert_se(streq(p, "one, two, three")); |
682cfdff | 142 | |
539ad707 | 143 | q = strv_join((char **)input_table_multiple, ";"); |
04045d84 | 144 | assert_se(q); |
7b68d618 | 145 | assert_se(streq(q, "one;two;three")); |
682cfdff DB |
146 | |
147 | r = strv_join((char **)input_table_multiple, NULL); | |
04045d84 | 148 | assert_se(r); |
7b68d618 | 149 | assert_se(streq(r, "one two three")); |
539ad707 TA |
150 | |
151 | s = strv_join((char **)input_table_one, ", "); | |
04045d84 | 152 | assert_se(s); |
7b68d618 | 153 | assert_se(streq(s, "one")); |
539ad707 TA |
154 | |
155 | t = strv_join((char **)input_table_none, ", "); | |
04045d84 | 156 | assert_se(t); |
7b68d618 | 157 | assert_se(streq(t, "")); |
afe773b0 ZJS |
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, "")); | |
682cfdff DB |
166 | } |
167 | ||
474a595a YW |
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 | ||
30bcc052 | 200 | static void test_strv_unquote(const char *quoted, char **list) { |
70f75a52 | 201 | _cleanup_strv_free_ char **s; |
a2a5291b | 202 | _cleanup_free_ char *j; |
70f75a52 LP |
203 | unsigned i = 0; |
204 | char **t; | |
b2fadec6 | 205 | int r; |
70f75a52 | 206 | |
8adaf7bd | 207 | r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES); |
8dd4c05b | 208 | assert_se(r == (int) strv_length(list)); |
70f75a52 | 209 | assert_se(s); |
a2a5291b | 210 | j = strv_join(s, " | "); |
bdf7026e | 211 | assert_se(j); |
a2a5291b | 212 | puts(j); |
70f75a52 LP |
213 | |
214 | STRV_FOREACH(t, s) | |
215 | assert_se(streq(list[i++], *t)); | |
216 | ||
217 | assert_se(list[i] == NULL); | |
218 | } | |
219 | ||
a2a5291b | 220 | static void test_invalid_unquote(const char *quoted) { |
b2fadec6 ZJS |
221 | char **s = NULL; |
222 | int r; | |
a2a5291b | 223 | |
8adaf7bd | 224 | r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_QUOTES); |
bdf7026e TA |
225 | assert_se(s == NULL); |
226 | assert_se(r == -EINVAL); | |
a2a5291b ZJS |
227 | } |
228 | ||
aed2ebfe | 229 | static void test_strv_split(void) { |
aed2ebfe DB |
230 | _cleanup_strv_free_ char **l = NULL; |
231 | const char str[] = "one,two,three"; | |
232 | ||
233 | l = strv_split(str, ","); | |
bdf7026e | 234 | assert_se(l); |
1f938af8 | 235 | assert_se(strv_equal(l, (char**) input_table_multiple)); |
aed2ebfe | 236 | |
0745ce75 YW |
237 | strv_free(l); |
238 | ||
239 | l = strv_split(" one two\t three", WHITESPACE); | |
240 | assert_se(l); | |
1f938af8 YW |
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)); | |
0745ce75 YW |
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 | ||
1f938af8 YW |
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 | ||
0745ce75 YW |
322 | strv_free(l); |
323 | l = strv_split(" ", WHITESPACE); | |
324 | assert_se(l); | |
325 | assert_se(strv_isempty(l)); | |
326 | ||
1f938af8 YW |
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)); | |
aed2ebfe DB |
351 | } |
352 | ||
8adaf7bd RM |
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); | |
8dd4c05b | 359 | assert_se(r == (int) strv_length(l)); |
8adaf7bd RM |
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 | ||
aed2ebfe DB |
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 | ||
bdf7026e | 376 | assert_se(l); |
aed2ebfe DB |
377 | |
378 | STRV_FOREACH(s, l) { | |
379 | assert_se(streq(*s, input_table_multiple[i++])); | |
380 | } | |
381 | } | |
382 | ||
2f213f74 DB |
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); | |
04045d84 | 388 | assert_se(l); |
2f213f74 DB |
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 | ||
10ddd913 TA |
396 | static void test_strv_parse_nulstr(void) { |
397 | _cleanup_strv_free_ char **l = NULL; | |
a2917d3d | 398 | const char nulstr[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx"; |
10ddd913 TA |
399 | |
400 | l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1); | |
04045d84 | 401 | assert_se(l); |
10ddd913 TA |
402 | puts("Parse nulstr:"); |
403 | strv_print(l); | |
404 | ||
a2917d3d YW |
405 | assert_se(streq(l[0], "hoge")); |
406 | assert_se(streq(l[1], "hoge2")); | |
407 | assert_se(streq(l[2], "hoge3")); | |
7b68d618 | 408 | assert_se(streq(l[3], "")); |
a2917d3d | 409 | assert_se(streq(l[4], "hoge5")); |
7b68d618 DB |
410 | assert_se(streq(l[5], "")); |
411 | assert_se(streq(l[6], "xxx")); | |
10ddd913 TA |
412 | } |
413 | ||
539ad707 TA |
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 | ||
7b68d618 DB |
432 | assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap)); |
433 | assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique)); | |
539ad707 TA |
434 | } |
435 | ||
436 | static void test_strv_sort(void) { | |
1e64bbc1 | 437 | const char* input_table[] = { |
539ad707 TA |
438 | "durian", |
439 | "apple", | |
440 | "citrus", | |
441 | "CAPITAL LETTERS FIRST", | |
442 | "banana", | |
443 | NULL | |
444 | }; | |
445 | ||
446 | strv_sort((char **)input_table); | |
447 | ||
7b68d618 DB |
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")); | |
3a7719d3 | 453 | } |
e3aa71c3 | 454 | |
e3e45d4f | 455 | static void test_strv_extend_strv_concat(void) { |
7d6884b6 | 456 | _cleanup_strv_free_ char **a = NULL, **b = NULL; |
343a8969 | 457 | |
bea1a013 LP |
458 | a = strv_new("without", "suffix"); |
459 | b = strv_new("with", "suffix"); | |
04045d84 DB |
460 | assert_se(a); |
461 | assert_se(b); | |
343a8969 | 462 | |
e3e45d4f | 463 | assert_se(strv_extend_strv_concat(&a, b, "_suffix") >= 0); |
343a8969 | 464 | |
e3e45d4f SP |
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")); | |
343a8969 DB |
469 | } |
470 | ||
e3e45d4f | 471 | static void test_strv_extend_strv(void) { |
ea9b54f8 | 472 | _cleanup_strv_free_ char **a = NULL, **b = NULL, **n = NULL; |
a1022300 | 473 | |
bea1a013 LP |
474 | a = strv_new("abc", "def", "ghi"); |
475 | b = strv_new("jkl", "mno", "abc", "pqr"); | |
04045d84 DB |
476 | assert_se(a); |
477 | assert_se(b); | |
a1022300 | 478 | |
e287086b | 479 | assert_se(strv_extend_strv(&a, b, true) == 3); |
a1022300 | 480 | |
e3e45d4f SP |
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")); | |
e3e45d4f | 487 | assert_se(strv_length(a) == 6); |
ea9b54f8 ZJS |
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); | |
a1022300 DB |
495 | } |
496 | ||
e3e45d4f SP |
497 | static void test_strv_extend(void) { |
498 | _cleanup_strv_free_ char **a = NULL, **b = NULL; | |
40857008 | 499 | |
bea1a013 | 500 | a = strv_new("test", "test1"); |
04045d84 | 501 | assert_se(a); |
e3e45d4f SP |
502 | assert_se(strv_extend(&a, "test2") >= 0); |
503 | assert_se(strv_extend(&b, "test3") >= 0); | |
40857008 | 504 | |
e3e45d4f SP |
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")); | |
40857008 DB |
509 | } |
510 | ||
4a336a69 RC |
511 | static void test_strv_extendf(void) { |
512 | _cleanup_strv_free_ char **a = NULL, **b = NULL; | |
513 | ||
bea1a013 | 514 | a = strv_new("test", "test1"); |
4a336a69 RC |
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 | ||
02f19706 | 525 | static void test_strv_foreach(void) { |
250a918d LP |
526 | _cleanup_strv_free_ char **a; |
527 | unsigned i = 0; | |
528 | char **check; | |
02f19706 | 529 | |
bea1a013 | 530 | a = strv_new("one", "two", "three"); |
02f19706 | 531 | |
250a918d | 532 | assert_se(a); |
02f19706 | 533 | |
250a918d LP |
534 | STRV_FOREACH(check, a) { |
535 | assert_se(streq(*check, input_table_multiple[i++])); | |
536 | } | |
02f19706 DB |
537 | } |
538 | ||
539 | static void test_strv_foreach_backwards(void) { | |
250a918d LP |
540 | _cleanup_strv_free_ char **a; |
541 | unsigned i = 2; | |
542 | char **check; | |
02f19706 | 543 | |
bea1a013 | 544 | a = strv_new("one", "two", "three"); |
02f19706 | 545 | |
250a918d | 546 | assert_se(a); |
02f19706 | 547 | |
4a39c774 | 548 | STRV_FOREACH_BACKWARDS(check, a) |
5fba7bbf | 549 | assert_se(streq_ptr(*check, input_table_multiple[i--])); |
4a39c774 LP |
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."); | |
02f19706 DB |
556 | } |
557 | ||
4c325b2e DB |
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", | |
bea1a013 | 564 | "pair_three", "pair_three"); |
4c325b2e DB |
565 | |
566 | STRV_FOREACH_PAIR(x, y, a) { | |
567 | assert_se(streq(*x, *y)); | |
568 | } | |
569 | } | |
570 | ||
897e7561 | 571 | static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) { |
250a918d LP |
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) { | |
897e7561 LP |
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); | |
250a918d LP |
589 | } |
590 | ||
6e888894 ZJS |
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 | ||
7bd57a87 RC |
621 | static void test_strv_push_prepend(void) { |
622 | _cleanup_strv_free_ char **a = NULL; | |
623 | ||
bea1a013 | 624 | a = strv_new("foo", "bar", "three"); |
7bd57a87 RC |
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 | ||
98940a3c LP |
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 | ||
e74aa253 RC |
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 | ||
bea1a013 | 664 | a = strv_new("one", "two", "three"); |
e74aa253 | 665 | assert_se(a); |
bea1a013 | 666 | b = strv_new("one", "two", "three"); |
e74aa253 | 667 | assert_se(a); |
bea1a013 | 668 | c = strv_new("one", "two", "three", "four"); |
e74aa253 RC |
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 | ||
e1dd6790 LP |
680 | static void test_strv_is_uniq(void) { |
681 | _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; | |
682 | ||
bea1a013 | 683 | a = strv_new(NULL); |
e1dd6790 LP |
684 | assert_se(a); |
685 | assert_se(strv_is_uniq(a)); | |
686 | ||
bea1a013 | 687 | b = strv_new("foo"); |
e1dd6790 LP |
688 | assert_se(b); |
689 | assert_se(strv_is_uniq(b)); | |
690 | ||
bea1a013 | 691 | c = strv_new("foo", "bar"); |
e1dd6790 LP |
692 | assert_se(c); |
693 | assert_se(strv_is_uniq(c)); | |
694 | ||
bea1a013 | 695 | d = strv_new("foo", "bar", "waldo", "bar", "piep"); |
e1dd6790 LP |
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 | ||
bea1a013 | 703 | a = strv_new(NULL); |
e1dd6790 LP |
704 | assert_se(a); |
705 | ||
706 | strv_reverse(a); | |
707 | assert_se(strv_isempty(a)); | |
708 | ||
bea1a013 | 709 | b = strv_new("foo"); |
e1dd6790 LP |
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 | ||
bea1a013 | 715 | c = strv_new("foo", "bar"); |
e1dd6790 LP |
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 | ||
bea1a013 | 722 | d = strv_new("foo", "bar", "waldo"); |
e1dd6790 LP |
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 | ||
04c14b25 RM |
731 | static void test_strv_shell_escape(void) { |
732 | _cleanup_strv_free_ char **v = NULL; | |
733 | ||
bea1a013 | 734 | v = strv_new("foo:bar", "bar,baz", "wal\\do"); |
04c14b25 RM |
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 | ||
e3ead6bb LP |
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 | ||
8dd4c05b LP |
765 | static void test_strv_extend_n(void) { |
766 | _cleanup_strv_free_ char **v = NULL; | |
767 | ||
bea1a013 | 768 | v = strv_new("foo", "bar"); |
8dd4c05b LP |
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 | ||
e287086b LP |
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; | |
f41794d0 | 795 | const char *s = NULL; |
e287086b | 796 | size_t n, m; |
f41794d0 | 797 | unsigned i = 0; |
e287086b LP |
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); | |
f41794d0 | 806 | |
b60df13b | 807 | NULSTR_FOREACH(s, b) |
f41794d0 | 808 | assert_se(streq(s, l[i++])); |
f41794d0 | 809 | assert_se(i == strv_length(l)); |
e287086b LP |
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 | ||
bff8f950 ZJS |
820 | static void test_strv_free_free(void) { |
821 | char ***t; | |
822 | ||
823 | assert_se(t = new(char**, 3)); | |
bea1a013 LP |
824 | assert_se(t[0] = strv_new("a", "b")); |
825 | assert_se(t[1] = strv_new("c", "d", "e")); | |
bff8f950 ZJS |
826 | t[2] = NULL; |
827 | ||
828 | t = strv_free_free(t); | |
829 | } | |
830 | ||
ebde5cb2 RC |
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 | ||
2027927b | 850 | static void test_strv_fnmatch(void) { |
57681e84 | 851 | _cleanup_strv_free_ char **v = NULL; |
2027927b EV |
852 | |
853 | assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a", 0)); | |
854 | ||
bea1a013 | 855 | v = strv_new("*\\*"); |
2027927b EV |
856 | assert_se(!strv_fnmatch(v, "\\", 0)); |
857 | assert_se(strv_fnmatch(v, "\\", FNM_NOESCAPE)); | |
858 | } | |
859 | ||
3a7719d3 | 860 | int main(int argc, char *argv[]) { |
3a7719d3 | 861 | test_specifier_printf(); |
c7bf9d51 ZJS |
862 | test_str_in_set(); |
863 | test_strptr_in_set(); | |
52f15520 | 864 | test_startswith_set(); |
02f19706 DB |
865 | test_strv_foreach(); |
866 | test_strv_foreach_backwards(); | |
4c325b2e | 867 | test_strv_foreach_pair(); |
539ad707 TA |
868 | test_strv_find(); |
869 | test_strv_find_prefix(); | |
7bd57a87 | 870 | test_strv_find_startswith(); |
682cfdff | 871 | test_strv_join(); |
474a595a | 872 | test_strv_join_prefix(); |
a6fde353 | 873 | |
30bcc052 ZJS |
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\"")); | |
73381fcf | 886 | |
ba774317 ZJS |
887 | /* trailing backslashes */ |
888 | test_strv_unquote(" x\\\\", STRV_MAKE("x\\")); | |
889 | test_invalid_unquote(" x\\"); | |
890 | ||
f88e6be5 LP |
891 | test_invalid_unquote("a --b='c \"d e\"''"); |
892 | test_invalid_unquote("a --b='c \"d e\" '\""); | |
a2a5291b | 893 | test_invalid_unquote("a --b='c \"d e\"garbage"); |
b2fadec6 ZJS |
894 | test_invalid_unquote("'"); |
895 | test_invalid_unquote("\""); | |
f88e6be5 | 896 | test_invalid_unquote("'x'y'g"); |
70f75a52 | 897 | |
aed2ebfe | 898 | test_strv_split(); |
0745ce75 | 899 | test_strv_split_empty(); |
8adaf7bd | 900 | test_strv_split_extract(); |
aed2ebfe | 901 | test_strv_split_newlines(); |
2f213f74 | 902 | test_strv_split_nulstr(); |
10ddd913 | 903 | test_strv_parse_nulstr(); |
539ad707 TA |
904 | test_strv_overlap(); |
905 | test_strv_sort(); | |
e3e45d4f SP |
906 | test_strv_extend_strv(); |
907 | test_strv_extend_strv_concat(); | |
908 | test_strv_extend(); | |
4a336a69 | 909 | test_strv_extendf(); |
250a918d | 910 | test_strv_from_stdarg_alloca(); |
6e888894 | 911 | test_strv_insert(); |
7bd57a87 | 912 | test_strv_push_prepend(); |
98940a3c | 913 | test_strv_push(); |
e74aa253 | 914 | test_strv_equal(); |
e1dd6790 LP |
915 | test_strv_is_uniq(); |
916 | test_strv_reverse(); | |
04c14b25 | 917 | test_strv_shell_escape(); |
e3ead6bb | 918 | test_strv_skip(); |
8dd4c05b | 919 | test_strv_extend_n(); |
e287086b | 920 | test_strv_make_nulstr(); |
bff8f950 | 921 | test_strv_free_free(); |
2c4b304e | 922 | |
ebde5cb2 | 923 | test_foreach_string(); |
2027927b | 924 | test_strv_fnmatch(); |
ebde5cb2 | 925 | |
f90cf44c LP |
926 | return 0; |
927 | } |