• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
AsynchronousSignalHandlerTest()24   AsynchronousSignalHandlerTest() {}
~AsynchronousSignalHandlerTest()25   virtual ~AsynchronousSignalHandlerTest() {}
26 
SetUp()27   virtual void SetUp() {
28     brillo_loop_.SetAsCurrent();
29     handler_.Init();
30   }
31 
TearDown()32   virtual void TearDown() {}
33 
RecordInfoAndQuit(bool response,const struct signalfd_siginfo & info)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 
TEST_F(AsynchronousSignalHandlerTest,CheckTerm)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 
TEST_F(AsynchronousSignalHandlerTest,CheckSignalUnregistration)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 
TEST_F(AsynchronousSignalHandlerTest,CheckMultipleSignal)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 
TEST_F(AsynchronousSignalHandlerTest,CheckChld)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