]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-util.c
util: rework safe_atod() to be locale-independent
[thirdparty/systemd.git] / src / test / test-util.c
CommitLineData
539ad707
TA
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>
dbd73f9e
TA
24#include <unistd.h>
25#include <fcntl.h>
d6dd604b 26#include <locale.h>
539ad707
TA
27
28#include "util.h"
29
30static void test_streq_ptr(void) {
8354c34e
TA
31 assert_se(streq_ptr(NULL, NULL));
32 assert_se(!streq_ptr("abc", "cdef"));
539ad707
TA
33}
34
35static void test_first_word(void) {
8354c34e
TA
36 assert_se(first_word("Hello", ""));
37 assert_se(first_word("Hello", "Hello"));
38 assert_se(first_word("Hello world", "Hello"));
39 assert_se(first_word("Hello\tworld", "Hello"));
40 assert_se(first_word("Hello\nworld", "Hello"));
41 assert_se(first_word("Hello\rworld", "Hello"));
42 assert_se(first_word("Hello ", "Hello"));
43
44 assert_se(!first_word("Hello", "Hellooo"));
45 assert_se(!first_word("Hello", "xxxxx"));
46 assert_se(!first_word("Hellooo", "Hello"));
47}
48
dbd73f9e
TA
49static void test_close_many(void) {
50 int fds[3];
51 char name0[] = "/tmp/test-close-many.XXXXXX";
52 char name1[] = "/tmp/test-close-many.XXXXXX";
53 char name2[] = "/tmp/test-close-many.XXXXXX";
54
55 fds[0] = mkstemp(name0);
56 fds[1] = mkstemp(name1);
57 fds[2] = mkstemp(name2);
58
59 close_many(fds, 2);
60
61 assert_se(fcntl(fds[0], F_GETFD) == -1);
62 assert_se(fcntl(fds[1], F_GETFD) == -1);
63 assert_se(fcntl(fds[2], F_GETFD) >= 0);
64
65 close_nointr_nofail(fds[2]);
66
67 unlink(name0);
68 unlink(name1);
69 unlink(name2);
70}
71
8354c34e
TA
72static void test_parse_boolean(void) {
73 assert_se(parse_boolean("1") == 1);
74 assert_se(parse_boolean("y") == 1);
75 assert_se(parse_boolean("Y") == 1);
76 assert_se(parse_boolean("yes") == 1);
77 assert_se(parse_boolean("YES") == 1);
78 assert_se(parse_boolean("true") == 1);
79 assert_se(parse_boolean("TRUE") == 1);
80 assert_se(parse_boolean("on") == 1);
81 assert_se(parse_boolean("ON") == 1);
82
83 assert_se(parse_boolean("0") == 0);
84 assert_se(parse_boolean("n") == 0);
85 assert_se(parse_boolean("N") == 0);
86 assert_se(parse_boolean("no") == 0);
87 assert_se(parse_boolean("NO") == 0);
88 assert_se(parse_boolean("false") == 0);
89 assert_se(parse_boolean("FALSE") == 0);
90 assert_se(parse_boolean("off") == 0);
91 assert_se(parse_boolean("OFF") == 0);
92
93 assert_se(parse_boolean("garbage") < 0);
94 assert_se(parse_boolean("") < 0);
539ad707
TA
95}
96
8d99e5f5
TA
97static void test_parse_pid(void) {
98 int r;
99 pid_t pid;
100
101 r = parse_pid("100", &pid);
102 assert_se(r == 0);
103 assert_se(pid == 100);
104
105 r = parse_pid("0x7FFFFFFF", &pid);
106 assert_se(r == 0);
107 assert_se(pid == 2147483647);
108
109 pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
110 r = parse_pid("0", &pid);
111 assert_se(r == -ERANGE);
112 assert_se(pid == 65);
113
114 pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
115 r = parse_pid("-100", &pid);
116 assert_se(r == -ERANGE);
117 assert_se(pid == 65);
118
119 pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */
120 r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid);
121 assert(r == -ERANGE);
122 assert_se(pid == 65);
123}
124
125static void test_parse_uid(void) {
126 int r;
127 uid_t uid;
128
129 r = parse_uid("100", &uid);
130 assert_se(r == 0);
131 assert_se(uid == 100);
132}
133
134static void test_safe_atolli(void) {
135 int r;
136 long long l;
137
138 r = safe_atolli("12345", &l);
139 assert_se(r == 0);
140 assert_se(l == 12345);
141
142 r = safe_atolli("junk", &l);
143 assert_se(r == -EINVAL);
144}
145
146static void test_safe_atod(void) {
147 int r;
148 double d;
d6dd604b
LP
149 char *e;
150
151 r = safe_atod("junk", &d);
152 assert_se(r == -EINVAL);
8d99e5f5
TA
153
154 r = safe_atod("0.2244", &d);
155 assert_se(r == 0);
156 assert_se(abs(d - 0.2244) < 0.000001);
157
d6dd604b 158 r = safe_atod("0,5", &d);
8d99e5f5 159 assert_se(r == -EINVAL);
d6dd604b
LP
160
161 errno = 0;
162 strtod("0,5", &e);
163 assert_se(*e == ',');
164
165 /* Check if this really is locale independent */
166 setlocale(LC_NUMERIC, "de_DE.utf8");
167
168 r = safe_atod("0.2244", &d);
169 assert_se(r == 0);
170 assert_se(abs(d - 0.2244) < 0.000001);
171
172 r = safe_atod("0,5", &d);
173 assert_se(r == -EINVAL);
174
175 errno = 0;
176 assert_se(abs(strtod("0,5", &e) - 0.5) < 0.00001);
177
178 /* And check again, reset */
179 setlocale(LC_NUMERIC, "C");
180
181 r = safe_atod("0.2244", &d);
182 assert_se(r == 0);
183 assert_se(abs(d - 0.2244) < 0.000001);
184
185 r = safe_atod("0,5", &d);
186 assert_se(r == -EINVAL);
187
188 errno = 0;
189 strtod("0,5", &e);
190 assert_se(*e == ',');
8d99e5f5
TA
191}
192
dbd73f9e
TA
193static void test_strappend(void) {
194 _cleanup_free_ char *t1, *t2, *t3, *t4;
195
196 t1 = strappend(NULL, NULL);
197 assert_se(streq(t1, ""));
198
199 t2 = strappend(NULL, "suf");
200 assert_se(streq(t2, "suf"));
201
202 t3 = strappend("pre", NULL);
203 assert_se(streq(t3, "pre"));
204
205 t4 = strappend("pre", "suf");
206 assert_se(streq(t4, "presuf"));
207}
208
1ef04f0b
TA
209static void test_strstrip(void) {
210 char *r;
211 char input[] = " hello, waldo. ";
212
213 r = strstrip(input);
214 assert_se(streq(r, "hello, waldo."));
215
216}
217
218static 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
226static void test_in_charset(void) {
227 assert_se(in_charset("dddaaabbbcccc", "abcd"));
228 assert_se(!in_charset("dddaaabbbcccc", "abc f"));
229}
230
44f4c86c
DB
231static void test_hexchar(void) {
232 assert_se(hexchar(0xa) == 'a');
233 assert_se(hexchar(0x0) == '0');
234}
235
236static void test_unhexchar(void) {
237 assert_se(unhexchar('a') == 0xA);
238 assert_se(unhexchar('A') == 0xA);
239 assert_se(unhexchar('0') == 0x0);
240}
241
242static void test_octchar(void) {
243 assert_se(octchar(00) == '0');
244 assert_se(octchar(07) == '7');
245}
246
247static void test_unoctchar(void) {
248 assert_se(unoctchar('0') == 00);
249 assert_se(unoctchar('7') == 07);
250}
251
252static void test_decchar(void) {
253 assert_se(decchar(0) == '0');
254 assert_se(decchar(9) == '9');
255}
256
257static void test_undecchar(void) {
258 assert_se(undecchar('0') == 0);
259 assert_se(undecchar('9') == 9);
260}
261
1ef04f0b
TA
262static void test_foreach_word(void) {
263 char *w, *state;
264 size_t l;
265 int i = 0;
266 const char test[] = "test abc d\te f ";
267 const char * const expected[] = {
268 "test",
269 "abc",
270 "d",
271 "e",
272 "f",
273 "",
274 NULL
275 };
276
277 FOREACH_WORD(w, l, test, state) {
278 assert_se(strneq(expected[i++], w, l));
279 }
280}
281
539ad707
TA
282static void test_foreach_word_quoted(void) {
283 char *w, *state;
284 size_t l;
1ef04f0b
TA
285 int i = 0;
286 const char test[] = "test a b c 'd' e '' '' hhh '' '' \"a b c\"";
287 const char * const expected[] = {
288 "test",
289 "a",
290 "b",
291 "c",
292 "d",
293 "e",
294 "",
295 "",
296 "hhh",
297 "",
298 "",
299 "a b c",
300 NULL
301 };
302
539ad707
TA
303 printf("<%s>\n", test);
304 FOREACH_WORD_QUOTED(w, l, test, state) {
1ef04f0b 305 _cleanup_free_ char *t = NULL;
539ad707
TA
306
307 assert_se(t = strndup(w, l));
1ef04f0b 308 assert_se(strneq(expected[i++], w, l));
539ad707 309 printf("<%s>\n", t);
539ad707
TA
310 }
311}
312
313static void test_default_term_for_tty(void) {
314 puts(default_term_for_tty("/dev/tty23"));
315 puts(default_term_for_tty("/dev/ttyS23"));
316 puts(default_term_for_tty("/dev/tty0"));
317 puts(default_term_for_tty("/dev/pty0"));
318 puts(default_term_for_tty("/dev/pts/0"));
319 puts(default_term_for_tty("/dev/console"));
320 puts(default_term_for_tty("tty23"));
321 puts(default_term_for_tty("ttyS23"));
322 puts(default_term_for_tty("tty0"));
323 puts(default_term_for_tty("pty0"));
324 puts(default_term_for_tty("pts/0"));
325 puts(default_term_for_tty("console"));
326}
327
0d585d82
TA
328static void test_memdup_multiply(void) {
329 int org[] = {1, 2, 3};
330 int *dup;
331
332 dup = (int*)memdup_multiply(org, sizeof(int), 3);
333
334 assert_se(dup);
335 assert_se(dup[0] == 1);
336 assert_se(dup[1] == 2);
337 assert_se(dup[2] == 3);
338 free(dup);
339}
340
d47c78be
LP
341static void test_bus_path_escape_one(const char *a, const char *b) {
342 _cleanup_free_ char *t = NULL, *x = NULL, *y = NULL;
343
344 assert_se(t = bus_path_escape(a));
345 assert_se(streq(t, b));
346
347 assert_se(x = bus_path_unescape(t));
348 assert_se(streq(a, x));
349
350 assert_se(y = bus_path_unescape(b));
351 assert_se(streq(a, y));
352}
353
354static void test_bus_path_escape(void) {
355 test_bus_path_escape_one("foo123bar", "foo123bar");
356 test_bus_path_escape_one("foo.bar", "foo_2ebar");
357 test_bus_path_escape_one("foo_2ebar", "foo_5f2ebar");
358 test_bus_path_escape_one("", "_");
359 test_bus_path_escape_one("_", "_5f");
360 test_bus_path_escape_one("1", "_31");
361 test_bus_path_escape_one(":1", "_3a1");
362}
363
aa3c5cf8
LP
364static void test_hostname_is_valid(void) {
365 assert(hostname_is_valid("foobar"));
366 assert(hostname_is_valid("foobar.com"));
367 assert(!hostname_is_valid("fööbar"));
368 assert(!hostname_is_valid(""));
369 assert(!hostname_is_valid("."));
370 assert(!hostname_is_valid(".."));
371 assert(!hostname_is_valid("foobar."));
372 assert(!hostname_is_valid(".foobar"));
373 assert(!hostname_is_valid("foo..bar"));
374 assert(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
375}
376
144e51ec
CR
377static void test_u64log2(void) {
378 assert(u64log2(0) == 0);
379 assert(u64log2(8) == 3);
380 assert(u64log2(9) == 3);
381 assert(u64log2(15) == 3);
382 assert(u64log2(16) == 4);
383 assert(u64log2(1024*1024) == 20);
384 assert(u64log2(1024*1024+5) == 20);
385}
386
49aa47c7
LP
387static void test_get_process_comm(void) {
388 _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
389 unsigned long long b;
390 pid_t e;
391 uid_t u;
392 gid_t g;
393 dev_t h;
394 int r;
395
396 assert_se(get_process_comm(1, &a) >= 0);
397 log_info("pid1 comm: '%s'", a);
398
399 assert_se(get_starttime_of_pid(1, &b) >= 0);
400 log_info("pid1 starttime: '%llu'", b);
401
402 assert_se(get_process_cmdline(1, 0, true, &c) >= 0);
403 log_info("pid1 cmdline: '%s'", c);
404
405 assert_se(get_process_cmdline(1, 8, false, &d) >= 0);
406 log_info("pid1 cmdline truncated: '%s'", d);
407
408 assert_se(get_parent_of_pid(1, &e) >= 0);
409 log_info("pid1 ppid: '%llu'", (unsigned long long) e);
410 assert_se(e == 0);
411
412 assert_se(is_kernel_thread(1) == 0);
413
414 r = get_process_exe(1, &f);
415 assert_se(r >= 0 || r == -EACCES);
416 log_info("pid1 exe: '%s'", strna(f));
417
418 assert_se(get_process_uid(1, &u) == 0);
419 log_info("pid1 uid: '%llu'", (unsigned long long) u);
420 assert_se(u == 0);
421
422 assert_se(get_process_gid(1, &g) == 0);
423 log_info("pid1 gid: '%llu'", (unsigned long long) g);
424 assert_se(g == 0);
425
426 assert(get_ctty_devnr(1, &h) == -ENOENT);
427
428 getenv_for_pid(1, "PATH", &i);
429 log_info("pid1 $PATH: '%s'", strna(i));
430}
431
539ad707
TA
432int main(int argc, char *argv[]) {
433 test_streq_ptr();
434 test_first_word();
dbd73f9e 435 test_close_many();
8354c34e 436 test_parse_boolean();
8d99e5f5
TA
437 test_parse_pid();
438 test_parse_uid();
439 test_safe_atolli();
440 test_safe_atod();
dbd73f9e 441 test_strappend();
1ef04f0b
TA
442 test_strstrip();
443 test_delete_chars();
444 test_in_charset();
44f4c86c
DB
445 test_hexchar();
446 test_unhexchar();
447 test_octchar();
448 test_unoctchar();
449 test_decchar();
450 test_undecchar();
1ef04f0b 451 test_foreach_word();
539ad707 452 test_foreach_word_quoted();
1ef04f0b 453 test_default_term_for_tty();
0d585d82 454 test_memdup_multiply();
d47c78be 455 test_bus_path_escape();
aa3c5cf8 456 test_hostname_is_valid();
144e51ec 457 test_u64log2();
49aa47c7 458 test_get_process_comm();
539ad707
TA
459
460 return 0;
461}