chiark / gitweb /
journal: u64log2 can be expressed just as __builtin_clzll(n) ^ 63U
[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
27 #include "util.h"
28
29 static void test_streq_ptr(void) {
30         assert_se(streq_ptr(NULL, NULL));
31         assert_se(!streq_ptr("abc", "cdef"));
32 }
33
34 static void test_first_word(void) {
35         assert_se(first_word("Hello", ""));
36         assert_se(first_word("Hello", "Hello"));
37         assert_se(first_word("Hello world", "Hello"));
38         assert_se(first_word("Hello\tworld", "Hello"));
39         assert_se(first_word("Hello\nworld", "Hello"));
40         assert_se(first_word("Hello\rworld", "Hello"));
41         assert_se(first_word("Hello ", "Hello"));
42
43         assert_se(!first_word("Hello", "Hellooo"));
44         assert_se(!first_word("Hello", "xxxxx"));
45         assert_se(!first_word("Hellooo", "Hello"));
46 }
47
48 static void test_close_many(void) {
49         int fds[3];
50         char name0[] = "/tmp/test-close-many.XXXXXX";
51         char name1[] = "/tmp/test-close-many.XXXXXX";
52         char name2[] = "/tmp/test-close-many.XXXXXX";
53
54         fds[0] = mkstemp(name0);
55         fds[1] = mkstemp(name1);
56         fds[2] = mkstemp(name2);
57
58         close_many(fds, 2);
59
60         assert_se(fcntl(fds[0], F_GETFD) == -1);
61         assert_se(fcntl(fds[1], F_GETFD) == -1);
62         assert_se(fcntl(fds[2], F_GETFD) >= 0);
63
64         close_nointr_nofail(fds[2]);
65
66         unlink(name0);
67         unlink(name1);
68         unlink(name2);
69 }
70
71 static void test_parse_boolean(void) {
72         assert_se(parse_boolean("1") == 1);
73         assert_se(parse_boolean("y") == 1);
74         assert_se(parse_boolean("Y") == 1);
75         assert_se(parse_boolean("yes") == 1);
76         assert_se(parse_boolean("YES") == 1);
77         assert_se(parse_boolean("true") == 1);
78         assert_se(parse_boolean("TRUE") == 1);
79         assert_se(parse_boolean("on") == 1);
80         assert_se(parse_boolean("ON") == 1);
81
82         assert_se(parse_boolean("0") == 0);
83         assert_se(parse_boolean("n") == 0);
84         assert_se(parse_boolean("N") == 0);
85         assert_se(parse_boolean("no") == 0);
86         assert_se(parse_boolean("NO") == 0);
87         assert_se(parse_boolean("false") == 0);
88         assert_se(parse_boolean("FALSE") == 0);
89         assert_se(parse_boolean("off") == 0);
90         assert_se(parse_boolean("OFF") == 0);
91
92         assert_se(parse_boolean("garbage") < 0);
93         assert_se(parse_boolean("") < 0);
94 }
95
96 static void test_parse_pid(void) {
97         int r;
98         pid_t pid;
99
100         r = parse_pid("100", &pid);
101         assert_se(r == 0);
102         assert_se(pid == 100);
103
104         r = parse_pid("0x7FFFFFFF", &pid);
105         assert_se(r == 0);
106         assert_se(pid == 2147483647);
107
108         pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
109         r = parse_pid("0", &pid);
110         assert_se(r == -ERANGE);
111         assert_se(pid == 65);
112
113         pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
114         r = parse_pid("-100", &pid);
115         assert_se(r == -ERANGE);
116         assert_se(pid == 65);
117
118         pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
119         r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid);
120         assert(r == -ERANGE);
121         assert_se(pid == 65);
122 }
123
124 static void test_parse_uid(void) {
125         int r;
126         uid_t uid;
127
128         r = parse_uid("100", &uid);
129         assert_se(r == 0);
130         assert_se(uid == 100);
131 }
132
133 static void test_safe_atolli(void) {
134         int r;
135         long long l;
136
137         r = safe_atolli("12345", &l);
138         assert_se(r == 0);
139         assert_se(l == 12345);
140
141         r = safe_atolli("junk", &l);
142         assert_se(r == -EINVAL);
143 }
144
145 static void test_safe_atod(void) {
146         int r;
147         double d;
148
149         r = safe_atod("0.2244", &d);
150         assert_se(r == 0);
151         assert_se(abs(d - 0.2244) < 0.000001);
152
153         r = safe_atod("junk", &d);
154         assert_se(r == -EINVAL);
155 }
156
157 static void test_strappend(void) {
158        _cleanup_free_ char *t1, *t2, *t3, *t4;
159
160        t1 = strappend(NULL, NULL);
161        assert_se(streq(t1, ""));
162
163        t2 = strappend(NULL, "suf");
164        assert_se(streq(t2, "suf"));
165
166        t3 = strappend("pre", NULL);
167        assert_se(streq(t3, "pre"));
168
169        t4 = strappend("pre", "suf");
170        assert_se(streq(t4, "presuf"));
171 }
172
173 static void test_strstrip(void) {
174        char *r;
175        char input[] = "   hello, waldo.   ";
176
177        r = strstrip(input);
178        assert_se(streq(r, "hello, waldo."));
179
180 }
181
182 static void test_delete_chars(void) {
183        char *r;
184        char input[] = "   hello, waldo.   abc";
185
186        r = delete_chars(input, WHITESPACE);
187        assert_se(streq(r, "hello,waldo.abc"));
188 }
189
190 static void test_in_charset(void) {
191       assert_se(in_charset("dddaaabbbcccc", "abcd"));
192       assert_se(!in_charset("dddaaabbbcccc", "abc f"));
193 }
194
195 static void test_hexchar(void) {
196         assert_se(hexchar(0xa) == 'a');
197         assert_se(hexchar(0x0) == '0');
198 }
199
200 static void test_unhexchar(void) {
201         assert_se(unhexchar('a') == 0xA);
202         assert_se(unhexchar('A') == 0xA);
203         assert_se(unhexchar('0') == 0x0);
204 }
205
206 static void test_octchar(void) {
207         assert_se(octchar(00) == '0');
208         assert_se(octchar(07) == '7');
209 }
210
211 static void test_unoctchar(void) {
212         assert_se(unoctchar('0') == 00);
213         assert_se(unoctchar('7') == 07);
214 }
215
216 static void test_decchar(void) {
217         assert_se(decchar(0) == '0');
218         assert_se(decchar(9) == '9');
219 }
220
221 static void test_undecchar(void) {
222         assert_se(undecchar('0') == 0);
223         assert_se(undecchar('9') == 9);
224 }
225
226 static void test_foreach_word(void) {
227         char *w, *state;
228         size_t l;
229         int i = 0;
230         const char test[] = "test abc d\te   f   ";
231         const char * const expected[] = {
232                 "test",
233                 "abc",
234                 "d",
235                 "e",
236                 "f",
237                 "",
238                 NULL
239         };
240
241         FOREACH_WORD(w, l, test, state) {
242                 assert_se(strneq(expected[i++], w, l));
243         }
244 }
245
246 static void test_foreach_word_quoted(void) {
247         char *w, *state;
248         size_t l;
249         int i = 0;
250         const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\"";
251         const char * const expected[] = {
252                 "test",
253                 "a",
254                 "b",
255                 "c",
256                 "d",
257                 "e",
258                 "",
259                 "",
260                 "hhh",
261                 "",
262                 "",
263                 "a b c",
264                 NULL
265         };
266
267         printf("<%s>\n", test);
268         FOREACH_WORD_QUOTED(w, l, test, state) {
269                 _cleanup_free_ char *t = NULL;
270
271                 assert_se(t = strndup(w, l));
272                 assert_se(strneq(expected[i++], w, l));
273                 printf("<%s>\n", t);
274         }
275 }
276
277 static void test_default_term_for_tty(void) {
278         puts(default_term_for_tty("/dev/tty23"));
279         puts(default_term_for_tty("/dev/ttyS23"));
280         puts(default_term_for_tty("/dev/tty0"));
281         puts(default_term_for_tty("/dev/pty0"));
282         puts(default_term_for_tty("/dev/pts/0"));
283         puts(default_term_for_tty("/dev/console"));
284         puts(default_term_for_tty("tty23"));
285         puts(default_term_for_tty("ttyS23"));
286         puts(default_term_for_tty("tty0"));
287         puts(default_term_for_tty("pty0"));
288         puts(default_term_for_tty("pts/0"));
289         puts(default_term_for_tty("console"));
290 }
291
292 static void test_memdup_multiply(void) {
293         int org[] = {1, 2, 3};
294         int *dup;
295
296         dup = (int*)memdup_multiply(org, sizeof(int), 3);
297
298         assert_se(dup);
299         assert_se(dup[0] == 1);
300         assert_se(dup[1] == 2);
301         assert_se(dup[2] == 3);
302         free(dup);
303 }
304
305 static void test_bus_path_escape_one(const char *a, const char *b) {
306         _cleanup_free_ char *t = NULL, *x = NULL, *y = NULL;
307
308         assert_se(t = bus_path_escape(a));
309         assert_se(streq(t, b));
310
311         assert_se(x = bus_path_unescape(t));
312         assert_se(streq(a, x));
313
314         assert_se(y = bus_path_unescape(b));
315         assert_se(streq(a, y));
316 }
317
318 static void test_bus_path_escape(void) {
319         test_bus_path_escape_one("foo123bar", "foo123bar");
320         test_bus_path_escape_one("foo.bar", "foo_2ebar");
321         test_bus_path_escape_one("foo_2ebar", "foo_5f2ebar");
322         test_bus_path_escape_one("", "_");
323         test_bus_path_escape_one("_", "_5f");
324         test_bus_path_escape_one("1", "_31");
325         test_bus_path_escape_one(":1", "_3a1");
326 }
327
328 static void test_hostname_is_valid(void) {
329         assert(hostname_is_valid("foobar"));
330         assert(hostname_is_valid("foobar.com"));
331         assert(!hostname_is_valid("fööbar"));
332         assert(!hostname_is_valid(""));
333         assert(!hostname_is_valid("."));
334         assert(!hostname_is_valid(".."));
335         assert(!hostname_is_valid("foobar."));
336         assert(!hostname_is_valid(".foobar"));
337         assert(!hostname_is_valid("foo..bar"));
338         assert(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
339 }
340
341 static void test_u64log2(void) {
342         assert(u64log2(0) == 0);
343         assert(u64log2(8) == 3);
344         assert(u64log2(9) == 3);
345         assert(u64log2(15) == 3);
346         assert(u64log2(16) == 4);
347         assert(u64log2(1024*1024) == 20);
348         assert(u64log2(1024*1024+5) == 20);
349 }
350
351 int main(int argc, char *argv[]) {
352         test_streq_ptr();
353         test_first_word();
354         test_close_many();
355         test_parse_boolean();
356         test_parse_pid();
357         test_parse_uid();
358         test_safe_atolli();
359         test_safe_atod();
360         test_strappend();
361         test_strstrip();
362         test_delete_chars();
363         test_in_charset();
364         test_hexchar();
365         test_unhexchar();
366         test_octchar();
367         test_unoctchar();
368         test_decchar();
369         test_undecchar();
370         test_foreach_word();
371         test_foreach_word_quoted();
372         test_default_term_for_tty();
373         test_memdup_multiply();
374         test_bus_path_escape();
375         test_hostname_is_valid();
376         test_u64log2();
377
378         return 0;
379 }