1 /* SPDX-License-Identifier: LGPL-2.1+ */
7 #include "extract-word.h"
9 #include "string-util.h"
11 static void test_extract_first_word(void) {
12 const char *p
, *original
;
15 p
= original
= "foobar waldo";
16 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
17 assert_se(streq(t
, "foobar"));
19 assert_se(p
== original
+ 7);
21 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
22 assert_se(streq(t
, "waldo"));
24 assert_se(isempty(p
));
26 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
28 assert_se(isempty(p
));
30 p
= original
= "\"foobar\" \'waldo\'";
31 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
32 assert_se(streq(t
, "\"foobar\""));
34 assert_se(p
== original
+ 9);
36 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
37 assert_se(streq(t
, "\'waldo\'"));
39 assert_se(isempty(p
));
41 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
43 assert_se(isempty(p
));
45 p
= original
= "\"foobar\" \'waldo\'";
46 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
47 assert_se(streq(t
, "foobar"));
49 assert_se(p
== original
+ 9);
51 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
52 assert_se(streq(t
, "waldo"));
54 assert_se(isempty(p
));
56 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
58 assert_se(isempty(p
));
61 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
62 assert_se(streq(t
, "\""));
64 assert_se(isempty(p
));
67 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) == -EINVAL
);
68 assert_se(p
== original
+ 1);
71 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
72 assert_se(streq(t
, "\'"));
74 assert_se(isempty(p
));
77 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) == -EINVAL
);
78 assert_se(p
== original
+ 1);
80 p
= original
= "\'fooo";
81 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
82 assert_se(streq(t
, "\'fooo"));
84 assert_se(isempty(p
));
86 p
= original
= "\'fooo";
87 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) == -EINVAL
);
88 assert_se(p
== original
+ 5);
90 p
= original
= "\'fooo";
91 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
) > 0);
92 assert_se(streq(t
, "fooo"));
94 assert_se(isempty(p
));
96 p
= original
= "\"fooo";
97 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
) > 0);
98 assert_se(streq(t
, "fooo"));
100 assert_se(isempty(p
));
102 p
= original
= "yay\'foo\'bar";
103 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
104 assert_se(streq(t
, "yay\'foo\'bar"));
106 assert_se(isempty(p
));
108 p
= original
= "yay\'foo\'bar";
109 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
110 assert_se(streq(t
, "yayfoobar"));
112 assert_se(isempty(p
));
114 p
= original
= " foobar ";
115 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
116 assert_se(streq(t
, "foobar"));
118 assert_se(isempty(p
));
120 p
= original
= " foo\\ba\\x6ar ";
121 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) > 0);
122 assert_se(streq(t
, "foo\ba\x6ar"));
124 assert_se(isempty(p
));
126 p
= original
= " foo\\ba\\x6ar ";
127 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
128 assert_se(streq(t
, "foobax6ar"));
130 assert_se(isempty(p
));
132 p
= original
= " f\\u00f6o \"pi\\U0001F4A9le\" ";
133 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) > 0);
134 assert_se(streq(t
, "föo"));
136 assert_se(p
== original
+ 13);
138 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
) > 0);
139 assert_se(streq(t
, "pi\360\237\222\251le"));
141 assert_se(isempty(p
));
143 p
= original
= "fooo\\";
144 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RELAX
) > 0);
145 assert_se(streq(t
, "fooo"));
147 assert_se(isempty(p
));
149 p
= original
= "fooo\\";
150 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
) > 0);
151 assert_se(streq(t
, "fooo\\"));
153 assert_se(isempty(p
));
155 p
= original
= "fooo\\";
156 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
157 assert_se(streq(t
, "fooo\\"));
159 assert_se(isempty(p
));
161 p
= original
= "fooo\\";
162 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
163 assert_se(streq(t
, "fooo\\"));
165 assert_se(isempty(p
));
167 p
= original
= "\"foo\\";
168 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == -EINVAL
);
169 assert_se(p
== original
+ 5);
171 p
= original
= "\"foo\\";
172 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
) > 0);
173 assert_se(streq(t
, "foo"));
175 assert_se(isempty(p
));
177 p
= original
= "foo::bar";
178 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
179 assert_se(streq(t
, "foo"));
181 assert_se(p
== original
+ 5);
183 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
184 assert_se(streq(t
, "bar"));
186 assert_se(isempty(p
));
188 assert_se(extract_first_word(&p
, &t
, ":", 0) == 0);
190 assert_se(isempty(p
));
192 p
= original
= "foo\\:bar::waldo";
193 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
194 assert_se(streq(t
, "foo:bar"));
196 assert_se(p
== original
+ 10);
198 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
199 assert_se(streq(t
, "waldo"));
201 assert_se(isempty(p
));
203 assert_se(extract_first_word(&p
, &t
, ":", 0) == 0);
205 assert_se(isempty(p
));
207 p
= original
= "\"foo\\";
208 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE_RELAX
) == -EINVAL
);
209 assert_se(p
== original
+ 5);
211 p
= original
= "\"foo\\";
212 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
213 assert_se(streq(t
, "foo\\"));
215 assert_se(isempty(p
));
217 p
= original
= "\"foo\\";
218 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
219 assert_se(streq(t
, "foo\\"));
221 assert_se(isempty(p
));
223 p
= original
= "fooo\\ bar quux";
224 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RELAX
) > 0);
225 assert_se(streq(t
, "fooo bar"));
227 assert_se(p
== original
+ 10);
229 p
= original
= "fooo\\ bar quux";
230 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
) > 0);
231 assert_se(streq(t
, "fooo bar"));
233 assert_se(p
== original
+ 10);
235 p
= original
= "fooo\\ bar quux";
236 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
237 assert_se(streq(t
, "fooo bar"));
239 assert_se(p
== original
+ 10);
241 p
= original
= "fooo\\ bar quux";
242 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) == -EINVAL
);
243 assert_se(p
== original
+ 5);
245 p
= original
= "fooo\\ bar quux";
246 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
247 assert_se(streq(t
, "fooo\\ bar"));
249 assert_se(p
== original
+ 10);
251 p
= original
= "\\w+@\\K[\\d.]+";
252 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) == -EINVAL
);
253 assert_se(p
== original
+ 1);
255 p
= original
= "\\w+@\\K[\\d.]+";
256 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
257 assert_se(streq(t
, "\\w+@\\K[\\d.]+"));
259 assert_se(isempty(p
));
261 p
= original
= "\\w+\\b";
262 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
263 assert_se(streq(t
, "\\w+\b"));
265 assert_se(isempty(p
));
267 p
= original
= "-N ''";
268 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
269 assert_se(streq(t
, "-N"));
271 assert_se(p
== original
+ 3);
273 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
274 assert_se(streq(t
, ""));
276 assert_se(isempty(p
));
278 p
= original
= ":foo\\:bar::waldo:";
279 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
281 assert_se(streq(t
, ""));
283 assert_se(p
== original
+ 1);
285 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
286 assert_se(streq(t
, "foo:bar"));
288 assert_se(p
== original
+ 10);
290 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
292 assert_se(streq(t
, ""));
294 assert_se(p
== original
+ 11);
296 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
297 assert_se(streq(t
, "waldo"));
299 assert_se(p
== original
+ 17);
301 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
302 assert_se(streq(t
, ""));
304 assert_se(p
== NULL
);
306 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 0);
311 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
312 assert_se(streq(t
, "fooxbar"));
314 assert_se(p
== NULL
);
317 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RETAIN_ESCAPE
) > 0);
318 assert_se(streq(t
, "foo\\xbar"));
320 assert_se(p
== NULL
);
323 static void test_extract_first_word_and_warn(void) {
324 const char *p
, *original
;
327 p
= original
= "foobar waldo";
328 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
329 assert_se(streq(t
, "foobar"));
331 assert_se(p
== original
+ 7);
333 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
334 assert_se(streq(t
, "waldo"));
336 assert_se(isempty(p
));
338 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) == 0);
340 assert_se(isempty(p
));
342 p
= original
= "\"foobar\" \'waldo\'";
343 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) > 0);
344 assert_se(streq(t
, "foobar"));
346 assert_se(p
== original
+ 9);
348 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) > 0);
349 assert_se(streq(t
, "waldo"));
351 assert_se(isempty(p
));
353 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) == 0);
355 assert_se(isempty(p
));
358 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
359 assert_se(p
== original
+ 1);
362 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
363 assert_se(p
== original
+ 1);
365 p
= original
= "\'fooo";
366 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
367 assert_se(p
== original
+ 5);
369 p
= original
= "\'fooo";
370 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
371 assert_se(streq(t
, "fooo"));
373 assert_se(isempty(p
));
375 p
= original
= " foo\\ba\\x6ar ";
376 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
377 assert_se(streq(t
, "foo\ba\x6ar"));
379 assert_se(isempty(p
));
381 p
= original
= " foo\\ba\\x6ar ";
382 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
383 assert_se(streq(t
, "foobax6ar"));
385 assert_se(isempty(p
));
387 p
= original
= " f\\u00f6o \"pi\\U0001F4A9le\" ";
388 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
389 assert_se(streq(t
, "föo"));
391 assert_se(p
== original
+ 13);
393 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
394 assert_se(streq(t
, "pi\360\237\222\251le"));
396 assert_se(isempty(p
));
398 p
= original
= "fooo\\";
399 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
400 assert_se(streq(t
, "fooo"));
402 assert_se(isempty(p
));
404 p
= original
= "fooo\\";
405 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
406 assert_se(streq(t
, "fooo\\"));
408 assert_se(isempty(p
));
410 p
= original
= "fooo\\";
411 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
412 assert_se(streq(t
, "fooo\\"));
414 assert_se(isempty(p
));
416 p
= original
= "\"foo\\";
417 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
418 assert_se(p
== original
+ 5);
420 p
= original
= "\"foo\\";
421 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
422 assert_se(streq(t
, "foo"));
424 assert_se(isempty(p
));
426 p
= original
= "\"foo\\";
427 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) == -EINVAL
);
428 assert_se(p
== original
+ 5);
430 p
= original
= "\"foo\\";
431 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
432 assert_se(streq(t
, "foo"));
434 assert_se(isempty(p
));
436 p
= original
= "fooo\\ bar quux";
437 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
438 assert_se(streq(t
, "fooo bar"));
440 assert_se(p
== original
+ 10);
442 p
= original
= "fooo\\ bar quux";
443 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
444 assert_se(streq(t
, "fooo bar"));
446 assert_se(p
== original
+ 10);
448 p
= original
= "fooo\\ bar quux";
449 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
450 assert_se(streq(t
, "fooo\\ bar"));
452 assert_se(p
== original
+ 10);
454 p
= original
= "\\w+@\\K[\\d.]+";
455 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
456 assert_se(streq(t
, "\\w+@\\K[\\d.]+"));
458 assert_se(isempty(p
));
460 p
= original
= "\\w+\\b";
461 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
462 assert_se(streq(t
, "\\w+\b"));
464 assert_se(isempty(p
));
467 static void test_extract_many_words(void) {
468 const char *p
, *original
;
471 p
= original
= "foobar waldi piep";
472 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 3);
473 assert_se(isempty(p
));
474 assert_se(streq_ptr(a
, "foobar"));
475 assert_se(streq_ptr(b
, "waldi"));
476 assert_se(streq_ptr(c
, "piep"));
481 p
= original
= "'foobar' wa\"ld\"i ";
482 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 2);
483 assert_se(isempty(p
));
484 assert_se(streq_ptr(a
, "'foobar'"));
485 assert_se(streq_ptr(b
, "wa\"ld\"i"));
486 assert_se(streq_ptr(c
, NULL
));
490 p
= original
= "'foobar' wa\"ld\"i ";
491 assert_se(extract_many_words(&p
, NULL
, EXTRACT_QUOTES
, &a
, &b
, &c
, NULL
) == 2);
492 assert_se(isempty(p
));
493 assert_se(streq_ptr(a
, "foobar"));
494 assert_se(streq_ptr(b
, "waldi"));
495 assert_se(streq_ptr(c
, NULL
));
500 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 0);
501 assert_se(isempty(p
));
502 assert_se(streq_ptr(a
, NULL
));
503 assert_se(streq_ptr(b
, NULL
));
504 assert_se(streq_ptr(c
, NULL
));
507 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 0);
508 assert_se(isempty(p
));
509 assert_se(streq_ptr(a
, NULL
));
510 assert_se(streq_ptr(b
, NULL
));
511 assert_se(streq_ptr(c
, NULL
));
513 p
= original
= "foobar";
514 assert_se(extract_many_words(&p
, NULL
, 0, NULL
) == 0);
515 assert_se(p
== original
);
517 p
= original
= "foobar waldi";
518 assert_se(extract_many_words(&p
, NULL
, 0, &a
, NULL
) == 1);
519 assert_se(p
== original
+7);
520 assert_se(streq_ptr(a
, "foobar"));
523 p
= original
= " foobar ";
524 assert_se(extract_many_words(&p
, NULL
, 0, &a
, NULL
) == 1);
525 assert_se(isempty(p
));
526 assert_se(streq_ptr(a
, "foobar"));
530 int main(int argc
, char *argv
[]) {
531 log_parse_environment();
534 test_extract_first_word();
535 test_extract_first_word_and_warn();
536 test_extract_many_words();