blob: ca1c8701ef4af09ed3597b3165d7d2a831bbf607 [file] [log] [blame]
Benjamin Lerman21c7e372014-07-10 14:20:27 +02001// 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 "chromeos/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/at_exit.h>
Benjamin Lerman21c7e372014-07-10 14:20:27 +020014#include <base/bind.h>
Alex Vakulenkof2418e52014-09-04 08:26:42 -070015#include <base/macros.h>
Benjamin Lerman21c7e372014-07-10 14:20:27 +020016#include <base/message_loop/message_loop.h>
17#include <base/run_loop.h>
18#include <gtest/gtest.h>
19
20namespace chromeos {
21
22class AsynchronousSignalHandlerTest : public ::testing::Test {
23 public:
24 AsynchronousSignalHandlerTest() {}
25 virtual ~AsynchronousSignalHandlerTest() {}
26
27 virtual void SetUp() {
28 handler_.Init();
29 }
30
31 virtual void TearDown() {}
32
33 bool RecordInfoAndQuit(bool response, const struct signalfd_siginfo& info) {
34 infos_.push_back(info);
35 loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
36 return response;
37 }
38
39 void Run() {
40 base::RunLoop run_loop;
41 run_loop.Run();
42 }
43
44 protected:
45 base::AtExitManager at_exit_;
46 base::MessageLoopForIO loop_;
47 std::vector<struct signalfd_siginfo> infos_;
48 AsynchronousSignalHandler handler_;
49
50 private:
51 DISALLOW_COPY_AND_ASSIGN(AsynchronousSignalHandlerTest);
52};
53
54TEST_F(AsynchronousSignalHandlerTest, CheckTerm) {
55 handler_.RegisterHandler(
56 SIGTERM, base::Bind(&AsynchronousSignalHandlerTest::RecordInfoAndQuit,
57 base::Unretained(this), true));
58 EXPECT_EQ(0, infos_.size());
59 EXPECT_EQ(0, kill(getpid(), SIGTERM));
60
61 // Spin the message loop.
62 Run();
63
64 ASSERT_EQ(1, infos_.size());
65 EXPECT_EQ(SIGTERM, infos_[0].ssi_signo);
66}
67
68TEST_F(AsynchronousSignalHandlerTest, CheckSignalUnregistration) {
69 handler_.RegisterHandler(
70 SIGCHLD, base::Bind(&AsynchronousSignalHandlerTest::RecordInfoAndQuit,
71 base::Unretained(this), true));
72 EXPECT_EQ(0, infos_.size());
73 EXPECT_EQ(0, kill(getpid(), SIGCHLD));
74
75 // Spin the message loop.
76 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 loop_.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
85 base::TimeDelta::FromMilliseconds(10));
86 Run();
87
88 // The signal handle should have been unregistered. No new message are
89 // expected.
90 EXPECT_EQ(1, infos_.size());
91}
92
93TEST_F(AsynchronousSignalHandlerTest, CheckMultipleSignal) {
94 const uint8_t NB_SIGNALS = 5;
95 handler_.RegisterHandler(
96 SIGCHLD, base::Bind(&AsynchronousSignalHandlerTest::RecordInfoAndQuit,
97 base::Unretained(this), false));
98 EXPECT_EQ(0, infos_.size());
99 for (int i = 0; i < NB_SIGNALS; ++i) {
100 EXPECT_EQ(0, kill(getpid(), SIGCHLD));
101
102 // Spin the message loop.
103 Run();
104 }
105
106 ASSERT_EQ(NB_SIGNALS, infos_.size());
107 for (int i = 0; i < NB_SIGNALS; ++i) {
108 EXPECT_EQ(SIGCHLD, infos_[i].ssi_signo);
109 }
110}
111
112TEST_F(AsynchronousSignalHandlerTest, CheckChld) {
113 handler_.RegisterHandler(
114 SIGCHLD, base::Bind(&AsynchronousSignalHandlerTest::RecordInfoAndQuit,
115 base::Unretained(this), false));
116 pid_t child_pid = fork();
117 if (child_pid == 0) {
118 _Exit(EXIT_SUCCESS);
119 }
120
121 EXPECT_EQ(0, infos_.size());
122 // Spin the message loop.
123 Run();
124
125 ASSERT_EQ(1, infos_.size());
126 EXPECT_EQ(SIGCHLD, infos_[0].ssi_signo);
127 EXPECT_EQ(child_pid, infos_[0].ssi_pid);
128 EXPECT_EQ(static_cast<int>(CLD_EXITED), infos_[0].ssi_code);
129 EXPECT_EQ(EXIT_SUCCESS, infos_[0].ssi_status);
130}
131
132} // namespace chromeos