]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
9fe4ea21 | 2 | |
8d915666 ZJS |
3 | #include <ctype.h> |
4 | ||
6571a64e | 5 | #include "alloc-util.h" |
8409f688 | 6 | #include "locale-util.h" |
6571a64e | 7 | #include "macro.h" |
9fe4ea21 | 8 | #include "string-util.h" |
6571a64e | 9 | #include "strv.h" |
7f546026 | 10 | #include "tests.h" |
9924aef6 | 11 | #include "utf8.h" |
9fe4ea21 | 12 | |
4f7452a8 | 13 | TEST(string_erase) { |
0176728a | 14 | char *x; |
2f82562b | 15 | x = strdupa_safe(""); |
53caaffd LP |
16 | assert_se(streq(string_erase(x), "")); |
17 | ||
2f82562b | 18 | x = strdupa_safe("1"); |
53caaffd LP |
19 | assert_se(streq(string_erase(x), "")); |
20 | ||
2f82562b | 21 | x = strdupa_safe("123456789"); |
53caaffd LP |
22 | assert_se(streq(string_erase(x), "")); |
23 | ||
24 | assert_se(x[1] == '\0'); | |
25 | assert_se(x[2] == '\0'); | |
26 | assert_se(x[3] == '\0'); | |
27 | assert_se(x[4] == '\0'); | |
28 | assert_se(x[5] == '\0'); | |
29 | assert_se(x[6] == '\0'); | |
30 | assert_se(x[7] == '\0'); | |
31 | assert_se(x[8] == '\0'); | |
32 | assert_se(x[9] == '\0'); | |
33 | } | |
34 | ||
7f546026 | 35 | static void test_free_and_strndup_one(char **t, const char *src, size_t l, const char *expected, bool change) { |
c0f86d66 | 36 | log_debug("%s: \"%s\", \"%s\", %zu (expect \"%s\", %s)", |
7f546026 ZJS |
37 | __func__, strnull(*t), strnull(src), l, strnull(expected), yes_no(change)); |
38 | ||
0176728a | 39 | int r = free_and_strndup(t, src, l); |
7f546026 ZJS |
40 | assert_se(streq_ptr(*t, expected)); |
41 | assert_se(r == change); /* check that change occurs only when necessary */ | |
42 | } | |
43 | ||
4f7452a8 | 44 | TEST(free_and_strndup) { |
7f546026 ZJS |
45 | static const struct test_case { |
46 | const char *src; | |
47 | size_t len; | |
48 | const char *expected; | |
49 | } cases[] = { | |
50 | {"abc", 0, ""}, | |
51 | {"abc", 0, ""}, | |
52 | {"abc", 1, "a"}, | |
53 | {"abc", 2, "ab"}, | |
54 | {"abc", 3, "abc"}, | |
55 | {"abc", 4, "abc"}, | |
56 | {"abc", 5, "abc"}, | |
57 | {"abc", 5, "abc"}, | |
58 | {"abc", 4, "abc"}, | |
59 | {"abc", 3, "abc"}, | |
60 | {"abc", 2, "ab"}, | |
61 | {"abc", 1, "a"}, | |
62 | {"abc", 0, ""}, | |
63 | ||
64 | {"", 0, ""}, | |
65 | {"", 1, ""}, | |
66 | {"", 2, ""}, | |
67 | {"", 0, ""}, | |
68 | {"", 1, ""}, | |
69 | {"", 2, ""}, | |
70 | {"", 2, ""}, | |
71 | {"", 1, ""}, | |
72 | {"", 0, ""}, | |
73 | ||
74 | {NULL, 0, NULL}, | |
75 | ||
76 | {"foo", 3, "foo"}, | |
77 | {"foobar", 6, "foobar"}, | |
78 | }; | |
79 | ||
80 | _cleanup_free_ char *t = NULL; | |
81 | const char *prev_expected = t; | |
82 | ||
83 | for (unsigned i = 0; i < ELEMENTSOF(cases); i++) { | |
84 | test_free_and_strndup_one(&t, | |
85 | cases[i].src, cases[i].len, cases[i].expected, | |
86 | !streq_ptr(cases[i].expected, prev_expected)); | |
87 | prev_expected = t; | |
88 | } | |
89 | } | |
90 | ||
4f7452a8 | 91 | TEST(ascii_strcasecmp_n) { |
522d85ae LP |
92 | assert_se(ascii_strcasecmp_n("", "", 0) == 0); |
93 | assert_se(ascii_strcasecmp_n("", "", 1) == 0); | |
94 | assert_se(ascii_strcasecmp_n("", "a", 1) < 0); | |
95 | assert_se(ascii_strcasecmp_n("", "a", 2) < 0); | |
96 | assert_se(ascii_strcasecmp_n("a", "", 1) > 0); | |
97 | assert_se(ascii_strcasecmp_n("a", "", 2) > 0); | |
98 | assert_se(ascii_strcasecmp_n("a", "a", 1) == 0); | |
99 | assert_se(ascii_strcasecmp_n("a", "a", 2) == 0); | |
100 | assert_se(ascii_strcasecmp_n("a", "b", 1) < 0); | |
101 | assert_se(ascii_strcasecmp_n("a", "b", 2) < 0); | |
102 | assert_se(ascii_strcasecmp_n("b", "a", 1) > 0); | |
103 | assert_se(ascii_strcasecmp_n("b", "a", 2) > 0); | |
104 | assert_se(ascii_strcasecmp_n("xxxxyxxxx", "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 | assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxYxxxx", 9) < 0); | |
109 | ||
110 | assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxYxxxx", 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 | assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxXxxxx", 9) > 0); | |
115 | } | |
116 | ||
4f7452a8 | 117 | TEST(ascii_strcasecmp_nn) { |
c1749834 LP |
118 | assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0); |
119 | assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0); | |
120 | assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0); | |
121 | assert_se(ascii_strcasecmp_nn("", 1, "", 1) == 0); | |
122 | ||
123 | assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaAa", 4) == 0); | |
124 | assert_se(ascii_strcasecmp_nn("aaa", 3, "aaAa", 4) < 0); | |
125 | assert_se(ascii_strcasecmp_nn("aaa", 4, "aaAa", 4) < 0); | |
126 | assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaA", 3) > 0); | |
127 | assert_se(ascii_strcasecmp_nn("aaaa", 4, "AAA", 4) > 0); | |
128 | ||
129 | assert_se(ascii_strcasecmp_nn("aaaa", 4, "bbbb", 4) < 0); | |
130 | assert_se(ascii_strcasecmp_nn("aaAA", 4, "BBbb", 4) < 0); | |
131 | assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0); | |
132 | } | |
133 | ||
4f7452a8 | 134 | TEST(cellescape) { |
8409f688 ZJS |
135 | char buf[40]; |
136 | ||
61f6e276 LP |
137 | assert_se(streq(cellescape(buf, 1, ""), "")); |
138 | assert_se(streq(cellescape(buf, 1, "1"), "")); | |
139 | assert_se(streq(cellescape(buf, 1, "12"), "")); | |
140 | ||
141 | assert_se(streq(cellescape(buf, 2, ""), "")); | |
142 | assert_se(streq(cellescape(buf, 2, "1"), "1")); | |
143 | assert_se(streq(cellescape(buf, 2, "12"), ".")); | |
144 | assert_se(streq(cellescape(buf, 2, "123"), ".")); | |
145 | ||
146 | assert_se(streq(cellescape(buf, 3, ""), "")); | |
147 | assert_se(streq(cellescape(buf, 3, "1"), "1")); | |
148 | assert_se(streq(cellescape(buf, 3, "12"), "12")); | |
149 | assert_se(streq(cellescape(buf, 3, "123"), "..")); | |
150 | assert_se(streq(cellescape(buf, 3, "1234"), "..")); | |
151 | ||
152 | assert_se(streq(cellescape(buf, 4, ""), "")); | |
153 | assert_se(streq(cellescape(buf, 4, "1"), "1")); | |
154 | assert_se(streq(cellescape(buf, 4, "12"), "12")); | |
155 | assert_se(streq(cellescape(buf, 4, "123"), "123")); | |
156 | assert_se(streq(cellescape(buf, 4, "1234"), is_locale_utf8() ? "…" : "...")); | |
157 | assert_se(streq(cellescape(buf, 4, "12345"), is_locale_utf8() ? "…" : "...")); | |
158 | ||
159 | assert_se(streq(cellescape(buf, 5, ""), "")); | |
160 | assert_se(streq(cellescape(buf, 5, "1"), "1")); | |
161 | assert_se(streq(cellescape(buf, 5, "12"), "12")); | |
162 | assert_se(streq(cellescape(buf, 5, "123"), "123")); | |
163 | assert_se(streq(cellescape(buf, 5, "1234"), "1234")); | |
164 | assert_se(streq(cellescape(buf, 5, "12345"), is_locale_utf8() ? "1…" : "1...")); | |
165 | assert_se(streq(cellescape(buf, 5, "123456"), is_locale_utf8() ? "1…" : "1...")); | |
166 | ||
167 | assert_se(streq(cellescape(buf, 1, "\020"), "")); | |
168 | assert_se(streq(cellescape(buf, 2, "\020"), ".")); | |
169 | assert_se(streq(cellescape(buf, 3, "\020"), "..")); | |
647082cf | 170 | assert_se(streq(cellescape(buf, 4, "\020"), is_locale_utf8() ? "…" : "...")); |
61f6e276 LP |
171 | assert_se(streq(cellescape(buf, 5, "\020"), "\\020")); |
172 | ||
647082cf | 173 | assert_se(streq(cellescape(buf, 5, "1234\020"), is_locale_utf8() ? "1…" : "1...")); |
174 | assert_se(streq(cellescape(buf, 6, "1234\020"), is_locale_utf8() ? "12…" : "12...")); | |
175 | assert_se(streq(cellescape(buf, 7, "1234\020"), is_locale_utf8() ? "123…" : "123...")); | |
176 | assert_se(streq(cellescape(buf, 8, "1234\020"), is_locale_utf8() ? "1234…" : "1234...")); | |
61f6e276 LP |
177 | assert_se(streq(cellescape(buf, 9, "1234\020"), "1234\\020")); |
178 | ||
179 | assert_se(streq(cellescape(buf, 1, "\t\n"), "")); | |
180 | assert_se(streq(cellescape(buf, 2, "\t\n"), ".")); | |
181 | assert_se(streq(cellescape(buf, 3, "\t\n"), "..")); | |
647082cf | 182 | assert_se(streq(cellescape(buf, 4, "\t\n"), is_locale_utf8() ? "…" : "...")); |
61f6e276 LP |
183 | assert_se(streq(cellescape(buf, 5, "\t\n"), "\\t\\n")); |
184 | ||
647082cf | 185 | assert_se(streq(cellescape(buf, 5, "1234\t\n"), is_locale_utf8() ? "1…" : "1...")); |
186 | assert_se(streq(cellescape(buf, 6, "1234\t\n"), is_locale_utf8() ? "12…" : "12...")); | |
187 | assert_se(streq(cellescape(buf, 7, "1234\t\n"), is_locale_utf8() ? "123…" : "123...")); | |
188 | assert_se(streq(cellescape(buf, 8, "1234\t\n"), is_locale_utf8() ? "1234…" : "1234...")); | |
61f6e276 LP |
189 | assert_se(streq(cellescape(buf, 9, "1234\t\n"), "1234\\t\\n")); |
190 | ||
647082cf | 191 | assert_se(streq(cellescape(buf, 4, "x\t\020\n"), is_locale_utf8() ? "…" : "...")); |
192 | assert_se(streq(cellescape(buf, 5, "x\t\020\n"), is_locale_utf8() ? "x…" : "x...")); | |
193 | assert_se(streq(cellescape(buf, 6, "x\t\020\n"), is_locale_utf8() ? "x…" : "x...")); | |
194 | assert_se(streq(cellescape(buf, 7, "x\t\020\n"), is_locale_utf8() ? "x\\t…" : "x\\t...")); | |
195 | assert_se(streq(cellescape(buf, 8, "x\t\020\n"), is_locale_utf8() ? "x\\t…" : "x\\t...")); | |
196 | assert_se(streq(cellescape(buf, 9, "x\t\020\n"), is_locale_utf8() ? "x\\t…" : "x\\t...")); | |
61f6e276 LP |
197 | assert_se(streq(cellescape(buf, 10, "x\t\020\n"), "x\\t\\020\\n")); |
198 | ||
199 | assert_se(streq(cellescape(buf, 6, "1\011"), "1\\t")); | |
200 | assert_se(streq(cellescape(buf, 6, "1\020"), "1\\020")); | |
201 | assert_se(streq(cellescape(buf, 6, "1\020x"), is_locale_utf8() ? "1…" : "1...")); | |
8409f688 ZJS |
202 | |
203 | assert_se(streq(cellescape(buf, 40, "1\020"), "1\\020")); | |
204 | assert_se(streq(cellescape(buf, 40, "1\020x"), "1\\020x")); | |
205 | ||
206 | assert_se(streq(cellescape(buf, 40, "\a\b\f\n\r\t\v\\\"'"), "\\a\\b\\f\\n\\r\\t\\v\\\\\\\"\\'")); | |
61f6e276 LP |
207 | assert_se(streq(cellescape(buf, 6, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a...")); |
208 | assert_se(streq(cellescape(buf, 7, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a...")); | |
209 | assert_se(streq(cellescape(buf, 8, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a\\b…" : "\\a\\b...")); | |
8409f688 ZJS |
210 | |
211 | assert_se(streq(cellescape(buf, sizeof buf, "1\020"), "1\\020")); | |
212 | assert_se(streq(cellescape(buf, sizeof buf, "1\020x"), "1\\020x")); | |
213 | } | |
214 | ||
4f7452a8 | 215 | TEST(streq_ptr) { |
6571a64e RC |
216 | assert_se(streq_ptr(NULL, NULL)); |
217 | assert_se(!streq_ptr("abc", "cdef")); | |
218 | } | |
219 | ||
4f7452a8 | 220 | TEST(strstrip) { |
0176728a | 221 | char *ret, input[] = " hello, waldo. "; |
6571a64e | 222 | |
0176728a ZJS |
223 | ret = strstrip(input); |
224 | assert_se(streq(ret, "hello, waldo.")); | |
6571a64e RC |
225 | } |
226 | ||
4f7452a8 | 227 | TEST(strextend) { |
bb8ad9ea LP |
228 | _cleanup_free_ char *str = NULL; |
229 | ||
230 | assert_se(strextend(&str, NULL)); | |
231 | assert_se(streq_ptr(str, "")); | |
c2bc710b | 232 | assert_se(strextend(&str, "", "0", "", "", "123")); |
bb8ad9ea | 233 | assert_se(streq_ptr(str, "0123")); |
c2bc710b | 234 | assert_se(strextend(&str, "456", "78", "9")); |
bb8ad9ea LP |
235 | assert_se(streq_ptr(str, "0123456789")); |
236 | } | |
237 | ||
4f7452a8 | 238 | TEST(strextend_with_separator) { |
bb8ad9ea LP |
239 | _cleanup_free_ char *str = NULL; |
240 | ||
241 | assert_se(strextend_with_separator(&str, NULL, NULL)); | |
242 | assert_se(streq_ptr(str, "")); | |
243 | str = mfree(str); | |
244 | ||
245 | assert_se(strextend_with_separator(&str, "...", NULL)); | |
246 | assert_se(streq_ptr(str, "")); | |
247 | assert_se(strextend_with_separator(&str, "...", NULL)); | |
248 | assert_se(streq_ptr(str, "")); | |
249 | str = mfree(str); | |
250 | ||
c2bc710b | 251 | assert_se(strextend_with_separator(&str, "xyz", "a", "bb", "ccc")); |
bb8ad9ea LP |
252 | assert_se(streq_ptr(str, "axyzbbxyzccc")); |
253 | str = mfree(str); | |
254 | ||
c2bc710b | 255 | assert_se(strextend_with_separator(&str, ",", "start", "", "1", "234")); |
bb8ad9ea | 256 | assert_se(streq_ptr(str, "start,,1,234")); |
c2bc710b | 257 | assert_se(strextend_with_separator(&str, ";", "more", "5", "678")); |
bb8ad9ea | 258 | assert_se(streq_ptr(str, "start,,1,234;more;5;678")); |
6571a64e RC |
259 | } |
260 | ||
4f7452a8 | 261 | TEST(strrep) { |
6571a64e RC |
262 | _cleanup_free_ char *one, *three, *zero; |
263 | one = strrep("waldo", 1); | |
264 | three = strrep("waldo", 3); | |
265 | zero = strrep("waldo", 0); | |
266 | ||
267 | assert_se(streq(one, "waldo")); | |
268 | assert_se(streq(three, "waldowaldowaldo")); | |
269 | assert_se(streq(zero, "")); | |
270 | } | |
271 | ||
4f7452a8 | 272 | TEST(string_has_cc) { |
6571a64e RC |
273 | assert_se(string_has_cc("abc\1", NULL)); |
274 | assert_se(string_has_cc("abc\x7f", NULL)); | |
275 | assert_se(string_has_cc("abc\x7f", NULL)); | |
276 | assert_se(string_has_cc("abc\t\x7f", "\t")); | |
277 | assert_se(string_has_cc("abc\t\x7f", "\t")); | |
278 | assert_se(string_has_cc("\x7f", "\t")); | |
279 | assert_se(string_has_cc("\x7f", "\t\a")); | |
280 | ||
281 | assert_se(!string_has_cc("abc\t\t", "\t")); | |
282 | assert_se(!string_has_cc("abc\t\t\a", "\t\a")); | |
283 | assert_se(!string_has_cc("a\ab\tc", "\t\a")); | |
284 | } | |
285 | ||
4f7452a8 | 286 | TEST(ascii_strlower) { |
6571a64e RC |
287 | char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK"; |
288 | assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk")); | |
289 | } | |
290 | ||
4f7452a8 | 291 | TEST(strshorten) { |
6571a64e RC |
292 | char s[] = "foobar"; |
293 | ||
294 | assert_se(strlen(strshorten(s, 6)) == 6); | |
295 | assert_se(strlen(strshorten(s, 12)) == 6); | |
296 | assert_se(strlen(strshorten(s, 2)) == 2); | |
297 | assert_se(strlen(strshorten(s, 0)) == 0); | |
298 | } | |
299 | ||
4f7452a8 | 300 | TEST(strjoina) { |
6571a64e RC |
301 | char *actual; |
302 | ||
303 | actual = strjoina("", "foo", "bar"); | |
304 | assert_se(streq(actual, "foobar")); | |
305 | ||
306 | actual = strjoina("foo", "bar", "baz"); | |
307 | assert_se(streq(actual, "foobarbaz")); | |
308 | ||
309 | actual = strjoina("foo", "", "bar", "baz"); | |
310 | assert_se(streq(actual, "foobarbaz")); | |
311 | ||
312 | actual = strjoina("foo"); | |
313 | assert_se(streq(actual, "foo")); | |
314 | ||
315 | actual = strjoina(NULL); | |
316 | assert_se(streq(actual, "")); | |
317 | ||
318 | actual = strjoina(NULL, "foo"); | |
319 | assert_se(streq(actual, "")); | |
320 | ||
321 | actual = strjoina("foo", NULL, "bar"); | |
322 | assert_se(streq(actual, "foo")); | |
e4645ca5 ZJS |
323 | |
324 | actual = strjoina("/sys/fs/cgroup/", "dn", "/a/b/c", "/cgroup.procs"); | |
325 | assert_se(streq(actual, "/sys/fs/cgroup/dn/a/b/c/cgroup.procs")); | |
326 | ||
327 | actual = strjoina("/sys/fs/cgroup/", "dn", NULL, NULL); | |
328 | assert_se(streq(actual, "/sys/fs/cgroup/dn")); | |
6571a64e RC |
329 | } |
330 | ||
4f7452a8 | 331 | TEST(strjoin) { |
7eac7b4c ZJS |
332 | char *actual; |
333 | ||
334 | actual = strjoin("", "foo", "bar"); | |
335 | assert_se(streq(actual, "foobar")); | |
336 | mfree(actual); | |
337 | ||
338 | actual = strjoin("foo", "bar", "baz"); | |
339 | assert_se(streq(actual, "foobarbaz")); | |
340 | mfree(actual); | |
341 | ||
342 | actual = strjoin("foo", "", "bar", "baz"); | |
343 | assert_se(streq(actual, "foobarbaz")); | |
344 | mfree(actual); | |
345 | ||
346 | actual = strjoin("foo", NULL); | |
347 | assert_se(streq(actual, "foo")); | |
348 | mfree(actual); | |
349 | ||
350 | actual = strjoin(NULL, NULL); | |
351 | assert_se(streq(actual, "")); | |
352 | mfree(actual); | |
353 | ||
354 | actual = strjoin(NULL, "foo"); | |
355 | assert_se(streq(actual, "")); | |
356 | mfree(actual); | |
357 | ||
358 | actual = strjoin("foo", NULL, "bar"); | |
359 | assert_se(streq(actual, "foo")); | |
360 | mfree(actual); | |
361 | } | |
362 | ||
4f7452a8 | 363 | TEST(strcmp_ptr) { |
6571a64e RC |
364 | assert_se(strcmp_ptr(NULL, NULL) == 0); |
365 | assert_se(strcmp_ptr("", NULL) > 0); | |
366 | assert_se(strcmp_ptr("foo", NULL) > 0); | |
367 | assert_se(strcmp_ptr(NULL, "") < 0); | |
368 | assert_se(strcmp_ptr(NULL, "bar") < 0); | |
369 | assert_se(strcmp_ptr("foo", "bar") > 0); | |
370 | assert_se(strcmp_ptr("bar", "baz") < 0); | |
371 | assert_se(strcmp_ptr("foo", "foo") == 0); | |
372 | assert_se(strcmp_ptr("", "") == 0); | |
373 | } | |
374 | ||
4f7452a8 | 375 | TEST(foreach_word) { |
d59d954d | 376 | const char *test = "test abc d\te f "; |
6571a64e RC |
377 | const char * const expected[] = { |
378 | "test", | |
379 | "abc", | |
380 | "d", | |
381 | "e", | |
382 | "f", | |
6571a64e RC |
383 | }; |
384 | ||
d59d954d ZJS |
385 | size_t i = 0; |
386 | int r; | |
387 | for (const char *p = test;;) { | |
388 | _cleanup_free_ char *word = NULL; | |
389 | ||
390 | r = extract_first_word(&p, &word, NULL, 0); | |
391 | if (r == 0) { | |
392 | assert_se(i == ELEMENTSOF(expected)); | |
393 | break; | |
394 | } | |
395 | assert_se(r > 0); | |
396 | ||
397 | assert_se(streq(expected[i++], word)); | |
398 | } | |
6571a64e RC |
399 | } |
400 | ||
401 | static void check(const char *test, char** expected, bool trailing) { | |
d59d954d ZJS |
402 | size_t i = 0; |
403 | int r; | |
6571a64e RC |
404 | |
405 | printf("<<<%s>>>\n", test); | |
bc8ec170 ZJS |
406 | for (;;) { |
407 | _cleanup_free_ char *word = NULL; | |
408 | ||
4ec85141 | 409 | r = extract_first_word(&test, &word, NULL, EXTRACT_UNQUOTE); |
bc8ec170 ZJS |
410 | if (r == 0) { |
411 | assert_se(!trailing); | |
412 | break; | |
413 | } else if (r < 0) { | |
414 | assert_se(trailing); | |
415 | break; | |
416 | } | |
417 | ||
418 | assert_se(streq(word, expected[i++])); | |
419 | printf("<%s>\n", word); | |
6571a64e | 420 | } |
6571a64e | 421 | assert_se(expected[i] == NULL); |
6571a64e RC |
422 | } |
423 | ||
4f7452a8 | 424 | TEST(foreach_word_quoted) { |
6571a64e RC |
425 | check("test a b c 'd' e '' '' hhh '' '' \"a b c\"", |
426 | STRV_MAKE("test", | |
427 | "a", | |
428 | "b", | |
429 | "c", | |
430 | "d", | |
431 | "e", | |
432 | "", | |
433 | "", | |
434 | "hhh", | |
435 | "", | |
436 | "", | |
437 | "a b c"), | |
438 | false); | |
439 | ||
440 | check("test \"xxx", | |
441 | STRV_MAKE("test"), | |
442 | true); | |
443 | ||
444 | check("test\\", | |
445 | STRV_MAKE_EMPTY, | |
446 | true); | |
447 | } | |
448 | ||
4f7452a8 | 449 | TEST(endswith) { |
6571a64e RC |
450 | assert_se(endswith("foobar", "bar")); |
451 | assert_se(endswith("foobar", "")); | |
452 | assert_se(endswith("foobar", "foobar")); | |
453 | assert_se(endswith("", "")); | |
454 | ||
455 | assert_se(!endswith("foobar", "foo")); | |
456 | assert_se(!endswith("foobar", "foobarfoofoo")); | |
457 | } | |
458 | ||
4f7452a8 | 459 | TEST(endswith_no_case) { |
6571a64e RC |
460 | assert_se(endswith_no_case("fooBAR", "bar")); |
461 | assert_se(endswith_no_case("foobar", "")); | |
462 | assert_se(endswith_no_case("foobar", "FOOBAR")); | |
463 | assert_se(endswith_no_case("", "")); | |
464 | ||
465 | assert_se(!endswith_no_case("foobar", "FOO")); | |
466 | assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO")); | |
467 | } | |
468 | ||
4f7452a8 | 469 | TEST(delete_chars) { |
7546145e LP |
470 | char *s, input[] = " hello, waldo. abc"; |
471 | ||
472 | s = delete_chars(input, WHITESPACE); | |
473 | assert_se(streq(s, "hello,waldo.abc")); | |
474 | assert_se(s == input); | |
475 | } | |
476 | ||
4f7452a8 | 477 | TEST(delete_trailing_chars) { |
7546145e LP |
478 | char *s, |
479 | input1[] = " \n \r k \n \r ", | |
480 | input2[] = "kkkkthiskkkiskkkaktestkkk", | |
481 | input3[] = "abcdef"; | |
482 | ||
483 | s = delete_trailing_chars(input1, WHITESPACE); | |
484 | assert_se(streq(s, " \n \r k")); | |
485 | assert_se(s == input1); | |
486 | ||
487 | s = delete_trailing_chars(input2, "kt"); | |
488 | assert_se(streq(s, "kkkkthiskkkiskkkaktes")); | |
489 | assert_se(s == input2); | |
490 | ||
491 | s = delete_trailing_chars(input3, WHITESPACE); | |
492 | assert_se(streq(s, "abcdef")); | |
493 | assert_se(s == input3); | |
494 | ||
495 | s = delete_trailing_chars(input3, "fe"); | |
496 | assert_se(streq(s, "abcd")); | |
497 | assert_se(s == input3); | |
498 | } | |
499 | ||
4f7452a8 | 500 | TEST(delete_trailing_slashes) { |
ca4d708d ZJS |
501 | char s1[] = "foobar//", |
502 | s2[] = "foobar/", | |
503 | s3[] = "foobar", | |
504 | s4[] = ""; | |
505 | ||
506 | assert_se(streq(delete_trailing_chars(s1, "_"), "foobar//")); | |
507 | assert_se(streq(delete_trailing_chars(s1, "/"), "foobar")); | |
508 | assert_se(streq(delete_trailing_chars(s2, "/"), "foobar")); | |
509 | assert_se(streq(delete_trailing_chars(s3, "/"), "foobar")); | |
510 | assert_se(streq(delete_trailing_chars(s4, "/"), "")); | |
511 | } | |
512 | ||
4f7452a8 | 513 | TEST(skip_leading_chars) { |
7546145e LP |
514 | char input1[] = " \n \r k \n \r ", |
515 | input2[] = "kkkkthiskkkiskkkaktestkkk", | |
516 | input3[] = "abcdef"; | |
6571a64e | 517 | |
7546145e LP |
518 | assert_se(streq(skip_leading_chars(input1, WHITESPACE), "k \n \r ")); |
519 | assert_se(streq(skip_leading_chars(input2, "k"), "thiskkkiskkkaktestkkk")); | |
520 | assert_se(streq(skip_leading_chars(input2, "tk"), "hiskkkiskkkaktestkkk")); | |
521 | assert_se(streq(skip_leading_chars(input3, WHITESPACE), "abcdef")); | |
522 | assert_se(streq(skip_leading_chars(input3, "bcaef"), "def")); | |
6571a64e RC |
523 | } |
524 | ||
4f7452a8 | 525 | TEST(in_charset) { |
6571a64e RC |
526 | assert_se(in_charset("dddaaabbbcccc", "abcd")); |
527 | assert_se(!in_charset("dddaaabbbcccc", "abc f")); | |
528 | } | |
529 | ||
4f7452a8 | 530 | TEST(split_pair) { |
6571a64e RC |
531 | _cleanup_free_ char *a = NULL, *b = NULL; |
532 | ||
533 | assert_se(split_pair("", "", &a, &b) == -EINVAL); | |
534 | assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL); | |
535 | assert_se(split_pair("", "=", &a, &b) == -EINVAL); | |
536 | assert_se(split_pair("foo=bar", "=", &a, &b) >= 0); | |
537 | assert_se(streq(a, "foo")); | |
538 | assert_se(streq(b, "bar")); | |
539 | free(a); | |
540 | free(b); | |
541 | assert_se(split_pair("==", "==", &a, &b) >= 0); | |
542 | assert_se(streq(a, "")); | |
543 | assert_se(streq(b, "")); | |
544 | free(a); | |
545 | free(b); | |
546 | ||
547 | assert_se(split_pair("===", "==", &a, &b) >= 0); | |
548 | assert_se(streq(a, "")); | |
549 | assert_se(streq(b, "=")); | |
550 | } | |
551 | ||
4f7452a8 | 552 | TEST(first_word) { |
6571a64e RC |
553 | assert_se(first_word("Hello", "")); |
554 | assert_se(first_word("Hello", "Hello")); | |
555 | assert_se(first_word("Hello world", "Hello")); | |
556 | assert_se(first_word("Hello\tworld", "Hello")); | |
557 | assert_se(first_word("Hello\nworld", "Hello")); | |
558 | assert_se(first_word("Hello\rworld", "Hello")); | |
559 | assert_se(first_word("Hello ", "Hello")); | |
560 | ||
561 | assert_se(!first_word("Hello", "Hellooo")); | |
562 | assert_se(!first_word("Hello", "xxxxx")); | |
563 | assert_se(!first_word("Hellooo", "Hello")); | |
564 | } | |
565 | ||
4f7452a8 | 566 | TEST(strlen_ptr) { |
7bf7ce28 LP |
567 | assert_se(strlen_ptr("foo") == 3); |
568 | assert_se(strlen_ptr("") == 0); | |
569 | assert_se(strlen_ptr(NULL) == 0); | |
570 | } | |
571 | ||
4f7452a8 | 572 | TEST(memory_startswith) { |
9b8ff183 LP |
573 | assert_se(streq(memory_startswith("", 0, ""), "")); |
574 | assert_se(streq(memory_startswith("", 1, ""), "")); | |
575 | assert_se(streq(memory_startswith("x", 2, ""), "x")); | |
576 | assert_se(!memory_startswith("", 1, "x")); | |
577 | assert_se(!memory_startswith("", 1, "xxxxxxxx")); | |
578 | assert_se(streq(memory_startswith("xxx", 4, "x"), "xx")); | |
579 | assert_se(streq(memory_startswith("xxx", 4, "xx"), "x")); | |
580 | assert_se(streq(memory_startswith("xxx", 4, "xxx"), "")); | |
581 | assert_se(!memory_startswith("xxx", 4, "xxxx")); | |
582 | } | |
583 | ||
4f7452a8 | 584 | TEST(memory_startswith_no_case) { |
21224070 DP |
585 | assert_se(streq(memory_startswith_no_case("", 0, ""), "")); |
586 | assert_se(streq(memory_startswith_no_case("", 1, ""), "")); | |
587 | assert_se(streq(memory_startswith_no_case("x", 2, ""), "x")); | |
588 | assert_se(streq(memory_startswith_no_case("X", 2, ""), "X")); | |
589 | assert_se(!memory_startswith_no_case("", 1, "X")); | |
590 | assert_se(!memory_startswith_no_case("", 1, "xxxxXXXX")); | |
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, "X"), "XX")); | |
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, "XX"), "X")); | |
597 | assert_se(streq(memory_startswith_no_case("xxx", 4, "XXX"), "")); | |
598 | assert_se(streq(memory_startswith_no_case("XXX", 4, "xxx"), "")); | |
599 | assert_se(streq(memory_startswith_no_case("XXX", 4, "XXX"), "")); | |
600 | ||
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 | assert_se(memory_startswith_no_case((char[2]){'X', 'X'}, 2, "XX")); | |
605 | } | |
606 | ||
8dd6491e LP |
607 | static void test_string_truncate_lines_one(const char *input, size_t n_lines, const char *output, bool truncation) { |
608 | _cleanup_free_ char *b = NULL; | |
609 | int k; | |
610 | ||
611 | assert_se((k = string_truncate_lines(input, n_lines, &b)) >= 0); | |
612 | assert_se(streq(b, output)); | |
613 | assert_se(!!k == truncation); | |
614 | } | |
615 | ||
4f7452a8 | 616 | TEST(string_truncate_lines) { |
8dd6491e LP |
617 | test_string_truncate_lines_one("", 0, "", false); |
618 | test_string_truncate_lines_one("", 1, "", false); | |
619 | test_string_truncate_lines_one("", 2, "", false); | |
620 | test_string_truncate_lines_one("", 3, "", false); | |
621 | ||
622 | test_string_truncate_lines_one("x", 0, "", true); | |
623 | test_string_truncate_lines_one("x", 1, "x", false); | |
624 | test_string_truncate_lines_one("x", 2, "x", false); | |
625 | test_string_truncate_lines_one("x", 3, "x", false); | |
626 | ||
627 | test_string_truncate_lines_one("x\n", 0, "", true); | |
628 | test_string_truncate_lines_one("x\n", 1, "x", false); | |
629 | test_string_truncate_lines_one("x\n", 2, "x", false); | |
630 | test_string_truncate_lines_one("x\n", 3, "x", false); | |
631 | ||
632 | test_string_truncate_lines_one("x\ny", 0, "", true); | |
633 | test_string_truncate_lines_one("x\ny", 1, "x", true); | |
634 | test_string_truncate_lines_one("x\ny", 2, "x\ny", false); | |
635 | test_string_truncate_lines_one("x\ny", 3, "x\ny", false); | |
636 | ||
637 | test_string_truncate_lines_one("x\ny\n", 0, "", true); | |
638 | test_string_truncate_lines_one("x\ny\n", 1, "x", true); | |
639 | test_string_truncate_lines_one("x\ny\n", 2, "x\ny", false); | |
640 | test_string_truncate_lines_one("x\ny\n", 3, "x\ny", false); | |
641 | ||
642 | test_string_truncate_lines_one("x\ny\nz", 0, "", true); | |
643 | test_string_truncate_lines_one("x\ny\nz", 1, "x", true); | |
644 | test_string_truncate_lines_one("x\ny\nz", 2, "x\ny", true); | |
645 | test_string_truncate_lines_one("x\ny\nz", 3, "x\ny\nz", false); | |
646 | ||
647 | test_string_truncate_lines_one("x\ny\nz\n", 0, "", true); | |
648 | test_string_truncate_lines_one("x\ny\nz\n", 1, "x", true); | |
649 | test_string_truncate_lines_one("x\ny\nz\n", 2, "x\ny", true); | |
650 | test_string_truncate_lines_one("x\ny\nz\n", 3, "x\ny\nz", false); | |
651 | ||
652 | test_string_truncate_lines_one("\n", 0, "", false); | |
653 | test_string_truncate_lines_one("\n", 1, "", false); | |
654 | test_string_truncate_lines_one("\n", 2, "", false); | |
655 | test_string_truncate_lines_one("\n", 3, "", false); | |
656 | ||
657 | test_string_truncate_lines_one("\n\n", 0, "", false); | |
658 | test_string_truncate_lines_one("\n\n", 1, "", false); | |
659 | test_string_truncate_lines_one("\n\n", 2, "", false); | |
660 | test_string_truncate_lines_one("\n\n", 3, "", false); | |
661 | ||
662 | test_string_truncate_lines_one("\n\n\n", 0, "", false); | |
663 | test_string_truncate_lines_one("\n\n\n", 1, "", false); | |
664 | test_string_truncate_lines_one("\n\n\n", 2, "", false); | |
665 | test_string_truncate_lines_one("\n\n\n", 3, "", false); | |
666 | ||
667 | test_string_truncate_lines_one("\nx\n\n", 0, "", true); | |
668 | test_string_truncate_lines_one("\nx\n\n", 1, "", true); | |
669 | test_string_truncate_lines_one("\nx\n\n", 2, "\nx", false); | |
670 | test_string_truncate_lines_one("\nx\n\n", 3, "\nx", false); | |
671 | ||
672 | test_string_truncate_lines_one("\n\nx\n", 0, "", true); | |
673 | test_string_truncate_lines_one("\n\nx\n", 1, "", true); | |
674 | test_string_truncate_lines_one("\n\nx\n", 2, "", true); | |
675 | test_string_truncate_lines_one("\n\nx\n", 3, "\n\nx", false); | |
676 | } | |
677 | ||
f6857fa6 LP |
678 | static void test_string_extract_lines_one(const char *input, size_t i, const char *output, bool more) { |
679 | _cleanup_free_ char *b = NULL; | |
680 | int k; | |
681 | ||
682 | assert_se((k = string_extract_line(input, i, &b)) >= 0); | |
683 | assert_se(streq(b ?: input, output)); | |
684 | assert_se(!!k == more); | |
685 | } | |
686 | ||
4f7452a8 | 687 | TEST(string_extract_line) { |
f6857fa6 LP |
688 | test_string_extract_lines_one("", 0, "", false); |
689 | test_string_extract_lines_one("", 1, "", false); | |
690 | test_string_extract_lines_one("", 2, "", false); | |
691 | test_string_extract_lines_one("", 3, "", false); | |
692 | ||
693 | test_string_extract_lines_one("x", 0, "x", false); | |
694 | test_string_extract_lines_one("x", 1, "", false); | |
695 | test_string_extract_lines_one("x", 2, "", false); | |
696 | test_string_extract_lines_one("x", 3, "", false); | |
697 | ||
698 | test_string_extract_lines_one("x\n", 0, "x", false); | |
699 | test_string_extract_lines_one("x\n", 1, "", false); | |
700 | test_string_extract_lines_one("x\n", 2, "", false); | |
701 | test_string_extract_lines_one("x\n", 3, "", false); | |
702 | ||
703 | test_string_extract_lines_one("x\ny", 0, "x", true); | |
704 | test_string_extract_lines_one("x\ny", 1, "y", false); | |
705 | test_string_extract_lines_one("x\ny", 2, "", false); | |
706 | test_string_extract_lines_one("x\ny", 3, "", false); | |
707 | ||
708 | test_string_extract_lines_one("x\ny\n", 0, "x", true); | |
709 | test_string_extract_lines_one("x\ny\n", 1, "y", false); | |
710 | test_string_extract_lines_one("x\ny\n", 2, "", false); | |
711 | test_string_extract_lines_one("x\ny\n", 3, "", false); | |
712 | ||
713 | test_string_extract_lines_one("x\ny\nz", 0, "x", true); | |
714 | test_string_extract_lines_one("x\ny\nz", 1, "y", true); | |
715 | test_string_extract_lines_one("x\ny\nz", 2, "z", false); | |
716 | test_string_extract_lines_one("x\ny\nz", 3, "", false); | |
717 | ||
718 | test_string_extract_lines_one("\n", 0, "", false); | |
719 | test_string_extract_lines_one("\n", 1, "", false); | |
720 | test_string_extract_lines_one("\n", 2, "", false); | |
721 | test_string_extract_lines_one("\n", 3, "", false); | |
722 | ||
723 | test_string_extract_lines_one("\n\n", 0, "", true); | |
724 | test_string_extract_lines_one("\n\n", 1, "", false); | |
725 | test_string_extract_lines_one("\n\n", 2, "", false); | |
726 | test_string_extract_lines_one("\n\n", 3, "", false); | |
727 | ||
728 | test_string_extract_lines_one("\n\n\n", 0, "", true); | |
729 | test_string_extract_lines_one("\n\n\n", 1, "", true); | |
730 | test_string_extract_lines_one("\n\n\n", 2, "", false); | |
731 | test_string_extract_lines_one("\n\n\n", 3, "", false); | |
732 | ||
733 | test_string_extract_lines_one("\n\n\n\n", 0, "", true); | |
734 | test_string_extract_lines_one("\n\n\n\n", 1, "", true); | |
735 | test_string_extract_lines_one("\n\n\n\n", 2, "", true); | |
736 | test_string_extract_lines_one("\n\n\n\n", 3, "", false); | |
737 | ||
738 | test_string_extract_lines_one("\nx\n\n\n", 0, "", true); | |
739 | test_string_extract_lines_one("\nx\n\n\n", 1, "x", true); | |
740 | test_string_extract_lines_one("\nx\n\n\n", 2, "", true); | |
741 | test_string_extract_lines_one("\nx\n\n\n", 3, "", false); | |
742 | ||
743 | test_string_extract_lines_one("\n\nx\n\n", 0, "", true); | |
744 | test_string_extract_lines_one("\n\nx\n\n", 1, "", true); | |
745 | test_string_extract_lines_one("\n\nx\n\n", 2, "x", true); | |
746 | test_string_extract_lines_one("\n\nx\n\n", 3, "", false); | |
747 | ||
748 | test_string_extract_lines_one("\n\n\nx\n", 0, "", true); | |
749 | test_string_extract_lines_one("\n\n\nx\n", 1, "", true); | |
750 | test_string_extract_lines_one("\n\n\nx\n", 2, "", true); | |
751 | test_string_extract_lines_one("\n\n\nx\n", 3, "x", false); | |
752 | } | |
753 | ||
4f7452a8 | 754 | TEST(string_contains_word_strv) { |
46bf625a ZJS |
755 | const char *w; |
756 | ||
757 | assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), NULL)); | |
758 | ||
759 | assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), &w)); | |
760 | assert_se(streq(w, "a")); | |
761 | ||
762 | assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE("d"), &w)); | |
763 | assert_se(w == NULL); | |
764 | ||
765 | assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", "a"), &w)); | |
766 | assert_se(streq(w, "a")); | |
767 | ||
768 | assert_se(string_contains_word_strv("b a b cc", NULL, STRV_MAKE("b", "a", "b"), &w)); | |
769 | assert_se(streq(w, "b")); | |
770 | ||
771 | assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", ""), &w)); | |
772 | assert_se(streq(w, "b")); | |
773 | ||
774 | assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE(""), &w)); | |
775 | assert_se(w == NULL); | |
776 | ||
777 | assert_se(string_contains_word_strv("a b cc", " ", STRV_MAKE(""), &w)); | |
778 | assert_se(streq(w, "")); | |
779 | } | |
780 | ||
4f7452a8 | 781 | TEST(string_contains_word) { |
53cd7f33 ZJS |
782 | assert_se( string_contains_word("a b cc", NULL, "a")); |
783 | assert_se( string_contains_word("a b cc", NULL, "b")); | |
784 | assert_se(!string_contains_word("a b cc", NULL, "c")); | |
785 | assert_se( string_contains_word("a b cc", NULL, "cc")); | |
786 | assert_se(!string_contains_word("a b cc", NULL, "d")); | |
787 | assert_se(!string_contains_word("a b cc", NULL, "a b")); | |
788 | assert_se(!string_contains_word("a b cc", NULL, "a b c")); | |
789 | assert_se(!string_contains_word("a b cc", NULL, "b c")); | |
790 | assert_se(!string_contains_word("a b cc", NULL, "b cc")); | |
791 | assert_se(!string_contains_word("a b cc", NULL, "a ")); | |
792 | assert_se(!string_contains_word("a b cc", NULL, " b ")); | |
793 | assert_se(!string_contains_word("a b cc", NULL, " cc")); | |
794 | ||
795 | assert_se( string_contains_word(" a b\t\tcc", NULL, "a")); | |
796 | assert_se( string_contains_word(" a b\t\tcc", NULL, "b")); | |
797 | assert_se(!string_contains_word(" a b\t\tcc", NULL, "c")); | |
798 | assert_se( string_contains_word(" a b\t\tcc", NULL, "cc")); | |
799 | assert_se(!string_contains_word(" a b\t\tcc", NULL, "d")); | |
800 | assert_se(!string_contains_word(" a b\t\tcc", NULL, "a b")); | |
801 | assert_se(!string_contains_word(" a b\t\tcc", NULL, "a b\t\tc")); | |
802 | assert_se(!string_contains_word(" a b\t\tcc", NULL, "b\t\tc")); | |
803 | assert_se(!string_contains_word(" a b\t\tcc", NULL, "b\t\tcc")); | |
804 | assert_se(!string_contains_word(" a b\t\tcc", NULL, "a ")); | |
805 | assert_se(!string_contains_word(" a b\t\tcc", NULL, " b ")); | |
806 | assert_se(!string_contains_word(" a b\t\tcc", NULL, " cc")); | |
807 | ||
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", NULL, " ")); | |
811 | assert_se( string_contains_word(" a b\t\tcc", " ", "")); | |
812 | assert_se( string_contains_word(" a b\t\tcc", "\t", "")); | |
813 | assert_se( string_contains_word(" a b\t\tcc", WHITESPACE, "")); | |
814 | ||
815 | assert_se( string_contains_word("a:b:cc", ":#", "a")); | |
816 | assert_se( string_contains_word("a:b:cc", ":#", "b")); | |
817 | assert_se(!string_contains_word("a:b:cc", ":#", "c")); | |
818 | assert_se( string_contains_word("a:b:cc", ":#", "cc")); | |
819 | assert_se(!string_contains_word("a:b:cc", ":#", "d")); | |
820 | assert_se(!string_contains_word("a:b:cc", ":#", "a:b")); | |
821 | assert_se(!string_contains_word("a:b:cc", ":#", "a:b:c")); | |
822 | assert_se(!string_contains_word("a:b:cc", ":#", "b:c")); | |
823 | assert_se(!string_contains_word("a#b#cc", ":#", "b:cc")); | |
824 | assert_se( string_contains_word("a#b#cc", ":#", "b")); | |
825 | assert_se( string_contains_word("a#b#cc", ":#", "cc")); | |
826 | assert_se(!string_contains_word("a:b:cc", ":#", "a:")); | |
827 | assert_se(!string_contains_word("a:b cc", ":#", "b")); | |
828 | assert_se( string_contains_word("a:b cc", ":#", "b cc")); | |
829 | assert_se(!string_contains_word("a:b:cc", ":#", ":cc")); | |
830 | } | |
831 | ||
d970092f ZJS |
832 | static void test_strverscmp_improved_one(const char* a, const char *b, int expected) { |
833 | int r = strverscmp_improved(a, b); | |
834 | ||
835 | log_info("'%s' %s '%s'%s", | |
836 | strnull(a), | |
f90ee9ff | 837 | comparison_operator(r), |
d970092f ZJS |
838 | strnull(b), |
839 | r == expected ? "" : " !!!!!!!!!!!!!"); | |
840 | assert_se(r == expected); | |
841 | } | |
842 | ||
843 | static void test_strverscmp_improved_newer(const char *older, const char *newer) { | |
844 | test_strverscmp_improved_one(older, newer, -1); | |
87b7d9b6 | 845 | |
87b7d9b6 | 846 | assert_se(strverscmp_improved(older, older) == 0); |
d970092f ZJS |
847 | assert_se(strverscmp_improved(older, newer) < 0); |
848 | assert_se(strverscmp_improved(newer, older) > 0); | |
849 | assert_se(strverscmp_improved(newer, newer) == 0); | |
87b7d9b6 YW |
850 | } |
851 | ||
4f7452a8 | 852 | TEST(strverscmp_improved) { |
87b7d9b6 | 853 | static const char * const versions[] = { |
87b7d9b6 | 854 | "~1", |
46083ab3 | 855 | "", |
87b7d9b6 YW |
856 | "ab", |
857 | "abb", | |
858 | "abc", | |
859 | "0001", | |
860 | "002", | |
861 | "12", | |
862 | "122", | |
863 | "122.9", | |
864 | "123~rc1", | |
865 | "123", | |
866 | "123-a", | |
867 | "123-a.1", | |
868 | "123-a1", | |
869 | "123-a1.1", | |
870 | "123-3", | |
871 | "123-3.1", | |
872 | "123^patch1", | |
873 | "123^1", | |
8aa35d09 | 874 | "123.a-1", |
87b7d9b6 YW |
875 | "123.1-1", |
876 | "123a-1", | |
877 | "124", | |
878 | NULL, | |
879 | }; | |
87b7d9b6 YW |
880 | |
881 | STRV_FOREACH(p, versions) | |
882 | STRV_FOREACH(q, p + 1) | |
d970092f ZJS |
883 | test_strverscmp_improved_newer(*p, *q); |
884 | ||
885 | test_strverscmp_improved_newer("123.45-67.88", "123.45-67.89"); | |
886 | test_strverscmp_improved_newer("123.45-67.89", "123.45-67.89a"); | |
887 | test_strverscmp_improved_newer("123.45-67.ab", "123.45-67.89"); | |
888 | test_strverscmp_improved_newer("123.45-67.9", "123.45-67.89"); | |
889 | test_strverscmp_improved_newer("123.45-67", "123.45-67.89"); | |
890 | test_strverscmp_improved_newer("123.45-66.89", "123.45-67.89"); | |
891 | test_strverscmp_improved_newer("123.45-9.99", "123.45-67.89"); | |
892 | test_strverscmp_improved_newer("123.42-99.99", "123.45-67.89"); | |
893 | test_strverscmp_improved_newer("123-99.99", "123.45-67.89"); | |
87b7d9b6 YW |
894 | |
895 | /* '~' : pre-releases */ | |
d970092f ZJS |
896 | test_strverscmp_improved_newer("123~rc1-99.99", "123.45-67.89"); |
897 | test_strverscmp_improved_newer("123~rc1-99.99", "123-45.67.89"); | |
898 | test_strverscmp_improved_newer("123~rc1-99.99", "123~rc2-67.89"); | |
899 | test_strverscmp_improved_newer("123~rc1-99.99", "123^aa2-67.89"); | |
900 | test_strverscmp_improved_newer("123~rc1-99.99", "123aa2-67.89"); | |
87b7d9b6 YW |
901 | |
902 | /* '-' : separator between version and release. */ | |
d970092f ZJS |
903 | test_strverscmp_improved_newer("123-99.99", "123.45-67.89"); |
904 | test_strverscmp_improved_newer("123-99.99", "123^aa2-67.89"); | |
905 | test_strverscmp_improved_newer("123-99.99", "123aa2-67.89"); | |
87b7d9b6 YW |
906 | |
907 | /* '^' : patch releases */ | |
d970092f ZJS |
908 | test_strverscmp_improved_newer("123^45-67.89", "123.45-67.89"); |
909 | test_strverscmp_improved_newer("123^aa1-99.99", "123^aa2-67.89"); | |
910 | test_strverscmp_improved_newer("123^aa2-67.89", "123aa2-67.89"); | |
87b7d9b6 YW |
911 | |
912 | /* '.' : point release */ | |
d970092f ZJS |
913 | test_strverscmp_improved_newer("123.aa2-67.89", "123aa2-67.89"); |
914 | test_strverscmp_improved_newer("123.aa2-67.89", "123.ab2-67.89"); | |
87b7d9b6 YW |
915 | |
916 | /* invalid characters */ | |
917 | assert_se(strverscmp_improved("123_aa2-67.89", "123aa+2-67.89") == 0); | |
8d915666 | 918 | |
46083ab3 ZJS |
919 | /* some corner cases */ |
920 | assert_se(strverscmp_improved("123.", "123") > 0); /* One more version segment */ | |
921 | assert_se(strverscmp_improved("12_3", "123") < 0); /* 12 < 123 */ | |
922 | assert_se(strverscmp_improved("12_3", "12") > 0); /* 3 > '' */ | |
923 | assert_se(strverscmp_improved("12_3", "12.3") > 0); /* 3 > '' */ | |
924 | assert_se(strverscmp_improved("123.0", "123") > 0); /* 0 > '' */ | |
925 | assert_se(strverscmp_improved("123_0", "123") > 0); /* 0 > '' */ | |
926 | assert_se(strverscmp_improved("123..0", "123.0") < 0); /* '' < 0 */ | |
927 | ||
928 | /* empty strings or strings with ignored characters only */ | |
929 | assert_se(strverscmp_improved("", NULL) == 0); | |
930 | assert_se(strverscmp_improved(NULL, "") == 0); | |
931 | assert_se(strverscmp_improved("0_", "0") == 0); | |
932 | assert_se(strverscmp_improved("_0_", "0") == 0); | |
933 | assert_se(strverscmp_improved("_0", "0") == 0); | |
934 | assert_se(strverscmp_improved("0", "0___") == 0); | |
935 | assert_se(strverscmp_improved("", "_") == 0); | |
936 | assert_se(strverscmp_improved("_", "") == 0); | |
937 | assert_se(strverscmp_improved("_", "_") == 0); | |
938 | assert_se(strverscmp_improved("", "~") > 0); | |
939 | assert_se(strverscmp_improved("~", "") < 0); | |
940 | assert_se(strverscmp_improved("~", "~") == 0); | |
941 | ||
8d915666 ZJS |
942 | /* non-ASCII digits */ |
943 | (void) setlocale(LC_NUMERIC, "ar_YE.utf8"); | |
944 | assert_se(strverscmp_improved("1٠١٢٣٤٥٦٧٨٩", "1") == 0); | |
945 | ||
946 | (void) setlocale(LC_NUMERIC, "th_TH.utf8"); | |
947 | assert_se(strverscmp_improved("1๐๑๒๓๔๕๖๗๘๙", "1") == 0); | |
87b7d9b6 YW |
948 | } |
949 | ||
d970092f ZJS |
950 | #define RPMVERCMP(a, b, c) \ |
951 | test_strverscmp_improved_one(STRINGIFY(a), STRINGIFY(b), (c)) | |
952 | ||
953 | TEST(strverscmp_improved_rpm) { | |
954 | /* Tests copied from rmp's rpmio test suite, under the LGPL license: | |
955 | * https://github.com/rpm-software-management/rpm/blob/master/tests/rpmvercmp.at. | |
956 | * The original form is retained for easy comparisons and updates. | |
957 | */ | |
958 | ||
959 | RPMVERCMP(1.0, 1.0, 0); | |
960 | RPMVERCMP(1.0, 2.0, -1); | |
961 | RPMVERCMP(2.0, 1.0, 1); | |
962 | ||
963 | RPMVERCMP(2.0.1, 2.0.1, 0); | |
964 | RPMVERCMP(2.0, 2.0.1, -1); | |
965 | RPMVERCMP(2.0.1, 2.0, 1); | |
966 | ||
967 | RPMVERCMP(2.0.1a, 2.0.1a, 0); | |
968 | RPMVERCMP(2.0.1a, 2.0.1, 1); | |
969 | RPMVERCMP(2.0.1, 2.0.1a, -1); | |
970 | ||
971 | RPMVERCMP(5.5p1, 5.5p1, 0); | |
972 | RPMVERCMP(5.5p1, 5.5p2, -1); | |
973 | RPMVERCMP(5.5p2, 5.5p1, 1); | |
974 | ||
975 | RPMVERCMP(5.5p10, 5.5p10, 0); | |
976 | RPMVERCMP(5.5p1, 5.5p10, -1); | |
977 | RPMVERCMP(5.5p10, 5.5p1, 1); | |
978 | ||
979 | RPMVERCMP(10xyz, 10.1xyz, 1); /* Note: this is reversed from rpm's vercmp */ | |
980 | RPMVERCMP(10.1xyz, 10xyz, -1); /* Note: this is reversed from rpm's vercmp */ | |
981 | ||
982 | RPMVERCMP(xyz10, xyz10, 0); | |
983 | RPMVERCMP(xyz10, xyz10.1, -1); | |
984 | RPMVERCMP(xyz10.1, xyz10, 1); | |
985 | ||
986 | RPMVERCMP(xyz.4, xyz.4, 0); | |
987 | RPMVERCMP(xyz.4, 8, -1); | |
988 | RPMVERCMP(8, xyz.4, 1); | |
989 | RPMVERCMP(xyz.4, 2, -1); | |
990 | RPMVERCMP(2, xyz.4, 1); | |
991 | ||
992 | RPMVERCMP(5.5p2, 5.6p1, -1); | |
993 | RPMVERCMP(5.6p1, 5.5p2, 1); | |
994 | ||
995 | RPMVERCMP(5.6p1, 6.5p1, -1); | |
996 | RPMVERCMP(6.5p1, 5.6p1, 1); | |
997 | ||
998 | RPMVERCMP(6.0.rc1, 6.0, 1); | |
999 | RPMVERCMP(6.0, 6.0.rc1, -1); | |
1000 | ||
1001 | RPMVERCMP(10b2, 10a1, 1); | |
1002 | RPMVERCMP(10a2, 10b2, -1); | |
1003 | ||
1004 | RPMVERCMP(1.0aa, 1.0aa, 0); | |
1005 | RPMVERCMP(1.0a, 1.0aa, -1); | |
1006 | RPMVERCMP(1.0aa, 1.0a, 1); | |
1007 | ||
1008 | RPMVERCMP(10.0001, 10.0001, 0); | |
1009 | RPMVERCMP(10.0001, 10.1, 0); | |
1010 | RPMVERCMP(10.1, 10.0001, 0); | |
1011 | RPMVERCMP(10.0001, 10.0039, -1); | |
1012 | RPMVERCMP(10.0039, 10.0001, 1); | |
1013 | ||
1014 | RPMVERCMP(4.999.9, 5.0, -1); | |
1015 | RPMVERCMP(5.0, 4.999.9, 1); | |
1016 | ||
1017 | RPMVERCMP(20101121, 20101121, 0); | |
1018 | RPMVERCMP(20101121, 20101122, -1); | |
1019 | RPMVERCMP(20101122, 20101121, 1); | |
1020 | ||
1021 | RPMVERCMP(2_0, 2_0, 0); | |
1022 | RPMVERCMP(2.0, 2_0, -1); /* Note: in rpm those compare equal */ | |
1023 | RPMVERCMP(2_0, 2.0, 1); /* Note: in rpm those compare equal */ | |
1024 | ||
1025 | /* RhBug:178798 case */ | |
1026 | RPMVERCMP(a, a, 0); | |
1027 | RPMVERCMP(a+, a+, 0); | |
1028 | RPMVERCMP(a+, a_, 0); | |
1029 | RPMVERCMP(a_, a+, 0); | |
1030 | RPMVERCMP(+a, +a, 0); | |
1031 | RPMVERCMP(+a, _a, 0); | |
1032 | RPMVERCMP(_a, +a, 0); | |
1033 | RPMVERCMP(+_, +_, 0); | |
1034 | RPMVERCMP(_+, +_, 0); | |
1035 | RPMVERCMP(_+, _+, 0); | |
1036 | RPMVERCMP(+, _, 0); | |
1037 | RPMVERCMP(_, +, 0); | |
1038 | ||
1039 | /* Basic testcases for tilde sorting */ | |
1040 | RPMVERCMP(1.0~rc1, 1.0~rc1, 0); | |
1041 | RPMVERCMP(1.0~rc1, 1.0, -1); | |
1042 | RPMVERCMP(1.0, 1.0~rc1, 1); | |
1043 | RPMVERCMP(1.0~rc1, 1.0~rc2, -1); | |
1044 | RPMVERCMP(1.0~rc2, 1.0~rc1, 1); | |
1045 | RPMVERCMP(1.0~rc1~git123, 1.0~rc1~git123, 0); | |
1046 | RPMVERCMP(1.0~rc1~git123, 1.0~rc1, -1); | |
1047 | RPMVERCMP(1.0~rc1, 1.0~rc1~git123, 1); | |
1048 | ||
1049 | /* Basic testcases for caret sorting */ | |
1050 | RPMVERCMP(1.0^, 1.0^, 0); | |
1051 | RPMVERCMP(1.0^, 1.0, 1); | |
1052 | RPMVERCMP(1.0, 1.0^, -1); | |
1053 | RPMVERCMP(1.0^git1, 1.0^git1, 0); | |
1054 | RPMVERCMP(1.0^git1, 1.0, 1); | |
1055 | RPMVERCMP(1.0, 1.0^git1, -1); | |
1056 | RPMVERCMP(1.0^git1, 1.0^git2, -1); | |
1057 | RPMVERCMP(1.0^git2, 1.0^git1, 1); | |
1058 | RPMVERCMP(1.0^git1, 1.01, -1); | |
1059 | RPMVERCMP(1.01, 1.0^git1, 1); | |
1060 | RPMVERCMP(1.0^20160101, 1.0^20160101, 0); | |
1061 | RPMVERCMP(1.0^20160101, 1.0.1, -1); | |
1062 | RPMVERCMP(1.0.1, 1.0^20160101, 1); | |
1063 | RPMVERCMP(1.0^20160101^git1, 1.0^20160101^git1, 0); | |
1064 | RPMVERCMP(1.0^20160102, 1.0^20160101^git1, 1); | |
1065 | RPMVERCMP(1.0^20160101^git1, 1.0^20160102, -1); | |
1066 | ||
1067 | /* Basic testcases for tilde and caret sorting */ | |
1068 | RPMVERCMP(1.0~rc1^git1, 1.0~rc1^git1, 0); | |
1069 | RPMVERCMP(1.0~rc1^git1, 1.0~rc1, 1); | |
1070 | RPMVERCMP(1.0~rc1, 1.0~rc1^git1, -1); | |
1071 | RPMVERCMP(1.0^git1~pre, 1.0^git1~pre, 0); | |
1072 | RPMVERCMP(1.0^git1, 1.0^git1~pre, 1); | |
1073 | RPMVERCMP(1.0^git1~pre, 1.0^git1, -1); | |
1074 | ||
1075 | /* These are included here to document current, arguably buggy behaviors | |
1076 | * for reference purposes and for easy checking against unintended | |
1077 | * behavior changes. */ | |
1078 | log_info("/* RPM version comparison oddities */"); | |
1079 | /* RhBug:811992 case */ | |
1080 | RPMVERCMP(1b.fc17, 1b.fc17, 0); | |
1081 | RPMVERCMP(1b.fc17, 1.fc17, 1); /* Note: this is reversed from rpm's vercmp, WAT! */ | |
1082 | RPMVERCMP(1.fc17, 1b.fc17, -1); | |
1083 | RPMVERCMP(1g.fc17, 1g.fc17, 0); | |
1084 | RPMVERCMP(1g.fc17, 1.fc17, 1); | |
1085 | RPMVERCMP(1.fc17, 1g.fc17, -1); | |
1086 | ||
1087 | /* Non-ascii characters are considered equal so these are all the same, eh… */ | |
1088 | RPMVERCMP(1.1.α, 1.1.α, 0); | |
1089 | RPMVERCMP(1.1.α, 1.1.β, 0); | |
1090 | RPMVERCMP(1.1.β, 1.1.α, 0); | |
1091 | RPMVERCMP(1.1.αα, 1.1.α, 0); | |
1092 | RPMVERCMP(1.1.α, 1.1.ββ, 0); | |
1093 | RPMVERCMP(1.1.ββ, 1.1.αα, 0); | |
1094 | } | |
1095 | ||
4f7452a8 | 1096 | TEST(strextendf) { |
e9b88a6d LP |
1097 | _cleanup_free_ char *p = NULL; |
1098 | ||
1099 | assert_se(strextendf(&p, "<%i>", 77) >= 0); | |
1100 | assert_se(streq(p, "<77>")); | |
1101 | ||
1102 | assert_se(strextendf(&p, "<%i>", 99) >= 0); | |
1103 | assert_se(streq(p, "<77><99>")); | |
1104 | ||
1105 | assert_se(strextendf(&p, "<%80i>", 88) >= 0); | |
1106 | assert_se(streq(p, "<77><99>< 88>")); | |
1107 | ||
5570a097 | 1108 | assert_se(strextendf(&p, "<%08x>", 0x1234u) >= 0); |
e9b88a6d | 1109 | assert_se(streq(p, "<77><99>< 88><00001234>")); |
6b13ca8a YW |
1110 | |
1111 | p = mfree(p); | |
1112 | ||
1113 | assert_se(strextendf_with_separator(&p, ",", "<%i>", 77) >= 0); | |
1114 | assert_se(streq(p, "<77>")); | |
1115 | ||
1116 | assert_se(strextendf_with_separator(&p, ",", "<%i>", 99) >= 0); | |
1117 | assert_se(streq(p, "<77>,<99>")); | |
1118 | ||
1119 | assert_se(strextendf_with_separator(&p, ",", "<%80i>", 88) >= 0); | |
1120 | assert_se(streq(p, "<77>,<99>,< 88>")); | |
1121 | ||
5570a097 | 1122 | assert_se(strextendf_with_separator(&p, ",", "<%08x>", 0x1234u) >= 0); |
6b13ca8a | 1123 | assert_se(streq(p, "<77>,<99>,< 88>,<00001234>")); |
e9b88a6d LP |
1124 | } |
1125 | ||
072f5f9b | 1126 | TEST(string_replace_char) { |
88f8bd75 LB |
1127 | assert_se(streq(string_replace_char(strdupa_safe(""), 'a', 'b'), "")); |
1128 | assert_se(streq(string_replace_char(strdupa_safe("abc"), 'a', 'b'), "bbc")); | |
1129 | assert_se(streq(string_replace_char(strdupa_safe("hoge"), 'a', 'b'), "hoge")); | |
1130 | assert_se(streq(string_replace_char(strdupa_safe("aaaa"), 'a', 'b'), "bbbb")); | |
1131 | assert_se(streq(string_replace_char(strdupa_safe("aaaa"), 'a', '\t'), "\t\t\t\t")); | |
072f5f9b YW |
1132 | } |
1133 | ||
146f4482 YW |
1134 | TEST(strspn_from_end) { |
1135 | assert_se(strspn_from_end(NULL, NULL) == 0); | |
1136 | assert_se(strspn_from_end("hoge", NULL) == 0); | |
1137 | assert_se(strspn_from_end(NULL, DIGITS) == 0); | |
1138 | assert_se(strspn_from_end("", DIGITS) == 0); | |
1139 | assert_se(strspn_from_end("hoge", DIGITS) == 0); | |
1140 | assert_se(strspn_from_end("1234", DIGITS) == 4); | |
1141 | assert_se(strspn_from_end("aaa1234", DIGITS) == 4); | |
1142 | assert_se(strspn_from_end("aaa1234aaa", DIGITS) == 0); | |
1143 | assert_se(strspn_from_end("aaa12aa34", DIGITS) == 2); | |
1144 | } | |
1145 | ||
4f7452a8 | 1146 | TEST(streq_skip_trailing_chars) { |
8034b42c ADT |
1147 | /* NULL is WHITESPACE by default*/ |
1148 | assert_se(streq_skip_trailing_chars("foo bar", "foo bar", NULL)); | |
1149 | assert_se(streq_skip_trailing_chars("foo", "foo", NULL)); | |
1150 | assert_se(streq_skip_trailing_chars("foo bar ", "foo bar", NULL)); | |
1151 | assert_se(streq_skip_trailing_chars("foo bar", "foo bar\t\t", NULL)); | |
1152 | assert_se(streq_skip_trailing_chars("foo bar ", "foo bar\t\t", NULL)); | |
1153 | assert_se(streq_skip_trailing_chars("foo\nbar", "foo\nbar", NULL)); | |
1154 | assert_se(streq_skip_trailing_chars("\t\tfoo bar", "\t\tfoo bar", NULL)); | |
1155 | assert_se(streq_skip_trailing_chars(" foo bar\t", " foo bar\n", NULL)); | |
1156 | ||
1157 | assert_se(!streq_skip_trailing_chars("foobar", "foo bar", NULL)); | |
1158 | assert_se(!streq_skip_trailing_chars("foo\nbar", "foo\tbar", NULL)); | |
1159 | assert_se(!streq_skip_trailing_chars("\t\nfoo bar", "\t foo bar", NULL)); | |
1160 | ||
1161 | assert_se(streq_skip_trailing_chars("foo bar ", "foo bar", WHITESPACE)); | |
1162 | assert_se(!streq_skip_trailing_chars("foo bar ", "foo bar", NEWLINE)); | |
1163 | ||
1164 | assert_se(streq_skip_trailing_chars(NULL, NULL, NULL)); | |
1165 | assert_se(streq_skip_trailing_chars("", "", NULL)); | |
1166 | assert_se(!streq_skip_trailing_chars(NULL, "foo bar", NULL)); | |
1167 | assert_se(!streq_skip_trailing_chars("foo", NULL, NULL)); | |
1168 | assert_se(!streq_skip_trailing_chars("", "f", NULL)); | |
1169 | } | |
1170 | ||
4f7452a8 | 1171 | DEFINE_TEST_MAIN(LOG_DEBUG); |