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