chiark / gitweb /
a57bd8c7f93b2199872d13e40542aa52b28c1cce
[elogind.git] / src / test / test-process-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   Copyright © 2013 Thomas H.P. Andersen
4 ***/
5
6 #include <sched.h>
7 #include <sys/mount.h>
8 #include <sys/personality.h>
9 #include <sys/prctl.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13 #include <unistd.h>
14 #if HAVE_VALGRIND_VALGRIND_H
15 #include <valgrind/valgrind.h>
16 #endif
17
18 #include "alloc-util.h"
19 //#include "architecture.h"
20 #include "fd-util.h"
21 #include "log.h"
22 #include "macro.h"
23 #include "parse-util.h"
24 #include "process-util.h"
25 #include "signal-util.h"
26 #include "stdio-util.h"
27 #include "string-util.h"
28 #include "terminal-util.h"
29 #include "test-helper.h"
30 #include "util.h"
31 #include "virt.h"
32
33 static void test_get_process_comm(pid_t pid) {
34         struct stat st;
35         _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL;
36         _cleanup_free_ char *env = NULL;
37         char path[STRLEN("/proc//comm") + DECIMAL_STR_MAX(pid_t)];
38 #if 0 /// UNNEEDED by elogind
39         pid_t e;
40         uid_t u;
41         gid_t g;
42 #endif // 0
43         dev_t h;
44         int r;
45
46         xsprintf(path, "/proc/"PID_FMT"/comm", pid);
47
48         if (stat(path, &st) == 0) {
49                 assert_se(get_process_comm(pid, &a) >= 0);
50                 log_info("PID"PID_FMT" comm: '%s'", pid, a);
51         } else
52                 log_warning("%s not exist.", path);
53
54         assert_se(get_process_cmdline(pid, 0, true, &c) >= 0);
55         log_info("PID"PID_FMT" cmdline: '%s'", pid, c);
56
57         assert_se(get_process_cmdline(pid, 8, false, &d) >= 0);
58         log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d);
59
60         free(d);
61         assert_se(get_process_cmdline(pid, 1, false, &d) >= 0);
62         log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
63
64 #if 0 /// UNNEEDED by elogind
65         assert_se(get_process_ppid(pid, &e) >= 0);
66         log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
67         assert_se(pid == 1 ? e == 0 : e > 0);
68 #endif // 0
69
70         assert_se(is_kernel_thread(pid) == 0 || pid != 1);
71
72         r = get_process_exe(pid, &f);
73         assert_se(r >= 0 || r == -EACCES);
74         log_info("PID"PID_FMT" exe: '%s'", pid, strna(f));
75
76 #if 0 /// UNNEEDED by elogind
77         assert_se(get_process_uid(pid, &u) == 0);
78         log_info("PID"PID_FMT" UID: "UID_FMT, pid, u);
79         assert_se(u == 0 || pid != 1);
80
81         assert_se(get_process_gid(pid, &g) == 0);
82         log_info("PID"PID_FMT" GID: "GID_FMT, pid, g);
83         assert_se(g == 0 || pid != 1);
84
85         r = get_process_environ(pid, &env);
86         assert_se(r >= 0 || r == -EACCES);
87         log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno);
88 #endif // 0
89
90         if (!detect_container())
91                 assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1);
92
93         (void) getenv_for_pid(pid, "PATH", &i);
94         log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i));
95 }
96
97 static void test_get_process_comm_escape_one(const char *input, const char *output) {
98         _cleanup_free_ char *n = NULL;
99
100         log_info("input: <%s> — output: <%s>", input, output);
101
102         assert_se(prctl(PR_SET_NAME, input) >= 0);
103         assert_se(get_process_comm(0, &n) >= 0);
104
105         log_info("got: <%s>", n);
106
107         assert_se(streq_ptr(n, output));
108 }
109
110 static void test_get_process_comm_escape(void) {
111         _cleanup_free_ char *saved = NULL;
112
113         assert_se(get_process_comm(0, &saved) >= 0);
114
115         test_get_process_comm_escape_one("", "");
116         test_get_process_comm_escape_one("foo", "foo");
117         test_get_process_comm_escape_one("012345678901234", "012345678901234");
118         test_get_process_comm_escape_one("0123456789012345", "012345678901234");
119         test_get_process_comm_escape_one("äöüß", "\\303\\244\\303…");
120         test_get_process_comm_escape_one("xäöüß", "x\\303\\244…");
121         test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244…");
122         test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244…");
123         test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244…");
124         test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303…");
125
126         assert_se(prctl(PR_SET_NAME, saved) >= 0);
127 }
128
129 static void test_pid_is_unwaited(void) {
130         pid_t pid;
131
132         pid = fork();
133         assert_se(pid >= 0);
134         if (pid == 0) {
135                 _exit(EXIT_SUCCESS);
136         } else {
137                 int status;
138
139                 waitpid(pid, &status, 0);
140                 assert_se(!pid_is_unwaited(pid));
141         }
142         assert_se(pid_is_unwaited(getpid_cached()));
143         assert_se(!pid_is_unwaited(-1));
144 }
145
146 static void test_pid_is_alive(void) {
147         pid_t pid;
148
149         pid = fork();
150         assert_se(pid >= 0);
151         if (pid == 0) {
152                 _exit(EXIT_SUCCESS);
153         } else {
154                 int status;
155
156                 waitpid(pid, &status, 0);
157                 assert_se(!pid_is_alive(pid));
158         }
159         assert_se(pid_is_alive(getpid_cached()));
160         assert_se(!pid_is_alive(-1));
161 }
162
163 #if 0 /// UNNEEDED by elogind
164 static void test_personality(void) {
165
166         assert_se(personality_to_string(PER_LINUX));
167         assert_se(!personality_to_string(PERSONALITY_INVALID));
168
169         assert_se(streq(personality_to_string(PER_LINUX), architecture_to_string(native_architecture())));
170
171         assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX);
172         assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX);
173
174 #ifdef __x86_64__
175         assert_se(streq_ptr(personality_to_string(PER_LINUX), "x86-64"));
176         assert_se(streq_ptr(personality_to_string(PER_LINUX32), "x86"));
177
178         assert_se(personality_from_string("x86-64") == PER_LINUX);
179         assert_se(personality_from_string("x86") == PER_LINUX32);
180         assert_se(personality_from_string("ia64") == PERSONALITY_INVALID);
181         assert_se(personality_from_string(NULL) == PERSONALITY_INVALID);
182
183         assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32);
184 #endif
185 }
186 #endif // 0
187
188 static void test_get_process_cmdline_harder(void) {
189         char path[] = "/tmp/test-cmdlineXXXXXX";
190         _cleanup_close_ int fd = -1;
191         _cleanup_free_ char *line = NULL;
192         pid_t pid;
193
194         if (geteuid() != 0)
195                 return;
196
197 #if HAVE_VALGRIND_VALGRIND_H
198         /* valgrind patches open(/proc//cmdline)
199          * so, test_get_process_cmdline_harder fails always
200          * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
201         if (RUNNING_ON_VALGRIND)
202                 return;
203 #endif
204
205         pid = fork();
206         if (pid > 0) {
207                 siginfo_t si;
208
209                 (void) wait_for_terminate(pid, &si);
210
211                 assert_se(si.si_code == CLD_EXITED);
212                 assert_se(si.si_status == 0);
213
214                 return;
215         }
216
217         assert_se(pid == 0);
218         assert_se(unshare(CLONE_NEWNS) >= 0);
219
220         assert_se(mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) >= 0);
221
222         fd = mkostemp(path, O_CLOEXEC);
223         assert_se(fd >= 0);
224
225         if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) {
226                 /* This happens under selinux… Abort the test in this case. */
227                 log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m");
228                 assert(errno == EACCES);
229                 return;
230         }
231
232         assert_se(unlink(path) >= 0);
233
234         assert_se(prctl(PR_SET_NAME, "testa") >= 0);
235
236         assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
237
238         assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
239         assert_se(streq(line, "[testa]"));
240         line = mfree(line);
241
242         assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
243         assert_se(streq(line, ""));
244         line = mfree(line);
245
246         assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
247         assert_se(streq(line, "["));
248         line = mfree(line);
249
250         assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
251         assert_se(streq(line, "[."));
252         line = mfree(line);
253
254         assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
255         assert_se(streq(line, "[.."));
256         line = mfree(line);
257
258         assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
259         assert_se(streq(line, "[..."));
260         line = mfree(line);
261
262         assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
263         assert_se(streq(line, "[...]"));
264         line = mfree(line);
265
266         assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
267         assert_se(streq(line, "[t...]"));
268         line = mfree(line);
269
270         assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
271         assert_se(streq(line, "[testa]"));
272         line = mfree(line);
273
274         assert_se(write(fd, "\0\0\0\0\0\0\0\0\0", 10) == 10);
275
276         assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
277
278         assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
279         assert_se(streq(line, "[testa]"));
280         line = mfree(line);
281
282         assert_se(write(fd, "foo\0bar\0\0\0\0\0", 10) == 10);
283
284         assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
285         assert_se(streq(line, "foo bar"));
286         line = mfree(line);
287
288         assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
289         assert_se(streq(line, "foo bar"));
290         line = mfree(line);
291
292         assert_se(write(fd, "quux", 4) == 4);
293         assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) >= 0);
294         assert_se(streq(line, "foo bar quux"));
295         line = mfree(line);
296
297         assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
298         assert_se(streq(line, "foo bar quux"));
299         line = mfree(line);
300
301         assert_se(get_process_cmdline(getpid_cached(), 1, true, &line) >= 0);
302         assert_se(streq(line, ""));
303         line = mfree(line);
304
305         assert_se(get_process_cmdline(getpid_cached(), 2, true, &line) >= 0);
306         assert_se(streq(line, "."));
307         line = mfree(line);
308
309         assert_se(get_process_cmdline(getpid_cached(), 3, true, &line) >= 0);
310         assert_se(streq(line, ".."));
311         line = mfree(line);
312
313         assert_se(get_process_cmdline(getpid_cached(), 4, true, &line) >= 0);
314         assert_se(streq(line, "..."));
315         line = mfree(line);
316
317         assert_se(get_process_cmdline(getpid_cached(), 5, true, &line) >= 0);
318         assert_se(streq(line, "f..."));
319         line = mfree(line);
320
321         assert_se(get_process_cmdline(getpid_cached(), 6, true, &line) >= 0);
322         assert_se(streq(line, "fo..."));
323         line = mfree(line);
324
325         assert_se(get_process_cmdline(getpid_cached(), 7, true, &line) >= 0);
326         assert_se(streq(line, "foo..."));
327         line = mfree(line);
328
329         assert_se(get_process_cmdline(getpid_cached(), 8, true, &line) >= 0);
330         assert_se(streq(line, "foo..."));
331         line = mfree(line);
332
333         assert_se(get_process_cmdline(getpid_cached(), 9, true, &line) >= 0);
334         assert_se(streq(line, "foo b..."));
335         line = mfree(line);
336
337         assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
338         assert_se(streq(line, "foo ba..."));
339         line = mfree(line);
340
341         assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
342         assert_se(streq(line, "foo bar..."));
343         line = mfree(line);
344
345         assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
346         assert_se(streq(line, "foo bar..."));
347         line = mfree(line);
348
349         assert_se(get_process_cmdline(getpid_cached(), 13, true, &line) >= 0);
350         assert_se(streq(line, "foo bar quux"));
351         line = mfree(line);
352
353         assert_se(get_process_cmdline(getpid_cached(), 14, true, &line) >= 0);
354         assert_se(streq(line, "foo bar quux"));
355         line = mfree(line);
356
357         assert_se(get_process_cmdline(getpid_cached(), 1000, true, &line) >= 0);
358         assert_se(streq(line, "foo bar quux"));
359         line = mfree(line);
360
361         assert_se(ftruncate(fd, 0) >= 0);
362         assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0);
363
364         assert_se(get_process_cmdline(getpid_cached(), 0, false, &line) == -ENOENT);
365
366         assert_se(get_process_cmdline(getpid_cached(), 0, true, &line) >= 0);
367         assert_se(streq(line, "[aaaa bbbb cccc]"));
368         line = mfree(line);
369
370         assert_se(get_process_cmdline(getpid_cached(), 10, true, &line) >= 0);
371         assert_se(streq(line, "[aaaa...]"));
372         line = mfree(line);
373
374         assert_se(get_process_cmdline(getpid_cached(), 11, true, &line) >= 0);
375         assert_se(streq(line, "[aaaa...]"));
376         line = mfree(line);
377
378         assert_se(get_process_cmdline(getpid_cached(), 12, true, &line) >= 0);
379         assert_se(streq(line, "[aaaa b...]"));
380         line = mfree(line);
381
382         safe_close(fd);
383         _exit(EXIT_SUCCESS);
384 }
385
386 #if 0 /// UNNEEDED by elogind
387 static void test_rename_process_now(const char *p, int ret) {
388         _cleanup_free_ char *comm = NULL, *cmdline = NULL;
389         int r;
390
391         r = rename_process(p);
392         assert_se(r == ret ||
393                   (ret == 0 && r >= 0) ||
394                   (ret > 0 && r > 0));
395
396         if (r < 0)
397                 return;
398
399 #if HAVE_VALGRIND_VALGRIND_H
400         /* see above, valgrind is weird, we can't verify what we are doing here */
401         if (RUNNING_ON_VALGRIND)
402                 return;
403 #endif
404
405         assert_se(get_process_comm(0, &comm) >= 0);
406         log_info("comm = <%s>", comm);
407         assert_se(strneq(comm, p, TASK_COMM_LEN-1));
408
409         assert_se(get_process_cmdline(0, 0, false, &cmdline) >= 0);
410         /* we cannot expect cmdline to be renamed properly without privileges */
411         if (geteuid() == 0) {
412                 log_info("cmdline = <%s>", cmdline);
413                 assert_se(strneq(p, cmdline, STRLEN("test-process-util")));
414                 assert_se(startswith(p, cmdline));
415         } else
416                 log_info("cmdline = <%s> (not verified)", cmdline);
417 }
418
419 static void test_rename_process_one(const char *p, int ret) {
420         siginfo_t si;
421         pid_t pid;
422
423         pid = fork();
424         assert_se(pid >= 0);
425
426         if (pid == 0) {
427                 /* child */
428                 test_rename_process_now(p, ret);
429                 _exit(EXIT_SUCCESS);
430         }
431
432         assert_se(wait_for_terminate(pid, &si) >= 0);
433         assert_se(si.si_code == CLD_EXITED);
434         assert_se(si.si_status == EXIT_SUCCESS);
435 }
436
437 static void test_rename_process_multi(void) {
438         pid_t pid;
439
440         pid = fork();
441         assert_se(pid >= 0);
442
443         if (pid > 0) {
444                 siginfo_t si;
445
446                 assert_se(wait_for_terminate(pid, &si) >= 0);
447                 assert_se(si.si_code == CLD_EXITED);
448                 assert_se(si.si_status == EXIT_SUCCESS);
449
450                 return;
451         }
452
453         /* child */
454         test_rename_process_now("one", 1);
455         test_rename_process_now("more", 0); /* longer than "one", hence truncated */
456         (void) setresuid(99, 99, 99); /* change uid when running privileged */
457         test_rename_process_now("time!", 0);
458         test_rename_process_now("0", 1); /* shorter than "one", should fit */
459         test_rename_process_one("", -EINVAL);
460         test_rename_process_one(NULL, -EINVAL);
461         _exit(EXIT_SUCCESS);
462 }
463
464 static void test_rename_process(void) {
465         test_rename_process_one(NULL, -EINVAL);
466         test_rename_process_one("", -EINVAL);
467         test_rename_process_one("foo", 1); /* should always fit */
468         test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */
469         test_rename_process_one("1234567", 1); /* should always fit */
470         test_rename_process_multi(); /* multiple invocations and dropped privileges */
471 }
472 #endif // 0
473
474 static void test_getpid_cached(void) {
475         siginfo_t si;
476         pid_t a, b, c, d, e, f, child;
477
478         a = raw_getpid();
479         b = getpid_cached();
480         c = getpid();
481
482         assert_se(a == b && a == c);
483
484         child = fork();
485         assert_se(child >= 0);
486
487         if (child == 0) {
488                 /* In child */
489                 a = raw_getpid();
490                 b = getpid_cached();
491                 c = getpid();
492
493                 assert_se(a == b && a == c);
494                 _exit(EXIT_SUCCESS);
495         }
496
497         d = raw_getpid();
498         e = getpid_cached();
499         f = getpid();
500
501         assert_se(a == d && a == e && a == f);
502
503         assert_se(wait_for_terminate(child, &si) >= 0);
504         assert_se(si.si_status == 0);
505         assert_se(si.si_code == CLD_EXITED);
506 }
507
508 #define MEASURE_ITERATIONS (10000000LLU)
509
510 static void test_getpid_measure(void) {
511         unsigned long long i;
512         usec_t t, q;
513
514         t = now(CLOCK_MONOTONIC);
515         for (i = 0; i < MEASURE_ITERATIONS; i++)
516                 (void) getpid();
517         q = now(CLOCK_MONOTONIC) - t;
518
519         log_info(" glibc getpid(): %llu/s\n", (unsigned long long) (MEASURE_ITERATIONS*USEC_PER_SEC/q));
520
521         t = now(CLOCK_MONOTONIC);
522         for (i = 0; i < MEASURE_ITERATIONS; i++)
523                 (void) getpid_cached();
524         q = now(CLOCK_MONOTONIC) - t;
525
526         log_info("getpid_cached(): %llu/s\n", (unsigned long long) (MEASURE_ITERATIONS*USEC_PER_SEC/q));
527 }
528
529 static void test_safe_fork(void) {
530         siginfo_t status;
531         pid_t pid;
532         int r;
533
534         BLOCK_SIGNALS(SIGCHLD);
535
536         r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_REOPEN_LOG, &pid);
537         assert_se(r >= 0);
538
539         if (r == 0) {
540                 /* child */
541                 usleep(100 * USEC_PER_MSEC);
542
543                 _exit(88);
544         }
545
546         assert_se(wait_for_terminate(pid, &status) >= 0);
547         assert_se(status.si_code == CLD_EXITED);
548         assert_se(status.si_status == 88);
549 }
550
551 static void test_pid_to_ptr(void) {
552
553         assert_se(PTR_TO_PID(NULL) == 0);
554         assert_se(PID_TO_PTR(0) == NULL);
555
556         assert_se(PTR_TO_PID(PID_TO_PTR(1)) == 1);
557         assert_se(PTR_TO_PID(PID_TO_PTR(2)) == 2);
558         assert_se(PTR_TO_PID(PID_TO_PTR(-1)) == -1);
559         assert_se(PTR_TO_PID(PID_TO_PTR(-2)) == -2);
560
561         assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MAX)) == INT16_MAX);
562         assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MIN)) == INT16_MIN);
563
564 #if SIZEOF_PID_T >= 4
565         assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MAX)) == INT32_MAX);
566         assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MIN)) == INT32_MIN);
567 #endif
568 }
569
570 static void test_ioprio_class_from_to_string_one(const char *val, int expected) {
571         assert_se(ioprio_class_from_string(val) == expected);
572         if (expected >= 0) {
573                 _cleanup_free_ char *s = NULL;
574                 unsigned ret;
575
576                 assert_se(ioprio_class_to_string_alloc(expected, &s) == 0);
577                 /* We sometimes get a class number and sometimes a number back */
578                 assert_se(streq(s, val) ||
579                           safe_atou(val, &ret) == 0);
580         }
581 }
582
583 static void test_ioprio_class_from_to_string(void) {
584         test_ioprio_class_from_to_string_one("none", IOPRIO_CLASS_NONE);
585         test_ioprio_class_from_to_string_one("realtime", IOPRIO_CLASS_RT);
586         test_ioprio_class_from_to_string_one("best-effort", IOPRIO_CLASS_BE);
587         test_ioprio_class_from_to_string_one("idle", IOPRIO_CLASS_IDLE);
588         test_ioprio_class_from_to_string_one("0", 0);
589         test_ioprio_class_from_to_string_one("1", 1);
590         test_ioprio_class_from_to_string_one("7", 7);
591         test_ioprio_class_from_to_string_one("8", 8);
592         test_ioprio_class_from_to_string_one("9", -1);
593         test_ioprio_class_from_to_string_one("-1", -1);
594 }
595
596 int main(int argc, char *argv[]) {
597         log_set_max_level(LOG_DEBUG);
598         log_parse_environment();
599         log_open();
600
601         saved_argc = argc;
602         saved_argv = argv;
603
604         if (argc > 1) {
605                 pid_t pid = 0;
606
607                 (void) parse_pid(argv[1], &pid);
608                 test_get_process_comm(pid);
609         } else {
610                 TEST_REQ_RUNNING_SYSTEMD(test_get_process_comm(1));
611                 test_get_process_comm(getpid());
612         }
613
614         test_get_process_comm_escape();
615         test_pid_is_unwaited();
616         test_pid_is_alive();
617 #if 0 /// UNNEEDED by elogind
618         test_personality();
619 #endif // 0
620         test_get_process_cmdline_harder();
621 #if 0 /// UNNEEDED by elogind
622         test_rename_process();
623 #endif // 0
624         test_getpid_cached();
625         test_getpid_measure();
626         test_safe_fork();
627         test_pid_to_ptr();
628         test_ioprio_class_from_to_string();
629
630         return 0;
631 }