1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include "extract-word.h"
8 #include "string-util.h"
10 static void test_extract_first_word(void) {
11 const char *p
, *original
;
14 p
= original
= "foobar waldo";
15 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
16 assert_se(streq(t
, "foobar"));
18 assert_se(p
== original
+ 7);
20 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
21 assert_se(streq(t
, "waldo"));
23 assert_se(isempty(p
));
25 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
27 assert_se(isempty(p
));
29 p
= original
= "\"foobar\" \'waldo\'";
30 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
31 assert_se(streq(t
, "\"foobar\""));
33 assert_se(p
== original
+ 9);
35 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
36 assert_se(streq(t
, "\'waldo\'"));
38 assert_se(isempty(p
));
40 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
42 assert_se(isempty(p
));
44 p
= original
= "\"foobar\" \'waldo\'";
45 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) > 0);
46 assert_se(streq(t
, "foobar"));
48 assert_se(p
== original
+ 9);
50 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) > 0);
51 assert_se(streq(t
, "waldo"));
53 assert_se(isempty(p
));
55 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
57 assert_se(isempty(p
));
60 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
61 assert_se(streq(t
, "\""));
63 assert_se(isempty(p
));
66 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) == -EINVAL
);
67 assert_se(p
== original
+ 1);
70 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
71 assert_se(streq(t
, "\'"));
73 assert_se(isempty(p
));
76 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) == -EINVAL
);
77 assert_se(p
== original
+ 1);
79 p
= original
= "\'fooo";
80 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
81 assert_se(streq(t
, "\'fooo"));
83 assert_se(isempty(p
));
85 p
= original
= "KEY=val \"KEY2=val with space\" \"KEY3=val with \\\"quotation\\\"\"";
86 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) == 1);
87 assert_se(streq(t
, "KEY=val"));
89 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) == 1);
90 assert_se(streq(t
, "KEY2=val with space"));
92 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) == 1);
93 assert_se(streq(t
, "KEY3=val with \"quotation\""));
95 assert_se(isempty(p
));
97 p
= original
= "KEY=val \"KEY2=val space\" \"KEY3=val with \\\"quotation\\\"\"";
98 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RETAIN_ESCAPE
) == 1);
99 assert_se(streq(t
, "KEY=val"));
101 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RETAIN_ESCAPE
) == 1);
102 assert_se(streq(t
, "\"KEY2=val"));
104 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RETAIN_ESCAPE
) == 1);
105 assert_se(streq(t
, "space\""));
107 assert_se(startswith(p
, "\"KEY3="));
109 p
= original
= "\'fooo";
110 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) == -EINVAL
);
111 assert_se(p
== original
+ 5);
113 p
= original
= "\'fooo";
114 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_RELAX
) > 0);
115 assert_se(streq(t
, "fooo"));
117 assert_se(isempty(p
));
119 p
= original
= "\"fooo";
120 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_RELAX
) > 0);
121 assert_se(streq(t
, "fooo"));
123 assert_se(isempty(p
));
125 p
= original
= "yay\'foo\'bar";
126 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
127 assert_se(streq(t
, "yay\'foo\'bar"));
129 assert_se(isempty(p
));
131 p
= original
= "yay\'foo\'bar";
132 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) > 0);
133 assert_se(streq(t
, "yayfoobar"));
135 assert_se(isempty(p
));
137 p
= original
= " foobar ";
138 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
139 assert_se(streq(t
, "foobar"));
141 assert_se(isempty(p
));
143 p
= original
= " foo\\ba\\x6ar ";
144 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) > 0);
145 assert_se(streq(t
, "foo\ba\x6ar"));
147 assert_se(isempty(p
));
149 p
= original
= " foo\\ba\\x6ar ";
150 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
151 assert_se(streq(t
, "foobax6ar"));
153 assert_se(isempty(p
));
155 p
= original
= " f\\u00f6o \"pi\\U0001F4A9le\" ";
156 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) > 0);
157 assert_se(streq(t
, "föo"));
159 assert_se(p
== original
+ 13);
161 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_CUNESCAPE
) > 0);
162 assert_se(streq(t
, "pi\360\237\222\251le"));
164 assert_se(isempty(p
));
166 p
= original
= "fooo\\";
167 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RELAX
) > 0);
168 assert_se(streq(t
, "fooo"));
170 assert_se(isempty(p
));
172 p
= original
= "fooo\\";
173 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
) > 0);
174 assert_se(streq(t
, "fooo\\"));
176 assert_se(isempty(p
));
178 p
= original
= "fooo\\";
179 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
180 assert_se(streq(t
, "fooo\\"));
182 assert_se(isempty(p
));
184 p
= original
= "fooo\\";
185 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
186 assert_se(streq(t
, "fooo\\"));
188 assert_se(isempty(p
));
190 p
= original
= "\"foo\\";
191 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == -EINVAL
);
192 assert_se(p
== original
+ 5);
194 p
= original
= "\"foo\\";
195 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_RELAX
) > 0);
196 assert_se(streq(t
, "foo"));
198 assert_se(isempty(p
));
200 p
= original
= "foo::bar";
201 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
202 assert_se(streq(t
, "foo"));
204 assert_se(p
== original
+ 5);
206 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
207 assert_se(streq(t
, "bar"));
209 assert_se(isempty(p
));
211 assert_se(extract_first_word(&p
, &t
, ":", 0) == 0);
213 assert_se(isempty(p
));
215 p
= original
= "foo\\:bar::waldo";
216 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
217 assert_se(streq(t
, "foo:bar"));
219 assert_se(p
== original
+ 10);
221 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
222 assert_se(streq(t
, "waldo"));
224 assert_se(isempty(p
));
226 assert_se(extract_first_word(&p
, &t
, ":", 0) == 0);
228 assert_se(isempty(p
));
230 p
= original
= "\"foo\\";
231 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_CUNESCAPE_RELAX
) == -EINVAL
);
232 assert_se(p
== original
+ 5);
234 p
= original
= "\"foo\\";
235 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
236 assert_se(streq(t
, "foo\\"));
238 assert_se(isempty(p
));
240 p
= original
= "\"foo\\";
241 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
242 assert_se(streq(t
, "foo\\"));
244 assert_se(isempty(p
));
246 p
= original
= "fooo\\ bar quux";
247 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RELAX
) > 0);
248 assert_se(streq(t
, "fooo bar"));
250 assert_se(p
== original
+ 10);
252 p
= original
= "fooo\\ bar quux";
253 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
) > 0);
254 assert_se(streq(t
, "fooo bar"));
256 assert_se(p
== original
+ 10);
258 p
= original
= "fooo\\ bar quux";
259 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
260 assert_se(streq(t
, "fooo bar"));
262 assert_se(p
== original
+ 10);
264 p
= original
= "fooo\\ bar quux";
265 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) == -EINVAL
);
266 assert_se(p
== original
+ 5);
268 p
= original
= "fooo\\ bar quux";
269 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
270 assert_se(streq(t
, "fooo\\ bar"));
272 assert_se(p
== original
+ 10);
274 p
= original
= "\\w+@\\K[\\d.]+";
275 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) == -EINVAL
);
276 assert_se(p
== original
+ 1);
278 p
= original
= "\\w+@\\K[\\d.]+";
279 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
280 assert_se(streq(t
, "\\w+@\\K[\\d.]+"));
282 assert_se(isempty(p
));
284 p
= original
= "\\w+\\b";
285 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
286 assert_se(streq(t
, "\\w+\b"));
288 assert_se(isempty(p
));
290 p
= original
= "-N ''";
291 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) > 0);
292 assert_se(streq(t
, "-N"));
294 assert_se(p
== original
+ 3);
296 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_UNQUOTE
) > 0);
297 assert_se(streq(t
, ""));
299 assert_se(isempty(p
));
301 p
= original
= ":foo\\:bar::waldo:";
302 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
304 assert_se(streq(t
, ""));
306 assert_se(p
== original
+ 1);
308 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
309 assert_se(streq(t
, "foo:bar"));
311 assert_se(p
== original
+ 10);
313 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
315 assert_se(streq(t
, ""));
317 assert_se(p
== original
+ 11);
319 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
320 assert_se(streq(t
, "waldo"));
322 assert_se(p
== original
+ 17);
324 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
325 assert_se(streq(t
, ""));
327 assert_se(p
== NULL
);
329 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 0);
334 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
335 assert_se(streq(t
, "fooxbar"));
337 assert_se(p
== NULL
);
340 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RETAIN_ESCAPE
) > 0);
341 assert_se(streq(t
, "foo\\xbar"));
343 assert_se(p
== NULL
);
346 static void test_extract_first_word_and_warn(void) {
347 const char *p
, *original
;
350 p
= original
= "foobar waldo";
351 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
352 assert_se(streq(t
, "foobar"));
354 assert_se(p
== original
+ 7);
356 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
357 assert_se(streq(t
, "waldo"));
359 assert_se(isempty(p
));
361 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) == 0);
363 assert_se(isempty(p
));
365 p
= original
= "\"foobar\" \'waldo\'";
366 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
, NULL
, "fake", 1, original
) > 0);
367 assert_se(streq(t
, "foobar"));
369 assert_se(p
== original
+ 9);
371 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
, NULL
, "fake", 1, original
) > 0);
372 assert_se(streq(t
, "waldo"));
374 assert_se(isempty(p
));
376 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) == 0);
378 assert_se(isempty(p
));
381 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
, NULL
, "fake", 1, original
) == -EINVAL
);
382 assert_se(p
== original
+ 1);
385 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
, NULL
, "fake", 1, original
) == -EINVAL
);
386 assert_se(p
== original
+ 1);
388 p
= original
= "\'fooo";
389 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
, NULL
, "fake", 1, original
) == -EINVAL
);
390 assert_se(p
== original
+ 5);
392 p
= original
= "\'fooo";
393 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
394 assert_se(streq(t
, "fooo"));
396 assert_se(isempty(p
));
398 p
= original
= " foo\\ba\\x6ar ";
399 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
400 assert_se(streq(t
, "foo\ba\x6ar"));
402 assert_se(isempty(p
));
404 p
= original
= " foo\\ba\\x6ar ";
405 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
406 assert_se(streq(t
, "foobax6ar"));
408 assert_se(isempty(p
));
410 p
= original
= " f\\u00f6o \"pi\\U0001F4A9le\" ";
411 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
412 assert_se(streq(t
, "föo"));
414 assert_se(p
== original
+ 13);
416 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
417 assert_se(streq(t
, "pi\360\237\222\251le"));
419 assert_se(isempty(p
));
421 p
= original
= "fooo\\";
422 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
423 assert_se(streq(t
, "fooo"));
425 assert_se(isempty(p
));
427 p
= original
= "fooo\\";
428 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
429 assert_se(streq(t
, "fooo\\"));
431 assert_se(isempty(p
));
433 p
= original
= "fooo\\";
434 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
435 assert_se(streq(t
, "fooo\\"));
437 assert_se(isempty(p
));
439 p
= original
= "\"foo\\";
440 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
, NULL
, "fake", 1, original
) == -EINVAL
);
441 assert_se(p
== original
+ 5);
443 p
= original
= "\"foo\\";
444 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
445 assert_se(streq(t
, "foo"));
447 assert_se(isempty(p
));
449 p
= original
= "\"foo\\";
450 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) == -EINVAL
);
451 assert_se(p
== original
+ 5);
453 p
= original
= "\"foo\\";
454 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_CUNESCAPE
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
455 assert_se(streq(t
, "foo"));
457 assert_se(isempty(p
));
459 p
= original
= "fooo\\ bar quux";
460 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
461 assert_se(streq(t
, "fooo bar"));
463 assert_se(p
== original
+ 10);
465 p
= original
= "fooo\\ bar quux";
466 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
467 assert_se(streq(t
, "fooo bar"));
469 assert_se(p
== original
+ 10);
471 p
= original
= "fooo\\ bar quux";
472 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
473 assert_se(streq(t
, "fooo\\ bar"));
475 assert_se(p
== original
+ 10);
477 p
= original
= "\\w+@\\K[\\d.]+";
478 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
479 assert_se(streq(t
, "\\w+@\\K[\\d.]+"));
481 assert_se(isempty(p
));
483 p
= original
= "\\w+\\b";
484 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
485 assert_se(streq(t
, "\\w+\b"));
487 assert_se(isempty(p
));
490 static void test_extract_many_words(void) {
491 const char *p
, *original
;
494 p
= original
= "foobar waldi piep";
495 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 3);
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
, "piep"));
504 p
= original
= "'foobar' wa\"ld\"i ";
505 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 2);
506 assert_se(isempty(p
));
507 assert_se(streq_ptr(a
, "'foobar'"));
508 assert_se(streq_ptr(b
, "wa\"ld\"i"));
509 assert_se(streq_ptr(c
, NULL
));
513 p
= original
= "'foobar' wa\"ld\"i ";
514 assert_se(extract_many_words(&p
, NULL
, EXTRACT_UNQUOTE
, &a
, &b
, &c
, NULL
) == 2);
515 assert_se(isempty(p
));
516 assert_se(streq_ptr(a
, "foobar"));
517 assert_se(streq_ptr(b
, "waldi"));
518 assert_se(streq_ptr(c
, NULL
));
523 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 0);
524 assert_se(isempty(p
));
525 assert_se(streq_ptr(a
, NULL
));
526 assert_se(streq_ptr(b
, NULL
));
527 assert_se(streq_ptr(c
, NULL
));
530 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 0);
531 assert_se(isempty(p
));
532 assert_se(streq_ptr(a
, NULL
));
533 assert_se(streq_ptr(b
, NULL
));
534 assert_se(streq_ptr(c
, NULL
));
536 p
= original
= "foobar";
537 assert_se(extract_many_words(&p
, NULL
, 0, NULL
) == 0);
538 assert_se(p
== original
);
540 p
= original
= "foobar waldi";
541 assert_se(extract_many_words(&p
, NULL
, 0, &a
, NULL
) == 1);
542 assert_se(p
== original
+7);
543 assert_se(streq_ptr(a
, "foobar"));
546 p
= original
= " foobar ";
547 assert_se(extract_many_words(&p
, NULL
, 0, &a
, NULL
) == 1);
548 assert_se(isempty(p
));
549 assert_se(streq_ptr(a
, "foobar"));
553 int main(int argc
, char *argv
[]) {
554 log_parse_environment();
557 test_extract_first_word();
558 test_extract_first_word_and_warn();
559 test_extract_many_words();