diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/ScopedSignalHandler.h | 12 | ||||
-rw-r--r-- | tests/pthread_test.cpp | 59 | ||||
-rw-r--r-- | tests/signal_test.cpp | 101 | ||||
-rw-r--r-- | tests/unistd_test.cpp | 4 |
4 files changed, 154 insertions, 22 deletions
diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h index 3ec23b0d8..3fb60a164 100644 --- a/tests/ScopedSignalHandler.h +++ b/tests/ScopedSignalHandler.h @@ -18,17 +18,27 @@ #define _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H #include <signal.h> +#include <string.h> class ScopedSignalHandler { public: ScopedSignalHandler(int signal_number, void (*handler)(int), int sa_flags = 0) : signal_number_(signal_number) { - sigemptyset(&action_.sa_mask); + memset(&action_, 0, sizeof(action_)); action_.sa_flags = sa_flags; action_.sa_handler = handler; sigaction(signal_number_, &action_, &old_action_); } + ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*), + int sa_flags = SA_SIGINFO) + : signal_number_(signal_number) { + memset(&action_, 0, sizeof(action_)); + action_.sa_flags = sa_flags; + action_.sa_sigaction = action; + sigaction(signal_number_, &action_, &old_action_); + } + ~ScopedSignalHandler() { sigaction(signal_number_, &old_action_, NULL); } diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index 797468efe..f63d1ee93 100644 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -178,17 +178,34 @@ static void* IdFn(void* arg) { return arg; } -static void* SleepFn(void* arg) { - sleep(reinterpret_cast<uintptr_t>(arg)); - return NULL; -} +class SpinFunctionHelper { + public: + SpinFunctionHelper() { + SpinFunctionHelper::spin_flag_ = true; + } + ~SpinFunctionHelper() { + UnSpin(); + } + auto GetFunction() -> void* (*)(void*) { + return SpinFunctionHelper::SpinFn; + } -static void* SpinFn(void* arg) { - volatile bool* b = reinterpret_cast<volatile bool*>(arg); - while (!*b) { + void UnSpin() { + SpinFunctionHelper::spin_flag_ = false; } - return NULL; -} + + private: + static void* SpinFn(void*) { + while (spin_flag_) {} + return NULL; + } + static volatile bool spin_flag_; +}; + +// It doesn't matter if spin_flag_ is used in several tests, +// because it is always set to false after each test. Each thread +// loops on spin_flag_ can find it becomes false at some time. +volatile bool SpinFunctionHelper::spin_flag_ = false; static void* JoinFn(void* arg) { return reinterpret_cast<void*>(pthread_join(reinterpret_cast<pthread_t>(arg), NULL)); @@ -229,8 +246,10 @@ TEST(pthread, pthread_create_EAGAIN) { } TEST(pthread, pthread_no_join_after_detach) { + SpinFunctionHelper spinhelper; + pthread_t t1; - ASSERT_EQ(0, pthread_create(&t1, NULL, SleepFn, reinterpret_cast<void*>(5))); + ASSERT_EQ(0, pthread_create(&t1, NULL, spinhelper.GetFunction(), NULL)); // After a pthread_detach... ASSERT_EQ(0, pthread_detach(t1)); @@ -241,10 +260,10 @@ TEST(pthread, pthread_no_join_after_detach) { } TEST(pthread, pthread_no_op_detach_after_join) { - bool done = false; + SpinFunctionHelper spinhelper; pthread_t t1; - ASSERT_EQ(0, pthread_create(&t1, NULL, SpinFn, &done)); + ASSERT_EQ(0, pthread_create(&t1, NULL, spinhelper.GetFunction(), NULL)); // If thread 2 is already waiting to join thread 1... pthread_t t2; @@ -256,7 +275,7 @@ TEST(pthread, pthread_no_op_detach_after_join) { ASSERT_EQ(0, pthread_detach(t1)); AssertDetached(t1, false); - done = true; + spinhelper.UnSpin(); // ...but t2's join on t1 still goes ahead (which we can tell because our join on t2 finishes). void* join_result; @@ -369,8 +388,10 @@ TEST(pthread, pthread_setname_np__self) { } TEST(pthread, pthread_setname_np__other) { + SpinFunctionHelper spinhelper; + pthread_t t1; - ASSERT_EQ(0, pthread_create(&t1, NULL, SleepFn, reinterpret_cast<void*>(5))); + ASSERT_EQ(0, pthread_create(&t1, NULL, spinhelper.GetFunction(), NULL)); ASSERT_EQ(0, pthread_setname_np(t1, "short 2")); } @@ -451,8 +472,10 @@ TEST(pthread, pthread_detach__leak) { } TEST(pthread, pthread_getcpuclockid__clock_gettime) { + SpinFunctionHelper spinhelper; + pthread_t t; - ASSERT_EQ(0, pthread_create(&t, NULL, SleepFn, reinterpret_cast<void*>(5))); + ASSERT_EQ(0, pthread_create(&t, NULL, spinhelper.GetFunction(), NULL)); clockid_t c; ASSERT_EQ(0, pthread_getcpuclockid(t, &c)); @@ -501,10 +524,10 @@ TEST(pthread, pthread_kill__no_such_thread) { } TEST(pthread, pthread_join__multijoin) { - bool done = false; + SpinFunctionHelper spinhelper; pthread_t t1; - ASSERT_EQ(0, pthread_create(&t1, NULL, SpinFn, &done)); + ASSERT_EQ(0, pthread_create(&t1, NULL, spinhelper.GetFunction(), NULL)); pthread_t t2; ASSERT_EQ(0, pthread_create(&t2, NULL, JoinFn, reinterpret_cast<void*>(t1))); @@ -514,7 +537,7 @@ TEST(pthread, pthread_join__multijoin) { // Multiple joins to the same thread should fail. ASSERT_EQ(EINVAL, pthread_join(t1, NULL)); - done = true; + spinhelper.UnSpin(); // ...but t2's join on t1 still goes ahead (which we can tell because our join on t2 finishes). void* join_result; diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp index 8fd8b72f7..f8fdc3f99 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -16,9 +16,10 @@ #include <signal.h> -#include <errno.h> #include <gtest/gtest.h> +#include <errno.h> + #include "ScopedSignalHandler.h" static size_t SIGNAL_MIN() { @@ -276,3 +277,101 @@ TEST(signal, limits) { // We don't currently reserve any at the top. ASSERT_EQ(SIGRTMAX, __SIGRTMAX); } + +static int g_sigqueue_signal_handler_call_count = 0; + +static void SigqueueSignalHandler(int signum, siginfo_t* info, void*) { + ASSERT_EQ(SIGALRM, signum); + ASSERT_EQ(SIGALRM, info->si_signo); + ASSERT_EQ(SI_QUEUE, info->si_code); + ASSERT_EQ(1, info->si_value.sival_int); + ++g_sigqueue_signal_handler_call_count; +} + +TEST(signal, sigqueue) { + ScopedSignalHandler ssh(SIGALRM, SigqueueSignalHandler, SA_SIGINFO); + sigval_t sigval; + sigval.sival_int = 1; + errno = 0; + ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); + ASSERT_EQ(0, errno); + ASSERT_EQ(1, g_sigqueue_signal_handler_call_count); +} + +TEST(signal, sigwaitinfo) { + // Block SIGALRM. + sigset_t just_SIGALRM; + sigemptyset(&just_SIGALRM); + sigaddset(&just_SIGALRM, SIGALRM); + sigset_t original_set; + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); + + // Raise SIGALRM. + sigval_t sigval; + sigval.sival_int = 1; + ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); + + // Get pending SIGALRM. + siginfo_t info; + errno = 0; + ASSERT_EQ(SIGALRM, sigwaitinfo(&just_SIGALRM, &info)); + ASSERT_EQ(0, errno); + ASSERT_EQ(SIGALRM, info.si_signo); + ASSERT_EQ(1, info.si_value.sival_int); + + ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); +} + +TEST(signal, sigtimedwait) { + // Block SIGALRM. + sigset_t just_SIGALRM; + sigemptyset(&just_SIGALRM); + sigaddset(&just_SIGALRM, SIGALRM); + sigset_t original_set; + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); + + // Raise SIGALRM. + sigval_t sigval; + sigval.sival_int = 1; + ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); + + // Get pending SIGALRM. + siginfo_t info; + struct timespec timeout; + timeout.tv_sec = 2; + timeout.tv_nsec = 0; + errno = 0; + ASSERT_EQ(SIGALRM, sigtimedwait(&just_SIGALRM, &info, &timeout)); + ASSERT_EQ(0, errno); + + ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); +} + +static int64_t NanoTime() { + struct timespec t; + t.tv_sec = t.tv_nsec = 0; + clock_gettime(CLOCK_MONOTONIC, &t); + return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec; +} + +TEST(signal, sigtimedwait_timeout) { + // Block SIGALRM. + sigset_t just_SIGALRM; + sigemptyset(&just_SIGALRM); + sigaddset(&just_SIGALRM, SIGALRM); + sigset_t original_set; + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); + + // Wait timeout. + int64_t start_time = NanoTime(); + siginfo_t info; + struct timespec timeout; + timeout.tv_sec = 0; + timeout.tv_nsec = 1000000; + errno = 0; + ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout)); + ASSERT_EQ(EAGAIN, errno); + ASSERT_GE(NanoTime() - start_time, 1000000); + + ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); +} diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp index f0aeb09c9..433c1b501 100644 --- a/tests/unistd_test.cpp +++ b/tests/unistd_test.cpp @@ -554,6 +554,7 @@ TEST(unistd, _POSIX_macros_smoke) { EXPECT_EQ(_POSIX_VERSION, _POSIX_PRIORITY_SCHEDULING); EXPECT_EQ(_POSIX_VERSION, _POSIX_RAW_SOCKETS); EXPECT_EQ(_POSIX_VERSION, _POSIX_READER_WRITER_LOCKS); + EXPECT_EQ(_POSIX_VERSION, _POSIX_REALTIME_SIGNALS); EXPECT_GT(_POSIX_REGEXP, 0); EXPECT_GT(_POSIX_RE_DUP_MAX, 0); EXPECT_GT(_POSIX_SAVED_IDS, 0); @@ -617,7 +618,6 @@ TEST(unistd, _POSIX_macros_smoke) { EXPECT_EQ(-1, _POSIX_CPUTIME); EXPECT_EQ(-1, _POSIX_MESSAGE_PASSING); EXPECT_EQ(-1, _POSIX_PRIORITIZED_IO); - EXPECT_EQ(-1, _POSIX_REALTIME_SIGNALS); EXPECT_EQ(-1, _POSIX_SHARED_MEMORY_OBJECTS); EXPECT_EQ(-1, _POSIX_SPAWN); EXPECT_EQ(-1, _POSIX_SPIN_LOCKS); @@ -702,6 +702,7 @@ TEST(unistd, sysconf) { VERIFY_SYSCONF_POSIX_VERSION(_SC_MEMLOCK_RANGE); VERIFY_SYSCONF_POSIX_VERSION(_SC_MEMORY_PROTECTION); VERIFY_SYSCONF_POSIX_VERSION(_SC_PRIORITY_SCHEDULING); + VERIFY_SYSCONF_POSIX_VERSION(_SC_REALTIME_SIGNALS); VERIFY_SYSCONF_POSIX_VERSION(_SC_SEMAPHORES); VERIFY_SYSCONF_POSIX_VERSION(_SC_SYNCHRONIZED_IO); VERIFY_SYSCONF_POSIX_VERSION(_SC_TIMERS); @@ -778,7 +779,6 @@ TEST(unistd, sysconf) { VERIFY_SYSCONF_NOT_SUPPORT(_SC_CPUTIME); VERIFY_SYSCONF_NOT_SUPPORT(_SC_MESSAGE_PASSING); VERIFY_SYSCONF_NOT_SUPPORT(_SC_PRIORITIZED_IO); - VERIFY_SYSCONF_NOT_SUPPORT(_SC_REALTIME_SIGNALS); VERIFY_SYSCONF_NOT_SUPPORT(_SC_SHARED_MEMORY_OBJECTS); VERIFY_SYSCONF_NOT_SUPPORT(_SC_SPAWN); VERIFY_SYSCONF_NOT_SUPPORT(_SC_SPIN_LOCKS); |