1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "alloc-util.h"
4 #include "locale-util.h"
5 #include "macro.h"
6 #include "string-util.h"
7 #include "strv.h"
8 #include "tests.h"
9 #include "utf8.h"
10 #include "util.h"
11 
TEST(string_erase)12 TEST(string_erase) {
13         char *x;
14         x = strdupa_safe("");
15         assert_se(streq(string_erase(x), ""));
16 
17         x = strdupa_safe("1");
18         assert_se(streq(string_erase(x), ""));
19 
20         x = strdupa_safe("123456789");
21         assert_se(streq(string_erase(x), ""));
22 
23         assert_se(x[1] == '\0');
24         assert_se(x[2] == '\0');
25         assert_se(x[3] == '\0');
26         assert_se(x[4] == '\0');
27         assert_se(x[5] == '\0');
28         assert_se(x[6] == '\0');
29         assert_se(x[7] == '\0');
30         assert_se(x[8] == '\0');
31         assert_se(x[9] == '\0');
32 }
33 
test_free_and_strndup_one(char ** t,const char * src,size_t l,const char * expected,bool change)34 static void test_free_and_strndup_one(char **t, const char *src, size_t l, const char *expected, bool change) {
35         log_debug("%s: \"%s\", \"%s\", %zd (expect \"%s\", %s)",
36                   __func__, strnull(*t), strnull(src), l, strnull(expected), yes_no(change));
37 
38         int r = free_and_strndup(t, src, l);
39         assert_se(streq_ptr(*t, expected));
40         assert_se(r == change); /* check that change occurs only when necessary */
41 }
42 
TEST(free_and_strndup)43 TEST(free_and_strndup) {
44         static const struct test_case {
45                 const char *src;
46                 size_t len;
47                 const char *expected;
48         } cases[] = {
49                      {"abc", 0, ""},
50                      {"abc", 0, ""},
51                      {"abc", 1, "a"},
52                      {"abc", 2, "ab"},
53                      {"abc", 3, "abc"},
54                      {"abc", 4, "abc"},
55                      {"abc", 5, "abc"},
56                      {"abc", 5, "abc"},
57                      {"abc", 4, "abc"},
58                      {"abc", 3, "abc"},
59                      {"abc", 2, "ab"},
60                      {"abc", 1, "a"},
61                      {"abc", 0, ""},
62 
63                      {"", 0, ""},
64                      {"", 1, ""},
65                      {"", 2, ""},
66                      {"", 0, ""},
67                      {"", 1, ""},
68                      {"", 2, ""},
69                      {"", 2, ""},
70                      {"", 1, ""},
71                      {"", 0, ""},
72 
73                      {NULL, 0, NULL},
74 
75                      {"foo", 3, "foo"},
76                      {"foobar", 6, "foobar"},
77         };
78 
79         _cleanup_free_ char *t = NULL;
80         const char *prev_expected = t;
81 
82         for (unsigned i = 0; i < ELEMENTSOF(cases); i++) {
83                 test_free_and_strndup_one(&t,
84                                           cases[i].src, cases[i].len, cases[i].expected,
85                                           !streq_ptr(cases[i].expected, prev_expected));
86                 prev_expected = t;
87         }
88 }
89 
TEST(ascii_strcasecmp_n)90 TEST(ascii_strcasecmp_n) {
91         assert_se(ascii_strcasecmp_n("", "", 0) == 0);
92         assert_se(ascii_strcasecmp_n("", "", 1) == 0);
93         assert_se(ascii_strcasecmp_n("", "a", 1) < 0);
94         assert_se(ascii_strcasecmp_n("", "a", 2) < 0);
95         assert_se(ascii_strcasecmp_n("a", "", 1) > 0);
96         assert_se(ascii_strcasecmp_n("a", "", 2) > 0);
97         assert_se(ascii_strcasecmp_n("a", "a", 1) == 0);
98         assert_se(ascii_strcasecmp_n("a", "a", 2) == 0);
99         assert_se(ascii_strcasecmp_n("a", "b", 1) < 0);
100         assert_se(ascii_strcasecmp_n("a", "b", 2) < 0);
101         assert_se(ascii_strcasecmp_n("b", "a", 1) > 0);
102         assert_se(ascii_strcasecmp_n("b", "a", 2) > 0);
103         assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxYxxxx", 9) == 0);
104         assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxyxxxx", 9) < 0);
105         assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxyxxxx", 9) < 0);
106         assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxYxxxx", 9) < 0);
107         assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxYxxxx", 9) < 0);
108 
109         assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxYxxxx", 9) == 0);
110         assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxxxxxx", 9) > 0);
111         assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxXxxxx", 9) > 0);
112         assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxxxxxx", 9) > 0);
113         assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxXxxxx", 9) > 0);
114 }
115 
TEST(ascii_strcasecmp_nn)116 TEST(ascii_strcasecmp_nn) {
117         assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0);
118         assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0);
119         assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0);
120         assert_se(ascii_strcasecmp_nn("", 1, "", 1) == 0);
121 
122         assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaAa", 4) == 0);
123         assert_se(ascii_strcasecmp_nn("aaa", 3, "aaAa", 4) < 0);
124         assert_se(ascii_strcasecmp_nn("aaa", 4, "aaAa", 4) < 0);
125         assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaA", 3) > 0);
126         assert_se(ascii_strcasecmp_nn("aaaa", 4, "AAA", 4) > 0);
127 
128         assert_se(ascii_strcasecmp_nn("aaaa", 4, "bbbb", 4) < 0);
129         assert_se(ascii_strcasecmp_nn("aaAA", 4, "BBbb", 4) < 0);
130         assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
131 }
132 
TEST(cellescape)133 TEST(cellescape) {
134         char buf[40];
135 
136         assert_se(streq(cellescape(buf, 1, ""), ""));
137         assert_se(streq(cellescape(buf, 1, "1"), ""));
138         assert_se(streq(cellescape(buf, 1, "12"), ""));
139 
140         assert_se(streq(cellescape(buf, 2, ""), ""));
141         assert_se(streq(cellescape(buf, 2, "1"), "1"));
142         assert_se(streq(cellescape(buf, 2, "12"), "."));
143         assert_se(streq(cellescape(buf, 2, "123"), "."));
144 
145         assert_se(streq(cellescape(buf, 3, ""), ""));
146         assert_se(streq(cellescape(buf, 3, "1"), "1"));
147         assert_se(streq(cellescape(buf, 3, "12"), "12"));
148         assert_se(streq(cellescape(buf, 3, "123"), ".."));
149         assert_se(streq(cellescape(buf, 3, "1234"), ".."));
150 
151         assert_se(streq(cellescape(buf, 4, ""), ""));
152         assert_se(streq(cellescape(buf, 4, "1"), "1"));
153         assert_se(streq(cellescape(buf, 4, "12"), "12"));
154         assert_se(streq(cellescape(buf, 4, "123"), "123"));
155         assert_se(streq(cellescape(buf, 4, "1234"), is_locale_utf8() ? "…" : "..."));
156         assert_se(streq(cellescape(buf, 4, "12345"), is_locale_utf8() ? "…" : "..."));
157 
158         assert_se(streq(cellescape(buf, 5, ""), ""));
159         assert_se(streq(cellescape(buf, 5, "1"), "1"));
160         assert_se(streq(cellescape(buf, 5, "12"), "12"));
161         assert_se(streq(cellescape(buf, 5, "123"), "123"));
162         assert_se(streq(cellescape(buf, 5, "1234"), "1234"));
163         assert_se(streq(cellescape(buf, 5, "12345"), is_locale_utf8() ? "1…" : "1..."));
164         assert_se(streq(cellescape(buf, 5, "123456"), is_locale_utf8() ? "1…" : "1..."));
165 
166         assert_se(streq(cellescape(buf, 1, "\020"), ""));
167         assert_se(streq(cellescape(buf, 2, "\020"), "."));
168         assert_se(streq(cellescape(buf, 3, "\020"), ".."));
169         assert_se(streq(cellescape(buf, 4, "\020"), is_locale_utf8() ? "…" : "..."));
170         assert_se(streq(cellescape(buf, 5, "\020"), "\\020"));
171 
172         assert_se(streq(cellescape(buf, 5, "1234\020"), is_locale_utf8() ? "1…" : "1..."));
173         assert_se(streq(cellescape(buf, 6, "1234\020"), is_locale_utf8() ? "12…" : "12..."));
174         assert_se(streq(cellescape(buf, 7, "1234\020"), is_locale_utf8() ? "123…" : "123..."));
175         assert_se(streq(cellescape(buf, 8, "1234\020"), is_locale_utf8() ? "1234…" : "1234..."));
176         assert_se(streq(cellescape(buf, 9, "1234\020"), "1234\\020"));
177 
178         assert_se(streq(cellescape(buf, 1, "\t\n"), ""));
179         assert_se(streq(cellescape(buf, 2, "\t\n"), "."));
180         assert_se(streq(cellescape(buf, 3, "\t\n"), ".."));
181         assert_se(streq(cellescape(buf, 4, "\t\n"), is_locale_utf8() ? "…" : "..."));
182         assert_se(streq(cellescape(buf, 5, "\t\n"), "\\t\\n"));
183 
184         assert_se(streq(cellescape(buf, 5, "1234\t\n"), is_locale_utf8() ? "1…" : "1..."));
185         assert_se(streq(cellescape(buf, 6, "1234\t\n"), is_locale_utf8() ? "12…" : "12..."));
186         assert_se(streq(cellescape(buf, 7, "1234\t\n"), is_locale_utf8() ? "123…" : "123..."));
187         assert_se(streq(cellescape(buf, 8, "1234\t\n"), is_locale_utf8() ? "1234…" : "1234..."));
188         assert_se(streq(cellescape(buf, 9, "1234\t\n"), "1234\\t\\n"));
189 
190         assert_se(streq(cellescape(buf, 4, "x\t\020\n"), is_locale_utf8() ? "…" : "..."));
191         assert_se(streq(cellescape(buf, 5, "x\t\020\n"), is_locale_utf8() ? "x…" : "x..."));
192         assert_se(streq(cellescape(buf, 6, "x\t\020\n"), is_locale_utf8() ? "x…" : "x..."));
193         assert_se(streq(cellescape(buf, 7, "x\t\020\n"), is_locale_utf8() ? "x\\t…" : "x\\t..."));
194         assert_se(streq(cellescape(buf, 8, "x\t\020\n"), is_locale_utf8() ? "x\\t…" : "x\\t..."));
195         assert_se(streq(cellescape(buf, 9, "x\t\020\n"), is_locale_utf8() ? "x\\t…" : "x\\t..."));
196         assert_se(streq(cellescape(buf, 10, "x\t\020\n"), "x\\t\\020\\n"));
197 
198         assert_se(streq(cellescape(buf, 6, "1\011"), "1\\t"));
199         assert_se(streq(cellescape(buf, 6, "1\020"), "1\\020"));
200         assert_se(streq(cellescape(buf, 6, "1\020x"), is_locale_utf8() ? "1…" : "1..."));
201 
202         assert_se(streq(cellescape(buf, 40, "1\020"), "1\\020"));
203         assert_se(streq(cellescape(buf, 40, "1\020x"), "1\\020x"));
204 
205         assert_se(streq(cellescape(buf, 40, "\a\b\f\n\r\t\v\\\"'"), "\\a\\b\\f\\n\\r\\t\\v\\\\\\\"\\'"));
206         assert_se(streq(cellescape(buf, 6, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a..."));
207         assert_se(streq(cellescape(buf, 7, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a..."));
208         assert_se(streq(cellescape(buf, 8, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a\\b…" : "\\a\\b..."));
209 
210         assert_se(streq(cellescape(buf, sizeof buf, "1\020"), "1\\020"));
211         assert_se(streq(cellescape(buf, sizeof buf, "1\020x"), "1\\020x"));
212 }
213 
TEST(streq_ptr)214 TEST(streq_ptr) {
215         assert_se(streq_ptr(NULL, NULL));
216         assert_se(!streq_ptr("abc", "cdef"));
217 }
218 
TEST(strstrip)219 TEST(strstrip) {
220         char *ret, input[] = "   hello, waldo.   ";
221 
222         ret = strstrip(input);
223         assert_se(streq(ret, "hello, waldo."));
224 }
225 
TEST(strextend)226 TEST(strextend) {
227         _cleanup_free_ char *str = NULL;
228 
229         assert_se(strextend(&str, NULL));
230         assert_se(streq_ptr(str, ""));
231         assert_se(strextend(&str, "", "0", "", "", "123"));
232         assert_se(streq_ptr(str, "0123"));
233         assert_se(strextend(&str, "456", "78", "9"));
234         assert_se(streq_ptr(str, "0123456789"));
235 }
236 
TEST(strextend_with_separator)237 TEST(strextend_with_separator) {
238         _cleanup_free_ char *str = NULL;
239 
240         assert_se(strextend_with_separator(&str, NULL, NULL));
241         assert_se(streq_ptr(str, ""));
242         str = mfree(str);
243 
244         assert_se(strextend_with_separator(&str, "...", NULL));
245         assert_se(streq_ptr(str, ""));
246         assert_se(strextend_with_separator(&str, "...", NULL));
247         assert_se(streq_ptr(str, ""));
248         str = mfree(str);
249 
250         assert_se(strextend_with_separator(&str, "xyz", "a", "bb", "ccc"));
251         assert_se(streq_ptr(str, "axyzbbxyzccc"));
252         str = mfree(str);
253 
254         assert_se(strextend_with_separator(&str, ",", "start", "", "1", "234"));
255         assert_se(streq_ptr(str, "start,,1,234"));
256         assert_se(strextend_with_separator(&str, ";", "more", "5", "678"));
257         assert_se(streq_ptr(str, "start,,1,234;more;5;678"));
258 }
259 
TEST(strrep)260 TEST(strrep) {
261         _cleanup_free_ char *one, *three, *zero;
262         one = strrep("waldo", 1);
263         three = strrep("waldo", 3);
264         zero = strrep("waldo", 0);
265 
266         assert_se(streq(one, "waldo"));
267         assert_se(streq(three, "waldowaldowaldo"));
268         assert_se(streq(zero, ""));
269 }
270 
TEST(string_has_cc)271 TEST(string_has_cc) {
272         assert_se(string_has_cc("abc\1", NULL));
273         assert_se(string_has_cc("abc\x7f", NULL));
274         assert_se(string_has_cc("abc\x7f", NULL));
275         assert_se(string_has_cc("abc\t\x7f", "\t"));
276         assert_se(string_has_cc("abc\t\x7f", "\t"));
277         assert_se(string_has_cc("\x7f", "\t"));
278         assert_se(string_has_cc("\x7f", "\t\a"));
279 
280         assert_se(!string_has_cc("abc\t\t", "\t"));
281         assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
282         assert_se(!string_has_cc("a\ab\tc", "\t\a"));
283 }
284 
TEST(ascii_strlower)285 TEST(ascii_strlower) {
286         char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
287         assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
288 }
289 
TEST(strshorten)290 TEST(strshorten) {
291         char s[] = "foobar";
292 
293         assert_se(strlen(strshorten(s, 6)) == 6);
294         assert_se(strlen(strshorten(s, 12)) == 6);
295         assert_se(strlen(strshorten(s, 2)) == 2);
296         assert_se(strlen(strshorten(s, 0)) == 0);
297 }
298 
TEST(strjoina)299 TEST(strjoina) {
300         char *actual;
301 
302         actual = strjoina("", "foo", "bar");
303         assert_se(streq(actual, "foobar"));
304 
305         actual = strjoina("foo", "bar", "baz");
306         assert_se(streq(actual, "foobarbaz"));
307 
308         actual = strjoina("foo", "", "bar", "baz");
309         assert_se(streq(actual, "foobarbaz"));
310 
311         actual = strjoina("foo");
312         assert_se(streq(actual, "foo"));
313 
314         actual = strjoina(NULL);
315         assert_se(streq(actual, ""));
316 
317         actual = strjoina(NULL, "foo");
318         assert_se(streq(actual, ""));
319 
320         actual = strjoina("foo", NULL, "bar");
321         assert_se(streq(actual, "foo"));
322 
323         actual = strjoina("/sys/fs/cgroup/", "dn", "/a/b/c", "/cgroup.procs");
324         assert_se(streq(actual, "/sys/fs/cgroup/dn/a/b/c/cgroup.procs"));
325 
326         actual = strjoina("/sys/fs/cgroup/", "dn", NULL, NULL);
327         assert_se(streq(actual, "/sys/fs/cgroup/dn"));
328 }
329 
TEST(strjoin)330 TEST(strjoin) {
331         char *actual;
332 
333         actual = strjoin("", "foo", "bar");
334         assert_se(streq(actual, "foobar"));
335         mfree(actual);
336 
337         actual = strjoin("foo", "bar", "baz");
338         assert_se(streq(actual, "foobarbaz"));
339         mfree(actual);
340 
341         actual = strjoin("foo", "", "bar", "baz");
342         assert_se(streq(actual, "foobarbaz"));
343         mfree(actual);
344 
345         actual = strjoin("foo", NULL);
346         assert_se(streq(actual, "foo"));
347         mfree(actual);
348 
349         actual = strjoin(NULL, NULL);
350         assert_se(streq(actual, ""));
351         mfree(actual);
352 
353         actual = strjoin(NULL, "foo");
354         assert_se(streq(actual, ""));
355         mfree(actual);
356 
357         actual = strjoin("foo", NULL, "bar");
358         assert_se(streq(actual, "foo"));
359         mfree(actual);
360 }
361 
TEST(strcmp_ptr)362 TEST(strcmp_ptr) {
363         assert_se(strcmp_ptr(NULL, NULL) == 0);
364         assert_se(strcmp_ptr("", NULL) > 0);
365         assert_se(strcmp_ptr("foo", NULL) > 0);
366         assert_se(strcmp_ptr(NULL, "") < 0);
367         assert_se(strcmp_ptr(NULL, "bar") < 0);
368         assert_se(strcmp_ptr("foo", "bar") > 0);
369         assert_se(strcmp_ptr("bar", "baz") < 0);
370         assert_se(strcmp_ptr("foo", "foo") == 0);
371         assert_se(strcmp_ptr("", "") == 0);
372 }
373 
TEST(foreach_word)374 TEST(foreach_word) {
375         const char *test = "test abc d\te   f   ";
376         const char * const expected[] = {
377                 "test",
378                 "abc",
379                 "d",
380                 "e",
381                 "f",
382         };
383 
384         size_t i = 0;
385         int r;
386         for (const char *p = test;;) {
387                 _cleanup_free_ char *word = NULL;
388 
389                 r = extract_first_word(&p, &word, NULL, 0);
390                 if (r == 0) {
391                         assert_se(i == ELEMENTSOF(expected));
392                         break;
393                 }
394                 assert_se(r > 0);
395 
396                 assert_se(streq(expected[i++], word));
397         }
398 }
399 
check(const char * test,char ** expected,bool trailing)400 static void check(const char *test, char** expected, bool trailing) {
401         size_t i = 0;
402         int r;
403 
404         printf("<<<%s>>>\n", test);
405         for (;;) {
406                 _cleanup_free_ char *word = NULL;
407 
408                 r = extract_first_word(&test, &word, NULL, EXTRACT_UNQUOTE);
409                 if (r == 0) {
410                         assert_se(!trailing);
411                         break;
412                 } else if (r < 0) {
413                         assert_se(trailing);
414                         break;
415                 }
416 
417                 assert_se(streq(word, expected[i++]));
418                 printf("<%s>\n", word);
419         }
420         assert_se(expected[i] == NULL);
421 }
422 
TEST(foreach_word_quoted)423 TEST(foreach_word_quoted) {
424         check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
425               STRV_MAKE("test",
426                         "a",
427                         "b",
428                         "c",
429                         "d",
430                         "e",
431                         "",
432                         "",
433                         "hhh",
434                         "",
435                         "",
436                         "a b c"),
437               false);
438 
439         check("test \"xxx",
440               STRV_MAKE("test"),
441               true);
442 
443         check("test\\",
444               STRV_MAKE_EMPTY,
445               true);
446 }
447 
TEST(endswith)448 TEST(endswith) {
449         assert_se(endswith("foobar", "bar"));
450         assert_se(endswith("foobar", ""));
451         assert_se(endswith("foobar", "foobar"));
452         assert_se(endswith("", ""));
453 
454         assert_se(!endswith("foobar", "foo"));
455         assert_se(!endswith("foobar", "foobarfoofoo"));
456 }
457 
TEST(endswith_no_case)458 TEST(endswith_no_case) {
459         assert_se(endswith_no_case("fooBAR", "bar"));
460         assert_se(endswith_no_case("foobar", ""));
461         assert_se(endswith_no_case("foobar", "FOOBAR"));
462         assert_se(endswith_no_case("", ""));
463 
464         assert_se(!endswith_no_case("foobar", "FOO"));
465         assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
466 }
467 
TEST(delete_chars)468 TEST(delete_chars) {
469         char *s, input[] = "   hello, waldo.   abc";
470 
471         s = delete_chars(input, WHITESPACE);
472         assert_se(streq(s, "hello,waldo.abc"));
473         assert_se(s == input);
474 }
475 
TEST(delete_trailing_chars)476 TEST(delete_trailing_chars) {
477         char *s,
478                 input1[] = " \n \r k \n \r ",
479                 input2[] = "kkkkthiskkkiskkkaktestkkk",
480                 input3[] = "abcdef";
481 
482         s = delete_trailing_chars(input1, WHITESPACE);
483         assert_se(streq(s, " \n \r k"));
484         assert_se(s == input1);
485 
486         s = delete_trailing_chars(input2, "kt");
487         assert_se(streq(s, "kkkkthiskkkiskkkaktes"));
488         assert_se(s == input2);
489 
490         s = delete_trailing_chars(input3, WHITESPACE);
491         assert_se(streq(s, "abcdef"));
492         assert_se(s == input3);
493 
494         s = delete_trailing_chars(input3, "fe");
495         assert_se(streq(s, "abcd"));
496         assert_se(s == input3);
497 }
498 
TEST(delete_trailing_slashes)499 TEST(delete_trailing_slashes) {
500         char s1[] = "foobar//",
501              s2[] = "foobar/",
502              s3[] = "foobar",
503              s4[] = "";
504 
505         assert_se(streq(delete_trailing_chars(s1, "_"), "foobar//"));
506         assert_se(streq(delete_trailing_chars(s1, "/"), "foobar"));
507         assert_se(streq(delete_trailing_chars(s2, "/"), "foobar"));
508         assert_se(streq(delete_trailing_chars(s3, "/"), "foobar"));
509         assert_se(streq(delete_trailing_chars(s4, "/"), ""));
510 }
511 
TEST(skip_leading_chars)512 TEST(skip_leading_chars) {
513         char input1[] = " \n \r k \n \r ",
514                 input2[] = "kkkkthiskkkiskkkaktestkkk",
515                 input3[] = "abcdef";
516 
517         assert_se(streq(skip_leading_chars(input1, WHITESPACE), "k \n \r "));
518         assert_se(streq(skip_leading_chars(input2, "k"), "thiskkkiskkkaktestkkk"));
519         assert_se(streq(skip_leading_chars(input2, "tk"), "hiskkkiskkkaktestkkk"));
520         assert_se(streq(skip_leading_chars(input3, WHITESPACE), "abcdef"));
521         assert_se(streq(skip_leading_chars(input3, "bcaef"), "def"));
522 }
523 
TEST(in_charset)524 TEST(in_charset) {
525         assert_se(in_charset("dddaaabbbcccc", "abcd"));
526         assert_se(!in_charset("dddaaabbbcccc", "abc f"));
527 }
528 
TEST(split_pair)529 TEST(split_pair) {
530         _cleanup_free_ char *a = NULL, *b = NULL;
531 
532         assert_se(split_pair("", "", &a, &b) == -EINVAL);
533         assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
534         assert_se(split_pair("", "=", &a, &b) == -EINVAL);
535         assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
536         assert_se(streq(a, "foo"));
537         assert_se(streq(b, "bar"));
538         free(a);
539         free(b);
540         assert_se(split_pair("==", "==", &a, &b) >= 0);
541         assert_se(streq(a, ""));
542         assert_se(streq(b, ""));
543         free(a);
544         free(b);
545 
546         assert_se(split_pair("===", "==", &a, &b) >= 0);
547         assert_se(streq(a, ""));
548         assert_se(streq(b, "="));
549 }
550 
TEST(first_word)551 TEST(first_word) {
552         assert_se(first_word("Hello", ""));
553         assert_se(first_word("Hello", "Hello"));
554         assert_se(first_word("Hello world", "Hello"));
555         assert_se(first_word("Hello\tworld", "Hello"));
556         assert_se(first_word("Hello\nworld", "Hello"));
557         assert_se(first_word("Hello\rworld", "Hello"));
558         assert_se(first_word("Hello ", "Hello"));
559 
560         assert_se(!first_word("Hello", "Hellooo"));
561         assert_se(!first_word("Hello", "xxxxx"));
562         assert_se(!first_word("Hellooo", "Hello"));
563 }
564 
TEST(strlen_ptr)565 TEST(strlen_ptr) {
566         assert_se(strlen_ptr("foo") == 3);
567         assert_se(strlen_ptr("") == 0);
568         assert_se(strlen_ptr(NULL) == 0);
569 }
570 
TEST(memory_startswith)571 TEST(memory_startswith) {
572         assert_se(streq(memory_startswith("", 0, ""), ""));
573         assert_se(streq(memory_startswith("", 1, ""), ""));
574         assert_se(streq(memory_startswith("x", 2, ""), "x"));
575         assert_se(!memory_startswith("", 1, "x"));
576         assert_se(!memory_startswith("", 1, "xxxxxxxx"));
577         assert_se(streq(memory_startswith("xxx", 4, "x"), "xx"));
578         assert_se(streq(memory_startswith("xxx", 4, "xx"), "x"));
579         assert_se(streq(memory_startswith("xxx", 4, "xxx"), ""));
580         assert_se(!memory_startswith("xxx", 4, "xxxx"));
581 }
582 
TEST(memory_startswith_no_case)583 TEST(memory_startswith_no_case) {
584         assert_se(streq(memory_startswith_no_case("", 0, ""), ""));
585         assert_se(streq(memory_startswith_no_case("", 1, ""), ""));
586         assert_se(streq(memory_startswith_no_case("x", 2, ""), "x"));
587         assert_se(streq(memory_startswith_no_case("X", 2, ""), "X"));
588         assert_se(!memory_startswith_no_case("", 1, "X"));
589         assert_se(!memory_startswith_no_case("", 1, "xxxxXXXX"));
590         assert_se(streq(memory_startswith_no_case("xxx", 4, "X"), "xx"));
591         assert_se(streq(memory_startswith_no_case("XXX", 4, "x"), "XX"));
592         assert_se(streq(memory_startswith_no_case("XXX", 4, "X"), "XX"));
593         assert_se(streq(memory_startswith_no_case("xxx", 4, "XX"), "x"));
594         assert_se(streq(memory_startswith_no_case("XXX", 4, "xx"), "X"));
595         assert_se(streq(memory_startswith_no_case("XXX", 4, "XX"), "X"));
596         assert_se(streq(memory_startswith_no_case("xxx", 4, "XXX"), ""));
597         assert_se(streq(memory_startswith_no_case("XXX", 4, "xxx"), ""));
598         assert_se(streq(memory_startswith_no_case("XXX", 4, "XXX"), ""));
599 
600         assert_se(memory_startswith_no_case((char[2]){'x', 'x'}, 2, "xx"));
601         assert_se(memory_startswith_no_case((char[2]){'x', 'X'}, 2, "xX"));
602         assert_se(memory_startswith_no_case((char[2]){'X', 'x'}, 2, "Xx"));
603         assert_se(memory_startswith_no_case((char[2]){'X', 'X'}, 2, "XX"));
604 }
605 
test_string_truncate_lines_one(const char * input,size_t n_lines,const char * output,bool truncation)606 static void test_string_truncate_lines_one(const char *input, size_t n_lines, const char *output, bool truncation) {
607         _cleanup_free_ char *b = NULL;
608         int k;
609 
610         assert_se((k = string_truncate_lines(input, n_lines, &b)) >= 0);
611         assert_se(streq(b, output));
612         assert_se(!!k == truncation);
613 }
614 
TEST(string_truncate_lines)615 TEST(string_truncate_lines) {
616         test_string_truncate_lines_one("", 0, "", false);
617         test_string_truncate_lines_one("", 1, "", false);
618         test_string_truncate_lines_one("", 2, "", false);
619         test_string_truncate_lines_one("", 3, "", false);
620 
621         test_string_truncate_lines_one("x", 0, "", true);
622         test_string_truncate_lines_one("x", 1, "x", false);
623         test_string_truncate_lines_one("x", 2, "x", false);
624         test_string_truncate_lines_one("x", 3, "x", false);
625 
626         test_string_truncate_lines_one("x\n", 0, "", true);
627         test_string_truncate_lines_one("x\n", 1, "x", false);
628         test_string_truncate_lines_one("x\n", 2, "x", false);
629         test_string_truncate_lines_one("x\n", 3, "x", false);
630 
631         test_string_truncate_lines_one("x\ny", 0, "", true);
632         test_string_truncate_lines_one("x\ny", 1, "x", true);
633         test_string_truncate_lines_one("x\ny", 2, "x\ny", false);
634         test_string_truncate_lines_one("x\ny", 3, "x\ny", false);
635 
636         test_string_truncate_lines_one("x\ny\n", 0, "", true);
637         test_string_truncate_lines_one("x\ny\n", 1, "x", true);
638         test_string_truncate_lines_one("x\ny\n", 2, "x\ny", false);
639         test_string_truncate_lines_one("x\ny\n", 3, "x\ny", false);
640 
641         test_string_truncate_lines_one("x\ny\nz", 0, "", true);
642         test_string_truncate_lines_one("x\ny\nz", 1, "x", true);
643         test_string_truncate_lines_one("x\ny\nz", 2, "x\ny", true);
644         test_string_truncate_lines_one("x\ny\nz", 3, "x\ny\nz", false);
645 
646         test_string_truncate_lines_one("x\ny\nz\n", 0, "", true);
647         test_string_truncate_lines_one("x\ny\nz\n", 1, "x", true);
648         test_string_truncate_lines_one("x\ny\nz\n", 2, "x\ny", true);
649         test_string_truncate_lines_one("x\ny\nz\n", 3, "x\ny\nz", false);
650 
651         test_string_truncate_lines_one("\n", 0, "", false);
652         test_string_truncate_lines_one("\n", 1, "", false);
653         test_string_truncate_lines_one("\n", 2, "", false);
654         test_string_truncate_lines_one("\n", 3, "", false);
655 
656         test_string_truncate_lines_one("\n\n", 0, "", false);
657         test_string_truncate_lines_one("\n\n", 1, "", false);
658         test_string_truncate_lines_one("\n\n", 2, "", false);
659         test_string_truncate_lines_one("\n\n", 3, "", false);
660 
661         test_string_truncate_lines_one("\n\n\n", 0, "", false);
662         test_string_truncate_lines_one("\n\n\n", 1, "", false);
663         test_string_truncate_lines_one("\n\n\n", 2, "", false);
664         test_string_truncate_lines_one("\n\n\n", 3, "", false);
665 
666         test_string_truncate_lines_one("\nx\n\n", 0, "", true);
667         test_string_truncate_lines_one("\nx\n\n", 1, "", true);
668         test_string_truncate_lines_one("\nx\n\n", 2, "\nx", false);
669         test_string_truncate_lines_one("\nx\n\n", 3, "\nx", false);
670 
671         test_string_truncate_lines_one("\n\nx\n", 0, "", true);
672         test_string_truncate_lines_one("\n\nx\n", 1, "", true);
673         test_string_truncate_lines_one("\n\nx\n", 2, "", true);
674         test_string_truncate_lines_one("\n\nx\n", 3, "\n\nx", false);
675 }
676 
test_string_extract_lines_one(const char * input,size_t i,const char * output,bool more)677 static void test_string_extract_lines_one(const char *input, size_t i, const char *output, bool more) {
678         _cleanup_free_ char *b = NULL;
679         int k;
680 
681         assert_se((k = string_extract_line(input, i, &b)) >= 0);
682         assert_se(streq(b ?: input, output));
683         assert_se(!!k == more);
684 }
685 
TEST(string_extract_line)686 TEST(string_extract_line) {
687         test_string_extract_lines_one("", 0, "", false);
688         test_string_extract_lines_one("", 1, "", false);
689         test_string_extract_lines_one("", 2, "", false);
690         test_string_extract_lines_one("", 3, "", false);
691 
692         test_string_extract_lines_one("x", 0, "x", false);
693         test_string_extract_lines_one("x", 1, "", false);
694         test_string_extract_lines_one("x", 2, "", false);
695         test_string_extract_lines_one("x", 3, "", false);
696 
697         test_string_extract_lines_one("x\n", 0, "x", false);
698         test_string_extract_lines_one("x\n", 1, "", false);
699         test_string_extract_lines_one("x\n", 2, "", false);
700         test_string_extract_lines_one("x\n", 3, "", false);
701 
702         test_string_extract_lines_one("x\ny", 0, "x", true);
703         test_string_extract_lines_one("x\ny", 1, "y", false);
704         test_string_extract_lines_one("x\ny", 2, "", false);
705         test_string_extract_lines_one("x\ny", 3, "", false);
706 
707         test_string_extract_lines_one("x\ny\n", 0, "x", true);
708         test_string_extract_lines_one("x\ny\n", 1, "y", false);
709         test_string_extract_lines_one("x\ny\n", 2, "", false);
710         test_string_extract_lines_one("x\ny\n", 3, "", false);
711 
712         test_string_extract_lines_one("x\ny\nz", 0, "x", true);
713         test_string_extract_lines_one("x\ny\nz", 1, "y", true);
714         test_string_extract_lines_one("x\ny\nz", 2, "z", false);
715         test_string_extract_lines_one("x\ny\nz", 3, "", false);
716 
717         test_string_extract_lines_one("\n", 0, "", false);
718         test_string_extract_lines_one("\n", 1, "", false);
719         test_string_extract_lines_one("\n", 2, "", false);
720         test_string_extract_lines_one("\n", 3, "", false);
721 
722         test_string_extract_lines_one("\n\n", 0, "", true);
723         test_string_extract_lines_one("\n\n", 1, "", false);
724         test_string_extract_lines_one("\n\n", 2, "", false);
725         test_string_extract_lines_one("\n\n", 3, "", false);
726 
727         test_string_extract_lines_one("\n\n\n", 0, "", true);
728         test_string_extract_lines_one("\n\n\n", 1, "", true);
729         test_string_extract_lines_one("\n\n\n", 2, "", false);
730         test_string_extract_lines_one("\n\n\n", 3, "", false);
731 
732         test_string_extract_lines_one("\n\n\n\n", 0, "", true);
733         test_string_extract_lines_one("\n\n\n\n", 1, "", true);
734         test_string_extract_lines_one("\n\n\n\n", 2, "", true);
735         test_string_extract_lines_one("\n\n\n\n", 3, "", false);
736 
737         test_string_extract_lines_one("\nx\n\n\n", 0, "", true);
738         test_string_extract_lines_one("\nx\n\n\n", 1, "x", true);
739         test_string_extract_lines_one("\nx\n\n\n", 2, "", true);
740         test_string_extract_lines_one("\nx\n\n\n", 3, "", false);
741 
742         test_string_extract_lines_one("\n\nx\n\n", 0, "", true);
743         test_string_extract_lines_one("\n\nx\n\n", 1, "", true);
744         test_string_extract_lines_one("\n\nx\n\n", 2, "x", true);
745         test_string_extract_lines_one("\n\nx\n\n", 3, "", false);
746 
747         test_string_extract_lines_one("\n\n\nx\n", 0, "", true);
748         test_string_extract_lines_one("\n\n\nx\n", 1, "", true);
749         test_string_extract_lines_one("\n\n\nx\n", 2, "", true);
750         test_string_extract_lines_one("\n\n\nx\n", 3, "x", false);
751 }
752 
TEST(string_contains_word_strv)753 TEST(string_contains_word_strv) {
754         const char *w;
755 
756         assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), NULL));
757 
758         assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), &w));
759         assert_se(streq(w, "a"));
760 
761         assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE("d"), &w));
762         assert_se(w == NULL);
763 
764         assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", "a"), &w));
765         assert_se(streq(w, "a"));
766 
767         assert_se(string_contains_word_strv("b a b cc", NULL, STRV_MAKE("b", "a", "b"), &w));
768         assert_se(streq(w, "b"));
769 
770         assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", ""), &w));
771         assert_se(streq(w, "b"));
772 
773         assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE(""), &w));
774         assert_se(w == NULL);
775 
776         assert_se(string_contains_word_strv("a b  cc", " ", STRV_MAKE(""), &w));
777         assert_se(streq(w, ""));
778 }
779 
TEST(string_contains_word)780 TEST(string_contains_word) {
781         assert_se( string_contains_word("a b cc", NULL, "a"));
782         assert_se( string_contains_word("a b cc", NULL, "b"));
783         assert_se(!string_contains_word("a b cc", NULL, "c"));
784         assert_se( string_contains_word("a b cc", NULL, "cc"));
785         assert_se(!string_contains_word("a b cc", NULL, "d"));
786         assert_se(!string_contains_word("a b cc", NULL, "a b"));
787         assert_se(!string_contains_word("a b cc", NULL, "a b c"));
788         assert_se(!string_contains_word("a b cc", NULL, "b c"));
789         assert_se(!string_contains_word("a b cc", NULL, "b cc"));
790         assert_se(!string_contains_word("a b cc", NULL, "a "));
791         assert_se(!string_contains_word("a b cc", NULL, " b "));
792         assert_se(!string_contains_word("a b cc", NULL, " cc"));
793 
794         assert_se( string_contains_word("  a  b\t\tcc", NULL, "a"));
795         assert_se( string_contains_word("  a  b\t\tcc", NULL, "b"));
796         assert_se(!string_contains_word("  a  b\t\tcc", NULL, "c"));
797         assert_se( string_contains_word("  a  b\t\tcc", NULL, "cc"));
798         assert_se(!string_contains_word("  a  b\t\tcc", NULL, "d"));
799         assert_se(!string_contains_word("  a  b\t\tcc", NULL, "a b"));
800         assert_se(!string_contains_word("  a  b\t\tcc", NULL, "a b\t\tc"));
801         assert_se(!string_contains_word("  a  b\t\tcc", NULL, "b\t\tc"));
802         assert_se(!string_contains_word("  a  b\t\tcc", NULL, "b\t\tcc"));
803         assert_se(!string_contains_word("  a  b\t\tcc", NULL, "a "));
804         assert_se(!string_contains_word("  a  b\t\tcc", NULL, " b "));
805         assert_se(!string_contains_word("  a  b\t\tcc", NULL, " cc"));
806 
807         assert_se(!string_contains_word("  a  b\t\tcc", NULL, ""));
808         assert_se(!string_contains_word("  a  b\t\tcc", NULL, " "));
809         assert_se(!string_contains_word("  a  b\t\tcc", NULL, "  "));
810         assert_se( string_contains_word("  a  b\t\tcc", " ", ""));
811         assert_se( string_contains_word("  a  b\t\tcc", "\t", ""));
812         assert_se( string_contains_word("  a  b\t\tcc", WHITESPACE, ""));
813 
814         assert_se( string_contains_word("a:b:cc", ":#", "a"));
815         assert_se( string_contains_word("a:b:cc", ":#", "b"));
816         assert_se(!string_contains_word("a:b:cc", ":#", "c"));
817         assert_se( string_contains_word("a:b:cc", ":#", "cc"));
818         assert_se(!string_contains_word("a:b:cc", ":#", "d"));
819         assert_se(!string_contains_word("a:b:cc", ":#", "a:b"));
820         assert_se(!string_contains_word("a:b:cc", ":#", "a:b:c"));
821         assert_se(!string_contains_word("a:b:cc", ":#", "b:c"));
822         assert_se(!string_contains_word("a#b#cc", ":#", "b:cc"));
823         assert_se( string_contains_word("a#b#cc", ":#", "b"));
824         assert_se( string_contains_word("a#b#cc", ":#", "cc"));
825         assert_se(!string_contains_word("a:b:cc", ":#", "a:"));
826         assert_se(!string_contains_word("a:b cc", ":#", "b"));
827         assert_se( string_contains_word("a:b cc", ":#", "b cc"));
828         assert_se(!string_contains_word("a:b:cc", ":#", ":cc"));
829 }
830 
test_strverscmp_improved_one(const char * newer,const char * older)831 static void test_strverscmp_improved_one(const char *newer, const char *older) {
832         log_info("/* %s(%s, %s) */", __func__, strnull(newer), strnull(older));
833 
834         assert_se(strverscmp_improved(newer, newer) == 0);
835         assert_se(strverscmp_improved(newer, older) >  0);
836         assert_se(strverscmp_improved(older, newer) <  0);
837         assert_se(strverscmp_improved(older, older) == 0);
838 }
839 
TEST(strverscmp_improved)840 TEST(strverscmp_improved) {
841         static const char * const versions[] = {
842                 "",
843                 "~1",
844                 "ab",
845                 "abb",
846                 "abc",
847                 "0001",
848                 "002",
849                 "12",
850                 "122",
851                 "122.9",
852                 "123~rc1",
853                 "123",
854                 "123-a",
855                 "123-a.1",
856                 "123-a1",
857                 "123-a1.1",
858                 "123-3",
859                 "123-3.1",
860                 "123^patch1",
861                 "123^1",
862                 "123.a-1",
863                 "123.1-1",
864                 "123a-1",
865                 "124",
866                 NULL,
867         };
868 
869         STRV_FOREACH(p, versions)
870                 STRV_FOREACH(q, p + 1)
871                         test_strverscmp_improved_one(*q, *p);
872 
873         test_strverscmp_improved_one("123.45-67.89", "123.45-67.88");
874         test_strverscmp_improved_one("123.45-67.89a", "123.45-67.89");
875         test_strverscmp_improved_one("123.45-67.89", "123.45-67.ab");
876         test_strverscmp_improved_one("123.45-67.89", "123.45-67.9");
877         test_strverscmp_improved_one("123.45-67.89", "123.45-67");
878         test_strverscmp_improved_one("123.45-67.89", "123.45-66.89");
879         test_strverscmp_improved_one("123.45-67.89", "123.45-9.99");
880         test_strverscmp_improved_one("123.45-67.89", "123.42-99.99");
881         test_strverscmp_improved_one("123.45-67.89", "123-99.99");
882 
883         /* '~' : pre-releases */
884         test_strverscmp_improved_one("123.45-67.89", "123~rc1-99.99");
885         test_strverscmp_improved_one("123-45.67.89", "123~rc1-99.99");
886         test_strverscmp_improved_one("123~rc2-67.89", "123~rc1-99.99");
887         test_strverscmp_improved_one("123^aa2-67.89", "123~rc1-99.99");
888         test_strverscmp_improved_one("123aa2-67.89", "123~rc1-99.99");
889 
890         /* '-' : separator between version and release. */
891         test_strverscmp_improved_one("123.45-67.89", "123-99.99");
892         test_strverscmp_improved_one("123^aa2-67.89", "123-99.99");
893         test_strverscmp_improved_one("123aa2-67.89", "123-99.99");
894 
895         /* '^' : patch releases */
896         test_strverscmp_improved_one("123.45-67.89", "123^45-67.89");
897         test_strverscmp_improved_one("123^aa2-67.89", "123^aa1-99.99");
898         test_strverscmp_improved_one("123aa2-67.89", "123^aa2-67.89");
899 
900         /* '.' : point release */
901         test_strverscmp_improved_one("123aa2-67.89", "123.aa2-67.89");
902         test_strverscmp_improved_one("123.ab2-67.89", "123.aa2-67.89");
903 
904         /* invalid characters */
905         assert_se(strverscmp_improved("123_aa2-67.89", "123aa+2-67.89") == 0);
906 }
907 
TEST(strextendf)908 TEST(strextendf) {
909         _cleanup_free_ char *p = NULL;
910 
911         assert_se(strextendf(&p, "<%i>", 77) >= 0);
912         assert_se(streq(p, "<77>"));
913 
914         assert_se(strextendf(&p, "<%i>", 99) >= 0);
915         assert_se(streq(p, "<77><99>"));
916 
917         assert_se(strextendf(&p, "<%80i>", 88) >= 0);
918         assert_se(streq(p, "<77><99><                                                                              88>"));
919 
920         assert_se(strextendf(&p, "<%08x>", 0x1234) >= 0);
921         assert_se(streq(p, "<77><99><                                                                              88><00001234>"));
922 
923         p = mfree(p);
924 
925         assert_se(strextendf_with_separator(&p, ",", "<%i>", 77) >= 0);
926         assert_se(streq(p, "<77>"));
927 
928         assert_se(strextendf_with_separator(&p, ",", "<%i>", 99) >= 0);
929         assert_se(streq(p, "<77>,<99>"));
930 
931         assert_se(strextendf_with_separator(&p, ",", "<%80i>", 88) >= 0);
932         assert_se(streq(p, "<77>,<99>,<                                                                              88>"));
933 
934         assert_se(strextendf_with_separator(&p, ",", "<%08x>", 0x1234) >= 0);
935         assert_se(streq(p, "<77>,<99>,<                                                                              88>,<00001234>"));
936 }
937 
TEST(string_replace_char)938 TEST(string_replace_char) {
939         assert_se(streq(string_replace_char(strdupa(""), 'a', 'b'), ""));
940         assert_se(streq(string_replace_char(strdupa("abc"), 'a', 'b'), "bbc"));
941         assert_se(streq(string_replace_char(strdupa("hoge"), 'a', 'b'), "hoge"));
942         assert_se(streq(string_replace_char(strdupa("aaaa"), 'a', 'b'), "bbbb"));
943         assert_se(streq(string_replace_char(strdupa("aaaa"), 'a', '\t'), "\t\t\t\t"));
944 }
945 
TEST(strspn_from_end)946 TEST(strspn_from_end) {
947         assert_se(strspn_from_end(NULL, NULL) == 0);
948         assert_se(strspn_from_end("hoge", NULL) == 0);
949         assert_se(strspn_from_end(NULL, DIGITS) == 0);
950         assert_se(strspn_from_end("", DIGITS) == 0);
951         assert_se(strspn_from_end("hoge", DIGITS) == 0);
952         assert_se(strspn_from_end("1234", DIGITS) == 4);
953         assert_se(strspn_from_end("aaa1234", DIGITS) == 4);
954         assert_se(strspn_from_end("aaa1234aaa", DIGITS) == 0);
955         assert_se(strspn_from_end("aaa12aa34", DIGITS) == 2);
956 }
957 
TEST(streq_skip_trailing_chars)958 TEST(streq_skip_trailing_chars) {
959         /* NULL is WHITESPACE by default*/
960         assert_se(streq_skip_trailing_chars("foo bar", "foo bar", NULL));
961         assert_se(streq_skip_trailing_chars("foo", "foo", NULL));
962         assert_se(streq_skip_trailing_chars("foo bar      ", "foo bar", NULL));
963         assert_se(streq_skip_trailing_chars("foo bar", "foo bar\t\t", NULL));
964         assert_se(streq_skip_trailing_chars("foo bar  ", "foo bar\t\t", NULL));
965         assert_se(streq_skip_trailing_chars("foo\nbar", "foo\nbar", NULL));
966         assert_se(streq_skip_trailing_chars("\t\tfoo bar", "\t\tfoo bar", NULL));
967         assert_se(streq_skip_trailing_chars(" foo bar\t", " foo bar\n", NULL));
968 
969         assert_se(!streq_skip_trailing_chars("foobar", "foo bar", NULL));
970         assert_se(!streq_skip_trailing_chars("foo\nbar", "foo\tbar", NULL));
971         assert_se(!streq_skip_trailing_chars("\t\nfoo bar", "\t foo bar", NULL));
972 
973         assert_se(streq_skip_trailing_chars("foo bar      ", "foo bar", WHITESPACE));
974         assert_se(!streq_skip_trailing_chars("foo bar      ", "foo bar", NEWLINE));
975 
976         assert_se(streq_skip_trailing_chars(NULL, NULL, NULL));
977         assert_se(streq_skip_trailing_chars("", "", NULL));
978         assert_se(!streq_skip_trailing_chars(NULL, "foo bar", NULL));
979         assert_se(!streq_skip_trailing_chars("foo", NULL, NULL));
980         assert_se(!streq_skip_trailing_chars("", "f", NULL));
981 }
982 
983 DEFINE_TEST_MAIN(LOG_DEBUG);
984