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