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"));
577 n = fstab_node_to_udev_node("PONIES=awesome");
579 assert_se(streq(n, "PONIES=awesome"));
582 n = fstab_node_to_udev_node("/dev/xda1");
584 assert_se(streq(n, "/dev/xda1"));
588 static void test_get_files_in_directory(void) {
589 _cleanup_strv_free_ char **l = NULL, **t = NULL;
591 assert_se(get_files_in_directory("/tmp", &l) >= 0);
592 assert_se(get_files_in_directory(".", &t) >= 0);
593 assert_se(get_files_in_directory(".", NULL) >= 0);
596 static void test_in_set(void) {
597 assert_se(IN_SET(1, 1));
598 assert_se(IN_SET(1, 1, 2, 3, 4));
599 assert_se(IN_SET(2, 1, 2, 3, 4));
600 assert_se(IN_SET(3, 1, 2, 3, 4));
601 assert_se(IN_SET(4, 1, 2, 3, 4));
602 assert_se(!IN_SET(0, 1));
603 assert_se(!IN_SET(0, 1, 2, 3, 4));
606 static void test_writing_tmpfile(void) {
607 char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
608 _cleanup_free_ char *contents = NULL;
613 IOVEC_SET_STRING(iov[0], "abc\n");
614 IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
615 IOVEC_SET_STRING(iov[2], "");
617 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
618 printf("tmpfile: %s", name);
620 r = writev(fd, iov, 3);
623 r = read_full_file(name, &contents, &size);
625 printf("contents: %s", contents);
626 assert(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
629 static void test_hexdump(void) {
633 hexdump(stdout, NULL, 0);
634 hexdump(stdout, "", 0);
635 hexdump(stdout, "", 1);
636 hexdump(stdout, "x", 1);
637 hexdump(stdout, "x", 2);
638 hexdump(stdout, "foobar", 7);
639 hexdump(stdout, "f\nobar", 7);
640 hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
642 for (i = 0; i < ELEMENTSOF(data); i++)
645 hexdump(stdout, data, sizeof(data));
648 static void test_log2i(void) {
649 assert_se(log2i(1) == 0);
650 assert_se(log2i(2) == 1);
651 assert_se(log2i(3) == 1);
652 assert_se(log2i(4) == 2);
653 assert_se(log2i(32) == 5);
654 assert_se(log2i(33) == 5);
655 assert_se(log2i(63) == 5);
656 assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
659 int main(int argc, char *argv[]) {
660 log_parse_environment();
666 test_parse_boolean();
684 test_foreach_word_quoted();
685 test_default_term_for_tty();
686 test_memdup_multiply();
687 test_hostname_is_valid();
689 test_get_process_comm();
690 test_protect_errno();
692 test_config_parse_iec_off();
696 test_fstab_node_to_udev_node();
697 test_get_files_in_directory();
699 test_writing_tmpfile();