chiark / gitweb /
315bc419c29391ad0f8fbb1b7ca20bd5479e473e
[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
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         _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         assert_se(get_process_comm(1, &a) >= 0);
410         log_info("pid1 comm: '%s'", a);
411
412         assert_se(get_starttime_of_pid(1, &b) >= 0);
413         log_info("pid1 starttime: '%llu'", b);
414
415         assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
416         log_info("pid1 cmdline: '%s'", c);
417
418         assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
419         log_info("pid1 cmdline truncated: '%s'", d);
420
421         assert_se(get_parent_of_pid(1, &e) >= 0);
422         log_info("pid1 ppid: '%llu'", (unsigned long long) e);
423         assert_se(e == 0);
424
425         assert_se(is_kernel_thread(1) == 0);
426
427         r = get_process_exe(1, &f);
428         assert_se(r >= 0 || r == -EACCES);
429         log_info("pid1 exe: '%s'", strna(f));
430
431         assert_se(get_process_uid(1, &u) == 0);
432         log_info("pid1 uid: '%llu'", (unsigned long long) u);
433         assert_se(u == 0);
434
435         assert_se(get_process_gid(1, &g) == 0);
436         log_info("pid1 gid: '%llu'", (unsigned long long) g);
437         assert_se(g == 0);
438
439         assert(get_ctty_devnr(1, &h) == -ENOENT);
440
441         getenv_for_pid(1, "PATH", &i);
442         log_info("pid1 $PATH: '%s'", strna(i));
443 }
444
445 static void test_protect_errno(void) {
446         errno = 12;
447         {
448                 PROTECT_ERRNO;
449                 errno = 11;
450         }
451         assert(errno == 12);
452 }
453
454 static void test_parse_bytes(void) {
455         off_t bytes;
456
457         assert_se(parse_bytes("111", &bytes) == 0);
458         assert_se(bytes == 111);
459
460         assert_se(parse_bytes(" 112 B", &bytes) == 0);
461         assert_se(bytes == 112);
462
463         assert_se(parse_bytes("3 K", &bytes) == 0);
464         assert_se(bytes == 3*1024);
465
466         assert_se(parse_bytes(" 4 M 11K", &bytes) == 0);
467         assert_se(bytes == 4*1024*1024 + 11 * 1024);
468
469         assert_se(parse_bytes("3B3G", &bytes) == 0);
470         assert_se(bytes == 3ULL*1024*1024*1024 + 3);
471
472         assert_se(parse_bytes("3B3G4T", &bytes) == 0);
473         assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
474
475         assert_se(parse_bytes("12P", &bytes) == 0);
476         assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
477
478         assert_se(parse_bytes("3E 2P", &bytes) == 0);
479         assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
480
481         assert_se(parse_bytes("12X", &bytes) == -EINVAL);
482
483         assert_se(parse_bytes("1024E", &bytes) == -ERANGE);
484         assert_se(parse_bytes("-1", &bytes) == -ERANGE);
485         assert_se(parse_bytes("-1024E", &bytes) == -ERANGE);
486
487         assert_se(parse_bytes("-1024P", &bytes) == -ERANGE);
488
489         assert_se(parse_bytes("-10B 20K", &bytes) == -ERANGE);
490 }
491
492 static void test_strextend(void) {
493         _cleanup_free_ char *str = strdup("0123");
494         strextend(&str, "456", "78", "9", NULL);
495         assert_se(streq(str, "0123456789"));
496 }
497
498 static void test_strrep(void) {
499         _cleanup_free_ char *one, *three, *zero;
500         one = strrep("waldo", 1);
501         three = strrep("waldo", 3);
502         zero = strrep("waldo", 0);
503
504         assert_se(streq(one, "waldo"));
505         assert_se(streq(three, "waldowaldowaldo"));
506         assert_se(streq(zero, ""));
507 }
508
509 static void test_parse_user_at_host(void) {
510         _cleanup_free_ char *both = strdup("waldo@waldoscomputer");
511         _cleanup_free_ char *onlyhost = strdup("mikescomputer");
512         char *user = NULL, *host = NULL;
513
514         parse_user_at_host(both, &user, &host);
515         assert_se(streq(user, "waldo"));
516         assert_se(streq(host, "waldoscomputer"));
517
518         user = host = NULL;
519         parse_user_at_host(onlyhost, &user, &host);
520         assert_se(user == NULL);
521         assert_se(streq(host, "mikescomputer"));
522 }
523
524 static void test_split_pair(void) {
525         _cleanup_free_ char *a = NULL, *b = NULL;
526
527         assert_se(split_pair("", "", &a, &b) == -EINVAL);
528         assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
529         assert_se(split_pair("", "=", &a, &b) == -EINVAL);
530         assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
531         assert_se(streq(a, "foo"));
532         assert_se(streq(b, "bar"));
533         free(a);
534         free(b);
535         assert_se(split_pair("==", "==", &a, &b) >= 0);
536         assert_se(streq(a, ""));
537         assert_se(streq(b, ""));
538         free(a);
539         free(b);
540
541         assert_se(split_pair("===", "==", &a, &b) >= 0);
542         assert_se(streq(a, ""));
543         assert_se(streq(b, "="));
544 }
545
546 int main(int argc, char *argv[]) {
547         test_streq_ptr();
548         test_first_word();
549         test_close_many();
550         test_parse_boolean();
551         test_parse_pid();
552         test_parse_uid();
553         test_safe_atolli();
554         test_safe_atod();
555         test_strappend();
556         test_strstrip();
557         test_delete_chars();
558         test_in_charset();
559         test_hexchar();
560         test_unhexchar();
561         test_octchar();
562         test_unoctchar();
563         test_decchar();
564         test_undecchar();
565         test_cescape();
566         test_cunescape();
567         test_foreach_word();
568         test_foreach_word_quoted();
569         test_default_term_for_tty();
570         test_memdup_multiply();
571         test_bus_path_escape();
572         test_hostname_is_valid();
573         test_u64log2();
574         test_get_process_comm();
575         test_protect_errno();
576         test_parse_bytes();
577         test_strextend();
578         test_strrep();
579         test_parse_user_at_host();
580         test_split_pair();
581
582         return 0;
583 }