chiark / gitweb /
macro: add a macro to test whether a value is in a specified list
[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_hostname_is_valid(void) {
355         assert(hostname_is_valid("foobar"));
356         assert(hostname_is_valid("foobar.com"));
357         assert(!hostname_is_valid("fööbar"));
358         assert(!hostname_is_valid(""));
359         assert(!hostname_is_valid("."));
360         assert(!hostname_is_valid(".."));
361         assert(!hostname_is_valid("foobar."));
362         assert(!hostname_is_valid(".foobar"));
363         assert(!hostname_is_valid("foo..bar"));
364         assert(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
365 }
366
367 static void test_u64log2(void) {
368         assert(u64log2(0) == 0);
369         assert(u64log2(8) == 3);
370         assert(u64log2(9) == 3);
371         assert(u64log2(15) == 3);
372         assert(u64log2(16) == 4);
373         assert(u64log2(1024*1024) == 20);
374         assert(u64log2(1024*1024+5) == 20);
375 }
376
377 static void test_get_process_comm(void) {
378         struct stat st;
379         _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
380         unsigned long long b;
381         pid_t e;
382         uid_t u;
383         gid_t g;
384         dev_t h;
385         int r;
386
387         if (stat("/proc/1/comm", &st) == 0) {
388                 assert_se(get_process_comm(1, &a) >= 0);
389                 log_info("pid1 comm: '%s'", a);
390         } else {
391                 log_warning("/proc/1/comm does not exist.");
392         }
393
394         assert_se(get_starttime_of_pid(1, &b) >= 0);
395         log_info("pid1 starttime: '%llu'", b);
396
397         assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
398         log_info("pid1 cmdline: '%s'", c);
399
400         assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
401         log_info("pid1 cmdline truncated: '%s'", d);
402
403         assert_se(get_parent_of_pid(1, &e) >= 0);
404         log_info("pid1 ppid: '%llu'", (unsigned long long) e);
405         assert_se(e == 0);
406
407         assert_se(is_kernel_thread(1) == 0);
408
409         r = get_process_exe(1, &f);
410         assert_se(r >= 0 || r == -EACCES);
411         log_info("pid1 exe: '%s'", strna(f));
412
413         assert_se(get_process_uid(1, &u) == 0);
414         log_info("pid1 uid: '%llu'", (unsigned long long) u);
415         assert_se(u == 0);
416
417         assert_se(get_process_gid(1, &g) == 0);
418         log_info("pid1 gid: '%llu'", (unsigned long long) g);
419         assert_se(g == 0);
420
421         assert(get_ctty_devnr(1, &h) == -ENOENT);
422
423         getenv_for_pid(1, "PATH", &i);
424         log_info("pid1 $PATH: '%s'", strna(i));
425 }
426
427 static void test_protect_errno(void) {
428         errno = 12;
429         {
430                 PROTECT_ERRNO;
431                 errno = 11;
432         }
433         assert(errno == 12);
434 }
435
436 static void test_parse_bytes(void) {
437         off_t bytes;
438
439         assert_se(parse_bytes("111", &bytes) == 0);
440         assert_se(bytes == 111);
441
442         assert_se(parse_bytes(" 112 B", &bytes) == 0);
443         assert_se(bytes == 112);
444
445         assert_se(parse_bytes("3 K", &bytes) == 0);
446         assert_se(bytes == 3*1024);
447
448         assert_se(parse_bytes(" 4 M 11K", &bytes) == 0);
449         assert_se(bytes == 4*1024*1024 + 11 * 1024);
450
451         assert_se(parse_bytes("3B3G", &bytes) == 0);
452         assert_se(bytes == 3ULL*1024*1024*1024 + 3);
453
454         assert_se(parse_bytes("3B3G4T", &bytes) == 0);
455         assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
456
457         assert_se(parse_bytes("12P", &bytes) == 0);
458         assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
459
460         assert_se(parse_bytes("3E 2P", &bytes) == 0);
461         assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
462
463         assert_se(parse_bytes("12X", &bytes) == -EINVAL);
464
465         assert_se(parse_bytes("1024E", &bytes) == -ERANGE);
466         assert_se(parse_bytes("-1", &bytes) == -ERANGE);
467         assert_se(parse_bytes("-1024E", &bytes) == -ERANGE);
468
469         assert_se(parse_bytes("-1024P", &bytes) == -ERANGE);
470
471         assert_se(parse_bytes("-10B 20K", &bytes) == -ERANGE);
472 }
473
474 static void test_strextend(void) {
475         _cleanup_free_ char *str = strdup("0123");
476         strextend(&str, "456", "78", "9", NULL);
477         assert_se(streq(str, "0123456789"));
478 }
479
480 static void test_strrep(void) {
481         _cleanup_free_ char *one, *three, *zero;
482         one = strrep("waldo", 1);
483         three = strrep("waldo", 3);
484         zero = strrep("waldo", 0);
485
486         assert_se(streq(one, "waldo"));
487         assert_se(streq(three, "waldowaldowaldo"));
488         assert_se(streq(zero, ""));
489 }
490
491 static void test_parse_user_at_host(void) {
492         _cleanup_free_ char *both = strdup("waldo@waldoscomputer");
493         _cleanup_free_ char *onlyhost = strdup("mikescomputer");
494         char *user = NULL, *host = NULL;
495
496         parse_user_at_host(both, &user, &host);
497         assert_se(streq(user, "waldo"));
498         assert_se(streq(host, "waldoscomputer"));
499
500         user = host = NULL;
501         parse_user_at_host(onlyhost, &user, &host);
502         assert_se(user == NULL);
503         assert_se(streq(host, "mikescomputer"));
504 }
505
506 static void test_split_pair(void) {
507         _cleanup_free_ char *a = NULL, *b = NULL;
508
509         assert_se(split_pair("", "", &a, &b) == -EINVAL);
510         assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
511         assert_se(split_pair("", "=", &a, &b) == -EINVAL);
512         assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
513         assert_se(streq(a, "foo"));
514         assert_se(streq(b, "bar"));
515         free(a);
516         free(b);
517         assert_se(split_pair("==", "==", &a, &b) >= 0);
518         assert_se(streq(a, ""));
519         assert_se(streq(b, ""));
520         free(a);
521         free(b);
522
523         assert_se(split_pair("===", "==", &a, &b) >= 0);
524         assert_se(streq(a, ""));
525         assert_se(streq(b, "="));
526 }
527
528 static void test_fstab_node_to_udev_node(void) {
529         char *n;
530
531         n = fstab_node_to_udev_node("LABEL=applé/jack");
532         puts(n);
533         assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
534         free(n);
535
536         n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
537         puts(n);
538         assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
539         free(n);
540
541         n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
542         puts(n);
543         assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
544         free(n);
545
546         n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
547         puts(n);
548         assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
549         free(n);
550
551
552         n = fstab_node_to_udev_node("PONIES=awesome");
553         puts(n);
554         assert_se(streq(n, "PONIES=awesome"));
555         free(n);
556
557         n = fstab_node_to_udev_node("/dev/xda1");
558         puts(n);
559         assert_se(streq(n, "/dev/xda1"));
560         free(n);
561 }
562
563 static void test_get_files_in_directory(void) {
564         _cleanup_strv_free_ char **l = NULL, **t = NULL;
565
566         assert_se(get_files_in_directory("/tmp", &l) >= 0);
567         assert_se(get_files_in_directory(".", &t) >= 0);
568         assert_se(get_files_in_directory(".", NULL) >= 0);
569 }
570
571 static void test_in_set(void) {
572         assert_se(IN_SET(1, 1));
573         assert_se(IN_SET(1, 1, 2, 3, 4));
574         assert_se(IN_SET(2, 1, 2, 3, 4));
575         assert_se(IN_SET(3, 1, 2, 3, 4));
576         assert_se(IN_SET(4, 1, 2, 3, 4));
577         assert_se(!IN_SET(0, 1));
578         assert_se(!IN_SET(0, 1, 2, 3, 4));
579 }
580
581 int main(int argc, char *argv[]) {
582         test_streq_ptr();
583         test_first_word();
584         test_close_many();
585         test_parse_boolean();
586         test_parse_pid();
587         test_parse_uid();
588         test_safe_atolli();
589         test_safe_atod();
590         test_strappend();
591         test_strstrip();
592         test_delete_chars();
593         test_in_charset();
594         test_hexchar();
595         test_unhexchar();
596         test_octchar();
597         test_unoctchar();
598         test_decchar();
599         test_undecchar();
600         test_cescape();
601         test_cunescape();
602         test_foreach_word();
603         test_foreach_word_quoted();
604         test_default_term_for_tty();
605         test_memdup_multiply();
606         test_hostname_is_valid();
607         test_u64log2();
608         test_get_process_comm();
609         test_protect_errno();
610         test_parse_bytes();
611         test_strextend();
612         test_strrep();
613         test_parse_user_at_host();
614         test_split_pair();
615         test_fstab_node_to_udev_node();
616         test_get_files_in_directory();
617         test_in_set();
618
619         return 0;
620 }