1 #include <cerrno> 2 #include <functional> 3 #include <gmock/gmock.h> 4 #include <gtest/gtest.h> 5 #include <memory> 6 #include <sdeventplus/event.hpp> 7 #include <sdeventplus/exception.hpp> 8 #include <sdeventplus/source/event.hpp> 9 #include <sdeventplus/test/sdevent.hpp> 10 #include <systemd/sd-event.h> 11 #include <type_traits> 12 #include <utility> 13 14 namespace sdeventplus 15 { 16 namespace source 17 { 18 namespace 19 { 20 21 using testing::DoAll; 22 using testing::Return; 23 using testing::SaveArg; 24 using testing::SetArgPointee; 25 26 using UniqueEvent = std::unique_ptr<Event, std::function<void(Event*)>>; 27 28 class EventTest : public testing::Test 29 { 30 protected: 31 testing::StrictMock<test::SdEventMock> mock; 32 sd_event_source* const expected_source = 33 reinterpret_cast<sd_event_source*>(1234); 34 sd_event* const expected_event = reinterpret_cast<sd_event*>(2345); 35 UniqueEvent event = make_event(expected_event); 36 37 UniqueEvent make_event(sd_event* event) 38 { 39 auto deleter = [this, event](Event* e) { 40 EXPECT_CALL(this->mock, sd_event_unref(event)) 41 .WillOnce(Return(nullptr)); 42 delete e; 43 }; 44 return UniqueEvent(new Event(event, std::false_type(), &mock), deleter); 45 } 46 47 void expect_destruct() 48 { 49 { 50 testing::InSequence sequence; 51 EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, 52 SD_EVENT_OFF)) 53 .WillOnce(Return(0)); 54 EXPECT_CALL(mock, sd_event_source_unref(expected_source)) 55 .WillOnce(Return(nullptr)); 56 } 57 EXPECT_CALL(mock, sd_event_unref(expected_event)) 58 .WillOnce(Return(nullptr)); 59 } 60 }; 61 62 TEST_F(EventTest, DeferConstruct) 63 { 64 EXPECT_CALL(mock, sd_event_ref(expected_event)) 65 .WillOnce(Return(expected_event)); 66 void* userdata; 67 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 68 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 69 sd_event_handler_t handler; 70 EXPECT_CALL(mock, sd_event_add_defer(expected_event, testing::_, testing::_, 71 nullptr)) 72 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 73 Return(0))); 74 int completions = 0; 75 EventBase::Callback callback = [&completions](EventBase&) { 76 completions++; 77 }; 78 Defer defer(*event, std::move(callback)); 79 EXPECT_EQ(&defer, userdata); 80 EXPECT_FALSE(callback); 81 EXPECT_EQ(0, completions); 82 83 EXPECT_EQ(0, handler(nullptr, &defer)); 84 EXPECT_EQ(1, completions); 85 86 expect_destruct(); 87 } 88 89 TEST_F(EventTest, PostConstruct) 90 { 91 EXPECT_CALL(mock, sd_event_ref(expected_event)) 92 .WillOnce(Return(expected_event)); 93 void* userdata; 94 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 95 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 96 sd_event_handler_t handler; 97 EXPECT_CALL(mock, sd_event_add_post(expected_event, testing::_, testing::_, 98 nullptr)) 99 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 100 Return(0))); 101 int completions = 0; 102 EventBase::Callback callback = [&completions](EventBase&) { 103 completions++; 104 }; 105 Post post(*event, std::move(callback)); 106 EXPECT_EQ(&post, userdata); 107 EXPECT_FALSE(callback); 108 EXPECT_EQ(0, completions); 109 110 EXPECT_EQ(0, handler(nullptr, &post)); 111 EXPECT_EQ(1, completions); 112 113 expect_destruct(); 114 } 115 116 TEST_F(EventTest, ExitConstruct) 117 { 118 EXPECT_CALL(mock, sd_event_ref(expected_event)) 119 .WillOnce(Return(expected_event)); 120 void* userdata; 121 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 122 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 123 sd_event_handler_t handler; 124 EXPECT_CALL(mock, sd_event_add_exit(expected_event, testing::_, testing::_, 125 nullptr)) 126 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 127 Return(0))); 128 int completions = 0; 129 EventBase::Callback callback = [&completions](EventBase&) { 130 completions++; 131 }; 132 Exit exit(*event, std::move(callback)); 133 EXPECT_EQ(&exit, userdata); 134 EXPECT_FALSE(callback); 135 EXPECT_EQ(0, completions); 136 137 EXPECT_EQ(0, handler(nullptr, &exit)); 138 EXPECT_EQ(1, completions); 139 140 expect_destruct(); 141 } 142 143 TEST_F(EventTest, ConstructFailure) 144 { 145 EXPECT_CALL(mock, sd_event_add_defer(expected_event, testing::_, testing::_, 146 nullptr)) 147 .WillOnce(Return(-EINVAL)); 148 int completions = 0; 149 EventBase::Callback callback = [&completions](EventBase&) { 150 completions++; 151 }; 152 EXPECT_THROW(Defer(*event, std::move(callback)), SdEventError); 153 EXPECT_TRUE(callback); 154 EXPECT_EQ(0, completions); 155 } 156 157 } // namespace 158 } // namespace source 159 } // namespace sdeventplus 160