xref: /openbmc/sdeventplus/test/source/child.cpp (revision 56dc78ba)
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;
245320b1f5SWilliam A. Kennington III using testing::ReturnPointee;
25571fdf9eSWilliam A. Kennington III using testing::SaveArg;
26571fdf9eSWilliam A. Kennington III using testing::SetArgPointee;
27571fdf9eSWilliam A. Kennington III 
28571fdf9eSWilliam A. Kennington III using UniqueEvent = std::unique_ptr<Event, std::function<void(Event*)>>;
29571fdf9eSWilliam A. Kennington III 
30571fdf9eSWilliam A. Kennington III class ChildTest : public testing::Test
31571fdf9eSWilliam A. Kennington III {
32571fdf9eSWilliam A. Kennington III   protected:
33571fdf9eSWilliam A. Kennington III     testing::StrictMock<test::SdEventMock> mock;
34571fdf9eSWilliam A. Kennington III     sd_event_source* const expected_source =
35571fdf9eSWilliam A. Kennington III         reinterpret_cast<sd_event_source*>(1234);
36571fdf9eSWilliam A. Kennington III     sd_event* const expected_event = reinterpret_cast<sd_event*>(2345);
37571fdf9eSWilliam A. Kennington III     UniqueEvent event = make_event(expected_event);
38571fdf9eSWilliam A. Kennington III 
39571fdf9eSWilliam A. Kennington III     UniqueEvent make_event(sd_event* event)
40571fdf9eSWilliam A. Kennington III     {
41571fdf9eSWilliam A. Kennington III         auto deleter = [this, event](Event* e) {
42571fdf9eSWilliam A. Kennington III             EXPECT_CALL(this->mock, sd_event_unref(event))
43571fdf9eSWilliam A. Kennington III                 .WillOnce(Return(nullptr));
44571fdf9eSWilliam A. Kennington III             delete e;
45571fdf9eSWilliam A. Kennington III         };
46571fdf9eSWilliam A. Kennington III         return UniqueEvent(new Event(event, std::false_type(), &mock), deleter);
47571fdf9eSWilliam A. Kennington III     }
48571fdf9eSWilliam A. Kennington III 
49571fdf9eSWilliam A. Kennington III     void expect_destruct()
50571fdf9eSWilliam A. Kennington III     {
51571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_unref(expected_source))
52571fdf9eSWilliam A. Kennington III             .WillOnce(Return(nullptr));
53571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_unref(expected_event))
54571fdf9eSWilliam A. Kennington III             .WillOnce(Return(nullptr));
55571fdf9eSWilliam A. Kennington III     }
56571fdf9eSWilliam A. Kennington III };
57571fdf9eSWilliam A. Kennington III 
58571fdf9eSWilliam A. Kennington III TEST_F(ChildTest, ConstructSuccess)
59571fdf9eSWilliam A. Kennington III {
60571fdf9eSWilliam A. Kennington III     const pid_t pid = 50;
61571fdf9eSWilliam A. Kennington III     const int options = WEXITED;
62571fdf9eSWilliam A. Kennington III 
63571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_ref(expected_event))
64571fdf9eSWilliam A. Kennington III         .WillOnce(Return(expected_event));
65571fdf9eSWilliam A. Kennington III     sd_event_child_handler_t handler;
66571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
67571fdf9eSWilliam A. Kennington III                                          options, testing::_, nullptr))
68571fdf9eSWilliam A. Kennington III         .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<4>(&handler),
69571fdf9eSWilliam A. Kennington III                         Return(0)));
705320b1f5SWilliam A. Kennington III     sd_event_destroy_t destroy;
71571fdf9eSWilliam A. Kennington III     void* userdata;
725320b1f5SWilliam A. Kennington III     {
735320b1f5SWilliam A. Kennington III         testing::InSequence seq;
745320b1f5SWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
755320b1f5SWilliam A. Kennington III                                                                testing::_))
765320b1f5SWilliam A. Kennington III             .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
775320b1f5SWilliam A. Kennington III         EXPECT_CALL(mock,
785320b1f5SWilliam A. Kennington III                     sd_event_source_set_userdata(expected_source, testing::_))
79571fdf9eSWilliam A. Kennington III             .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
805320b1f5SWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
815320b1f5SWilliam A. Kennington III             .WillRepeatedly(ReturnPointee(&userdata));
825320b1f5SWilliam A. Kennington III     }
83571fdf9eSWilliam A. Kennington III     int completions = 0;
84571fdf9eSWilliam A. Kennington III     const siginfo_t* return_si;
85571fdf9eSWilliam A. Kennington III     Child::Callback callback = [&](Child&, const siginfo_t* si) {
86571fdf9eSWilliam A. Kennington III         return_si = si;
87571fdf9eSWilliam A. Kennington III         completions++;
88571fdf9eSWilliam A. Kennington III     };
89571fdf9eSWilliam A. Kennington III     Child child(*event, pid, options, std::move(callback));
90571fdf9eSWilliam A. Kennington III     EXPECT_FALSE(callback);
915320b1f5SWilliam A. Kennington III     EXPECT_NE(&child, userdata);
92571fdf9eSWilliam A. Kennington III     EXPECT_EQ(0, completions);
93571fdf9eSWilliam A. Kennington III 
94571fdf9eSWilliam A. Kennington III     const siginfo_t* expected_si = reinterpret_cast<siginfo_t*>(865);
955320b1f5SWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, expected_si, userdata));
96571fdf9eSWilliam A. Kennington III     EXPECT_EQ(1, completions);
97571fdf9eSWilliam A. Kennington III     EXPECT_EQ(expected_si, return_si);
98571fdf9eSWilliam A. Kennington III 
99b53ef902SWilliam A. Kennington III     child.set_callback(std::bind([]() {}));
1005320b1f5SWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, expected_si, userdata));
101b53ef902SWilliam A. Kennington III     EXPECT_EQ(1, completions);
102b53ef902SWilliam A. Kennington III 
103571fdf9eSWilliam A. Kennington III     expect_destruct();
1045320b1f5SWilliam A. Kennington III     destroy(userdata);
105571fdf9eSWilliam A. Kennington III }
106571fdf9eSWilliam A. Kennington III 
107571fdf9eSWilliam A. Kennington III TEST_F(ChildTest, ConstructError)
108571fdf9eSWilliam A. Kennington III {
109571fdf9eSWilliam A. Kennington III     const pid_t pid = 50;
110571fdf9eSWilliam A. Kennington III     const int options = WEXITED;
111571fdf9eSWilliam A. Kennington III 
112571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
113571fdf9eSWilliam A. Kennington III                                          options, testing::_, nullptr))
114571fdf9eSWilliam A. Kennington III         .WillOnce(Return(-EINVAL));
115571fdf9eSWilliam A. Kennington III     int completions = 0;
116571fdf9eSWilliam A. Kennington III     Child::Callback callback = [&completions](Child&, const siginfo_t*) {
117571fdf9eSWilliam A. Kennington III         completions++;
118571fdf9eSWilliam A. Kennington III     };
119571fdf9eSWilliam A. Kennington III     EXPECT_THROW(Child(*event, pid, options, std::move(callback)),
120571fdf9eSWilliam A. Kennington III                  SdEventError);
121571fdf9eSWilliam A. Kennington III     EXPECT_TRUE(callback);
122571fdf9eSWilliam A. Kennington III     EXPECT_EQ(0, completions);
123571fdf9eSWilliam A. Kennington III }
124571fdf9eSWilliam A. Kennington III 
125571fdf9eSWilliam A. Kennington III class ChildMethodTest : public ChildTest
126571fdf9eSWilliam A. Kennington III {
127571fdf9eSWilliam A. Kennington III   protected:
128571fdf9eSWilliam A. Kennington III     std::unique_ptr<Child> child;
1295320b1f5SWilliam A. Kennington III     sd_event_destroy_t destroy;
1305320b1f5SWilliam A. Kennington III     void* userdata;
131571fdf9eSWilliam A. Kennington III 
132571fdf9eSWilliam A. Kennington III     void SetUp()
133571fdf9eSWilliam A. Kennington III     {
134571fdf9eSWilliam A. Kennington III         const pid_t pid = 50;
135571fdf9eSWilliam A. Kennington III         const int options = WEXITED;
136571fdf9eSWilliam A. Kennington III 
137571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_ref(expected_event))
138571fdf9eSWilliam A. Kennington III             .WillOnce(Return(expected_event));
139571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
140571fdf9eSWilliam A. Kennington III                                              options, testing::_, nullptr))
141571fdf9eSWilliam A. Kennington III             .WillOnce(DoAll(SetArgPointee<1>(expected_source), Return(0)));
1425320b1f5SWilliam A. Kennington III         {
1435320b1f5SWilliam A. Kennington III             testing::InSequence seq;
1445320b1f5SWilliam A. Kennington III             EXPECT_CALL(mock, sd_event_source_set_destroy_callback(
1455320b1f5SWilliam A. Kennington III                                   expected_source, testing::_))
1465320b1f5SWilliam A. Kennington III                 .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
1475320b1f5SWilliam A. Kennington III             EXPECT_CALL(
1485320b1f5SWilliam A. Kennington III                 mock, sd_event_source_set_userdata(expected_source, testing::_))
1495320b1f5SWilliam A. Kennington III                 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
1505320b1f5SWilliam A. Kennington III             EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
1515320b1f5SWilliam A. Kennington III                 .WillRepeatedly(ReturnPointee(&userdata));
1525320b1f5SWilliam A. Kennington III         }
153571fdf9eSWilliam A. Kennington III         child = std::make_unique<Child>(*event, pid, options,
154571fdf9eSWilliam A. Kennington III                                         [](Child&, const siginfo_t*) {});
155571fdf9eSWilliam A. Kennington III     }
156571fdf9eSWilliam A. Kennington III 
157571fdf9eSWilliam A. Kennington III     void TearDown()
158571fdf9eSWilliam A. Kennington III     {
159571fdf9eSWilliam A. Kennington III         expect_destruct();
160571fdf9eSWilliam A. Kennington III         child.reset();
1615320b1f5SWilliam A. Kennington III         destroy(userdata);
162571fdf9eSWilliam A. Kennington III     }
163571fdf9eSWilliam A. Kennington III };
164571fdf9eSWilliam A. Kennington III 
165*56dc78baSWilliam A. Kennington III TEST_F(ChildMethodTest, Copy)
166*56dc78baSWilliam A. Kennington III {
167*56dc78baSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_ref(expected_event))
168*56dc78baSWilliam A. Kennington III         .WillOnce(Return(expected_event));
169*56dc78baSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_source_ref(expected_source))
170*56dc78baSWilliam A. Kennington III         .WillOnce(Return(expected_source));
171*56dc78baSWilliam A. Kennington III     auto child2 = std::make_unique<Child>(*child);
172*56dc78baSWilliam A. Kennington III     {
173*56dc78baSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_ref(expected_event))
174*56dc78baSWilliam A. Kennington III             .WillOnce(Return(expected_event));
175*56dc78baSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_ref(expected_source))
176*56dc78baSWilliam A. Kennington III             .WillOnce(Return(expected_source));
177*56dc78baSWilliam A. Kennington III         Child child3(*child);
178*56dc78baSWilliam A. Kennington III 
179*56dc78baSWilliam A. Kennington III         expect_destruct();
180*56dc78baSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_ref(expected_event))
181*56dc78baSWilliam A. Kennington III             .WillOnce(Return(expected_event));
182*56dc78baSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_ref(expected_source))
183*56dc78baSWilliam A. Kennington III             .WillOnce(Return(expected_source));
184*56dc78baSWilliam A. Kennington III         *child2 = child3;
185*56dc78baSWilliam A. Kennington III 
186*56dc78baSWilliam A. Kennington III         expect_destruct();
187*56dc78baSWilliam A. Kennington III     }
188*56dc78baSWilliam A. Kennington III 
189*56dc78baSWilliam A. Kennington III     // Delete the original child
190*56dc78baSWilliam A. Kennington III     child2.swap(child);
191*56dc78baSWilliam A. Kennington III     expect_destruct();
192*56dc78baSWilliam A. Kennington III     child2.reset();
193*56dc78baSWilliam A. Kennington III 
194*56dc78baSWilliam A. Kennington III     // Make sure our new copy can still access data
195*56dc78baSWilliam A. Kennington III     child->set_callback(nullptr);
196*56dc78baSWilliam A. Kennington III }
197*56dc78baSWilliam A. Kennington III 
198571fdf9eSWilliam A. Kennington III TEST_F(ChildMethodTest, GetPidSuccess)
199571fdf9eSWilliam A. Kennington III {
200571fdf9eSWilliam A. Kennington III     const pid_t pid = 32;
201571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock,
202571fdf9eSWilliam A. Kennington III                 sd_event_source_get_child_pid(expected_source, testing::_))
203571fdf9eSWilliam A. Kennington III         .WillOnce(DoAll(SetArgPointee<1>(pid), Return(0)));
204571fdf9eSWilliam A. Kennington III     EXPECT_EQ(pid, child->get_pid());
205571fdf9eSWilliam A. Kennington III }
206571fdf9eSWilliam A. Kennington III 
207571fdf9eSWilliam A. Kennington III TEST_F(ChildMethodTest, GetPidError)
208571fdf9eSWilliam A. Kennington III {
209571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock,
210571fdf9eSWilliam A. Kennington III                 sd_event_source_get_child_pid(expected_source, testing::_))
211571fdf9eSWilliam A. Kennington III         .WillOnce(Return(-EINVAL));
212571fdf9eSWilliam A. Kennington III     EXPECT_THROW(child->get_pid(), SdEventError);
213571fdf9eSWilliam A. Kennington III }
214571fdf9eSWilliam A. Kennington III 
215571fdf9eSWilliam A. Kennington III } // namespace
216571fdf9eSWilliam A. Kennington III } // namespace source
217571fdf9eSWilliam A. Kennington III } // namespace sdeventplus
218