chiark / gitweb /
Properly check for overflow in offsets
[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_foreach_word(void) {
264         char *w, *state;
265         size_t l;
266         int i = 0;
267         const char test[] = "test abc d\te   f   ";
268         const char * const expected[] = {
269                 "test",
270                 "abc",
271                 "d",
272                 "e",
273                 "f",
274                 "",
275                 NULL
276         };
277
278         FOREACH_WORD(w, l, test, state) {
279                 assert_se(strneq(expected[i++], w, l));
280         }
281 }
282
283 static void test_foreach_word_quoted(void) {
284         char *w, *state;
285         size_t l;
286         int i = 0;
287         const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\"";
288         const char * const expected[] = {
289                 "test",
290                 "a",
291                 "b",
292                 "c",
293                 "d",
294                 "e",
295                 "",
296                 "",
297                 "hhh",
298                 "",
299                 "",
300                 "a b c",
301                 NULL
302         };
303
304         printf("<%s>\n", test);
305         FOREACH_WORD_QUOTED(w, l, test, state) {
306                 _cleanup_free_ char *t = NULL;
307
308                 assert_se(t = strndup(w, l));
309                 assert_se(strneq(expected[i++], w, l));
310                 printf("<%s>\n", t);
311         }
312 }
313
314 static void test_default_term_for_tty(void) {
315         puts(default_term_for_tty("/dev/tty23"));
316         puts(default_term_for_tty("/dev/ttyS23"));
317         puts(default_term_for_tty("/dev/tty0"));
318         puts(default_term_for_tty("/dev/pty0"));
319         puts(default_term_for_tty("/dev/pts/0"));
320         puts(default_term_for_tty("/dev/console"));
321         puts(default_term_for_tty("tty23"));
322         puts(default_term_for_tty("ttyS23"));
323         puts(default_term_for_tty("tty0"));
324         puts(default_term_for_tty("pty0"));
325         puts(default_term_for_tty("pts/0"));
326         puts(default_term_for_tty("console"));
327 }
328
329 static void test_memdup_multiply(void) {
330         int org[] = {1, 2, 3};
331         int *dup;
332
333         dup = (int*)memdup_multiply(org, sizeof(int), 3);
334
335         assert_se(dup);
336         assert_se(dup[0] == 1);
337         assert_se(dup[1] == 2);
338         assert_se(dup[2] == 3);
339         free(dup);
340 }
341
342 static void test_bus_path_escape_one(const char *a, const char *b) {
343         _cleanup_free_ char *t = NULL, *x = NULL, *y = NULL;
344
345         assert_se(t = bus_path_escape(a));
346         assert_se(streq(t, b));
347
348         assert_se(x = bus_path_unescape(t));
349         assert_se(streq(a, x));
350
351         assert_se(y = bus_path_unescape(b));
352         assert_se(streq(a, y));
353 }
354
355 static void test_bus_path_escape(void) {
356         test_bus_path_escape_one("foo123bar", "foo123bar");
357         test_bus_path_escape_one("foo.bar", "foo_2ebar");
358         test_bus_path_escape_one("foo_2ebar", "foo_5f2ebar");
359         test_bus_path_escape_one("", "_");
360         test_bus_path_escape_one("_", "_5f");
361         test_bus_path_escape_one("1", "_31");
362         test_bus_path_escape_one(":1", "_3a1");
363 }
364
365 static void test_hostname_is_valid(void) {
366         assert(hostname_is_valid("foobar"));
367         assert(hostname_is_valid("foobar.com"));
368         assert(!hostname_is_valid("fööbar"));
369         assert(!hostname_is_valid(""));
370         assert(!hostname_is_valid("."));
371         assert(!hostname_is_valid(".."));
372         assert(!hostname_is_valid("foobar."));
373         assert(!hostname_is_valid(".foobar"));
374         assert(!hostname_is_valid("foo..bar"));
375         assert(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
376 }
377
378 static void test_u64log2(void) {
379         assert(u64log2(0) == 0);
380         assert(u64log2(8) == 3);
381         assert(u64log2(9) == 3);
382         assert(u64log2(15) == 3);
383         assert(u64log2(16) == 4);
384         assert(u64log2(1024*1024) == 20);
385         assert(u64log2(1024*1024+5) == 20);
386 }
387
388 static void test_get_process_comm(void) {
389         _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
390         unsigned long long b;
391         pid_t e;
392         uid_t u;
393         gid_t g;
394         dev_t h;
395         int r;
396
397         assert_se(get_process_comm(1, &a) >= 0);
398         log_info("pid1 comm: '%s'", a);
399
400         assert_se(get_starttime_of_pid(1, &b) >= 0);
401         log_info("pid1 starttime: '%llu'", b);
402
403         assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
404         log_info("pid1 cmdline: '%s'", c);
405
406         assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
407         log_info("pid1 cmdline truncated: '%s'", d);
408
409         assert_se(get_parent_of_pid(1, &e) >= 0);
410         log_info("pid1 ppid: '%llu'", (unsigned long long) e);
411         assert_se(e == 0);
412
413         assert_se(is_kernel_thread(1) == 0);
414
415         r = get_process_exe(1, &f);
416         assert_se(r >= 0 || r == -EACCES);
417         log_info("pid1 exe: '%s'", strna(f));
418
419         assert_se(get_process_uid(1, &u) == 0);
420         log_info("pid1 uid: '%llu'", (unsigned long long) u);
421         assert_se(u == 0);
422
423         assert_se(get_process_gid(1, &g) == 0);
424         log_info("pid1 gid: '%llu'", (unsigned long long) g);
425         assert_se(g == 0);
426
427         assert(get_ctty_devnr(1, &h) == -ENOENT);
428
429         getenv_for_pid(1, "PATH", &i);
430         log_info("pid1 $PATH: '%s'", strna(i));
431 }
432
433 static void test_protect_errno(void) {
434         errno = 12;
435         {
436                 PROTECT_ERRNO;
437                 errno = 11;
438         }
439         assert(errno == 12);
440 }
441
442 static void test_parse_bytes(void) {
443         off_t bytes;
444
445         assert_se(parse_bytes("111", &bytes) == 0);
446         assert_se(bytes == 111);
447
448         assert_se(parse_bytes(" 112 B", &bytes) == 0);
449         assert_se(bytes == 112);
450
451         assert_se(parse_bytes("3 K", &bytes) == 0);
452         assert_se(bytes == 3*1024);
453
454         assert_se(parse_bytes(" 4 M 11K", &bytes) == 0);
455         assert_se(bytes == 4*1024*1024 + 11 * 1024);
456
457         assert_se(parse_bytes("3B3G", &bytes) == 0);
458         assert_se(bytes == 3ULL*1024*1024*1024 + 3);
459
460         assert_se(parse_bytes("3B3G4T", &bytes) == 0);
461         assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
462
463         assert_se(parse_bytes("12P", &bytes) == 0);
464         assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
465
466         assert_se(parse_bytes("3E 2P", &bytes) == 0);
467         assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
468
469         assert_se(parse_bytes("12X", &bytes) == -EINVAL);
470
471         assert_se(parse_bytes("1024E", &bytes) == -ERANGE);
472         assert_se(parse_bytes("-1", &bytes) == -ERANGE);
473         assert_se(parse_bytes("-1024E", &bytes) == -ERANGE);
474
475         assert_se(parse_bytes("-1024P", &bytes) == -ERANGE);
476
477         assert_se(parse_bytes("-10B 20K", &bytes) == -ERANGE);
478 }
479
480 int main(int argc, char *argv[]) {
481         test_streq_ptr();
482         test_first_word();
483         test_close_many();
484         test_parse_boolean();
485         test_parse_pid();
486         test_parse_uid();
487         test_safe_atolli();
488         test_safe_atod();
489         test_strappend();
490         test_strstrip();
491         test_delete_chars();
492         test_in_charset();
493         test_hexchar();
494         test_unhexchar();
495         test_octchar();
496         test_unoctchar();
497         test_decchar();
498         test_undecchar();
499         test_foreach_word();
500         test_foreach_word_quoted();
501         test_default_term_for_tty();
502         test_memdup_multiply();
503         test_bus_path_escape();
504         test_hostname_is_valid();
505         test_u64log2();
506         test_get_process_comm();
507         test_protect_errno();
508         test_parse_bytes();
509
510         return 0;
511 }