1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Thomas H.P. Andersen
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
33 #include "conf-parser.h"
35 static void test_streq_ptr(void) {
36 assert_se(streq_ptr(NULL, NULL));
37 assert_se(!streq_ptr("abc", "cdef"));
40 static void test_first_word(void) {
41 assert_se(first_word("Hello", ""));
42 assert_se(first_word("Hello", "Hello"));
43 assert_se(first_word("Hello world", "Hello"));
44 assert_se(first_word("Hello\tworld", "Hello"));
45 assert_se(first_word("Hello\nworld", "Hello"));
46 assert_se(first_word("Hello\rworld", "Hello"));
47 assert_se(first_word("Hello ", "Hello"));
49 assert_se(!first_word("Hello", "Hellooo"));
50 assert_se(!first_word("Hello", "xxxxx"));
51 assert_se(!first_word("Hellooo", "Hello"));
54 static void test_close_many(void) {
56 char name0[] = "/tmp/test-close-many.XXXXXX";
57 char name1[] = "/tmp/test-close-many.XXXXXX";
58 char name2[] = "/tmp/test-close-many.XXXXXX";
60 fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
61 fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
62 fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
66 assert_se(fcntl(fds[0], F_GETFD) == -1);
67 assert_se(fcntl(fds[1], F_GETFD) == -1);
68 assert_se(fcntl(fds[2], F_GETFD) >= 0);
70 close_nointr_nofail(fds[2]);
77 static void test_parse_boolean(void) {
78 assert_se(parse_boolean("1") == 1);
79 assert_se(parse_boolean("y") == 1);
80 assert_se(parse_boolean("Y") == 1);
81 assert_se(parse_boolean("yes") == 1);
82 assert_se(parse_boolean("YES") == 1);
83 assert_se(parse_boolean("true") == 1);
84 assert_se(parse_boolean("TRUE") == 1);
85 assert_se(parse_boolean("on") == 1);
86 assert_se(parse_boolean("ON") == 1);
88 assert_se(parse_boolean("0") == 0);
89 assert_se(parse_boolean("n") == 0);
90 assert_se(parse_boolean("N") == 0);
91 assert_se(parse_boolean("no") == 0);
92 assert_se(parse_boolean("NO") == 0);
93 assert_se(parse_boolean("false") == 0);
94 assert_se(parse_boolean("FALSE") == 0);
95 assert_se(parse_boolean("off") == 0);
96 assert_se(parse_boolean("OFF") == 0);
98 assert_se(parse_boolean("garbage") < 0);
99 assert_se(parse_boolean("") < 0);
102 static void test_parse_pid(void) {
106 r = parse_pid("100", &pid);
108 assert_se(pid == 100);
110 r = parse_pid("0x7FFFFFFF", &pid);
112 assert_se(pid == 2147483647);
114 pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
115 r = parse_pid("0", &pid);
116 assert_se(r == -ERANGE);
117 assert_se(pid == 65);
119 pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
120 r = parse_pid("-100", &pid);
121 assert_se(r == -ERANGE);
122 assert_se(pid == 65);
124 pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
125 r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid);
126 assert(r == -ERANGE);
127 assert_se(pid == 65);
130 static void test_parse_uid(void) {
134 r = parse_uid("100", &uid);
136 assert_se(uid == 100);
139 static void test_safe_atolli(void) {
143 r = safe_atolli("12345", &l);
145 assert_se(l == 12345);
147 r = safe_atolli("junk", &l);
148 assert_se(r == -EINVAL);
151 static void test_safe_atod(void) {
156 r = safe_atod("junk", &d);
157 assert_se(r == -EINVAL);
159 r = safe_atod("0.2244", &d);
161 assert_se(abs(d - 0.2244) < 0.000001);
163 r = safe_atod("0,5", &d);
164 assert_se(r == -EINVAL);
168 assert_se(*e == ',');
170 /* Check if this really is locale independent */
171 setlocale(LC_NUMERIC, "de_DE.utf8");
173 r = safe_atod("0.2244", &d);
175 assert_se(abs(d - 0.2244) < 0.000001);
177 r = safe_atod("0,5", &d);
178 assert_se(r == -EINVAL);
181 assert_se(abs(strtod("0,5", &e) - 0.5) < 0.00001);
183 /* And check again, reset */
184 setlocale(LC_NUMERIC, "C");
186 r = safe_atod("0.2244", &d);
188 assert_se(abs(d - 0.2244) < 0.000001);
190 r = safe_atod("0,5", &d);
191 assert_se(r == -EINVAL);
195 assert_se(*e == ',');
198 static void test_strappend(void) {
199 _cleanup_free_ char *t1, *t2, *t3, *t4;
201 t1 = strappend(NULL, NULL);
202 assert_se(streq(t1, ""));
204 t2 = strappend(NULL, "suf");
205 assert_se(streq(t2, "suf"));
207 t3 = strappend("pre", NULL);
208 assert_se(streq(t3, "pre"));
210 t4 = strappend("pre", "suf");
211 assert_se(streq(t4, "presuf"));
214 static void test_strstrip(void) {
216 char input[] = " hello, waldo. ";
219 assert_se(streq(r, "hello, waldo."));
222 static void test_delete_chars(void) {
224 char input[] = " hello, waldo. abc";
226 r = delete_chars(input, WHITESPACE);
227 assert_se(streq(r, "hello,waldo.abc"));
230 static void test_in_charset(void) {
231 assert_se(in_charset("dddaaabbbcccc", "abcd"));
232 assert_se(!in_charset("dddaaabbbcccc", "abc f"));
235 static void test_hexchar(void) {
236 assert_se(hexchar(0xa) == 'a');
237 assert_se(hexchar(0x0) == '0');
240 static void test_unhexchar(void) {
241 assert_se(unhexchar('a') == 0xA);
242 assert_se(unhexchar('A') == 0xA);
243 assert_se(unhexchar('0') == 0x0);
246 static void test_octchar(void) {
247 assert_se(octchar(00) == '0');
248 assert_se(octchar(07) == '7');
251 static void test_unoctchar(void) {
252 assert_se(unoctchar('0') == 00);
253 assert_se(unoctchar('7') == 07);
256 static void test_decchar(void) {
257 assert_se(decchar(0) == '0');
258 assert_se(decchar(9) == '9');
261 static void test_undecchar(void) {
262 assert_se(undecchar('0') == 0);
263 assert_se(undecchar('9') == 9);
266 static void test_cescape(void) {
267 _cleanup_free_ char *escaped;
268 escaped = cescape("abc\\\"\b\f\n\r\t\v\003\177\234\313");
269 assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\003\\177\\234\\313"));
272 static void test_cunescape(void) {
273 _cleanup_free_ char *unescaped;
274 unescaped = cunescape("abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\003\\177\\234\\313");
275 assert_se(streq(unescaped, "abc\\\"\b\f\n\r\t\v\003\177\234\313"));
278 static void test_foreach_word(void) {
282 const char test[] = "test abc d\te f ";
283 const char * const expected[] = {
293 FOREACH_WORD(w, l, test, state) {
294 assert_se(strneq(expected[i++], w, l));
298 static void test_foreach_word_quoted(void) {
302 const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\"";
303 const char * const expected[] = {
319 printf("<%s>\n", test);
320 FOREACH_WORD_QUOTED(w, l, test, state) {
321 _cleanup_free_ char *t = NULL;
323 assert_se(t = strndup(w, l));
324 assert_se(strneq(expected[i++], w, l));
329 static void test_default_term_for_tty(void) {
330 puts(default_term_for_tty("/dev/tty23"));
331 puts(default_term_for_tty("/dev/ttyS23"));
332 puts(default_term_for_tty("/dev/tty0"));
333 puts(default_term_for_tty("/dev/pty0"));
334 puts(default_term_for_tty("/dev/pts/0"));
335 puts(default_term_for_tty("/dev/console"));
336 puts(default_term_for_tty("tty23"));
337 puts(default_term_for_tty("ttyS23"));
338 puts(default_term_for_tty("tty0"));
339 puts(default_term_for_tty("pty0"));
340 puts(default_term_for_tty("pts/0"));
341 puts(default_term_for_tty("console"));
344 static void test_memdup_multiply(void) {
345 int org[] = {1, 2, 3};
348 dup = (int*)memdup_multiply(org, sizeof(int), 3);
351 assert_se(dup[0] == 1);
352 assert_se(dup[1] == 2);
353 assert_se(dup[2] == 3);
357 static void test_hostname_is_valid(void) {
358 assert(hostname_is_valid("foobar"));
359 assert(hostname_is_valid("foobar.com"));
360 assert(!hostname_is_valid("fööbar"));
361 assert(!hostname_is_valid(""));
362 assert(!hostname_is_valid("."));
363 assert(!hostname_is_valid(".."));
364 assert(!hostname_is_valid("foobar."));
365 assert(!hostname_is_valid(".foobar"));
366 assert(!hostname_is_valid("foo..bar"));
367 assert(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
370 static void test_u64log2(void) {
371 assert(u64log2(0) == 0);
372 assert(u64log2(8) == 3);
373 assert(u64log2(9) == 3);
374 assert(u64log2(15) == 3);
375 assert(u64log2(16) == 4);
376 assert(u64log2(1024*1024) == 20);
377 assert(u64log2(1024*1024+5) == 20);
380 static void test_get_process_comm(void) {
382 _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
383 unsigned long long b;
390 if (stat("/proc/1/comm", &st) == 0) {
391 assert_se(get_process_comm(1, &a) >= 0);
392 log_info("pid1 comm: '%s'", a);
394 log_warning("/proc/1/comm does not exist.");
397 assert_se(get_starttime_of_pid(1, &b) >= 0);
398 log_info("pid1 starttime: '%llu'", b);
400 assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
401 log_info("pid1 cmdline: '%s'", c);
403 assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
404 log_info("pid1 cmdline truncated: '%s'", d);
406 assert_se(get_parent_of_pid(1, &e) >= 0);
407 log_info("pid1 ppid: '%llu'", (unsigned long long) e);
410 assert_se(is_kernel_thread(1) == 0);
412 r = get_process_exe(1, &f);
413 assert_se(r >= 0 || r == -EACCES);
414 log_info("pid1 exe: '%s'", strna(f));
416 assert_se(get_process_uid(1, &u) == 0);
417 log_info("pid1 uid: '%llu'", (unsigned long long) u);
420 assert_se(get_process_gid(1, &g) == 0);
421 log_info("pid1 gid: '%llu'", (unsigned long long) g);
424 assert(get_ctty_devnr(1, &h) == -ENOENT);
426 getenv_for_pid(1, "PATH", &i);
427 log_info("pid1 $PATH: '%s'", strna(i));
430 static void test_protect_errno(void) {
439 static void test_parse_size(void) {
442 assert_se(parse_size("111", 1024, &bytes) == 0);
443 assert_se(bytes == 111);
445 assert_se(parse_size("111.4", 1024, &bytes) == 0);
446 assert_se(bytes == 111);
448 assert_se(parse_size(" 112 B", 1024, &bytes) == 0);
449 assert_se(bytes == 112);
451 assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0);
452 assert_se(bytes == 112);
454 assert_se(parse_size("3.5 K", 1024, &bytes) == 0);
455 assert_se(bytes == 3*1024 + 512);
457 assert_se(parse_size("3. K", 1024, &bytes) == 0);
458 assert_se(bytes == 3*1024);
460 assert_se(parse_size("3.0 K", 1024, &bytes) == 0);
461 assert_se(bytes == 3*1024);
463 assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL);
465 assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0);
466 assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512);
468 assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL);
470 assert_se(parse_size("3.5G3B", 1024, &bytes) == 0);
471 assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3);
473 assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0);
474 assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4);
476 assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL);
478 assert_se(parse_size("4T3G3B", 1024, &bytes) == 0);
479 assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
481 assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0);
482 assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
484 assert_se(parse_size("12P", 1024, &bytes) == 0);
485 assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
487 assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL);
489 assert_se(parse_size("3E 2P", 1024, &bytes) == 0);
490 assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
492 assert_se(parse_size("12X", 1024, &bytes) == -EINVAL);
494 assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL);
496 assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL);
498 assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE);
499 assert_se(parse_size("-1", 1024, &bytes) == -ERANGE);
500 assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE);
502 assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE);
504 assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
507 static void test_config_parse_iec_off(void) {
509 assert_se(config_parse_iec_off(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
510 assert_se(offset == 4 * 1024 * 1024);
512 assert_se(config_parse_iec_off(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
515 static void test_strextend(void) {
516 _cleanup_free_ char *str = strdup("0123");
517 strextend(&str, "456", "78", "9", NULL);
518 assert_se(streq(str, "0123456789"));
521 static void test_strrep(void) {
522 _cleanup_free_ char *one, *three, *zero;
523 one = strrep("waldo", 1);
524 three = strrep("waldo", 3);
525 zero = strrep("waldo", 0);
527 assert_se(streq(one, "waldo"));
528 assert_se(streq(three, "waldowaldowaldo"));
529 assert_se(streq(zero, ""));
532 static void test_split_pair(void) {
533 _cleanup_free_ char *a = NULL, *b = NULL;
535 assert_se(split_pair("", "", &a, &b) == -EINVAL);
536 assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
537 assert_se(split_pair("", "=", &a, &b) == -EINVAL);
538 assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
539 assert_se(streq(a, "foo"));
540 assert_se(streq(b, "bar"));
543 assert_se(split_pair("==", "==", &a, &b) >= 0);
544 assert_se(streq(a, ""));
545 assert_se(streq(b, ""));
549 assert_se(split_pair("===", "==", &a, &b) >= 0);
550 assert_se(streq(a, ""));
551 assert_se(streq(b, "="));
554 static void test_fstab_node_to_udev_node(void) {
557 n = fstab_node_to_udev_node("LABEL=applé/jack");
559 assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
562 n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
564 assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
567 n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
569 assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
572 n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
574 assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
578 n = fstab_node_to_udev_node("PONIES=awesome");
580 assert_se(streq(n, "PONIES=awesome"));
583 n = fstab_node_to_udev_node("/dev/xda1");
585 assert_se(streq(n, "/dev/xda1"));
589 static void test_get_files_in_directory(void) {
590 _cleanup_strv_free_ char **l = NULL, **t = NULL;
592 assert_se(get_files_in_directory("/tmp", &l) >= 0);
593 assert_se(get_files_in_directory(".", &t) >= 0);
594 assert_se(get_files_in_directory(".", NULL) >= 0);
597 static void test_in_set(void) {
598 assert_se(IN_SET(1, 1));
599 assert_se(IN_SET(1, 1, 2, 3, 4));
600 assert_se(IN_SET(2, 1, 2, 3, 4));
601 assert_se(IN_SET(3, 1, 2, 3, 4));
602 assert_se(IN_SET(4, 1, 2, 3, 4));
603 assert_se(!IN_SET(0, 1));
604 assert_se(!IN_SET(0, 1, 2, 3, 4));
607 static void test_writing_tmpfile(void) {
608 char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
609 _cleanup_free_ char *contents = NULL;
614 IOVEC_SET_STRING(iov[0], "abc\n");
615 IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
616 IOVEC_SET_STRING(iov[2], "");
618 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
619 printf("tmpfile: %s", name);
621 r = writev(fd, iov, 3);
624 r = read_full_file(name, &contents, &size);
626 printf("contents: %s", contents);
627 assert(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
630 int main(int argc, char *argv[]) {
631 log_parse_environment();
637 test_parse_boolean();
655 test_foreach_word_quoted();
656 test_default_term_for_tty();
657 test_memdup_multiply();
658 test_hostname_is_valid();
660 test_get_process_comm();
661 test_protect_errno();
663 test_config_parse_iec_off();
667 test_fstab_node_to_udev_node();
668 test_get_files_in_directory();
670 test_writing_tmpfile();