1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2010 Lennart Poettering
4 Copyright 2013 Thomas H.P. Andersen
11 #include "extract-word.h"
13 #include "string-util.h"
15 static void test_extract_first_word(void) {
16 const char *p
, *original
;
19 p
= original
= "foobar waldo";
20 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
21 assert_se(streq(t
, "foobar"));
23 assert_se(p
== original
+ 7);
25 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
26 assert_se(streq(t
, "waldo"));
28 assert_se(isempty(p
));
30 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
32 assert_se(isempty(p
));
34 p
= original
= "\"foobar\" \'waldo\'";
35 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
36 assert_se(streq(t
, "\"foobar\""));
38 assert_se(p
== original
+ 9);
40 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
41 assert_se(streq(t
, "\'waldo\'"));
43 assert_se(isempty(p
));
45 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
47 assert_se(isempty(p
));
49 p
= original
= "\"foobar\" \'waldo\'";
50 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
51 assert_se(streq(t
, "foobar"));
53 assert_se(p
== original
+ 9);
55 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
56 assert_se(streq(t
, "waldo"));
58 assert_se(isempty(p
));
60 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
62 assert_se(isempty(p
));
65 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
66 assert_se(streq(t
, "\""));
68 assert_se(isempty(p
));
71 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) == -EINVAL
);
72 assert_se(p
== original
+ 1);
75 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
76 assert_se(streq(t
, "\'"));
78 assert_se(isempty(p
));
81 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) == -EINVAL
);
82 assert_se(p
== original
+ 1);
84 p
= original
= "\'fooo";
85 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
86 assert_se(streq(t
, "\'fooo"));
88 assert_se(isempty(p
));
90 p
= original
= "\'fooo";
91 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) == -EINVAL
);
92 assert_se(p
== original
+ 5);
94 p
= original
= "\'fooo";
95 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
) > 0);
96 assert_se(streq(t
, "fooo"));
98 assert_se(isempty(p
));
100 p
= original
= "\"fooo";
101 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
) > 0);
102 assert_se(streq(t
, "fooo"));
104 assert_se(isempty(p
));
106 p
= original
= "yay\'foo\'bar";
107 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
108 assert_se(streq(t
, "yay\'foo\'bar"));
110 assert_se(isempty(p
));
112 p
= original
= "yay\'foo\'bar";
113 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
114 assert_se(streq(t
, "yayfoobar"));
116 assert_se(isempty(p
));
118 p
= original
= " foobar ";
119 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
120 assert_se(streq(t
, "foobar"));
122 assert_se(isempty(p
));
124 p
= original
= " foo\\ba\\x6ar ";
125 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) > 0);
126 assert_se(streq(t
, "foo\ba\x6ar"));
128 assert_se(isempty(p
));
130 p
= original
= " foo\\ba\\x6ar ";
131 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
132 assert_se(streq(t
, "foobax6ar"));
134 assert_se(isempty(p
));
136 p
= original
= " f\\u00f6o \"pi\\U0001F4A9le\" ";
137 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) > 0);
138 assert_se(streq(t
, "föo"));
140 assert_se(p
== original
+ 13);
142 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
) > 0);
143 assert_se(streq(t
, "pi\360\237\222\251le"));
145 assert_se(isempty(p
));
147 p
= original
= "fooo\\";
148 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RELAX
) > 0);
149 assert_se(streq(t
, "fooo"));
151 assert_se(isempty(p
));
153 p
= original
= "fooo\\";
154 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
) > 0);
155 assert_se(streq(t
, "fooo\\"));
157 assert_se(isempty(p
));
159 p
= original
= "fooo\\";
160 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
161 assert_se(streq(t
, "fooo\\"));
163 assert_se(isempty(p
));
165 p
= original
= "fooo\\";
166 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
167 assert_se(streq(t
, "fooo\\"));
169 assert_se(isempty(p
));
171 p
= original
= "\"foo\\";
172 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == -EINVAL
);
173 assert_se(p
== original
+ 5);
175 p
= original
= "\"foo\\";
176 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
) > 0);
177 assert_se(streq(t
, "foo"));
179 assert_se(isempty(p
));
181 p
= original
= "foo::bar";
182 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
183 assert_se(streq(t
, "foo"));
185 assert_se(p
== original
+ 5);
187 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
188 assert_se(streq(t
, "bar"));
190 assert_se(isempty(p
));
192 assert_se(extract_first_word(&p
, &t
, ":", 0) == 0);
194 assert_se(isempty(p
));
196 p
= original
= "foo\\:bar::waldo";
197 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
198 assert_se(streq(t
, "foo:bar"));
200 assert_se(p
== original
+ 10);
202 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
203 assert_se(streq(t
, "waldo"));
205 assert_se(isempty(p
));
207 assert_se(extract_first_word(&p
, &t
, ":", 0) == 0);
209 assert_se(isempty(p
));
211 p
= original
= "\"foo\\";
212 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE_RELAX
) == -EINVAL
);
213 assert_se(p
== original
+ 5);
215 p
= original
= "\"foo\\";
216 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
217 assert_se(streq(t
, "foo\\"));
219 assert_se(isempty(p
));
221 p
= original
= "\"foo\\";
222 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
223 assert_se(streq(t
, "foo\\"));
225 assert_se(isempty(p
));
227 p
= original
= "fooo\\ bar quux";
228 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RELAX
) > 0);
229 assert_se(streq(t
, "fooo bar"));
231 assert_se(p
== original
+ 10);
233 p
= original
= "fooo\\ bar quux";
234 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
) > 0);
235 assert_se(streq(t
, "fooo bar"));
237 assert_se(p
== original
+ 10);
239 p
= original
= "fooo\\ bar quux";
240 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
241 assert_se(streq(t
, "fooo bar"));
243 assert_se(p
== original
+ 10);
245 p
= original
= "fooo\\ bar quux";
246 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) == -EINVAL
);
247 assert_se(p
== original
+ 5);
249 p
= original
= "fooo\\ bar quux";
250 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
251 assert_se(streq(t
, "fooo\\ bar"));
253 assert_se(p
== original
+ 10);
255 p
= original
= "\\w+@\\K[\\d.]+";
256 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) == -EINVAL
);
257 assert_se(p
== original
+ 1);
259 p
= original
= "\\w+@\\K[\\d.]+";
260 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
261 assert_se(streq(t
, "\\w+@\\K[\\d.]+"));
263 assert_se(isempty(p
));
265 p
= original
= "\\w+\\b";
266 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
267 assert_se(streq(t
, "\\w+\b"));
269 assert_se(isempty(p
));
271 p
= original
= "-N ''";
272 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
273 assert_se(streq(t
, "-N"));
275 assert_se(p
== original
+ 3);
277 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
278 assert_se(streq(t
, ""));
280 assert_se(isempty(p
));
282 p
= original
= ":foo\\:bar::waldo:";
283 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
285 assert_se(streq(t
, ""));
287 assert_se(p
== original
+ 1);
289 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
290 assert_se(streq(t
, "foo:bar"));
292 assert_se(p
== original
+ 10);
294 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
296 assert_se(streq(t
, ""));
298 assert_se(p
== original
+ 11);
300 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
301 assert_se(streq(t
, "waldo"));
303 assert_se(p
== original
+ 17);
305 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
306 assert_se(streq(t
, ""));
308 assert_se(p
== NULL
);
310 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 0);
315 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
316 assert_se(streq(t
, "fooxbar"));
318 assert_se(p
== NULL
);
321 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RETAIN_ESCAPE
) > 0);
322 assert_se(streq(t
, "foo\\xbar"));
324 assert_se(p
== NULL
);
327 static void test_extract_first_word_and_warn(void) {
328 const char *p
, *original
;
331 p
= original
= "foobar waldo";
332 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
333 assert_se(streq(t
, "foobar"));
335 assert_se(p
== original
+ 7);
337 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
338 assert_se(streq(t
, "waldo"));
340 assert_se(isempty(p
));
342 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) == 0);
344 assert_se(isempty(p
));
346 p
= original
= "\"foobar\" \'waldo\'";
347 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) > 0);
348 assert_se(streq(t
, "foobar"));
350 assert_se(p
== original
+ 9);
352 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) > 0);
353 assert_se(streq(t
, "waldo"));
355 assert_se(isempty(p
));
357 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) == 0);
359 assert_se(isempty(p
));
362 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
363 assert_se(p
== original
+ 1);
366 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
367 assert_se(p
== original
+ 1);
369 p
= original
= "\'fooo";
370 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
371 assert_se(p
== original
+ 5);
373 p
= original
= "\'fooo";
374 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
375 assert_se(streq(t
, "fooo"));
377 assert_se(isempty(p
));
379 p
= original
= " foo\\ba\\x6ar ";
380 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
381 assert_se(streq(t
, "foo\ba\x6ar"));
383 assert_se(isempty(p
));
385 p
= original
= " foo\\ba\\x6ar ";
386 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
387 assert_se(streq(t
, "foobax6ar"));
389 assert_se(isempty(p
));
391 p
= original
= " f\\u00f6o \"pi\\U0001F4A9le\" ";
392 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
393 assert_se(streq(t
, "föo"));
395 assert_se(p
== original
+ 13);
397 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
398 assert_se(streq(t
, "pi\360\237\222\251le"));
400 assert_se(isempty(p
));
402 p
= original
= "fooo\\";
403 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
404 assert_se(streq(t
, "fooo"));
406 assert_se(isempty(p
));
408 p
= original
= "fooo\\";
409 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
410 assert_se(streq(t
, "fooo\\"));
412 assert_se(isempty(p
));
414 p
= original
= "fooo\\";
415 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
416 assert_se(streq(t
, "fooo\\"));
418 assert_se(isempty(p
));
420 p
= original
= "\"foo\\";
421 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
422 assert_se(p
== original
+ 5);
424 p
= original
= "\"foo\\";
425 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
426 assert_se(streq(t
, "foo"));
428 assert_se(isempty(p
));
430 p
= original
= "\"foo\\";
431 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) == -EINVAL
);
432 assert_se(p
== original
+ 5);
434 p
= original
= "\"foo\\";
435 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
436 assert_se(streq(t
, "foo"));
438 assert_se(isempty(p
));
440 p
= original
= "fooo\\ bar quux";
441 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
442 assert_se(streq(t
, "fooo bar"));
444 assert_se(p
== original
+ 10);
446 p
= original
= "fooo\\ bar quux";
447 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
448 assert_se(streq(t
, "fooo bar"));
450 assert_se(p
== original
+ 10);
452 p
= original
= "fooo\\ bar quux";
453 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
454 assert_se(streq(t
, "fooo\\ bar"));
456 assert_se(p
== original
+ 10);
458 p
= original
= "\\w+@\\K[\\d.]+";
459 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
460 assert_se(streq(t
, "\\w+@\\K[\\d.]+"));
462 assert_se(isempty(p
));
464 p
= original
= "\\w+\\b";
465 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
466 assert_se(streq(t
, "\\w+\b"));
468 assert_se(isempty(p
));
471 static void test_extract_many_words(void) {
472 const char *p
, *original
;
475 p
= original
= "foobar waldi piep";
476 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 3);
477 assert_se(isempty(p
));
478 assert_se(streq_ptr(a
, "foobar"));
479 assert_se(streq_ptr(b
, "waldi"));
480 assert_se(streq_ptr(c
, "piep"));
485 p
= original
= "'foobar' wa\"ld\"i ";
486 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 2);
487 assert_se(isempty(p
));
488 assert_se(streq_ptr(a
, "'foobar'"));
489 assert_se(streq_ptr(b
, "wa\"ld\"i"));
490 assert_se(streq_ptr(c
, NULL
));
494 p
= original
= "'foobar' wa\"ld\"i ";
495 assert_se(extract_many_words(&p
, NULL
, EXTRACT_QUOTES
, &a
, &b
, &c
, NULL
) == 2);
496 assert_se(isempty(p
));
497 assert_se(streq_ptr(a
, "foobar"));
498 assert_se(streq_ptr(b
, "waldi"));
499 assert_se(streq_ptr(c
, NULL
));
504 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 0);
505 assert_se(isempty(p
));
506 assert_se(streq_ptr(a
, NULL
));
507 assert_se(streq_ptr(b
, NULL
));
508 assert_se(streq_ptr(c
, NULL
));
511 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 0);
512 assert_se(isempty(p
));
513 assert_se(streq_ptr(a
, NULL
));
514 assert_se(streq_ptr(b
, NULL
));
515 assert_se(streq_ptr(c
, NULL
));
517 p
= original
= "foobar";
518 assert_se(extract_many_words(&p
, NULL
, 0, NULL
) == 0);
519 assert_se(p
== original
);
521 p
= original
= "foobar waldi";
522 assert_se(extract_many_words(&p
, NULL
, 0, &a
, NULL
) == 1);
523 assert_se(p
== original
+7);
524 assert_se(streq_ptr(a
, "foobar"));
527 p
= original
= " foobar ";
528 assert_se(extract_many_words(&p
, NULL
, 0, &a
, NULL
) == 1);
529 assert_se(isempty(p
));
530 assert_se(streq_ptr(a
, "foobar"));
534 int main(int argc
, char *argv
[]) {
535 log_parse_environment();
538 test_extract_first_word();
539 test_extract_first_word_and_warn();
540 test_extract_many_words();