Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <gtest/gtest.h>
     18 
     19 #include <errno.h>
     20 #include <signal.h>
     21 
     22 template <typename Fn>
     23 static void TestSigSet1(Fn fn) {
     24   // NULL sigset_t*.
     25   sigset_t* set_ptr = NULL;
     26   errno = 0;
     27   ASSERT_EQ(-1, fn(set_ptr));
     28   ASSERT_EQ(EINVAL, errno);
     29 
     30   // Non-NULL.
     31   sigset_t set;
     32   errno = 0;
     33   ASSERT_EQ(0, fn(&set));
     34   ASSERT_EQ(0, errno);
     35 }
     36 
     37 template <typename Fn>
     38 static void TestSigSet2(Fn fn) {
     39   // NULL sigset_t*.
     40   sigset_t* set_ptr = NULL;
     41   errno = 0;
     42   ASSERT_EQ(-1, fn(set_ptr, SIGSEGV));
     43   ASSERT_EQ(EINVAL, errno);
     44 
     45   sigset_t set;
     46   sigemptyset(&set);
     47 
     48   int min_signal = SIGHUP;
     49   int max_signal = SIGRTMAX;
     50 
     51 #if defined(__BIONIC__) && !defined(__mips__)
     52   // bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64.
     53   // This means you can't refer to any of the real-time signals.
     54   // See http://b/3038348 and http://b/5828899.
     55   max_signal = 32;
     56 #else
     57   // Other C libraries (or bionic for MIPS) are perfectly capable of using their largest signal.
     58   ASSERT_GE(sizeof(sigset_t) * 8, static_cast<size_t>(SIGRTMAX));
     59 #endif
     60 
     61   // Bad signal number: too small.
     62   errno = 0;
     63   ASSERT_EQ(-1, fn(&set, 0));
     64   ASSERT_EQ(EINVAL, errno);
     65 
     66   // Bad signal number: too high.
     67   errno = 0;
     68   ASSERT_EQ(-1, fn(&set, max_signal + 1));
     69   ASSERT_EQ(EINVAL, errno);
     70 
     71   // Good signal numbers, low and high ends of range.
     72   errno = 0;
     73   ASSERT_EQ(0, fn(&set, min_signal));
     74   ASSERT_EQ(0, errno);
     75   ASSERT_EQ(0, fn(&set, max_signal));
     76   ASSERT_EQ(0, errno);
     77 }
     78 
     79 class ScopedSignalHandler {
     80  public:
     81   ScopedSignalHandler(int signal_number, void (*handler)(int)) : signal_number_(signal_number) {
     82     sigemptyset(&action_.sa_mask);
     83     action_.sa_flags = 0;
     84     action_.sa_handler = handler;
     85     sigaction(signal_number_, &action_, &old_action_);
     86   }
     87 
     88   ~ScopedSignalHandler() {
     89     sigaction(signal_number_, &old_action_, NULL);
     90   }
     91 
     92  private:
     93   struct sigaction action_;
     94   struct sigaction old_action_;
     95   const int signal_number_;
     96 };
     97 
     98 TEST(signal, sigismember_invalid) {
     99   TestSigSet2(sigismember);
    100 }
    101 
    102 TEST(signal, sigaddset_invalid) {
    103   TestSigSet2(sigaddset);
    104 }
    105 
    106 TEST(signal, sigdelset_invalid) {
    107   TestSigSet2(sigdelset);
    108 }
    109 
    110 TEST(signal, sigemptyset_invalid) {
    111   TestSigSet1(sigemptyset);
    112 }
    113 
    114 TEST(signal, sigfillset_invalid) {
    115   TestSigSet1(sigfillset);
    116 }
    117 
    118 TEST(signal, raise_invalid) {
    119   errno = 0;
    120   ASSERT_EQ(-1, raise(-1));
    121   ASSERT_EQ(EINVAL, errno);
    122 }
    123 
    124 static void raise_in_signal_handler_helper(int signal_number) {
    125   ASSERT_EQ(SIGALRM, signal_number);
    126   static int count = 0;
    127   if (++count == 1) {
    128     raise(SIGALRM);
    129   }
    130 }
    131 
    132 TEST(signal, raise_in_signal_handler) {
    133   ScopedSignalHandler ssh(SIGALRM, raise_in_signal_handler_helper);
    134   raise(SIGALRM);
    135 }
    136 
    137 static void HandleSIGALRM(int signal_number) {
    138   ASSERT_EQ(SIGALRM, signal_number);
    139 }
    140 
    141 TEST(signal, sigwait) {
    142   ScopedSignalHandler ssh(SIGALRM, HandleSIGALRM);
    143 
    144   sigset_t wait_set;
    145   sigemptyset(&wait_set);
    146   sigaddset(&wait_set, SIGALRM);
    147 
    148   alarm(1);
    149 
    150   int received_signal;
    151   errno = 0;
    152   ASSERT_EQ(0, sigwait(&wait_set, &received_signal));
    153   ASSERT_EQ(0, errno);
    154   ASSERT_EQ(SIGALRM, received_signal);
    155 }
    156