add vfork test
authorSzabolcs Nagy <nsz@port70.net>
Wed, 8 Jan 2014 02:02:12 +0000 (03:02 +0100)
committerSzabolcs Nagy <nsz@port70.net>
Wed, 8 Jan 2014 02:02:12 +0000 (03:02 +0100)
src/functional/vfork.c [new file with mode: 0644]

diff --git a/src/functional/vfork.c b/src/functional/vfork.c
new file mode 100644 (file)
index 0000000..7ace682
--- /dev/null
@@ -0,0 +1,92 @@
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <string.h>
+#include "test.h"
+
+#define TEST(c, ...) ( (c) || (t_error(#c " failed: " __VA_ARGS__),0) )
+
+static int w(pid_t pid)
+{
+       int r, s;
+       r = waitpid(pid, &s, 0);
+       if (r == -1)
+               t_error("waitpid failed: %s\n", strerror(errno));
+       else if (r != pid)
+               t_error("child pid was %d, waitpid returned %d\n", pid, r);
+       else
+               return s;
+       return -1;
+}
+
+static void test_exit(int code)
+{
+       pid_t pid;
+       if((pid = vfork()) == 0) {
+               _exit(code);
+               t_error("exit failed: %s\n", strerror(errno));
+       }
+       if (pid == -1) {
+               t_error("vfork failed: %s\n", strerror(errno));
+               return;
+       }
+       int r = w(pid);
+       TEST(WIFEXITED(r), "child terminated abnormally\n");
+       TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code);
+}
+
+static void test_kill(int sig)
+{
+       pid_t pid;
+       if((pid = vfork()) == 0) {
+               raise(sig);
+               t_error("raise failed: %s\n", strerror(errno));
+       }
+       if (pid == -1) {
+               t_error("vfork failed: %s\n", strerror(errno));
+               return;
+       }
+       int r = w(pid);
+       TEST(WIFSIGNALED(r), "child did not get killed\n");
+       TEST(WTERMSIG(r) == sig, "child is killed by %d, expected %d\n", WTERMSIG(r), sig);
+}
+
+static int sh(const char *cmd)
+{
+       pid_t pid;
+       if((pid = vfork()) == 0) {
+               execl("/bin/sh", "/bin/sh", "-c", cmd, (char*)0);
+               t_error("execl failed: %s\n", strerror(errno));
+               _exit(1);
+       }
+       if (pid == -1) {
+               t_error("vfork failed: %s\n", strerror(errno));
+               return -1;
+       }
+       return w(pid);
+}
+
+static void test_shell_exit(const char *cmd, int code)
+{
+       int r = sh(cmd);
+       TEST(WIFEXITED(r), "child terminated abnormally\n");
+       TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code);
+}
+
+static void test_shell_kill(const char *cmd, int sig)
+{
+       int r = sh(cmd);
+       TEST(WIFSIGNALED(r), "child did not get killed\n");
+       TEST(WTERMSIG(r) == sig, "child is killed by %d, expected %d\n", WTERMSIG(r), sig);
+}
+
+int main() {
+       test_exit(0);
+       test_exit(1);
+       test_kill(SIGKILL);
+       test_shell_exit("exit 0", 0);
+       test_shell_exit("exit 1", 1);
+       test_shell_kill("kill -s HUP $$", SIGHUP);
+       return t_status;
+}