xref: /openbmc/sdeventplus/test/source/child.cpp (revision a8c11e3c)
1*a8c11e3cSPatrick Williams #include <sys/wait.h>
2*a8c11e3cSPatrick Williams #include <systemd/sd-event.h>
3*a8c11e3cSPatrick Williams 
4571fdf9eSWilliam A. Kennington III #include <sdeventplus/event.hpp>
5571fdf9eSWilliam A. Kennington III #include <sdeventplus/exception.hpp>
6571fdf9eSWilliam A. Kennington III #include <sdeventplus/source/child.hpp>
7571fdf9eSWilliam A. Kennington III #include <sdeventplus/test/sdevent.hpp>
8*a8c11e3cSPatrick Williams 
9*a8c11e3cSPatrick Williams #include <cerrno>
10*a8c11e3cSPatrick Williams #include <functional>
11*a8c11e3cSPatrick Williams #include <memory>
12571fdf9eSWilliam A. Kennington III #include <type_traits>
13571fdf9eSWilliam A. Kennington III #include <utility>
14571fdf9eSWilliam A. Kennington III 
15*a8c11e3cSPatrick Williams #include <gmock/gmock.h>
16*a8c11e3cSPatrick Williams #include <gtest/gtest.h>
17*a8c11e3cSPatrick Williams 
18571fdf9eSWilliam A. Kennington III namespace sdeventplus
19571fdf9eSWilliam A. Kennington III {
20571fdf9eSWilliam A. Kennington III namespace source
21571fdf9eSWilliam A. Kennington III {
22571fdf9eSWilliam A. Kennington III namespace
23571fdf9eSWilliam A. Kennington III {
24571fdf9eSWilliam A. Kennington III 
25571fdf9eSWilliam A. Kennington III using testing::DoAll;
26571fdf9eSWilliam A. Kennington III using testing::Return;
275320b1f5SWilliam A. Kennington III using testing::ReturnPointee;
28571fdf9eSWilliam A. Kennington III using testing::SaveArg;
29571fdf9eSWilliam A. Kennington III using testing::SetArgPointee;
30571fdf9eSWilliam A. Kennington III 
31571fdf9eSWilliam A. Kennington III using UniqueEvent = std::unique_ptr<Event, std::function<void(Event*)>>;
32571fdf9eSWilliam A. Kennington III 
33571fdf9eSWilliam A. Kennington III class ChildTest : public testing::Test
34571fdf9eSWilliam A. Kennington III {
35571fdf9eSWilliam A. Kennington III   protected:
36571fdf9eSWilliam A. Kennington III     testing::StrictMock<test::SdEventMock> mock;
37571fdf9eSWilliam A. Kennington III     sd_event_source* const expected_source =
38571fdf9eSWilliam A. Kennington III         reinterpret_cast<sd_event_source*>(1234);
39571fdf9eSWilliam A. Kennington III     sd_event* const expected_event = reinterpret_cast<sd_event*>(2345);
40571fdf9eSWilliam A. Kennington III     UniqueEvent event = make_event(expected_event);
41571fdf9eSWilliam A. Kennington III 
make_event(sd_event * event)42571fdf9eSWilliam A. Kennington III     UniqueEvent make_event(sd_event* event)
43571fdf9eSWilliam A. Kennington III     {
44571fdf9eSWilliam A. Kennington III         auto deleter = [this, event](Event* e) {
45571fdf9eSWilliam A. Kennington III             EXPECT_CALL(this->mock, sd_event_unref(event))
46571fdf9eSWilliam A. Kennington III                 .WillOnce(Return(nullptr));
47571fdf9eSWilliam A. Kennington III             delete e;
48571fdf9eSWilliam A. Kennington III         };
49571fdf9eSWilliam A. Kennington III         return UniqueEvent(new Event(event, std::false_type(), &mock), deleter);
50571fdf9eSWilliam A. Kennington III     }
51571fdf9eSWilliam A. Kennington III 
expect_destruct()52571fdf9eSWilliam A. Kennington III     void expect_destruct()
53571fdf9eSWilliam A. Kennington III     {
54571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_unref(expected_source))
55571fdf9eSWilliam A. Kennington III             .WillOnce(Return(nullptr));
56571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_unref(expected_event))
57571fdf9eSWilliam A. Kennington III             .WillOnce(Return(nullptr));
58571fdf9eSWilliam A. Kennington III     }
59571fdf9eSWilliam A. Kennington III };
60571fdf9eSWilliam A. Kennington III 
TEST_F(ChildTest,ConstructSuccess)61571fdf9eSWilliam A. Kennington III TEST_F(ChildTest, ConstructSuccess)
62571fdf9eSWilliam A. Kennington III {
63571fdf9eSWilliam A. Kennington III     const pid_t pid = 50;
64571fdf9eSWilliam A. Kennington III     const int options = WEXITED;
65571fdf9eSWilliam A. Kennington III 
66571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_ref(expected_event))
67571fdf9eSWilliam A. Kennington III         .WillOnce(Return(expected_event));
68571fdf9eSWilliam A. Kennington III     sd_event_child_handler_t handler;
69571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
70571fdf9eSWilliam A. Kennington III                                          options, testing::_, nullptr))
71571fdf9eSWilliam A. Kennington III         .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<4>(&handler),
72571fdf9eSWilliam A. Kennington III                         Return(0)));
735320b1f5SWilliam A. Kennington III     sd_event_destroy_t destroy;
74571fdf9eSWilliam A. Kennington III     void* userdata;
755320b1f5SWilliam A. Kennington III     {
765320b1f5SWilliam A. Kennington III         testing::InSequence seq;
775320b1f5SWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
785320b1f5SWilliam A. Kennington III                                                                testing::_))
795320b1f5SWilliam A. Kennington III             .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
805320b1f5SWilliam A. Kennington III         EXPECT_CALL(mock,
815320b1f5SWilliam A. Kennington III                     sd_event_source_set_userdata(expected_source, testing::_))
82571fdf9eSWilliam A. Kennington III             .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
835320b1f5SWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
845320b1f5SWilliam A. Kennington III             .WillRepeatedly(ReturnPointee(&userdata));
855320b1f5SWilliam A. Kennington III     }
86571fdf9eSWilliam A. Kennington III     int completions = 0;
87571fdf9eSWilliam A. Kennington III     const siginfo_t* return_si;
88571fdf9eSWilliam A. Kennington III     Child::Callback callback = [&](Child&, const siginfo_t* si) {
89571fdf9eSWilliam A. Kennington III         return_si = si;
90571fdf9eSWilliam A. Kennington III         completions++;
91571fdf9eSWilliam A. Kennington III     };
92571fdf9eSWilliam A. Kennington III     Child child(*event, pid, options, std::move(callback));
93571fdf9eSWilliam A. Kennington III     EXPECT_FALSE(callback);
945320b1f5SWilliam A. Kennington III     EXPECT_NE(&child, userdata);
95571fdf9eSWilliam A. Kennington III     EXPECT_EQ(0, completions);
96571fdf9eSWilliam A. Kennington III 
97571fdf9eSWilliam A. Kennington III     const siginfo_t* expected_si = reinterpret_cast<siginfo_t*>(865);
985320b1f5SWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, expected_si, userdata));
99571fdf9eSWilliam A. Kennington III     EXPECT_EQ(1, completions);
100571fdf9eSWilliam A. Kennington III     EXPECT_EQ(expected_si, return_si);
101571fdf9eSWilliam A. Kennington III 
102b53ef902SWilliam A. Kennington III     child.set_callback(std::bind([]() {}));
1035320b1f5SWilliam A. Kennington III     EXPECT_EQ(0, handler(nullptr, expected_si, userdata));
104b53ef902SWilliam A. Kennington III     EXPECT_EQ(1, completions);
105b53ef902SWilliam A. Kennington III 
106571fdf9eSWilliam A. Kennington III     expect_destruct();
1075320b1f5SWilliam A. Kennington III     destroy(userdata);
108571fdf9eSWilliam A. Kennington III }
109571fdf9eSWilliam A. Kennington III 
TEST_F(ChildTest,ConstructError)110571fdf9eSWilliam A. Kennington III TEST_F(ChildTest, ConstructError)
111571fdf9eSWilliam A. Kennington III {
112571fdf9eSWilliam A. Kennington III     const pid_t pid = 50;
113571fdf9eSWilliam A. Kennington III     const int options = WEXITED;
114571fdf9eSWilliam A. Kennington III 
115571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
116571fdf9eSWilliam A. Kennington III                                          options, testing::_, nullptr))
117571fdf9eSWilliam A. Kennington III         .WillOnce(Return(-EINVAL));
118571fdf9eSWilliam A. Kennington III     int completions = 0;
119571fdf9eSWilliam A. Kennington III     Child::Callback callback = [&completions](Child&, const siginfo_t*) {
120571fdf9eSWilliam A. Kennington III         completions++;
121571fdf9eSWilliam A. Kennington III     };
122571fdf9eSWilliam A. Kennington III     EXPECT_THROW(Child(*event, pid, options, std::move(callback)),
123571fdf9eSWilliam A. Kennington III                  SdEventError);
124571fdf9eSWilliam A. Kennington III     EXPECT_TRUE(callback);
125571fdf9eSWilliam A. Kennington III     EXPECT_EQ(0, completions);
126571fdf9eSWilliam A. Kennington III }
127571fdf9eSWilliam A. Kennington III 
128571fdf9eSWilliam A. Kennington III class ChildMethodTest : public ChildTest
129571fdf9eSWilliam A. Kennington III {
130571fdf9eSWilliam A. Kennington III   protected:
131571fdf9eSWilliam A. Kennington III     std::unique_ptr<Child> child;
1325320b1f5SWilliam A. Kennington III     sd_event_destroy_t destroy;
1335320b1f5SWilliam A. Kennington III     void* userdata;
134571fdf9eSWilliam A. Kennington III 
SetUp()135571fdf9eSWilliam A. Kennington III     void SetUp()
136571fdf9eSWilliam A. Kennington III     {
137571fdf9eSWilliam A. Kennington III         const pid_t pid = 50;
138571fdf9eSWilliam A. Kennington III         const int options = WEXITED;
139571fdf9eSWilliam A. Kennington III 
140571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_ref(expected_event))
141571fdf9eSWilliam A. Kennington III             .WillOnce(Return(expected_event));
142571fdf9eSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
143571fdf9eSWilliam A. Kennington III                                              options, testing::_, nullptr))
144571fdf9eSWilliam A. Kennington III             .WillOnce(DoAll(SetArgPointee<1>(expected_source), Return(0)));
1455320b1f5SWilliam A. Kennington III         {
1465320b1f5SWilliam A. Kennington III             testing::InSequence seq;
1475320b1f5SWilliam A. Kennington III             EXPECT_CALL(mock, sd_event_source_set_destroy_callback(
1485320b1f5SWilliam A. Kennington III                                   expected_source, testing::_))
1495320b1f5SWilliam A. Kennington III                 .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
1505320b1f5SWilliam A. Kennington III             EXPECT_CALL(
1515320b1f5SWilliam A. Kennington III                 mock, sd_event_source_set_userdata(expected_source, testing::_))
1525320b1f5SWilliam A. Kennington III                 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
1535320b1f5SWilliam A. Kennington III             EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
1545320b1f5SWilliam A. Kennington III                 .WillRepeatedly(ReturnPointee(&userdata));
1555320b1f5SWilliam A. Kennington III         }
156571fdf9eSWilliam A. Kennington III         child = std::make_unique<Child>(*event, pid, options,
157571fdf9eSWilliam A. Kennington III                                         [](Child&, const siginfo_t*) {});
158571fdf9eSWilliam A. Kennington III     }
159571fdf9eSWilliam A. Kennington III 
TearDown()160571fdf9eSWilliam A. Kennington III     void TearDown()
161571fdf9eSWilliam A. Kennington III     {
162571fdf9eSWilliam A. Kennington III         expect_destruct();
163571fdf9eSWilliam A. Kennington III         child.reset();
1645320b1f5SWilliam A. Kennington III         destroy(userdata);
165571fdf9eSWilliam A. Kennington III     }
166571fdf9eSWilliam A. Kennington III };
167571fdf9eSWilliam A. Kennington III 
TEST_F(ChildMethodTest,Copy)16856dc78baSWilliam A. Kennington III TEST_F(ChildMethodTest, Copy)
16956dc78baSWilliam A. Kennington III {
17056dc78baSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_ref(expected_event))
17156dc78baSWilliam A. Kennington III         .WillOnce(Return(expected_event));
17256dc78baSWilliam A. Kennington III     EXPECT_CALL(mock, sd_event_source_ref(expected_source))
17356dc78baSWilliam A. Kennington III         .WillOnce(Return(expected_source));
17456dc78baSWilliam A. Kennington III     auto child2 = std::make_unique<Child>(*child);
17556dc78baSWilliam A. Kennington III     {
17656dc78baSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_ref(expected_event))
17756dc78baSWilliam A. Kennington III             .WillOnce(Return(expected_event));
17856dc78baSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_ref(expected_source))
17956dc78baSWilliam A. Kennington III             .WillOnce(Return(expected_source));
18056dc78baSWilliam A. Kennington III         Child child3(*child);
18156dc78baSWilliam A. Kennington III 
18256dc78baSWilliam A. Kennington III         expect_destruct();
18356dc78baSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_ref(expected_event))
18456dc78baSWilliam A. Kennington III             .WillOnce(Return(expected_event));
18556dc78baSWilliam A. Kennington III         EXPECT_CALL(mock, sd_event_source_ref(expected_source))
18656dc78baSWilliam A. Kennington III             .WillOnce(Return(expected_source));
18756dc78baSWilliam A. Kennington III         *child2 = child3;
18856dc78baSWilliam A. Kennington III 
18956dc78baSWilliam A. Kennington III         expect_destruct();
19056dc78baSWilliam A. Kennington III     }
19156dc78baSWilliam A. Kennington III 
19256dc78baSWilliam A. Kennington III     // Delete the original child
19356dc78baSWilliam A. Kennington III     child2.swap(child);
19456dc78baSWilliam A. Kennington III     expect_destruct();
19556dc78baSWilliam A. Kennington III     child2.reset();
19656dc78baSWilliam A. Kennington III 
19756dc78baSWilliam A. Kennington III     // Make sure our new copy can still access data
19856dc78baSWilliam A. Kennington III     child->set_callback(nullptr);
19956dc78baSWilliam A. Kennington III }
20056dc78baSWilliam A. Kennington III 
TEST_F(ChildMethodTest,GetPidSuccess)201571fdf9eSWilliam A. Kennington III TEST_F(ChildMethodTest, GetPidSuccess)
202571fdf9eSWilliam A. Kennington III {
203571fdf9eSWilliam A. Kennington III     const pid_t pid = 32;
204571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock,
205571fdf9eSWilliam A. Kennington III                 sd_event_source_get_child_pid(expected_source, testing::_))
206571fdf9eSWilliam A. Kennington III         .WillOnce(DoAll(SetArgPointee<1>(pid), Return(0)));
207571fdf9eSWilliam A. Kennington III     EXPECT_EQ(pid, child->get_pid());
208571fdf9eSWilliam A. Kennington III }
209571fdf9eSWilliam A. Kennington III 
TEST_F(ChildMethodTest,GetPidError)210571fdf9eSWilliam A. Kennington III TEST_F(ChildMethodTest, GetPidError)
211571fdf9eSWilliam A. Kennington III {
212571fdf9eSWilliam A. Kennington III     EXPECT_CALL(mock,
213571fdf9eSWilliam A. Kennington III                 sd_event_source_get_child_pid(expected_source, testing::_))
214571fdf9eSWilliam A. Kennington III         .WillOnce(Return(-EINVAL));
215571fdf9eSWilliam A. Kennington III     EXPECT_THROW(child->get_pid(), SdEventError);
216571fdf9eSWilliam A. Kennington III }
217571fdf9eSWilliam A. Kennington III 
218571fdf9eSWilliam A. Kennington III } // namespace
219571fdf9eSWilliam A. Kennington III } // namespace source
220571fdf9eSWilliam A. Kennington III } // namespace sdeventplus
221