chiark / gitweb /
Prep v236 : Add missing SPDX-License-Identifier (8/9) src/test
[elogind.git] / src / test / test-string-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2015 Lennart Poettering
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include "alloc-util.h"
22 #include "macro.h"
23 #include "string-util.h"
24 #include "strv.h"
25
26 static void test_string_erase(void) {
27         char *x;
28
29         x = strdupa("");
30         assert_se(streq(string_erase(x), ""));
31
32         x = strdupa("1");
33         assert_se(streq(string_erase(x), ""));
34
35         x = strdupa("123456789");
36         assert_se(streq(string_erase(x), ""));
37
38         assert_se(x[1] == '\0');
39         assert_se(x[2] == '\0');
40         assert_se(x[3] == '\0');
41         assert_se(x[4] == '\0');
42         assert_se(x[5] == '\0');
43         assert_se(x[6] == '\0');
44         assert_se(x[7] == '\0');
45         assert_se(x[8] == '\0');
46         assert_se(x[9] == '\0');
47 }
48
49 #if 0 /// UNNEEDED by elogind
50 static void test_ascii_strcasecmp_n(void) {
51
52         assert_se(ascii_strcasecmp_n("", "", 0) == 0);
53         assert_se(ascii_strcasecmp_n("", "", 1) == 0);
54         assert_se(ascii_strcasecmp_n("", "a", 1) < 0);
55         assert_se(ascii_strcasecmp_n("", "a", 2) < 0);
56         assert_se(ascii_strcasecmp_n("a", "", 1) > 0);
57         assert_se(ascii_strcasecmp_n("a", "", 2) > 0);
58         assert_se(ascii_strcasecmp_n("a", "a", 1) == 0);
59         assert_se(ascii_strcasecmp_n("a", "a", 2) == 0);
60         assert_se(ascii_strcasecmp_n("a", "b", 1) < 0);
61         assert_se(ascii_strcasecmp_n("a", "b", 2) < 0);
62         assert_se(ascii_strcasecmp_n("b", "a", 1) > 0);
63         assert_se(ascii_strcasecmp_n("b", "a", 2) > 0);
64         assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxYxxxx", 9) == 0);
65         assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxyxxxx", 9) < 0);
66         assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxyxxxx", 9) < 0);
67         assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxYxxxx", 9) < 0);
68         assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxYxxxx", 9) < 0);
69
70         assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxYxxxx", 9) == 0);
71         assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxxxxxx", 9) > 0);
72         assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxXxxxx", 9) > 0);
73         assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxxxxxx", 9) > 0);
74         assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxXxxxx", 9) > 0);
75 }
76
77 static void test_ascii_strcasecmp_nn(void) {
78         assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0);
79         assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0);
80         assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0);
81         assert_se(ascii_strcasecmp_nn("", 1, "", 1) == 0);
82
83         assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaAa", 4) == 0);
84         assert_se(ascii_strcasecmp_nn("aaa", 3, "aaAa", 4) < 0);
85         assert_se(ascii_strcasecmp_nn("aaa", 4, "aaAa", 4) < 0);
86         assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaA", 3) > 0);
87         assert_se(ascii_strcasecmp_nn("aaaa", 4, "AAA", 4) > 0);
88
89         assert_se(ascii_strcasecmp_nn("aaaa", 4, "bbbb", 4) < 0);
90         assert_se(ascii_strcasecmp_nn("aaAA", 4, "BBbb", 4) < 0);
91         assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
92 }
93 #endif // 0
94
95 static void test_streq_ptr(void) {
96         assert_se(streq_ptr(NULL, NULL));
97         assert_se(!streq_ptr("abc", "cdef"));
98 }
99
100 static void test_strstrip(void) {
101         char *r;
102         char input[] = "   hello, waldo.   ";
103
104         r = strstrip(input);
105         assert_se(streq(r, "hello, waldo."));
106 }
107
108 static void test_strextend(void) {
109         _cleanup_free_ char *str = NULL;
110
111         assert_se(strextend(&str, NULL));
112         assert_se(streq_ptr(str, ""));
113         assert_se(strextend(&str, "", "0", "", "", "123", NULL));
114         assert_se(streq_ptr(str, "0123"));
115         assert_se(strextend(&str, "456", "78", "9", NULL));
116         assert_se(streq_ptr(str, "0123456789"));
117 }
118
119 static void test_strextend_with_separator(void) {
120         _cleanup_free_ char *str = NULL;
121
122         assert_se(strextend_with_separator(&str, NULL, NULL));
123         assert_se(streq_ptr(str, ""));
124         str = mfree(str);
125
126         assert_se(strextend_with_separator(&str, "...", NULL));
127         assert_se(streq_ptr(str, ""));
128         assert_se(strextend_with_separator(&str, "...", NULL));
129         assert_se(streq_ptr(str, ""));
130         str = mfree(str);
131
132         assert_se(strextend_with_separator(&str, "xyz", "a", "bb", "ccc", NULL));
133         assert_se(streq_ptr(str, "axyzbbxyzccc"));
134         str = mfree(str);
135
136         assert_se(strextend_with_separator(&str, ",", "start", "", "1", "234", NULL));
137         assert_se(streq_ptr(str, "start,,1,234"));
138         assert_se(strextend_with_separator(&str, ";", "more", "5", "678", NULL));
139         assert_se(streq_ptr(str, "start,,1,234;more;5;678"));
140 }
141
142 static void test_strrep(void) {
143         _cleanup_free_ char *one, *three, *zero;
144         one = strrep("waldo", 1);
145         three = strrep("waldo", 3);
146         zero = strrep("waldo", 0);
147
148         assert_se(streq(one, "waldo"));
149         assert_se(streq(three, "waldowaldowaldo"));
150         assert_se(streq(zero, ""));
151 }
152
153
154 static void test_strappend(void) {
155         _cleanup_free_ char *t1, *t2, *t3, *t4;
156
157         t1 = strappend(NULL, NULL);
158         assert_se(streq(t1, ""));
159
160         t2 = strappend(NULL, "suf");
161         assert_se(streq(t2, "suf"));
162
163         t3 = strappend("pre", NULL);
164         assert_se(streq(t3, "pre"));
165
166         t4 = strappend("pre", "suf");
167         assert_se(streq(t4, "presuf"));
168 }
169
170 static void test_string_has_cc(void) {
171         assert_se(string_has_cc("abc\1", NULL));
172         assert_se(string_has_cc("abc\x7f", NULL));
173         assert_se(string_has_cc("abc\x7f", NULL));
174         assert_se(string_has_cc("abc\t\x7f", "\t"));
175         assert_se(string_has_cc("abc\t\x7f", "\t"));
176         assert_se(string_has_cc("\x7f", "\t"));
177         assert_se(string_has_cc("\x7f", "\t\a"));
178
179         assert_se(!string_has_cc("abc\t\t", "\t"));
180         assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
181         assert_se(!string_has_cc("a\ab\tc", "\t\a"));
182 }
183
184 #if 0 /// UNNEEDED by elogind
185 static void test_ascii_strlower(void) {
186         char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
187         assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
188 }
189 #endif // 0
190
191 static void test_strshorten(void) {
192         char s[] = "foobar";
193
194         assert_se(strlen(strshorten(s, 6)) == 6);
195         assert_se(strlen(strshorten(s, 12)) == 6);
196         assert_se(strlen(strshorten(s, 2)) == 2);
197         assert_se(strlen(strshorten(s, 0)) == 0);
198 }
199
200 static void test_strjoina(void) {
201         char *actual;
202
203         actual = strjoina("", "foo", "bar");
204         assert_se(streq(actual, "foobar"));
205
206         actual = strjoina("foo", "bar", "baz");
207         assert_se(streq(actual, "foobarbaz"));
208
209         actual = strjoina("foo", "", "bar", "baz");
210         assert_se(streq(actual, "foobarbaz"));
211
212         actual = strjoina("foo");
213         assert_se(streq(actual, "foo"));
214
215         actual = strjoina(NULL);
216         assert_se(streq(actual, ""));
217
218         actual = strjoina(NULL, "foo");
219         assert_se(streq(actual, ""));
220
221         actual = strjoina("foo", NULL, "bar");
222         assert_se(streq(actual, "foo"));
223 }
224
225 static void test_strcmp_ptr(void) {
226         assert_se(strcmp_ptr(NULL, NULL) == 0);
227         assert_se(strcmp_ptr("", NULL) > 0);
228         assert_se(strcmp_ptr("foo", NULL) > 0);
229         assert_se(strcmp_ptr(NULL, "") < 0);
230         assert_se(strcmp_ptr(NULL, "bar") < 0);
231         assert_se(strcmp_ptr("foo", "bar") > 0);
232         assert_se(strcmp_ptr("bar", "baz") < 0);
233         assert_se(strcmp_ptr("foo", "foo") == 0);
234         assert_se(strcmp_ptr("", "") == 0);
235 }
236
237 static void test_foreach_word(void) {
238         const char *word, *state;
239         size_t l;
240         int i = 0;
241         const char test[] = "test abc d\te   f   ";
242         const char * const expected[] = {
243                 "test",
244                 "abc",
245                 "d",
246                 "e",
247                 "f",
248                 "",
249                 NULL
250         };
251
252         FOREACH_WORD(word, l, test, state)
253                 assert_se(strneq(expected[i++], word, l));
254 }
255
256 static void check(const char *test, char** expected, bool trailing) {
257         int i = 0, r;
258
259         printf("<<<%s>>>\n", test);
260         for (;;) {
261                 _cleanup_free_ char *word = NULL;
262
263                 r = extract_first_word(&test, &word, NULL, EXTRACT_QUOTES);
264                 if (r == 0) {
265                         assert_se(!trailing);
266                         break;
267                 } else if (r < 0) {
268                         assert_se(trailing);
269                         break;
270                 }
271
272                 assert_se(streq(word, expected[i++]));
273                 printf("<%s>\n", word);
274         }
275         assert_se(expected[i] == NULL);
276 }
277
278 static void test_foreach_word_quoted(void) {
279         check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
280               STRV_MAKE("test",
281                         "a",
282                         "b",
283                         "c",
284                         "d",
285                         "e",
286                         "",
287                         "",
288                         "hhh",
289                         "",
290                         "",
291                         "a b c"),
292               false);
293
294         check("test \"xxx",
295               STRV_MAKE("test"),
296               true);
297
298         check("test\\",
299               STRV_MAKE_EMPTY,
300               true);
301 }
302
303 static void test_endswith(void) {
304         assert_se(endswith("foobar", "bar"));
305         assert_se(endswith("foobar", ""));
306         assert_se(endswith("foobar", "foobar"));
307         assert_se(endswith("", ""));
308
309         assert_se(!endswith("foobar", "foo"));
310         assert_se(!endswith("foobar", "foobarfoofoo"));
311 }
312
313 static void test_endswith_no_case(void) {
314         assert_se(endswith_no_case("fooBAR", "bar"));
315         assert_se(endswith_no_case("foobar", ""));
316         assert_se(endswith_no_case("foobar", "FOOBAR"));
317         assert_se(endswith_no_case("", ""));
318
319         assert_se(!endswith_no_case("foobar", "FOO"));
320         assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
321 }
322
323 #if 0 /// UNNEEDED by elogind
324 static void test_delete_chars(void) {
325         char *s, input[] = "   hello, waldo.   abc";
326
327         s = delete_chars(input, WHITESPACE);
328         assert_se(streq(s, "hello,waldo.abc"));
329         assert_se(s == input);
330 }
331 #endif // 0
332
333 static void test_delete_trailing_chars(void) {
334
335         char *s,
336                 input1[] = " \n \r k \n \r ",
337                 input2[] = "kkkkthiskkkiskkkaktestkkk",
338                 input3[] = "abcdef";
339
340         s = delete_trailing_chars(input1, WHITESPACE);
341         assert_se(streq(s, " \n \r k"));
342         assert_se(s == input1);
343
344         s = delete_trailing_chars(input2, "kt");
345         assert_se(streq(s, "kkkkthiskkkiskkkaktes"));
346         assert_se(s == input2);
347
348         s = delete_trailing_chars(input3, WHITESPACE);
349         assert_se(streq(s, "abcdef"));
350         assert_se(s == input3);
351
352         s = delete_trailing_chars(input3, "fe");
353         assert_se(streq(s, "abcd"));
354         assert_se(s == input3);
355 }
356
357 static void test_delete_trailing_slashes(void) {
358         char s1[] = "foobar//",
359              s2[] = "foobar/",
360              s3[] = "foobar",
361              s4[] = "";
362
363         assert_se(streq(delete_trailing_chars(s1, "_"), "foobar//"));
364         assert_se(streq(delete_trailing_chars(s1, "/"), "foobar"));
365         assert_se(streq(delete_trailing_chars(s2, "/"), "foobar"));
366         assert_se(streq(delete_trailing_chars(s3, "/"), "foobar"));
367         assert_se(streq(delete_trailing_chars(s4, "/"), ""));
368 }
369
370 #if 0 /// UNNEEDED by elogind
371 static void test_skip_leading_chars(void) {
372         char input1[] = " \n \r k \n \r ",
373                 input2[] = "kkkkthiskkkiskkkaktestkkk",
374                 input3[] = "abcdef";
375
376         assert_se(streq(skip_leading_chars(input1, WHITESPACE), "k \n \r "));
377         assert_se(streq(skip_leading_chars(input2, "k"), "thiskkkiskkkaktestkkk"));
378         assert_se(streq(skip_leading_chars(input2, "tk"), "hiskkkiskkkaktestkkk"));
379         assert_se(streq(skip_leading_chars(input3, WHITESPACE), "abcdef"));
380         assert_se(streq(skip_leading_chars(input3, "bcaef"), "def"));
381 }
382 #endif // 0
383
384 static void test_in_charset(void) {
385         assert_se(in_charset("dddaaabbbcccc", "abcd"));
386         assert_se(!in_charset("dddaaabbbcccc", "abc f"));
387 }
388
389 static void test_split_pair(void) {
390         _cleanup_free_ char *a = NULL, *b = NULL;
391
392         assert_se(split_pair("", "", &a, &b) == -EINVAL);
393         assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
394         assert_se(split_pair("", "=", &a, &b) == -EINVAL);
395         assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
396         assert_se(streq(a, "foo"));
397         assert_se(streq(b, "bar"));
398         free(a);
399         free(b);
400         assert_se(split_pair("==", "==", &a, &b) >= 0);
401         assert_se(streq(a, ""));
402         assert_se(streq(b, ""));
403         free(a);
404         free(b);
405
406         assert_se(split_pair("===", "==", &a, &b) >= 0);
407         assert_se(streq(a, ""));
408         assert_se(streq(b, "="));
409 }
410
411 static void test_first_word(void) {
412         assert_se(first_word("Hello", ""));
413         assert_se(first_word("Hello", "Hello"));
414         assert_se(first_word("Hello world", "Hello"));
415         assert_se(first_word("Hello\tworld", "Hello"));
416         assert_se(first_word("Hello\nworld", "Hello"));
417         assert_se(first_word("Hello\rworld", "Hello"));
418         assert_se(first_word("Hello ", "Hello"));
419
420         assert_se(!first_word("Hello", "Hellooo"));
421         assert_se(!first_word("Hello", "xxxxx"));
422         assert_se(!first_word("Hellooo", "Hello"));
423 }
424
425 static void test_strlen_ptr(void) {
426         assert_se(strlen_ptr("foo") == 3);
427         assert_se(strlen_ptr("") == 0);
428         assert_se(strlen_ptr(NULL) == 0);
429 }
430
431 int main(int argc, char *argv[]) {
432         test_string_erase();
433 #if 0 /// UNNEEDED by elogind
434         test_ascii_strcasecmp_n();
435         test_ascii_strcasecmp_nn();
436 #endif // 0
437         test_streq_ptr();
438         test_strstrip();
439         test_strextend();
440         test_strextend_with_separator();
441         test_strrep();
442         test_strappend();
443         test_string_has_cc();
444 #if 0 /// UNNEEDED by elogind
445         test_ascii_strlower();
446 #endif // 0
447         test_strshorten();
448         test_strjoina();
449         test_strcmp_ptr();
450         test_foreach_word();
451         test_foreach_word_quoted();
452         test_endswith();
453         test_endswith_no_case();
454 #if 0 /// UNNEEDED by elogind
455         test_delete_chars();
456 #endif // 0
457         test_delete_trailing_chars();
458         test_delete_trailing_slashes();
459 #if 0 /// UNNEEDED by elogind
460         test_skip_leading_chars();
461 #endif // 0
462         test_in_charset();
463         test_split_pair();
464         test_first_word();
465         test_strlen_ptr();
466
467         return 0;
468 }