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