chiark / gitweb /
always use the same code for creating temporary files
[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_parse_user_at_host(void) {
494         _cleanup_free_ char *both = strdup("waldo@waldoscomputer");
495         _cleanup_free_ char *onlyhost = strdup("mikescomputer");
496         char *user = NULL, *host = NULL;
497
498         parse_user_at_host(both, &user, &host);
499         assert_se(streq(user, "waldo"));
500         assert_se(streq(host, "waldoscomputer"));
501
502         user = host = NULL;
503         parse_user_at_host(onlyhost, &user, &host);
504         assert_se(user == NULL);
505         assert_se(streq(host, "mikescomputer"));
506 }
507
508 static void test_split_pair(void) {
509         _cleanup_free_ char *a = NULL, *b = NULL;
510
511         assert_se(split_pair("", "", &a, &b) == -EINVAL);
512         assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
513         assert_se(split_pair("", "=", &a, &b) == -EINVAL);
514         assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
515         assert_se(streq(a, "foo"));
516         assert_se(streq(b, "bar"));
517         free(a);
518         free(b);
519         assert_se(split_pair("==", "==", &a, &b) >= 0);
520         assert_se(streq(a, ""));
521         assert_se(streq(b, ""));
522         free(a);
523         free(b);
524
525         assert_se(split_pair("===", "==", &a, &b) >= 0);
526         assert_se(streq(a, ""));
527         assert_se(streq(b, "="));
528 }
529
530 static void test_fstab_node_to_udev_node(void) {
531         char *n;
532
533         n = fstab_node_to_udev_node("LABEL=applé/jack");
534         puts(n);
535         assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
536         free(n);
537
538         n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
539         puts(n);
540         assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
541         free(n);
542
543         n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
544         puts(n);
545         assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
546         free(n);
547
548         n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
549         puts(n);
550         assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
551         free(n);
552
553
554         n = fstab_node_to_udev_node("PONIES=awesome");
555         puts(n);
556         assert_se(streq(n, "PONIES=awesome"));
557         free(n);
558
559         n = fstab_node_to_udev_node("/dev/xda1");
560         puts(n);
561         assert_se(streq(n, "/dev/xda1"));
562         free(n);
563 }
564
565 static void test_get_files_in_directory(void) {
566         _cleanup_strv_free_ char **l = NULL, **t = NULL;
567
568         assert_se(get_files_in_directory("/tmp", &l) >= 0);
569         assert_se(get_files_in_directory(".", &t) >= 0);
570         assert_se(get_files_in_directory(".", NULL) >= 0);
571 }
572
573 static void test_in_set(void) {
574         assert_se(IN_SET(1, 1));
575         assert_se(IN_SET(1, 1, 2, 3, 4));
576         assert_se(IN_SET(2, 1, 2, 3, 4));
577         assert_se(IN_SET(3, 1, 2, 3, 4));
578         assert_se(IN_SET(4, 1, 2, 3, 4));
579         assert_se(!IN_SET(0, 1));
580         assert_se(!IN_SET(0, 1, 2, 3, 4));
581 }
582
583 static void test_writev_safe(void) {
584         char name[] = "/tmp/test-writev_safe.XXXXXX";
585         _cleanup_free_ char *contents;
586         size_t size;
587         int fd, r;
588
589         struct iovec iov[3];
590         IOVEC_SET_STRING(iov[0], "abc\n");
591         IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
592         IOVEC_SET_STRING(iov[2], "");
593
594         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
595         printf("test_writev_safe: %s", name);
596
597         r = writev_safe(fd, iov, 3);
598         assert(r == 0);
599
600         r = read_full_file(name, &contents, &size);
601         assert(r == 0);
602         printf("contents: %s", contents);
603         assert(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
604 }
605
606 int main(int argc, char *argv[]) {
607         test_streq_ptr();
608         test_first_word();
609         test_close_many();
610         test_parse_boolean();
611         test_parse_pid();
612         test_parse_uid();
613         test_safe_atolli();
614         test_safe_atod();
615         test_strappend();
616         test_strstrip();
617         test_delete_chars();
618         test_in_charset();
619         test_hexchar();
620         test_unhexchar();
621         test_octchar();
622         test_unoctchar();
623         test_decchar();
624         test_undecchar();
625         test_cescape();
626         test_cunescape();
627         test_foreach_word();
628         test_foreach_word_quoted();
629         test_default_term_for_tty();
630         test_memdup_multiply();
631         test_hostname_is_valid();
632         test_u64log2();
633         test_get_process_comm();
634         test_protect_errno();
635         test_parse_bytes();
636         test_strextend();
637         test_strrep();
638         test_parse_user_at_host();
639         test_split_pair();
640         test_fstab_node_to_udev_node();
641         test_get_files_in_directory();
642         test_in_set();
643         test_writev_safe();
644
645         return 0;
646 }