1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
6 Copyright 2013 Thomas H.P. Andersen
13 #include "extract-word.h"
15 #include "string-util.h"
17 static void test_extract_first_word(void) {
18 const char *p
, *original
;
21 p
= original
= "foobar waldo";
22 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
23 assert_se(streq(t
, "foobar"));
25 assert_se(p
== original
+ 7);
27 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
28 assert_se(streq(t
, "waldo"));
30 assert_se(isempty(p
));
32 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
34 assert_se(isempty(p
));
36 p
= original
= "\"foobar\" \'waldo\'";
37 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
38 assert_se(streq(t
, "\"foobar\""));
40 assert_se(p
== original
+ 9);
42 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
43 assert_se(streq(t
, "\'waldo\'"));
45 assert_se(isempty(p
));
47 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
49 assert_se(isempty(p
));
51 p
= original
= "\"foobar\" \'waldo\'";
52 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
53 assert_se(streq(t
, "foobar"));
55 assert_se(p
== original
+ 9);
57 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
58 assert_se(streq(t
, "waldo"));
60 assert_se(isempty(p
));
62 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 0);
64 assert_se(isempty(p
));
67 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
68 assert_se(streq(t
, "\""));
70 assert_se(isempty(p
));
73 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) == -EINVAL
);
74 assert_se(p
== original
+ 1);
77 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
78 assert_se(streq(t
, "\'"));
80 assert_se(isempty(p
));
83 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) == -EINVAL
);
84 assert_se(p
== original
+ 1);
86 p
= original
= "\'fooo";
87 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == 1);
88 assert_se(streq(t
, "\'fooo"));
90 assert_se(isempty(p
));
92 p
= original
= "\'fooo";
93 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) == -EINVAL
);
94 assert_se(p
== original
+ 5);
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
= "\"fooo";
103 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
) > 0);
104 assert_se(streq(t
, "fooo"));
106 assert_se(isempty(p
));
108 p
= original
= "yay\'foo\'bar";
109 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
110 assert_se(streq(t
, "yay\'foo\'bar"));
112 assert_se(isempty(p
));
114 p
= original
= "yay\'foo\'bar";
115 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
116 assert_se(streq(t
, "yayfoobar"));
118 assert_se(isempty(p
));
120 p
= original
= " foobar ";
121 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
122 assert_se(streq(t
, "foobar"));
124 assert_se(isempty(p
));
126 p
= original
= " foo\\ba\\x6ar ";
127 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) > 0);
128 assert_se(streq(t
, "foo\ba\x6ar"));
130 assert_se(isempty(p
));
132 p
= original
= " foo\\ba\\x6ar ";
133 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
134 assert_se(streq(t
, "foobax6ar"));
136 assert_se(isempty(p
));
138 p
= original
= " f\\u00f6o \"pi\\U0001F4A9le\" ";
139 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) > 0);
140 assert_se(streq(t
, "föo"));
142 assert_se(p
== original
+ 13);
144 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
) > 0);
145 assert_se(streq(t
, "pi\360\237\222\251le"));
147 assert_se(isempty(p
));
149 p
= original
= "fooo\\";
150 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_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
) > 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_RELAX
|EXTRACT_RELAX
) > 0);
163 assert_se(streq(t
, "fooo\\"));
165 assert_se(isempty(p
));
167 p
= original
= "fooo\\";
168 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
169 assert_se(streq(t
, "fooo\\"));
171 assert_se(isempty(p
));
173 p
= original
= "\"foo\\";
174 assert_se(extract_first_word(&p
, &t
, NULL
, 0) == -EINVAL
);
175 assert_se(p
== original
+ 5);
177 p
= original
= "\"foo\\";
178 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
) > 0);
179 assert_se(streq(t
, "foo"));
181 assert_se(isempty(p
));
183 p
= original
= "foo::bar";
184 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
185 assert_se(streq(t
, "foo"));
187 assert_se(p
== original
+ 5);
189 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
190 assert_se(streq(t
, "bar"));
192 assert_se(isempty(p
));
194 assert_se(extract_first_word(&p
, &t
, ":", 0) == 0);
196 assert_se(isempty(p
));
198 p
= original
= "foo\\:bar::waldo";
199 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
200 assert_se(streq(t
, "foo:bar"));
202 assert_se(p
== original
+ 10);
204 assert_se(extract_first_word(&p
, &t
, ":", 0) == 1);
205 assert_se(streq(t
, "waldo"));
207 assert_se(isempty(p
));
209 assert_se(extract_first_word(&p
, &t
, ":", 0) == 0);
211 assert_se(isempty(p
));
213 p
= original
= "\"foo\\";
214 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE_RELAX
) == -EINVAL
);
215 assert_se(p
== original
+ 5);
217 p
= original
= "\"foo\\";
218 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
219 assert_se(streq(t
, "foo\\"));
221 assert_se(isempty(p
));
223 p
= original
= "\"foo\\";
224 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
|EXTRACT_RELAX
) > 0);
225 assert_se(streq(t
, "foo\\"));
227 assert_se(isempty(p
));
229 p
= original
= "fooo\\ bar quux";
230 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_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
) > 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_RELAX
|EXTRACT_RELAX
) > 0);
243 assert_se(streq(t
, "fooo bar"));
245 assert_se(p
== original
+ 10);
247 p
= original
= "fooo\\ bar quux";
248 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) == -EINVAL
);
249 assert_se(p
== original
+ 5);
251 p
= original
= "fooo\\ bar quux";
252 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
253 assert_se(streq(t
, "fooo\\ bar"));
255 assert_se(p
== original
+ 10);
257 p
= original
= "\\w+@\\K[\\d.]+";
258 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
) == -EINVAL
);
259 assert_se(p
== original
+ 1);
261 p
= original
= "\\w+@\\K[\\d.]+";
262 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
263 assert_se(streq(t
, "\\w+@\\K[\\d.]+"));
265 assert_se(isempty(p
));
267 p
= original
= "\\w+\\b";
268 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_CUNESCAPE_RELAX
) > 0);
269 assert_se(streq(t
, "\\w+\b"));
271 assert_se(isempty(p
));
273 p
= original
= "-N ''";
274 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
275 assert_se(streq(t
, "-N"));
277 assert_se(p
== original
+ 3);
279 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_QUOTES
) > 0);
280 assert_se(streq(t
, ""));
282 assert_se(isempty(p
));
284 p
= original
= ":foo\\:bar::waldo:";
285 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
287 assert_se(streq(t
, ""));
289 assert_se(p
== original
+ 1);
291 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
292 assert_se(streq(t
, "foo:bar"));
294 assert_se(p
== original
+ 10);
296 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
298 assert_se(streq(t
, ""));
300 assert_se(p
== original
+ 11);
302 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
303 assert_se(streq(t
, "waldo"));
305 assert_se(p
== original
+ 17);
307 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 1);
308 assert_se(streq(t
, ""));
310 assert_se(p
== NULL
);
312 assert_se(extract_first_word(&p
, &t
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
) == 0);
317 assert_se(extract_first_word(&p
, &t
, NULL
, 0) > 0);
318 assert_se(streq(t
, "fooxbar"));
320 assert_se(p
== NULL
);
323 assert_se(extract_first_word(&p
, &t
, NULL
, EXTRACT_RETAIN_ESCAPE
) > 0);
324 assert_se(streq(t
, "foo\\xbar"));
326 assert_se(p
== NULL
);
329 static void test_extract_first_word_and_warn(void) {
330 const char *p
, *original
;
333 p
= original
= "foobar waldo";
334 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
335 assert_se(streq(t
, "foobar"));
337 assert_se(p
== original
+ 7);
339 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
340 assert_se(streq(t
, "waldo"));
342 assert_se(isempty(p
));
344 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) == 0);
346 assert_se(isempty(p
));
348 p
= original
= "\"foobar\" \'waldo\'";
349 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) > 0);
350 assert_se(streq(t
, "foobar"));
352 assert_se(p
== original
+ 9);
354 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) > 0);
355 assert_se(streq(t
, "waldo"));
357 assert_se(isempty(p
));
359 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) == 0);
361 assert_se(isempty(p
));
364 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
365 assert_se(p
== original
+ 1);
368 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
369 assert_se(p
== original
+ 1);
371 p
= original
= "\'fooo";
372 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
373 assert_se(p
== original
+ 5);
375 p
= original
= "\'fooo";
376 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
377 assert_se(streq(t
, "fooo"));
379 assert_se(isempty(p
));
381 p
= original
= " foo\\ba\\x6ar ";
382 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
383 assert_se(streq(t
, "foo\ba\x6ar"));
385 assert_se(isempty(p
));
387 p
= original
= " foo\\ba\\x6ar ";
388 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, 0, NULL
, "fake", 1, original
) > 0);
389 assert_se(streq(t
, "foobax6ar"));
391 assert_se(isempty(p
));
393 p
= original
= " f\\u00f6o \"pi\\U0001F4A9le\" ";
394 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
395 assert_se(streq(t
, "föo"));
397 assert_se(p
== original
+ 13);
399 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
400 assert_se(streq(t
, "pi\360\237\222\251le"));
402 assert_se(isempty(p
));
404 p
= original
= "fooo\\";
405 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_RELAX
, 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
, 0, NULL
, "fake", 1, original
) > 0);
412 assert_se(streq(t
, "fooo\\"));
414 assert_se(isempty(p
));
416 p
= original
= "fooo\\";
417 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
418 assert_se(streq(t
, "fooo\\"));
420 assert_se(isempty(p
));
422 p
= original
= "\"foo\\";
423 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
, NULL
, "fake", 1, original
) == -EINVAL
);
424 assert_se(p
== original
+ 5);
426 p
= original
= "\"foo\\";
427 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
428 assert_se(streq(t
, "foo"));
430 assert_se(isempty(p
));
432 p
= original
= "\"foo\\";
433 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) == -EINVAL
);
434 assert_se(p
== original
+ 5);
436 p
= original
= "\"foo\\";
437 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_QUOTES
|EXTRACT_CUNESCAPE
|EXTRACT_RELAX
, NULL
, "fake", 1, original
) > 0);
438 assert_se(streq(t
, "foo"));
440 assert_se(isempty(p
));
442 p
= original
= "fooo\\ bar quux";
443 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_RELAX
, 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
, 0, NULL
, "fake", 1, original
) > 0);
450 assert_se(streq(t
, "fooo bar"));
452 assert_se(p
== original
+ 10);
454 p
= original
= "fooo\\ bar quux";
455 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
456 assert_se(streq(t
, "fooo\\ bar"));
458 assert_se(p
== original
+ 10);
460 p
= original
= "\\w+@\\K[\\d.]+";
461 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
462 assert_se(streq(t
, "\\w+@\\K[\\d.]+"));
464 assert_se(isempty(p
));
466 p
= original
= "\\w+\\b";
467 assert_se(extract_first_word_and_warn(&p
, &t
, NULL
, EXTRACT_CUNESCAPE
, NULL
, "fake", 1, original
) > 0);
468 assert_se(streq(t
, "\\w+\b"));
470 assert_se(isempty(p
));
473 static void test_extract_many_words(void) {
474 const char *p
, *original
;
477 p
= original
= "foobar waldi piep";
478 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 3);
479 assert_se(isempty(p
));
480 assert_se(streq_ptr(a
, "foobar"));
481 assert_se(streq_ptr(b
, "waldi"));
482 assert_se(streq_ptr(c
, "piep"));
487 p
= original
= "'foobar' wa\"ld\"i ";
488 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 2);
489 assert_se(isempty(p
));
490 assert_se(streq_ptr(a
, "'foobar'"));
491 assert_se(streq_ptr(b
, "wa\"ld\"i"));
492 assert_se(streq_ptr(c
, NULL
));
496 p
= original
= "'foobar' wa\"ld\"i ";
497 assert_se(extract_many_words(&p
, NULL
, EXTRACT_QUOTES
, &a
, &b
, &c
, NULL
) == 2);
498 assert_se(isempty(p
));
499 assert_se(streq_ptr(a
, "foobar"));
500 assert_se(streq_ptr(b
, "waldi"));
501 assert_se(streq_ptr(c
, NULL
));
506 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 0);
507 assert_se(isempty(p
));
508 assert_se(streq_ptr(a
, NULL
));
509 assert_se(streq_ptr(b
, NULL
));
510 assert_se(streq_ptr(c
, NULL
));
513 assert_se(extract_many_words(&p
, NULL
, 0, &a
, &b
, &c
, NULL
) == 0);
514 assert_se(isempty(p
));
515 assert_se(streq_ptr(a
, NULL
));
516 assert_se(streq_ptr(b
, NULL
));
517 assert_se(streq_ptr(c
, NULL
));
519 p
= original
= "foobar";
520 assert_se(extract_many_words(&p
, NULL
, 0, NULL
) == 0);
521 assert_se(p
== original
);
523 p
= original
= "foobar waldi";
524 assert_se(extract_many_words(&p
, NULL
, 0, &a
, NULL
) == 1);
525 assert_se(p
== original
+7);
526 assert_se(streq_ptr(a
, "foobar"));
529 p
= original
= " foobar ";
530 assert_se(extract_many_words(&p
, NULL
, 0, &a
, NULL
) == 1);
531 assert_se(isempty(p
));
532 assert_se(streq_ptr(a
, "foobar"));
536 int main(int argc
, char *argv
[]) {
537 log_parse_environment();
540 test_extract_first_word();
541 test_extract_first_word_and_warn();
542 test_extract_many_words();