add vfork test
[libc-test] / src / functional / vfork.c
1 #define _GNU_SOURCE
2 #include <unistd.h>
3 #include <sys/wait.h>
4 #include <errno.h>
5 #include <string.h>
6 #include "test.h"
7
8 #define TEST(c, ...) ( (c) || (t_error(#c " failed: " __VA_ARGS__),0) )
9
10 static int w(pid_t pid)
11 {
12         int r, s;
13         r = waitpid(pid, &s, 0);
14         if (r == -1)
15                 t_error("waitpid failed: %s\n", strerror(errno));
16         else if (r != pid)
17                 t_error("child pid was %d, waitpid returned %d\n", pid, r);
18         else
19                 return s;
20         return -1;
21 }
22
23 static void test_exit(int code)
24 {
25         pid_t pid;
26         if((pid = vfork()) == 0) {
27                 _exit(code);
28                 t_error("exit failed: %s\n", strerror(errno));
29         }
30         if (pid == -1) {
31                 t_error("vfork failed: %s\n", strerror(errno));
32                 return;
33         }
34         int r = w(pid);
35         TEST(WIFEXITED(r), "child terminated abnormally\n");
36         TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code);
37 }
38
39 static void test_kill(int sig)
40 {
41         pid_t pid;
42         if((pid = vfork()) == 0) {
43                 raise(sig);
44                 t_error("raise failed: %s\n", strerror(errno));
45         }
46         if (pid == -1) {
47                 t_error("vfork failed: %s\n", strerror(errno));
48                 return;
49         }
50         int r = w(pid);
51         TEST(WIFSIGNALED(r), "child did not get killed\n");
52         TEST(WTERMSIG(r) == sig, "child is killed by %d, expected %d\n", WTERMSIG(r), sig);
53 }
54
55 static int sh(const char *cmd)
56 {
57         pid_t pid;
58         if((pid = vfork()) == 0) {
59                 execl("/bin/sh", "/bin/sh", "-c", cmd, (char*)0);
60                 t_error("execl failed: %s\n", strerror(errno));
61                 _exit(1);
62         }
63         if (pid == -1) {
64                 t_error("vfork failed: %s\n", strerror(errno));
65                 return -1;
66         }
67         return w(pid);
68 }
69
70 static void test_shell_exit(const char *cmd, int code)
71 {
72         int r = sh(cmd);
73         TEST(WIFEXITED(r), "child terminated abnormally\n");
74         TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code);
75 }
76
77 static void test_shell_kill(const char *cmd, int sig)
78 {
79         int r = sh(cmd);
80         TEST(WIFSIGNALED(r), "child did not get killed\n");
81         TEST(WTERMSIG(r) == sig, "child is killed by %d, expected %d\n", WTERMSIG(r), sig);
82 }
83
84 int main() {
85         test_exit(0);
86         test_exit(1);
87         test_kill(SIGKILL);
88         test_shell_exit("exit 0", 0);
89         test_shell_exit("exit 1", 1);
90         test_shell_kill("kill -s HUP $$", SIGHUP);
91         return t_status;
92 }