chiark / gitweb /
74f83a2629e84a4febb26db8c1fcdc7a66937455
[elogind.git] / src / test / test-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7   Copyright 2013 Thomas H.P. Andersen
8
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.
13
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.
18
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/>.
21 ***/
22
23 #include <string.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <locale.h>
27 #include <errno.h>
28
29 #include "util.h"
30 #include "strv.h"
31 #include "def.h"
32 #include "fileio.h"
33 #include "conf-parser.h"
34
35 static void test_streq_ptr(void) {
36         assert_se(streq_ptr(NULL, NULL));
37         assert_se(!streq_ptr("abc", "cdef"));
38 }
39
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"));
48
49         assert_se(!first_word("Hello", "Hellooo"));
50         assert_se(!first_word("Hello", "xxxxx"));
51         assert_se(!first_word("Hellooo", "Hello"));
52 }
53
54 static void test_close_many(void) {
55         int fds[3];
56         char name0[] = "/tmp/test-close-many.XXXXXX";
57         char name1[] = "/tmp/test-close-many.XXXXXX";
58         char name2[] = "/tmp/test-close-many.XXXXXX";
59
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);
63
64         close_many(fds, 2);
65
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);
69
70         close_nointr_nofail(fds[2]);
71
72         unlink(name0);
73         unlink(name1);
74         unlink(name2);
75 }
76
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);
87
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);
97
98         assert_se(parse_boolean("garbage") < 0);
99         assert_se(parse_boolean("") < 0);
100 }
101
102 static void test_parse_pid(void) {
103         int r;
104         pid_t pid;
105
106         r = parse_pid("100", &pid);
107         assert_se(r == 0);
108         assert_se(pid == 100);
109
110         r = parse_pid("0x7FFFFFFF", &pid);
111         assert_se(r == 0);
112         assert_se(pid == 2147483647);
113
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);
118
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);
123
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);
128 }
129
130 static void test_parse_uid(void) {
131         int r;
132         uid_t uid;
133
134         r = parse_uid("100", &uid);
135         assert_se(r == 0);
136         assert_se(uid == 100);
137 }
138
139 static void test_safe_atolli(void) {
140         int r;
141         long long l;
142
143         r = safe_atolli("12345", &l);
144         assert_se(r == 0);
145         assert_se(l == 12345);
146
147         r = safe_atolli("junk", &l);
148         assert_se(r == -EINVAL);
149 }
150
151 static void test_safe_atod(void) {
152         int r;
153         double d;
154         char *e;
155
156         r = safe_atod("junk", &d);
157         assert_se(r == -EINVAL);
158
159         r = safe_atod("0.2244", &d);
160         assert_se(r == 0);
161         assert_se(abs(d - 0.2244) < 0.000001);
162
163         r = safe_atod("0,5", &d);
164         assert_se(r == -EINVAL);
165
166         errno = 0;
167         strtod("0,5", &e);
168         assert_se(*e == ',');
169
170         /* Check if this really is locale independent */
171         setlocale(LC_NUMERIC, "de_DE.utf8");
172
173         r = safe_atod("0.2244", &d);
174         assert_se(r == 0);
175         assert_se(abs(d - 0.2244) < 0.000001);
176
177         r = safe_atod("0,5", &d);
178         assert_se(r == -EINVAL);
179
180         errno = 0;
181         assert_se(abs(strtod("0,5", &e) - 0.5) < 0.00001);
182
183         /* And check again, reset */
184         setlocale(LC_NUMERIC, "C");
185
186         r = safe_atod("0.2244", &d);
187         assert_se(r == 0);
188         assert_se(abs(d - 0.2244) < 0.000001);
189
190         r = safe_atod("0,5", &d);
191         assert_se(r == -EINVAL);
192
193         errno = 0;
194         strtod("0,5", &e);
195         assert_se(*e == ',');
196 }
197
198 static void test_strappend(void) {
199         _cleanup_free_ char *t1, *t2, *t3, *t4;
200
201         t1 = strappend(NULL, NULL);
202         assert_se(streq(t1, ""));
203
204         t2 = strappend(NULL, "suf");
205         assert_se(streq(t2, "suf"));
206
207         t3 = strappend("pre", NULL);
208         assert_se(streq(t3, "pre"));
209
210         t4 = strappend("pre", "suf");
211         assert_se(streq(t4, "presuf"));
212 }
213
214 static void test_strstrip(void) {
215         char *r;
216         char input[] = "   hello, waldo.   ";
217
218         r = strstrip(input);
219         assert_se(streq(r, "hello, waldo."));
220 }
221
222 static void test_delete_chars(void) {
223         char *r;
224         char input[] = "   hello, waldo.   abc";
225
226         r = delete_chars(input, WHITESPACE);
227         assert_se(streq(r, "hello,waldo.abc"));
228 }
229
230 static void test_in_charset(void) {
231         assert_se(in_charset("dddaaabbbcccc", "abcd"));
232         assert_se(!in_charset("dddaaabbbcccc", "abc f"));
233 }
234
235 static void test_hexchar(void) {
236         assert_se(hexchar(0xa) == 'a');
237         assert_se(hexchar(0x0) == '0');
238 }
239
240 static void test_unhexchar(void) {
241         assert_se(unhexchar('a') == 0xA);
242         assert_se(unhexchar('A') == 0xA);
243         assert_se(unhexchar('0') == 0x0);
244 }
245
246 static void test_octchar(void) {
247         assert_se(octchar(00) == '0');
248         assert_se(octchar(07) == '7');
249 }
250
251 static void test_unoctchar(void) {
252         assert_se(unoctchar('0') == 00);
253         assert_se(unoctchar('7') == 07);
254 }
255
256 static void test_decchar(void) {
257         assert_se(decchar(0) == '0');
258         assert_se(decchar(9) == '9');
259 }
260
261 static void test_undecchar(void) {
262         assert_se(undecchar('0') == 0);
263         assert_se(undecchar('9') == 9);
264 }
265
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"));
270 }
271
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"));
276 }
277
278 static void test_foreach_word(void) {
279         char *w, *state;
280         size_t l;
281         int i = 0;
282         const char test[] = "test abc d\te   f   ";
283         const char * const expected[] = {
284                 "test",
285                 "abc",
286                 "d",
287                 "e",
288                 "f",
289                 "",
290                 NULL
291         };
292
293         FOREACH_WORD(w, l, test, state) {
294                 assert_se(strneq(expected[i++], w, l));
295         }
296 }
297
298 static void test_foreach_word_quoted(void) {
299         char *w, *state;
300         size_t l;
301         int i = 0;
302         const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\"";
303         const char * const expected[] = {
304                 "test",
305                 "a",
306                 "b",
307                 "c",
308                 "d",
309                 "e",
310                 "",
311                 "",
312                 "hhh",
313                 "",
314                 "",
315                 "a b c",
316                 NULL
317         };
318
319         printf("<%s>\n", test);
320         FOREACH_WORD_QUOTED(w, l, test, state) {
321                 _cleanup_free_ char *t = NULL;
322
323                 assert_se(t = strndup(w, l));
324                 assert_se(strneq(expected[i++], w, l));
325                 printf("<%s>\n", t);
326         }
327 }
328
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"));
342 }
343
344 static void test_memdup_multiply(void) {
345         int org[] = {1, 2, 3};
346         int *dup;
347
348         dup = (int*)memdup_multiply(org, sizeof(int), 3);
349
350         assert_se(dup);
351         assert_se(dup[0] == 1);
352         assert_se(dup[1] == 2);
353         assert_se(dup[2] == 3);
354         free(dup);
355 }
356
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"));
368 }
369
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);
378 }
379
380 static void test_get_process_comm(void) {
381         struct stat st;
382         _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
383         unsigned long long b;
384         pid_t e;
385         uid_t u;
386         gid_t g;
387         dev_t h;
388         int r;
389
390         if (stat("/proc/1/comm", &st) == 0) {
391                 assert_se(get_process_comm(1, &a) >= 0);
392                 log_info("pid1 comm: '%s'", a);
393         } else {
394                 log_warning("/proc/1/comm does not exist.");
395         }
396
397         assert_se(get_starttime_of_pid(1, &b) >= 0);
398         log_info("pid1 starttime: '%llu'", b);
399
400         assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
401         log_info("pid1 cmdline: '%s'", c);
402
403         assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
404         log_info("pid1 cmdline truncated: '%s'", d);
405
406         assert_se(get_parent_of_pid(1, &e) >= 0);
407         log_info("pid1 ppid: '%llu'", (unsigned long long) e);
408         assert_se(e == 0);
409
410         assert_se(is_kernel_thread(1) == 0);
411
412         r = get_process_exe(1, &f);
413         assert_se(r >= 0 || r == -EACCES);
414         log_info("pid1 exe: '%s'", strna(f));
415
416         assert_se(get_process_uid(1, &u) == 0);
417         log_info("pid1 uid: '%llu'", (unsigned long long) u);
418         assert_se(u == 0);
419
420         assert_se(get_process_gid(1, &g) == 0);
421         log_info("pid1 gid: '%llu'", (unsigned long long) g);
422         assert_se(g == 0);
423
424         assert(get_ctty_devnr(1, &h) == -ENOENT);
425
426         getenv_for_pid(1, "PATH", &i);
427         log_info("pid1 $PATH: '%s'", strna(i));
428 }
429
430 static void test_protect_errno(void) {
431         errno = 12;
432         {
433                 PROTECT_ERRNO;
434                 errno = 11;
435         }
436         assert(errno == 12);
437 }
438
439 static void test_parse_size(void) {
440         off_t bytes;
441
442         assert_se(parse_size("111", 1024, &bytes) == 0);
443         assert_se(bytes == 111);
444
445         assert_se(parse_size("111.4", 1024, &bytes) == 0);
446         assert_se(bytes == 111);
447
448         assert_se(parse_size(" 112 B", 1024, &bytes) == 0);
449         assert_se(bytes == 112);
450
451         assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0);
452         assert_se(bytes == 112);
453
454         assert_se(parse_size("3.5 K", 1024, &bytes) == 0);
455         assert_se(bytes == 3*1024 + 512);
456
457         assert_se(parse_size("3. K", 1024, &bytes) == 0);
458         assert_se(bytes == 3*1024);
459
460         assert_se(parse_size("3.0 K", 1024, &bytes) == 0);
461         assert_se(bytes == 3*1024);
462
463         assert_se(parse_size("3. 0 K", 1024, &bytes) == 0);
464         assert_se(bytes == 3);
465
466         assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0);
467         assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512);
468
469         assert_se(parse_size("3B3.5G", 1024, &bytes) == 0);
470         assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3);
471
472         assert_se(parse_size("3B3G4T", 1024, &bytes) == 0);
473         assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
474
475         assert_se(parse_size("12P", 1024, &bytes) == 0);
476         assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
477
478         assert_se(parse_size("3E 2P", 1024, &bytes) == 0);
479         assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
480
481         assert_se(parse_size("12X", 1024, &bytes) == -EINVAL);
482
483         assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL);
484
485         assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL);
486
487         assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE);
488         assert_se(parse_size("-1", 1024, &bytes) == -ERANGE);
489         assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE);
490
491         assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE);
492
493         assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
494 }
495
496 static void test_config_parse_iec_off(void) {
497         off_t offset = 0;
498         assert_se(config_parse_iec_off(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
499         assert_se(offset == 4 * 1024 * 1024);
500
501         assert_se(config_parse_iec_off(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
502 }
503
504 static void test_strextend(void) {
505         _cleanup_free_ char *str = strdup("0123");
506         strextend(&str, "456", "78", "9", NULL);
507         assert_se(streq(str, "0123456789"));
508 }
509
510 static void test_strrep(void) {
511         _cleanup_free_ char *one, *three, *zero;
512         one = strrep("waldo", 1);
513         three = strrep("waldo", 3);
514         zero = strrep("waldo", 0);
515
516         assert_se(streq(one, "waldo"));
517         assert_se(streq(three, "waldowaldowaldo"));
518         assert_se(streq(zero, ""));
519 }
520
521 static void test_split_pair(void) {
522         _cleanup_free_ char *a = NULL, *b = NULL;
523
524         assert_se(split_pair("", "", &a, &b) == -EINVAL);
525         assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
526         assert_se(split_pair("", "=", &a, &b) == -EINVAL);
527         assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
528         assert_se(streq(a, "foo"));
529         assert_se(streq(b, "bar"));
530         free(a);
531         free(b);
532         assert_se(split_pair("==", "==", &a, &b) >= 0);
533         assert_se(streq(a, ""));
534         assert_se(streq(b, ""));
535         free(a);
536         free(b);
537
538         assert_se(split_pair("===", "==", &a, &b) >= 0);
539         assert_se(streq(a, ""));
540         assert_se(streq(b, "="));
541 }
542
543 static void test_fstab_node_to_udev_node(void) {
544         char *n;
545
546         n = fstab_node_to_udev_node("LABEL=applé/jack");
547         puts(n);
548         assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
549         free(n);
550
551         n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
552         puts(n);
553         assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
554         free(n);
555
556         n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
557         puts(n);
558         assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
559         free(n);
560
561         n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
562         puts(n);
563         assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
564         free(n);
565
566
567         n = fstab_node_to_udev_node("PONIES=awesome");
568         puts(n);
569         assert_se(streq(n, "PONIES=awesome"));
570         free(n);
571
572         n = fstab_node_to_udev_node("/dev/xda1");
573         puts(n);
574         assert_se(streq(n, "/dev/xda1"));
575         free(n);
576 }
577
578 static void test_get_files_in_directory(void) {
579         _cleanup_strv_free_ char **l = NULL, **t = NULL;
580
581         assert_se(get_files_in_directory("/tmp", &l) >= 0);
582         assert_se(get_files_in_directory(".", &t) >= 0);
583         assert_se(get_files_in_directory(".", NULL) >= 0);
584 }
585
586 static void test_in_set(void) {
587         assert_se(IN_SET(1, 1));
588         assert_se(IN_SET(1, 1, 2, 3, 4));
589         assert_se(IN_SET(2, 1, 2, 3, 4));
590         assert_se(IN_SET(3, 1, 2, 3, 4));
591         assert_se(IN_SET(4, 1, 2, 3, 4));
592         assert_se(!IN_SET(0, 1));
593         assert_se(!IN_SET(0, 1, 2, 3, 4));
594 }
595
596 static void test_writing_tmpfile(void) {
597         char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
598         _cleanup_free_ char *contents = NULL;
599         size_t size;
600         int fd, r;
601         struct iovec iov[3];
602
603         IOVEC_SET_STRING(iov[0], "abc\n");
604         IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
605         IOVEC_SET_STRING(iov[2], "");
606
607         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
608         printf("tmpfile: %s", name);
609
610         r = writev(fd, iov, 3);
611         assert(r >= 0);
612
613         r = read_full_file(name, &contents, &size);
614         assert(r == 0);
615         printf("contents: %s", contents);
616         assert(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
617 }
618
619 int main(int argc, char *argv[]) {
620         log_parse_environment();
621         log_open();
622
623         test_streq_ptr();
624         test_first_word();
625         test_close_many();
626         test_parse_boolean();
627         test_parse_pid();
628         test_parse_uid();
629         test_safe_atolli();
630         test_safe_atod();
631         test_strappend();
632         test_strstrip();
633         test_delete_chars();
634         test_in_charset();
635         test_hexchar();
636         test_unhexchar();
637         test_octchar();
638         test_unoctchar();
639         test_decchar();
640         test_undecchar();
641         test_cescape();
642         test_cunescape();
643         test_foreach_word();
644         test_foreach_word_quoted();
645         test_default_term_for_tty();
646         test_memdup_multiply();
647         test_hostname_is_valid();
648         test_u64log2();
649         test_get_process_comm();
650         test_protect_errno();
651         test_parse_size();
652         test_config_parse_iec_off();
653         test_strextend();
654         test_strrep();
655         test_split_pair();
656         test_fstab_node_to_udev_node();
657         test_get_files_in_directory();
658         test_in_set();
659         test_writing_tmpfile();
660
661         return 0;
662 }