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