xref: /openbmc/sdeventplus/test/source/child.cpp (revision b53ef902)
1571fdf9eSWilliam A. Kennington III #include <cerrno>
2571fdf9eSWilliam A. Kennington III #include <functional>
3571fdf9eSWilliam A. Kennington III #include <gmock/gmock.h>
4571fdf9eSWilliam A. Kennington III #include <gtest/gtest.h>
5571fdf9eSWilliam A. Kennington III #include <memory>
6571fdf9eSWilliam A. Kennington III #include <sdeventplus/event.hpp>
7571fdf9eSWilliam A. Kennington III #include <sdeventplus/exception.hpp>
8571fdf9eSWilliam A. Kennington III #include <sdeventplus/source/child.hpp>
9571fdf9eSWilliam A. Kennington III #include <sdeventplus/test/sdevent.hpp>
10571fdf9eSWilliam A. Kennington III #include <sys/wait.h>
11571fdf9eSWilliam A. Kennington III #include <systemd/sd-event.h>
12571fdf9eSWilliam A. Kennington III #include <type_traits>
13571fdf9eSWilliam A. Kennington III #include <utility>
14571fdf9eSWilliam A. Kennington III 
15571fdf9eSWilliam A. Kennington III namespace sdeventplus
16571fdf9eSWilliam A. Kennington III {
17571fdf9eSWilliam A. Kennington III namespace source
18571fdf9eSWilliam A. Kennington III {
19571fdf9eSWilliam A. Kennington III namespace
20571fdf9eSWilliam A. Kennington III {
21571fdf9eSWilliam A. Kennington III 
22571fdf9eSWilliam A. Kennington III using testing::DoAll;
23571fdf9eSWilliam A. Kennington III using testing::Return;
24571fdf9eSWilliam A. Kennington III using testing::SaveArg;
25571fdf9eSWilliam A. Kennington III using testing::SetArgPointee;
26571fdf9eSWilliam A. Kennington III 
27571fdf9eSWilliam A. Kennington III using UniqueEvent = std::unique_ptr<Event, std::function<void(Event*)>>;
28571fdf9eSWilliam A. Kennington III 
29571fdf9eSWilliam A. Kennington III class ChildTest : public testing::Test
30571fdf9eSWilliam A. Kennington III {
31571fdf9eSWilliam A. Kennington III   protected:
32571fdf9eSWilliam A. Kennington III     testing::StrictMock<test::SdEventMock> mock;
33571fdf9eSWilliam A. Kennington III     sd_event_source* const expected_source =
34571fdf9eSWilliam A. Kennington III         reinterpret_cast<sd_event_source*>(1234);
35571fdf9eSWilliam A. Kennington III     sd_event* const expected_event = reinterpret_cast<sd_event*>(2345);
36571fdf9eSWilliam A. Kennington III     UniqueEvent event = make_event(expected_event);
37571fdf9eSWilliam A. Kennington III 
38571fdf9eSWilliam A. Kennington III     UniqueEvent make_event(sd_event* event)
39571fdf9eSWilliam A. Kennington III     {
40571fdf9eSWilliam A. Kennington III         auto deleter = [this, event](Event* e) {
41571fdf9eSWilliam A. Kennington III             EXPECT_CALL(this->mock, sd_event_unref(event))
42571fdf9eSWilliam A. Kennington III                 .WillOnce(Return(nullptr));
43571fdf9eSWilliam A. Kennington III             delete e;
44571fdf9eSWilliam A. Kennington III         };
45571fdf9eSWilliam A. Kennington III         return UniqueEvent(new Event(event, std::false_type(), &mock), deleter);
46571fdf9eSWilliam A. Kennington III     }
47571fdf9eSWilliam A. Kennington III 
48571fdf9eSWilliam A. Kennington III     void expect_destruct()
49571fdf9eSWilliam A. Kennington III     {
50571fdf9eSWilliam A. Kennington III         {
51571fdf9eSWilliam A. Kennington III             testing::InSequence sequence;
52571fdf9eSWilliam A. Kennington III             EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source,
53571fdf9eSWilliam A. Kennington III                                                           SD_EVENT_OFF))
54571fdf9eSWilliam A. Kennington III                 .WillOnce(Return(0));
55571fdf9eSWilliam A. Kennington III             EXPECT_CALL(mock, sd_event_source_unref(expected_source))
56571fdf9eSWilliam A. Kennington III                 .WillOnce(Return(nullptr));
57571fdf9eSWilliam A. Kennington III         }
58571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_unref(expected_event))
59571fdf9eSWilliam A. Kennington III             .WillOnce(Return(nullptr));
60571fdf9eSWilliam A. Kennington III     }
61571fdf9eSWilliam A. Kennington III };
62571fdf9eSWilliam A. Kennington III 
63571fdf9eSWilliam A. Kennington III TEST_F(ChildTest, ConstructSuccess)
64571fdf9eSWilliam A. Kennington III {
65571fdf9eSWilliam A. Kennington III     const pid_t pid = 50;
66571fdf9eSWilliam A. Kennington III     const int options = WEXITED;
67571fdf9eSWilliam A. Kennington III 
68571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_ref(expected_event))
69571fdf9eSWilliam A. Kennington III         .WillOnce(Return(expected_event));
70571fdf9eSWilliam A. Kennington III     sd_event_child_handler_t handler;
71571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
72571fdf9eSWilliam A. Kennington III                                          options, testing::_, nullptr))
73571fdf9eSWilliam A. Kennington III         .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<4>(&handler),
74571fdf9eSWilliam A. Kennington III                         Return(0)));
75571fdf9eSWilliam A. Kennington III     void* userdata;
76571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
77571fdf9eSWilliam A. Kennington III         .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
78571fdf9eSWilliam A. Kennington III     int completions = 0;
79571fdf9eSWilliam A. Kennington III     const siginfo_t* return_si;
80571fdf9eSWilliam A. Kennington III     Child::Callback callback = [&](Child&, const siginfo_t* si) {
81571fdf9eSWilliam A. Kennington III         return_si = si;
82571fdf9eSWilliam A. Kennington III         completions++;
83571fdf9eSWilliam A. Kennington III     };
84571fdf9eSWilliam A. Kennington III     Child child(*event, pid, options, std::move(callback));
85571fdf9eSWilliam A. Kennington III     EXPECT_FALSE(callback);
86571fdf9eSWilliam A. Kennington III     EXPECT_EQ(&child, userdata);
87571fdf9eSWilliam A. Kennington III     EXPECT_EQ(0, completions);
88571fdf9eSWilliam A. Kennington III 
89571fdf9eSWilliam A. Kennington III     const siginfo_t* expected_si = reinterpret_cast<siginfo_t*>(865);
90571fdf9eSWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, expected_si, &child));
91571fdf9eSWilliam A. Kennington III     EXPECT_EQ(1, completions);
92571fdf9eSWilliam A. Kennington III     EXPECT_EQ(expected_si, return_si);
93571fdf9eSWilliam A. Kennington III 
94*b53ef902SWilliam A. Kennington III     child.set_callback(std::bind([]() {}));
95*b53ef902SWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, expected_si, &child));
96*b53ef902SWilliam A. Kennington III     EXPECT_EQ(1, completions);
97*b53ef902SWilliam A. Kennington III 
98571fdf9eSWilliam A. Kennington III     expect_destruct();
99571fdf9eSWilliam A. Kennington III }
100571fdf9eSWilliam A. Kennington III 
101571fdf9eSWilliam A. Kennington III TEST_F(ChildTest, ConstructError)
102571fdf9eSWilliam A. Kennington III {
103571fdf9eSWilliam A. Kennington III     const pid_t pid = 50;
104571fdf9eSWilliam A. Kennington III     const int options = WEXITED;
105571fdf9eSWilliam A. Kennington III 
106571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
107571fdf9eSWilliam A. Kennington III                                          options, testing::_, nullptr))
108571fdf9eSWilliam A. Kennington III         .WillOnce(Return(-EINVAL));
109571fdf9eSWilliam A. Kennington III     int completions = 0;
110571fdf9eSWilliam A. Kennington III     Child::Callback callback = [&completions](Child&, const siginfo_t*) {
111571fdf9eSWilliam A. Kennington III         completions++;
112571fdf9eSWilliam A. Kennington III     };
113571fdf9eSWilliam A. Kennington III     EXPECT_THROW(Child(*event, pid, options, std::move(callback)),
114571fdf9eSWilliam A. Kennington III                  SdEventError);
115571fdf9eSWilliam A. Kennington III     EXPECT_TRUE(callback);
116571fdf9eSWilliam A. Kennington III     EXPECT_EQ(0, completions);
117571fdf9eSWilliam A. Kennington III }
118571fdf9eSWilliam A. Kennington III 
119571fdf9eSWilliam A. Kennington III class ChildMethodTest : public ChildTest
120571fdf9eSWilliam A. Kennington III {
121571fdf9eSWilliam A. Kennington III   protected:
122571fdf9eSWilliam A. Kennington III     std::unique_ptr<Child> child;
123571fdf9eSWilliam A. Kennington III 
124571fdf9eSWilliam A. Kennington III     void SetUp()
125571fdf9eSWilliam A. Kennington III     {
126571fdf9eSWilliam A. Kennington III         const pid_t pid = 50;
127571fdf9eSWilliam A. Kennington III         const int options = WEXITED;
128571fdf9eSWilliam A. Kennington III 
129571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_ref(expected_event))
130571fdf9eSWilliam A. Kennington III             .WillOnce(Return(expected_event));
131571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
132571fdf9eSWilliam A. Kennington III                                              options, testing::_, nullptr))
133571fdf9eSWilliam A. Kennington III             .WillOnce(DoAll(SetArgPointee<1>(expected_source), Return(0)));
134571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock,
135571fdf9eSWilliam A. Kennington III                     sd_event_source_set_userdata(expected_source, testing::_))
136571fdf9eSWilliam A. Kennington III             .WillOnce(Return(nullptr));
137571fdf9eSWilliam A. Kennington III         child = std::make_unique<Child>(*event, pid, options,
138571fdf9eSWilliam A. Kennington III                                         [](Child&, const siginfo_t*) {});
139571fdf9eSWilliam A. Kennington III     }
140571fdf9eSWilliam A. Kennington III 
141571fdf9eSWilliam A. Kennington III     void TearDown()
142571fdf9eSWilliam A. Kennington III     {
143571fdf9eSWilliam A. Kennington III         expect_destruct();
144571fdf9eSWilliam A. Kennington III         child.reset();
145571fdf9eSWilliam A. Kennington III     }
146571fdf9eSWilliam A. Kennington III };
147571fdf9eSWilliam A. Kennington III 
148571fdf9eSWilliam A. Kennington III TEST_F(ChildMethodTest, GetPidSuccess)
149571fdf9eSWilliam A. Kennington III {
150571fdf9eSWilliam A. Kennington III     const pid_t pid = 32;
151571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock,
152571fdf9eSWilliam A. Kennington III                 sd_event_source_get_child_pid(expected_source, testing::_))
153571fdf9eSWilliam A. Kennington III         .WillOnce(DoAll(SetArgPointee<1>(pid), Return(0)));
154571fdf9eSWilliam A. Kennington III     EXPECT_EQ(pid, child->get_pid());
155571fdf9eSWilliam A. Kennington III }
156571fdf9eSWilliam A. Kennington III 
157571fdf9eSWilliam A. Kennington III TEST_F(ChildMethodTest, GetPidError)
158571fdf9eSWilliam A. Kennington III {
159571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock,
160571fdf9eSWilliam A. Kennington III                 sd_event_source_get_child_pid(expected_source, testing::_))
161571fdf9eSWilliam A. Kennington III         .WillOnce(Return(-EINVAL));
162571fdf9eSWilliam A. Kennington III     EXPECT_THROW(child->get_pid(), SdEventError);
163571fdf9eSWilliam A. Kennington III }
164571fdf9eSWilliam A. Kennington III 
165571fdf9eSWilliam A. Kennington III } // namespace
166571fdf9eSWilliam A. Kennington III } // namespace source
167571fdf9eSWilliam A. Kennington III } // namespace sdeventplus
168