chiark / gitweb /
macro: add nice macro for disabling -Wnonnull temporarily
[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
34 static void test_streq_ptr(void) {
35         assert_se(streq_ptr(NULL, NULL));
36         assert_se(!streq_ptr("abc", "cdef"));
37 }
38
39 static void test_first_word(void) {
40         assert_se(first_word("Hello", ""));
41         assert_se(first_word("Hello", "Hello"));
42         assert_se(first_word("Hello world", "Hello"));
43         assert_se(first_word("Hello\tworld", "Hello"));
44         assert_se(first_word("Hello\nworld", "Hello"));
45         assert_se(first_word("Hello\rworld", "Hello"));
46         assert_se(first_word("Hello ", "Hello"));
47
48         assert_se(!first_word("Hello", "Hellooo"));
49         assert_se(!first_word("Hello", "xxxxx"));
50         assert_se(!first_word("Hellooo", "Hello"));
51 }
52
53 static void test_close_many(void) {
54         int fds[3];
55         char name0[] = "/tmp/test-close-many.XXXXXX";
56         char name1[] = "/tmp/test-close-many.XXXXXX";
57         char name2[] = "/tmp/test-close-many.XXXXXX";
58
59         fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
60         fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
61         fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
62
63         close_many(fds, 2);
64
65         assert_se(fcntl(fds[0], F_GETFD) == -1);
66         assert_se(fcntl(fds[1], F_GETFD) == -1);
67         assert_se(fcntl(fds[2], F_GETFD) >= 0);
68
69         close_nointr_nofail(fds[2]);
70
71         unlink(name0);
72         unlink(name1);
73         unlink(name2);
74 }
75
76 static void test_parse_boolean(void) {
77         assert_se(parse_boolean("1") == 1);
78         assert_se(parse_boolean("y") == 1);
79         assert_se(parse_boolean("Y") == 1);
80         assert_se(parse_boolean("yes") == 1);
81         assert_se(parse_boolean("YES") == 1);
82         assert_se(parse_boolean("true") == 1);
83         assert_se(parse_boolean("TRUE") == 1);
84         assert_se(parse_boolean("on") == 1);
85         assert_se(parse_boolean("ON") == 1);
86
87         assert_se(parse_boolean("0") == 0);
88         assert_se(parse_boolean("n") == 0);
89         assert_se(parse_boolean("N") == 0);
90         assert_se(parse_boolean("no") == 0);
91         assert_se(parse_boolean("NO") == 0);
92         assert_se(parse_boolean("false") == 0);
93         assert_se(parse_boolean("FALSE") == 0);
94         assert_se(parse_boolean("off") == 0);
95         assert_se(parse_boolean("OFF") == 0);
96
97         assert_se(parse_boolean("garbage") < 0);
98         assert_se(parse_boolean("") < 0);
99 }
100
101 static void test_parse_pid(void) {
102         int r;
103         pid_t pid;
104
105         r = parse_pid("100", &pid);
106         assert_se(r == 0);
107         assert_se(pid == 100);
108
109         r = parse_pid("0x7FFFFFFF", &pid);
110         assert_se(r == 0);
111         assert_se(pid == 2147483647);
112
113         pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
114         r = parse_pid("0", &pid);
115         assert_se(r == -ERANGE);
116         assert_se(pid == 65);
117
118         pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
119         r = parse_pid("-100", &pid);
120         assert_se(r == -ERANGE);
121         assert_se(pid == 65);
122
123         pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
124         r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid);
125         assert(r == -ERANGE);
126         assert_se(pid == 65);
127 }
128
129 static void test_parse_uid(void) {
130         int r;
131         uid_t uid;
132
133         r = parse_uid("100", &uid);
134         assert_se(r == 0);
135         assert_se(uid == 100);
136 }
137
138 static void test_safe_atolli(void) {
139         int r;
140         long long l;
141
142         r = safe_atolli("12345", &l);
143         assert_se(r == 0);
144         assert_se(l == 12345);
145
146         r = safe_atolli("junk", &l);
147         assert_se(r == -EINVAL);
148 }
149
150 static void test_safe_atod(void) {
151         int r;
152         double d;
153         char *e;
154
155         r = safe_atod("junk", &d);
156         assert_se(r == -EINVAL);
157
158         r = safe_atod("0.2244", &d);
159         assert_se(r == 0);
160         assert_se(abs(d - 0.2244) < 0.000001);
161
162         r = safe_atod("0,5", &d);
163         assert_se(r == -EINVAL);
164
165         errno = 0;
166         strtod("0,5", &e);
167         assert_se(*e == ',');
168
169         /* Check if this really is locale independent */
170         setlocale(LC_NUMERIC, "de_DE.utf8");
171
172         r = safe_atod("0.2244", &d);
173         assert_se(r == 0);
174         assert_se(abs(d - 0.2244) < 0.000001);
175
176         r = safe_atod("0,5", &d);
177         assert_se(r == -EINVAL);
178
179         errno = 0;
180         assert_se(abs(strtod("0,5", &e) - 0.5) < 0.00001);
181
182         /* And check again, reset */
183         setlocale(LC_NUMERIC, "C");
184
185         r = safe_atod("0.2244", &d);
186         assert_se(r == 0);
187         assert_se(abs(d - 0.2244) < 0.000001);
188
189         r = safe_atod("0,5", &d);
190         assert_se(r == -EINVAL);
191
192         errno = 0;
193         strtod("0,5", &e);
194         assert_se(*e == ',');
195 }
196
197 static void test_strappend(void) {
198         _cleanup_free_ char *t1, *t2, *t3, *t4;
199
200         t1 = strappend(NULL, NULL);
201         assert_se(streq(t1, ""));
202
203         t2 = strappend(NULL, "suf");
204         assert_se(streq(t2, "suf"));
205
206         t3 = strappend("pre", NULL);
207         assert_se(streq(t3, "pre"));
208
209         t4 = strappend("pre", "suf");
210         assert_se(streq(t4, "presuf"));
211 }
212
213 static void test_strstrip(void) {
214         char *r;
215         char input[] = "   hello, waldo.   ";
216
217         r = strstrip(input);
218         assert_se(streq(r, "hello, waldo."));
219 }
220
221 static void test_delete_chars(void) {
222         char *r;
223         char input[] = "   hello, waldo.   abc";
224
225         r = delete_chars(input, WHITESPACE);
226         assert_se(streq(r, "hello,waldo.abc"));
227 }
228
229 static void test_in_charset(void) {
230         assert_se(in_charset("dddaaabbbcccc", "abcd"));
231         assert_se(!in_charset("dddaaabbbcccc", "abc f"));
232 }
233
234 static void test_hexchar(void) {
235         assert_se(hexchar(0xa) == 'a');
236         assert_se(hexchar(0x0) == '0');
237 }
238
239 static void test_unhexchar(void) {
240         assert_se(unhexchar('a') == 0xA);
241         assert_se(unhexchar('A') == 0xA);
242         assert_se(unhexchar('0') == 0x0);
243 }
244
245 static void test_octchar(void) {
246         assert_se(octchar(00) == '0');
247         assert_se(octchar(07) == '7');
248 }
249
250 static void test_unoctchar(void) {
251         assert_se(unoctchar('0') == 00);
252         assert_se(unoctchar('7') == 07);
253 }
254
255 static void test_decchar(void) {
256         assert_se(decchar(0) == '0');
257         assert_se(decchar(9) == '9');
258 }
259
260 static void test_undecchar(void) {
261         assert_se(undecchar('0') == 0);
262         assert_se(undecchar('9') == 9);
263 }
264
265 static void test_cescape(void) {
266         _cleanup_free_ char *escaped;
267         escaped = cescape("abc\\\"\b\f\n\r\t\v\003\177\234\313");
268         assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\003\\177\\234\\313"));
269 }
270
271 static void test_cunescape(void) {
272         _cleanup_free_ char *unescaped;
273         unescaped = cunescape("abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\003\\177\\234\\313");
274         assert_se(streq(unescaped, "abc\\\"\b\f\n\r\t\v\003\177\234\313"));
275 }
276
277 static void test_foreach_word(void) {
278         char *w, *state;
279         size_t l;
280         int i = 0;
281         const char test[] = "test abc d\te   f   ";
282         const char * const expected[] = {
283                 "test",
284                 "abc",
285                 "d",
286                 "e",
287                 "f",
288                 "",
289                 NULL
290         };
291
292         FOREACH_WORD(w, l, test, state) {
293                 assert_se(strneq(expected[i++], w, l));
294         }
295 }
296
297 static void test_foreach_word_quoted(void) {
298         char *w, *state;
299         size_t l;
300         int i = 0;
301         const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\"";
302         const char * const expected[] = {
303                 "test",
304                 "a",
305                 "b",
306                 "c",
307                 "d",
308                 "e",
309                 "",
310                 "",
311                 "hhh",
312                 "",
313                 "",
314                 "a b c",
315                 NULL
316         };
317
318         printf("<%s>\n", test);
319         FOREACH_WORD_QUOTED(w, l, test, state) {
320                 _cleanup_free_ char *t = NULL;
321
322                 assert_se(t = strndup(w, l));
323                 assert_se(strneq(expected[i++], w, l));
324                 printf("<%s>\n", t);
325         }
326 }
327
328 static void test_default_term_for_tty(void) {
329         puts(default_term_for_tty("/dev/tty23"));
330         puts(default_term_for_tty("/dev/ttyS23"));
331         puts(default_term_for_tty("/dev/tty0"));
332         puts(default_term_for_tty("/dev/pty0"));
333         puts(default_term_for_tty("/dev/pts/0"));
334         puts(default_term_for_tty("/dev/console"));
335         puts(default_term_for_tty("tty23"));
336         puts(default_term_for_tty("ttyS23"));
337         puts(default_term_for_tty("tty0"));
338         puts(default_term_for_tty("pty0"));
339         puts(default_term_for_tty("pts/0"));
340         puts(default_term_for_tty("console"));
341 }
342
343 static void test_memdup_multiply(void) {
344         int org[] = {1, 2, 3};
345         int *dup;
346
347         dup = (int*)memdup_multiply(org, sizeof(int), 3);
348
349         assert_se(dup);
350         assert_se(dup[0] == 1);
351         assert_se(dup[1] == 2);
352         assert_se(dup[2] == 3);
353         free(dup);
354 }
355
356 static void test_hostname_is_valid(void) {
357         assert(hostname_is_valid("foobar"));
358         assert(hostname_is_valid("foobar.com"));
359         assert(!hostname_is_valid("fööbar"));
360         assert(!hostname_is_valid(""));
361         assert(!hostname_is_valid("."));
362         assert(!hostname_is_valid(".."));
363         assert(!hostname_is_valid("foobar."));
364         assert(!hostname_is_valid(".foobar"));
365         assert(!hostname_is_valid("foo..bar"));
366         assert(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
367 }
368
369 static void test_u64log2(void) {
370         assert(u64log2(0) == 0);
371         assert(u64log2(8) == 3);
372         assert(u64log2(9) == 3);
373         assert(u64log2(15) == 3);
374         assert(u64log2(16) == 4);
375         assert(u64log2(1024*1024) == 20);
376         assert(u64log2(1024*1024+5) == 20);
377 }
378
379 static void test_get_process_comm(void) {
380         struct stat st;
381         _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
382         unsigned long long b;
383         pid_t e;
384         uid_t u;
385         gid_t g;
386         dev_t h;
387         int r;
388
389         if (stat("/proc/1/comm", &st) == 0) {
390                 assert_se(get_process_comm(1, &a) >= 0);
391                 log_info("pid1 comm: '%s'", a);
392         } else {
393                 log_warning("/proc/1/comm does not exist.");
394         }
395
396         assert_se(get_starttime_of_pid(1, &b) >= 0);
397         log_info("pid1 starttime: '%llu'", b);
398
399         assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
400         log_info("pid1 cmdline: '%s'", c);
401
402         assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
403         log_info("pid1 cmdline truncated: '%s'", d);
404
405         assert_se(get_parent_of_pid(1, &e) >= 0);
406         log_info("pid1 ppid: '%llu'", (unsigned long long) e);
407         assert_se(e == 0);
408
409         assert_se(is_kernel_thread(1) == 0);
410
411         r = get_process_exe(1, &f);
412         assert_se(r >= 0 || r == -EACCES);
413         log_info("pid1 exe: '%s'", strna(f));
414
415         assert_se(get_process_uid(1, &u) == 0);
416         log_info("pid1 uid: '%llu'", (unsigned long long) u);
417         assert_se(u == 0);
418
419         assert_se(get_process_gid(1, &g) == 0);
420         log_info("pid1 gid: '%llu'", (unsigned long long) g);
421         assert_se(g == 0);
422
423         assert(get_ctty_devnr(1, &h) == -ENOENT);
424
425         getenv_for_pid(1, "PATH", &i);
426         log_info("pid1 $PATH: '%s'", strna(i));
427 }
428
429 static void test_protect_errno(void) {
430         errno = 12;
431         {
432                 PROTECT_ERRNO;
433                 errno = 11;
434         }
435         assert(errno == 12);
436 }
437
438 static void test_parse_bytes(void) {
439         off_t bytes;
440
441         assert_se(parse_bytes("111", &bytes) == 0);
442         assert_se(bytes == 111);
443
444         assert_se(parse_bytes(" 112 B", &bytes) == 0);
445         assert_se(bytes == 112);
446
447         assert_se(parse_bytes("3 K", &bytes) == 0);
448         assert_se(bytes == 3*1024);
449
450         assert_se(parse_bytes(" 4 M 11K", &bytes) == 0);
451         assert_se(bytes == 4*1024*1024 + 11 * 1024);
452
453         assert_se(parse_bytes("3B3G", &bytes) == 0);
454         assert_se(bytes == 3ULL*1024*1024*1024 + 3);
455
456         assert_se(parse_bytes("3B3G4T", &bytes) == 0);
457         assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
458
459         assert_se(parse_bytes("12P", &bytes) == 0);
460         assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
461
462         assert_se(parse_bytes("3E 2P", &bytes) == 0);
463         assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
464
465         assert_se(parse_bytes("12X", &bytes) == -EINVAL);
466
467         assert_se(parse_bytes("1024E", &bytes) == -ERANGE);
468         assert_se(parse_bytes("-1", &bytes) == -ERANGE);
469         assert_se(parse_bytes("-1024E", &bytes) == -ERANGE);
470
471         assert_se(parse_bytes("-1024P", &bytes) == -ERANGE);
472
473         assert_se(parse_bytes("-10B 20K", &bytes) == -ERANGE);
474 }
475
476 static void test_strextend(void) {
477         _cleanup_free_ char *str = strdup("0123");
478         strextend(&str, "456", "78", "9", NULL);
479         assert_se(streq(str, "0123456789"));
480 }
481
482 static void test_strrep(void) {
483         _cleanup_free_ char *one, *three, *zero;
484         one = strrep("waldo", 1);
485         three = strrep("waldo", 3);
486         zero = strrep("waldo", 0);
487
488         assert_se(streq(one, "waldo"));
489         assert_se(streq(three, "waldowaldowaldo"));
490         assert_se(streq(zero, ""));
491 }
492
493 static void test_split_pair(void) {
494         _cleanup_free_ char *a = NULL, *b = NULL;
495
496         assert_se(split_pair("", "", &a, &b) == -EINVAL);
497         assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
498         assert_se(split_pair("", "=", &a, &b) == -EINVAL);
499         assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
500         assert_se(streq(a, "foo"));
501         assert_se(streq(b, "bar"));
502         free(a);
503         free(b);
504         assert_se(split_pair("==", "==", &a, &b) >= 0);
505         assert_se(streq(a, ""));
506         assert_se(streq(b, ""));
507         free(a);
508         free(b);
509
510         assert_se(split_pair("===", "==", &a, &b) >= 0);
511         assert_se(streq(a, ""));
512         assert_se(streq(b, "="));
513 }
514
515 static void test_fstab_node_to_udev_node(void) {
516         char *n;
517
518         n = fstab_node_to_udev_node("LABEL=applé/jack");
519         puts(n);
520         assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
521         free(n);
522
523         n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
524         puts(n);
525         assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
526         free(n);
527
528         n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
529         puts(n);
530         assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
531         free(n);
532
533         n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
534         puts(n);
535         assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
536         free(n);
537
538
539         n = fstab_node_to_udev_node("PONIES=awesome");
540         puts(n);
541         assert_se(streq(n, "PONIES=awesome"));
542         free(n);
543
544         n = fstab_node_to_udev_node("/dev/xda1");
545         puts(n);
546         assert_se(streq(n, "/dev/xda1"));
547         free(n);
548 }
549
550 static void test_get_files_in_directory(void) {
551         _cleanup_strv_free_ char **l = NULL, **t = NULL;
552
553         assert_se(get_files_in_directory("/tmp", &l) >= 0);
554         assert_se(get_files_in_directory(".", &t) >= 0);
555         assert_se(get_files_in_directory(".", NULL) >= 0);
556 }
557
558 static void test_in_set(void) {
559         assert_se(IN_SET(1, 1));
560         assert_se(IN_SET(1, 1, 2, 3, 4));
561         assert_se(IN_SET(2, 1, 2, 3, 4));
562         assert_se(IN_SET(3, 1, 2, 3, 4));
563         assert_se(IN_SET(4, 1, 2, 3, 4));
564         assert_se(!IN_SET(0, 1));
565         assert_se(!IN_SET(0, 1, 2, 3, 4));
566 }
567
568 static void test_writing_tmpfile(void) {
569         char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
570         _cleanup_free_ char *contents = NULL;
571         size_t size;
572         int fd, r;
573         struct iovec iov[3];
574
575         IOVEC_SET_STRING(iov[0], "abc\n");
576         IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
577         IOVEC_SET_STRING(iov[2], "");
578
579         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
580         printf("tmpfile: %s", name);
581
582         r = writev(fd, iov, 3);
583         assert(r >= 0);
584
585         r = read_full_file(name, &contents, &size);
586         assert(r == 0);
587         printf("contents: %s", contents);
588         assert(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
589 }
590
591 int main(int argc, char *argv[]) {
592         test_streq_ptr();
593         test_first_word();
594         test_close_many();
595         test_parse_boolean();
596         test_parse_pid();
597         test_parse_uid();
598         test_safe_atolli();
599         test_safe_atod();
600         test_strappend();
601         test_strstrip();
602         test_delete_chars();
603         test_in_charset();
604         test_hexchar();
605         test_unhexchar();
606         test_octchar();
607         test_unoctchar();
608         test_decchar();
609         test_undecchar();
610         test_cescape();
611         test_cunescape();
612         test_foreach_word();
613         test_foreach_word_quoted();
614         test_default_term_for_tty();
615         test_memdup_multiply();
616         test_hostname_is_valid();
617         test_u64log2();
618         test_get_process_comm();
619         test_protect_errno();
620         test_parse_bytes();
621         test_strextend();
622         test_strrep();
623         test_split_pair();
624         test_fstab_node_to_udev_node();
625         test_get_files_in_directory();
626         test_in_set();
627         test_writing_tmpfile();
628
629         return 0;
630 }