Home | History | Annotate | Download | only in brillo
      1 // Copyright 2014 The Chromium OS Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "brillo/asynchronous_signal_handler.h"
      6 
      7 #include <signal.h>
      8 #include <sys/types.h>
      9 #include <unistd.h>
     10 
     11 #include <vector>
     12 
     13 #include <base/bind.h>
     14 #include <base/macros.h>
     15 #include <base/message_loop/message_loop.h>
     16 #include <base/run_loop.h>
     17 #include <brillo/message_loops/base_message_loop.h>
     18 #include <gtest/gtest.h>
     19 
     20 namespace brillo {
     21 
     22 class AsynchronousSignalHandlerTest : public ::testing::Test {
     23  public:
     24   AsynchronousSignalHandlerTest() {}
     25   virtual ~AsynchronousSignalHandlerTest() {}
     26 
     27   virtual void SetUp() {
     28     brillo_loop_.SetAsCurrent();
     29     handler_.Init();
     30   }
     31 
     32   virtual void TearDown() {}
     33 
     34   bool RecordInfoAndQuit(bool response, const struct signalfd_siginfo& info) {
     35     infos_.push_back(info);
     36     brillo_loop_.PostTask(FROM_HERE, brillo_loop_.QuitClosure());
     37     return response;
     38   }
     39 
     40  protected:
     41   base::MessageLoopForIO base_loop_;
     42   BaseMessageLoop brillo_loop_{&base_loop_};
     43   std::vector<struct signalfd_siginfo> infos_;
     44   AsynchronousSignalHandler handler_;
     45 
     46  private:
     47   DISALLOW_COPY_AND_ASSIGN(AsynchronousSignalHandlerTest);
     48 };
     49 
     50 TEST_F(AsynchronousSignalHandlerTest, CheckTerm) {
     51   handler_.RegisterHandler(
     52       SIGTERM,
     53       base::Bind(&AsynchronousSignalHandlerTest::RecordInfoAndQuit,
     54                  base::Unretained(this),
     55                  true));
     56   EXPECT_EQ(0, infos_.size());
     57   EXPECT_EQ(0, kill(getpid(), SIGTERM));
     58 
     59   // Spin the message loop.
     60   MessageLoop::current()->Run();
     61 
     62   ASSERT_EQ(1, infos_.size());
     63   EXPECT_EQ(SIGTERM, infos_[0].ssi_signo);
     64 }
     65 
     66 TEST_F(AsynchronousSignalHandlerTest, CheckSignalUnregistration) {
     67   handler_.RegisterHandler(
     68       SIGCHLD,
     69       base::Bind(&AsynchronousSignalHandlerTest::RecordInfoAndQuit,
     70                  base::Unretained(this),
     71                  true));
     72   EXPECT_EQ(0, infos_.size());
     73   EXPECT_EQ(0, kill(getpid(), SIGCHLD));
     74 
     75   // Spin the message loop.
     76   MessageLoop::current()->Run();
     77 
     78   ASSERT_EQ(1, infos_.size());
     79   EXPECT_EQ(SIGCHLD, infos_[0].ssi_signo);
     80 
     81   EXPECT_EQ(0, kill(getpid(), SIGCHLD));
     82 
     83   // Run the loop with a timeout, as no message are expected.
     84   brillo_loop_.PostDelayedTask(FROM_HERE,
     85                                base::Bind(&MessageLoop::BreakLoop,
     86                                           base::Unretained(&brillo_loop_)),
     87                                base::TimeDelta::FromMilliseconds(10));
     88   MessageLoop::current()->Run();
     89 
     90   // The signal handle should have been unregistered. No new message are
     91   // expected.
     92   EXPECT_EQ(1, infos_.size());
     93 }
     94 
     95 TEST_F(AsynchronousSignalHandlerTest, CheckMultipleSignal) {
     96   const uint8_t NB_SIGNALS = 5;
     97   handler_.RegisterHandler(
     98       SIGCHLD,
     99       base::Bind(&AsynchronousSignalHandlerTest::RecordInfoAndQuit,
    100                  base::Unretained(this),
    101                  false));
    102   EXPECT_EQ(0, infos_.size());
    103   for (int i = 0; i < NB_SIGNALS; ++i) {
    104     EXPECT_EQ(0, kill(getpid(), SIGCHLD));
    105 
    106     // Spin the message loop.
    107     MessageLoop::current()->Run();
    108   }
    109 
    110   ASSERT_EQ(NB_SIGNALS, infos_.size());
    111   for (int i = 0; i < NB_SIGNALS; ++i) {
    112     EXPECT_EQ(SIGCHLD, infos_[i].ssi_signo);
    113   }
    114 }
    115 
    116 TEST_F(AsynchronousSignalHandlerTest, CheckChld) {
    117   handler_.RegisterHandler(
    118       SIGCHLD,
    119       base::Bind(&AsynchronousSignalHandlerTest::RecordInfoAndQuit,
    120                  base::Unretained(this),
    121                  false));
    122   pid_t child_pid = fork();
    123   if (child_pid == 0) {
    124     _Exit(EXIT_SUCCESS);
    125   }
    126 
    127   EXPECT_EQ(0, infos_.size());
    128   // Spin the message loop.
    129   MessageLoop::current()->Run();
    130 
    131   ASSERT_EQ(1, infos_.size());
    132   EXPECT_EQ(SIGCHLD, infos_[0].ssi_signo);
    133   EXPECT_EQ(child_pid, infos_[0].ssi_pid);
    134   EXPECT_EQ(static_cast<int>(CLD_EXITED), infos_[0].ssi_code);
    135   EXPECT_EQ(EXIT_SUCCESS, infos_[0].ssi_status);
    136 }
    137 
    138 }  // namespace brillo
    139