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::ReturnPointee; 24 using testing::SaveArg; 25 using testing::SetArgPointee; 26 27 using UniqueEvent = std::unique_ptr<Event, std::function<void(Event*)>>; 28 29 class EventTest : public testing::Test 30 { 31 protected: 32 testing::StrictMock<test::SdEventMock> mock; 33 sd_event_source* const expected_source = 34 reinterpret_cast<sd_event_source*>(1234); 35 sd_event* const expected_event = reinterpret_cast<sd_event*>(2345); 36 UniqueEvent event = make_event(expected_event); 37 38 UniqueEvent make_event(sd_event* event) 39 { 40 auto deleter = [this, event](Event* e) { 41 EXPECT_CALL(this->mock, sd_event_unref(event)) 42 .WillOnce(Return(nullptr)); 43 delete e; 44 }; 45 return UniqueEvent(new Event(event, std::false_type(), &mock), deleter); 46 } 47 48 void expect_destruct() 49 { 50 EXPECT_CALL(mock, sd_event_source_unref(expected_source)) 51 .WillOnce(Return(nullptr)); 52 EXPECT_CALL(mock, sd_event_unref(expected_event)) 53 .WillOnce(Return(nullptr)); 54 } 55 }; 56 57 TEST_F(EventTest, DeferConstruct) 58 { 59 EXPECT_CALL(mock, sd_event_ref(expected_event)) 60 .WillOnce(Return(expected_event)); 61 sd_event_destroy_t destroy; 62 void* userdata; 63 { 64 testing::InSequence seq; 65 EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source, 66 testing::_)) 67 .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0))); 68 EXPECT_CALL(mock, 69 sd_event_source_set_userdata(expected_source, testing::_)) 70 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 71 EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source)) 72 .WillRepeatedly(ReturnPointee(&userdata)); 73 } 74 sd_event_handler_t handler; 75 EXPECT_CALL(mock, sd_event_add_defer(expected_event, testing::_, testing::_, 76 nullptr)) 77 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 78 Return(0))); 79 int completions = 0; 80 EventBase::Callback callback = [&completions](EventBase&) { 81 completions++; 82 }; 83 Defer defer(*event, std::move(callback)); 84 EXPECT_NE(&defer, userdata); 85 EXPECT_FALSE(callback); 86 EXPECT_EQ(0, completions); 87 88 EXPECT_EQ(0, handler(nullptr, userdata)); 89 EXPECT_EQ(1, completions); 90 91 defer.set_callback(std::bind([]() {})); 92 EXPECT_EQ(0, handler(nullptr, userdata)); 93 EXPECT_EQ(1, completions); 94 95 expect_destruct(); 96 destroy(userdata); 97 } 98 99 TEST_F(EventTest, PostConstruct) 100 { 101 EXPECT_CALL(mock, sd_event_ref(expected_event)) 102 .WillOnce(Return(expected_event)); 103 sd_event_destroy_t destroy; 104 void* userdata; 105 { 106 testing::InSequence seq; 107 EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source, 108 testing::_)) 109 .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0))); 110 EXPECT_CALL(mock, 111 sd_event_source_set_userdata(expected_source, testing::_)) 112 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 113 EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source)) 114 .WillRepeatedly(ReturnPointee(&userdata)); 115 } 116 sd_event_handler_t handler; 117 EXPECT_CALL(mock, sd_event_add_post(expected_event, testing::_, testing::_, 118 nullptr)) 119 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 120 Return(0))); 121 int completions = 0; 122 EventBase::Callback callback = [&completions](EventBase&) { 123 completions++; 124 }; 125 Post post(*event, std::move(callback)); 126 EXPECT_NE(&post, userdata); 127 EXPECT_FALSE(callback); 128 EXPECT_EQ(0, completions); 129 130 EXPECT_EQ(0, handler(nullptr, userdata)); 131 EXPECT_EQ(1, completions); 132 133 expect_destruct(); 134 destroy(userdata); 135 } 136 137 TEST_F(EventTest, ExitConstruct) 138 { 139 EXPECT_CALL(mock, sd_event_ref(expected_event)) 140 .WillOnce(Return(expected_event)); 141 sd_event_destroy_t destroy; 142 void* userdata; 143 { 144 testing::InSequence seq; 145 EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source, 146 testing::_)) 147 .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0))); 148 EXPECT_CALL(mock, 149 sd_event_source_set_userdata(expected_source, testing::_)) 150 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 151 EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source)) 152 .WillRepeatedly(ReturnPointee(&userdata)); 153 } 154 sd_event_handler_t handler; 155 EXPECT_CALL(mock, sd_event_add_exit(expected_event, testing::_, testing::_, 156 nullptr)) 157 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 158 Return(0))); 159 int completions = 0; 160 EventBase::Callback callback = [&completions](EventBase&) { 161 completions++; 162 }; 163 Exit exit(*event, std::move(callback)); 164 EXPECT_NE(&exit, userdata); 165 EXPECT_FALSE(callback); 166 EXPECT_EQ(0, completions); 167 168 EXPECT_EQ(0, handler(nullptr, userdata)); 169 EXPECT_EQ(1, completions); 170 171 expect_destruct(); 172 destroy(userdata); 173 } 174 175 TEST_F(EventTest, ConstructFailure) 176 { 177 EXPECT_CALL(mock, sd_event_add_defer(expected_event, testing::_, testing::_, 178 nullptr)) 179 .WillOnce(Return(-EINVAL)); 180 int completions = 0; 181 EventBase::Callback callback = [&completions](EventBase&) { 182 completions++; 183 }; 184 EXPECT_THROW(Defer(*event, std::move(callback)), SdEventError); 185 EXPECT_TRUE(callback); 186 EXPECT_EQ(0, completions); 187 } 188 189 } // namespace 190 } // namespace source 191 } // namespace sdeventplus 192