67 changes: 67 additions & 0 deletions libc/test/integration/src/unistd/fork_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#include "src/signal/raise.h"
#include "src/sys/wait/wait.h"
#include "src/sys/wait/wait4.h"
#include "src/sys/wait/waitpid.h"
#include "src/unistd/fork.h"

#include "utils/IntegrationTest/test.h"
Expand All @@ -17,6 +19,11 @@
#include <sys/wait.h>
#include <unistd.h>

// The tests wait4 and waitpid are present as tests for those functions
// really and not for the fork function. They are here along with the tests
// for fork because it is convenient to invoke and test them after forking
// a child.

void fork_and_wait_normal_exit() {
pid_t pid = __llvm_libc::fork();
if (pid == 0)
Expand All @@ -29,6 +36,33 @@ void fork_and_wait_normal_exit() {
ASSERT_TRUE(WIFEXITED(status));
}

void fork_and_wait4_normal_exit() {
pid_t pid = __llvm_libc::fork();
if (pid == 0)
return; // Just end without any thing special.
ASSERT_TRUE(pid > 0);
int status;
struct rusage usage;
usage.ru_utime = {0, 0};
usage.ru_stime = {0, 0};
pid_t cpid = __llvm_libc::wait4(pid, &status, 0, &usage);
ASSERT_TRUE(cpid > 0);
ASSERT_EQ(cpid, pid);
ASSERT_TRUE(WIFEXITED(status));
}

void fork_and_waitpid_normal_exit() {
pid_t pid = __llvm_libc::fork();
if (pid == 0)
return; // Just end without any thing special.
ASSERT_TRUE(pid > 0);
int status;
pid_t cpid = __llvm_libc::waitpid(pid, &status, 0);
ASSERT_TRUE(cpid > 0);
ASSERT_EQ(cpid, pid);
ASSERT_TRUE(WIFEXITED(status));
}

void fork_and_wait_signal_exit() {
pid_t pid = __llvm_libc::fork();
if (pid == 0)
Expand All @@ -42,8 +76,41 @@ void fork_and_wait_signal_exit() {
ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);
}

void fork_and_wait4_signal_exit() {
pid_t pid = __llvm_libc::fork();
if (pid == 0)
__llvm_libc::raise(SIGUSR1);
ASSERT_TRUE(pid > 0);
int status;
struct rusage usage;
usage.ru_utime = {0, 0};
usage.ru_stime = {0, 0};
pid_t cpid = __llvm_libc::wait4(pid, &status, 0, &usage);
ASSERT_TRUE(cpid > 0);
ASSERT_EQ(cpid, pid);
ASSERT_FALSE(WIFEXITED(status));
ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);
}

void fork_and_waitpid_signal_exit() {
pid_t pid = __llvm_libc::fork();
if (pid == 0)
__llvm_libc::raise(SIGUSR1);
ASSERT_TRUE(pid > 0);
int status;
pid_t cpid = __llvm_libc::waitpid(pid, &status, 0);
ASSERT_TRUE(cpid > 0);
ASSERT_EQ(cpid, pid);
ASSERT_FALSE(WIFEXITED(status));
ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);
}

TEST_MAIN(int argc, char **argv, char **envp) {
fork_and_wait_normal_exit();
fork_and_wait4_normal_exit();
fork_and_waitpid_normal_exit();
fork_and_wait_signal_exit();
fork_and_wait4_signal_exit();
fork_and_waitpid_signal_exit();
return 0;
}
1 change: 1 addition & 0 deletions libc/test/src/sys/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ add_subdirectory(resource)
add_subdirectory(sendfile)
add_subdirectory(stat)
add_subdirectory(utsname)
add_subdirectory(wait)
25 changes: 25 additions & 0 deletions libc/test/src/sys/wait/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
add_libc_testsuite(libc_sys_wait_unittests)

add_libc_unittest(
waitpid_test
SUITE
libc_sys_stat_unittests
SRCS
waitpid_test.cpp
DEPENDS
libc.include.errno
libc.include.sys_wait
libc.src.sys.wait.waitpid
)

add_libc_unittest(
wait4_test
SUITE
libc_sys_stat_unittests
SRCS
wait4_test.cpp
DEPENDS
libc.include.errno
libc.include.sys_wait
libc.src.sys.wait.wait4
)
23 changes: 23 additions & 0 deletions libc/test/src/sys/wait/wait4_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===-- Unittests for wait4 -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/sys/wait/wait4.h"
#include "test/ErrnoSetterMatcher.h"
#include "utils/UnitTest/Test.h"

#include <errno.h>
#include <sys/wait.h>

// The test here is a simpl test for WNOHANG functionality. For a more
// involved test, look at fork_test.

TEST(LlvmLibcwait4Test, NoHangTest) {
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
int status;
ASSERT_THAT(__llvm_libc::wait4(-1, &status, WNOHANG, nullptr), Fails(ECHILD));
}
23 changes: 23 additions & 0 deletions libc/test/src/sys/wait/waitpid_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===-- Unittests for waitpid ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/sys/wait/waitpid.h"
#include "test/ErrnoSetterMatcher.h"
#include "utils/UnitTest/Test.h"

#include <errno.h>
#include <sys/wait.h>

// The test here is a simpl test for WNOHANG functionality. For a more
// involved test, look at fork_test.

TEST(LlvmLibcWaitPidTest, NoHangTest) {
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
int status;
ASSERT_THAT(__llvm_libc::waitpid(-1, &status, WNOHANG), Fails(ECHILD));
}