]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-string-util.c
07ee98465c63e933d330e53e557671030136bb38
[thirdparty/systemd.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 static void test_ascii_strcasecmp_n(void) {
50
51 assert_se(ascii_strcasecmp_n("", "", 0) == 0);
52 assert_se(ascii_strcasecmp_n("", "", 1) == 0);
53 assert_se(ascii_strcasecmp_n("", "a", 1) < 0);
54 assert_se(ascii_strcasecmp_n("", "a", 2) < 0);
55 assert_se(ascii_strcasecmp_n("a", "", 1) > 0);
56 assert_se(ascii_strcasecmp_n("a", "", 2) > 0);
57 assert_se(ascii_strcasecmp_n("a", "a", 1) == 0);
58 assert_se(ascii_strcasecmp_n("a", "a", 2) == 0);
59 assert_se(ascii_strcasecmp_n("a", "b", 1) < 0);
60 assert_se(ascii_strcasecmp_n("a", "b", 2) < 0);
61 assert_se(ascii_strcasecmp_n("b", "a", 1) > 0);
62 assert_se(ascii_strcasecmp_n("b", "a", 2) > 0);
63 assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxYxxxx", 9) == 0);
64 assert_se(ascii_strcasecmp_n("xxxxxxxxx", "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
69 assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxYxxxx", 9) == 0);
70 assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxxxxxx", 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 }
75
76 static void test_ascii_strcasecmp_nn(void) {
77 assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0);
78 assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0);
79 assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0);
80 assert_se(ascii_strcasecmp_nn("", 1, "", 1) == 0);
81
82 assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaAa", 4) == 0);
83 assert_se(ascii_strcasecmp_nn("aaa", 3, "aaAa", 4) < 0);
84 assert_se(ascii_strcasecmp_nn("aaa", 4, "aaAa", 4) < 0);
85 assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaA", 3) > 0);
86 assert_se(ascii_strcasecmp_nn("aaaa", 4, "AAA", 4) > 0);
87
88 assert_se(ascii_strcasecmp_nn("aaaa", 4, "bbbb", 4) < 0);
89 assert_se(ascii_strcasecmp_nn("aaAA", 4, "BBbb", 4) < 0);
90 assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
91 }
92
93 static void test_streq_ptr(void) {
94 assert_se(streq_ptr(NULL, NULL));
95 assert_se(!streq_ptr("abc", "cdef"));
96 }
97
98 static void test_strstrip(void) {
99 char *r;
100 char input[] = " hello, waldo. ";
101
102 r = strstrip(input);
103 assert_se(streq(r, "hello, waldo."));
104 }
105
106 static void test_strextend(void) {
107 _cleanup_free_ char *str = NULL;
108
109 assert_se(strextend(&str, NULL));
110 assert_se(streq_ptr(str, ""));
111 assert_se(strextend(&str, "", "0", "", "", "123", NULL));
112 assert_se(streq_ptr(str, "0123"));
113 assert_se(strextend(&str, "456", "78", "9", NULL));
114 assert_se(streq_ptr(str, "0123456789"));
115 }
116
117 static void test_strextend_with_separator(void) {
118 _cleanup_free_ char *str = NULL;
119
120 assert_se(strextend_with_separator(&str, NULL, NULL));
121 assert_se(streq_ptr(str, ""));
122 str = mfree(str);
123
124 assert_se(strextend_with_separator(&str, "...", NULL));
125 assert_se(streq_ptr(str, ""));
126 assert_se(strextend_with_separator(&str, "...", NULL));
127 assert_se(streq_ptr(str, ""));
128 str = mfree(str);
129
130 assert_se(strextend_with_separator(&str, "xyz", "a", "bb", "ccc", NULL));
131 assert_se(streq_ptr(str, "axyzbbxyzccc"));
132 str = mfree(str);
133
134 assert_se(strextend_with_separator(&str, ",", "start", "", "1", "234", NULL));
135 assert_se(streq_ptr(str, "start,,1,234"));
136 assert_se(strextend_with_separator(&str, ";", "more", "5", "678", NULL));
137 assert_se(streq_ptr(str, "start,,1,234;more;5;678"));
138 }
139
140 static void test_strrep(void) {
141 _cleanup_free_ char *one, *three, *zero;
142 one = strrep("waldo", 1);
143 three = strrep("waldo", 3);
144 zero = strrep("waldo", 0);
145
146 assert_se(streq(one, "waldo"));
147 assert_se(streq(three, "waldowaldowaldo"));
148 assert_se(streq(zero, ""));
149 }
150
151
152 static void test_strappend(void) {
153 _cleanup_free_ char *t1, *t2, *t3, *t4;
154
155 t1 = strappend(NULL, NULL);
156 assert_se(streq(t1, ""));
157
158 t2 = strappend(NULL, "suf");
159 assert_se(streq(t2, "suf"));
160
161 t3 = strappend("pre", NULL);
162 assert_se(streq(t3, "pre"));
163
164 t4 = strappend("pre", "suf");
165 assert_se(streq(t4, "presuf"));
166 }
167
168 static void test_string_has_cc(void) {
169 assert_se(string_has_cc("abc\1", NULL));
170 assert_se(string_has_cc("abc\x7f", NULL));
171 assert_se(string_has_cc("abc\x7f", NULL));
172 assert_se(string_has_cc("abc\t\x7f", "\t"));
173 assert_se(string_has_cc("abc\t\x7f", "\t"));
174 assert_se(string_has_cc("\x7f", "\t"));
175 assert_se(string_has_cc("\x7f", "\t\a"));
176
177 assert_se(!string_has_cc("abc\t\t", "\t"));
178 assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
179 assert_se(!string_has_cc("a\ab\tc", "\t\a"));
180 }
181
182 static void test_ascii_strlower(void) {
183 char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
184 assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
185 }
186
187 static void test_strshorten(void) {
188 char s[] = "foobar";
189
190 assert_se(strlen(strshorten(s, 6)) == 6);
191 assert_se(strlen(strshorten(s, 12)) == 6);
192 assert_se(strlen(strshorten(s, 2)) == 2);
193 assert_se(strlen(strshorten(s, 0)) == 0);
194 }
195
196 static void test_strjoina(void) {
197 char *actual;
198
199 actual = strjoina("", "foo", "bar");
200 assert_se(streq(actual, "foobar"));
201
202 actual = strjoina("foo", "bar", "baz");
203 assert_se(streq(actual, "foobarbaz"));
204
205 actual = strjoina("foo", "", "bar", "baz");
206 assert_se(streq(actual, "foobarbaz"));
207
208 actual = strjoina("foo");
209 assert_se(streq(actual, "foo"));
210
211 actual = strjoina(NULL);
212 assert_se(streq(actual, ""));
213
214 actual = strjoina(NULL, "foo");
215 assert_se(streq(actual, ""));
216
217 actual = strjoina("foo", NULL, "bar");
218 assert_se(streq(actual, "foo"));
219 }
220
221 static void test_strcmp_ptr(void) {
222 assert_se(strcmp_ptr(NULL, NULL) == 0);
223 assert_se(strcmp_ptr("", NULL) > 0);
224 assert_se(strcmp_ptr("foo", NULL) > 0);
225 assert_se(strcmp_ptr(NULL, "") < 0);
226 assert_se(strcmp_ptr(NULL, "bar") < 0);
227 assert_se(strcmp_ptr("foo", "bar") > 0);
228 assert_se(strcmp_ptr("bar", "baz") < 0);
229 assert_se(strcmp_ptr("foo", "foo") == 0);
230 assert_se(strcmp_ptr("", "") == 0);
231 }
232
233 static void test_foreach_word(void) {
234 const char *word, *state;
235 size_t l;
236 int i = 0;
237 const char test[] = "test abc d\te f ";
238 const char * const expected[] = {
239 "test",
240 "abc",
241 "d",
242 "e",
243 "f",
244 "",
245 NULL
246 };
247
248 FOREACH_WORD(word, l, test, state)
249 assert_se(strneq(expected[i++], word, l));
250 }
251
252 static void check(const char *test, char** expected, bool trailing) {
253 int i = 0, r;
254
255 printf("<<<%s>>>\n", test);
256 for (;;) {
257 _cleanup_free_ char *word = NULL;
258
259 r = extract_first_word(&test, &word, NULL, EXTRACT_QUOTES);
260 if (r == 0) {
261 assert_se(!trailing);
262 break;
263 } else if (r < 0) {
264 assert_se(trailing);
265 break;
266 }
267
268 assert_se(streq(word, expected[i++]));
269 printf("<%s>\n", word);
270 }
271 assert_se(expected[i] == NULL);
272 }
273
274 static void test_foreach_word_quoted(void) {
275 check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
276 STRV_MAKE("test",
277 "a",
278 "b",
279 "c",
280 "d",
281 "e",
282 "",
283 "",
284 "hhh",
285 "",
286 "",
287 "a b c"),
288 false);
289
290 check("test \"xxx",
291 STRV_MAKE("test"),
292 true);
293
294 check("test\\",
295 STRV_MAKE_EMPTY,
296 true);
297 }
298
299 static void test_endswith(void) {
300 assert_se(endswith("foobar", "bar"));
301 assert_se(endswith("foobar", ""));
302 assert_se(endswith("foobar", "foobar"));
303 assert_se(endswith("", ""));
304
305 assert_se(!endswith("foobar", "foo"));
306 assert_se(!endswith("foobar", "foobarfoofoo"));
307 }
308
309 static void test_endswith_no_case(void) {
310 assert_se(endswith_no_case("fooBAR", "bar"));
311 assert_se(endswith_no_case("foobar", ""));
312 assert_se(endswith_no_case("foobar", "FOOBAR"));
313 assert_se(endswith_no_case("", ""));
314
315 assert_se(!endswith_no_case("foobar", "FOO"));
316 assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
317 }
318
319 static void test_delete_chars(void) {
320 char *s, input[] = " hello, waldo. abc";
321
322 s = delete_chars(input, WHITESPACE);
323 assert_se(streq(s, "hello,waldo.abc"));
324 assert_se(s == input);
325 }
326
327 static void test_delete_trailing_chars(void) {
328
329 char *s,
330 input1[] = " \n \r k \n \r ",
331 input2[] = "kkkkthiskkkiskkkaktestkkk",
332 input3[] = "abcdef";
333
334 s = delete_trailing_chars(input1, WHITESPACE);
335 assert_se(streq(s, " \n \r k"));
336 assert_se(s == input1);
337
338 s = delete_trailing_chars(input2, "kt");
339 assert_se(streq(s, "kkkkthiskkkiskkkaktes"));
340 assert_se(s == input2);
341
342 s = delete_trailing_chars(input3, WHITESPACE);
343 assert_se(streq(s, "abcdef"));
344 assert_se(s == input3);
345
346 s = delete_trailing_chars(input3, "fe");
347 assert_se(streq(s, "abcd"));
348 assert_se(s == input3);
349 }
350
351 static void test_delete_trailing_slashes(void) {
352 char s1[] = "foobar//",
353 s2[] = "foobar/",
354 s3[] = "foobar",
355 s4[] = "";
356
357 assert_se(streq(delete_trailing_chars(s1, "_"), "foobar//"));
358 assert_se(streq(delete_trailing_chars(s1, "/"), "foobar"));
359 assert_se(streq(delete_trailing_chars(s2, "/"), "foobar"));
360 assert_se(streq(delete_trailing_chars(s3, "/"), "foobar"));
361 assert_se(streq(delete_trailing_chars(s4, "/"), ""));
362 }
363
364 static void test_skip_leading_chars(void) {
365 char input1[] = " \n \r k \n \r ",
366 input2[] = "kkkkthiskkkiskkkaktestkkk",
367 input3[] = "abcdef";
368
369 assert_se(streq(skip_leading_chars(input1, WHITESPACE), "k \n \r "));
370 assert_se(streq(skip_leading_chars(input2, "k"), "thiskkkiskkkaktestkkk"));
371 assert_se(streq(skip_leading_chars(input2, "tk"), "hiskkkiskkkaktestkkk"));
372 assert_se(streq(skip_leading_chars(input3, WHITESPACE), "abcdef"));
373 assert_se(streq(skip_leading_chars(input3, "bcaef"), "def"));
374 }
375
376 static void test_in_charset(void) {
377 assert_se(in_charset("dddaaabbbcccc", "abcd"));
378 assert_se(!in_charset("dddaaabbbcccc", "abc f"));
379 }
380
381 static void test_split_pair(void) {
382 _cleanup_free_ char *a = NULL, *b = NULL;
383
384 assert_se(split_pair("", "", &a, &b) == -EINVAL);
385 assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
386 assert_se(split_pair("", "=", &a, &b) == -EINVAL);
387 assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
388 assert_se(streq(a, "foo"));
389 assert_se(streq(b, "bar"));
390 free(a);
391 free(b);
392 assert_se(split_pair("==", "==", &a, &b) >= 0);
393 assert_se(streq(a, ""));
394 assert_se(streq(b, ""));
395 free(a);
396 free(b);
397
398 assert_se(split_pair("===", "==", &a, &b) >= 0);
399 assert_se(streq(a, ""));
400 assert_se(streq(b, "="));
401 }
402
403 static void test_first_word(void) {
404 assert_se(first_word("Hello", ""));
405 assert_se(first_word("Hello", "Hello"));
406 assert_se(first_word("Hello world", "Hello"));
407 assert_se(first_word("Hello\tworld", "Hello"));
408 assert_se(first_word("Hello\nworld", "Hello"));
409 assert_se(first_word("Hello\rworld", "Hello"));
410 assert_se(first_word("Hello ", "Hello"));
411
412 assert_se(!first_word("Hello", "Hellooo"));
413 assert_se(!first_word("Hello", "xxxxx"));
414 assert_se(!first_word("Hellooo", "Hello"));
415 }
416
417 static void test_strlen_ptr(void) {
418 assert_se(strlen_ptr("foo") == 3);
419 assert_se(strlen_ptr("") == 0);
420 assert_se(strlen_ptr(NULL) == 0);
421 }
422
423 int main(int argc, char *argv[]) {
424 test_string_erase();
425 test_ascii_strcasecmp_n();
426 test_ascii_strcasecmp_nn();
427 test_streq_ptr();
428 test_strstrip();
429 test_strextend();
430 test_strextend_with_separator();
431 test_strrep();
432 test_strappend();
433 test_string_has_cc();
434 test_ascii_strlower();
435 test_strshorten();
436 test_strjoina();
437 test_strcmp_ptr();
438 test_foreach_word();
439 test_foreach_word_quoted();
440 test_endswith();
441 test_endswith_no_case();
442 test_delete_chars();
443 test_delete_trailing_chars();
444 test_delete_trailing_slashes();
445 test_skip_leading_chars();
446 test_in_charset();
447 test_split_pair();
448 test_first_word();
449 test_strlen_ptr();
450
451 return 0;
452 }