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