• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
w(pid_t pid)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 
test_exit(int code)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 
sh(const char * cmd)39 static int sh(const char *cmd)
40 {
41 	pid_t pid;
42 	if((pid = vfork()) == 0) {
43 		execl("/bin/sh", "/bin/sh", "-c", cmd, (char*)0);
44 		t_error("execl failed: %s\n", strerror(errno));
45 		_exit(1);
46 	}
47 	if (pid == -1) {
48 		t_error("vfork failed: %s\n", strerror(errno));
49 		return -1;
50 	}
51 	return w(pid);
52 }
53 
test_shell_exit(const char * cmd,int code)54 static void test_shell_exit(const char *cmd, int code)
55 {
56 	int r = sh(cmd);
57 	TEST(WIFEXITED(r), "child terminated abnormally\n");
58 	TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code);
59 }
60 
test_shell_kill(const char * cmd,int sig)61 static void test_shell_kill(const char *cmd, int sig)
62 {
63 	int r = sh(cmd);
64 	TEST(WIFSIGNALED(r), "child did not get killed\n");
65 	TEST(WTERMSIG(r) == sig, "child is killed by %d, expected %d\n", WTERMSIG(r), sig);
66 }
67 
main()68 int main() {
69 	test_exit(0);
70 	test_exit(1);
71 	test_shell_exit("exit 0", 0);
72 	test_shell_exit("exit 1", 1);
73 	test_shell_kill("kill -9 $$", 9);
74 	return t_status;
75 }
76