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