1 #include <cerrno> 2 #include <gmock/gmock.h> 3 #include <gtest/gtest.h> 4 #include <memory> 5 #include <sdeventplus/event.hpp> 6 #include <sdeventplus/exception.hpp> 7 #include <sdeventplus/internal/sdevent.hpp> 8 #include <sdeventplus/source/base.hpp> 9 #include <sdeventplus/test/sdevent.hpp> 10 #include <string> 11 #include <systemd/sd-event.h> 12 #include <type_traits> 13 #include <utility> 14 15 namespace sdeventplus 16 { 17 namespace source 18 { 19 namespace 20 { 21 22 using testing::DoAll; 23 using testing::Return; 24 using testing::SaveArg; 25 using testing::SetArgPointee; 26 27 using UniqueEvent = std::unique_ptr<Event, std::function<void(Event*)>>; 28 29 class BaseImpl : public Base 30 { 31 public: 32 BaseImpl(const Event& event, sd_event_source* source) : Base(event, source) 33 { 34 } 35 BaseImpl(const Event& event, sd_event_source* source, std::false_type) : 36 Base(event, source, std::false_type()) 37 { 38 } 39 }; 40 41 class BaseTest : public testing::Test 42 { 43 protected: 44 testing::StrictMock<test::SdEventMock> mock; 45 sd_event_source* const expected_source = 46 reinterpret_cast<sd_event_source*>(1234); 47 sd_event* const expected_event = reinterpret_cast<sd_event*>(2345); 48 UniqueEvent event = make_event(expected_event); 49 50 UniqueEvent make_event(sd_event* event) 51 { 52 auto deleter = [this, event](Event* e) { 53 EXPECT_CALL(this->mock, sd_event_unref(event)) 54 .WillOnce(Return(nullptr)); 55 delete e; 56 }; 57 return UniqueEvent(new Event(event, std::false_type(), &mock), deleter); 58 } 59 60 // Using a unique_ptr to make sure we don't get any superfluous moves or 61 // copies. 62 std::unique_ptr<BaseImpl> make_base(const Event& event, 63 sd_event_source* source) 64 { 65 EXPECT_CALL(mock, sd_event_ref(event.get())) 66 .WillOnce(Return(event.get())); 67 void* userdata; 68 EXPECT_CALL(mock, sd_event_source_set_userdata(source, testing::_)) 69 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 70 auto ret = std::make_unique<BaseImpl>(event, source, std::false_type()); 71 EXPECT_EQ(ret.get(), userdata); 72 EXPECT_EQ(source, ret->get()); 73 EXPECT_NE(&event, &ret->get_event()); 74 EXPECT_EQ(event.get(), ret->get_event().get()); 75 EXPECT_FALSE(ret->get_prepare()); 76 return ret; 77 } 78 79 void set_prepare_placeholder(Base& base) 80 { 81 EXPECT_CALL(mock, sd_event_source_set_prepare(base.get(), testing::_)) 82 .WillOnce(Return(0)); 83 base.set_prepare([](Base&) {}); 84 EXPECT_TRUE(base.get_prepare()); 85 } 86 87 void empty_base(BaseImpl&& other) 88 { 89 void* userdata; 90 EXPECT_CALL(mock, sd_event_source_set_userdata(other.get(), testing::_)) 91 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 92 BaseImpl mover(std::move(other)); 93 EXPECT_EQ(&mover, userdata); 94 EXPECT_EQ(nullptr, other.get()); 95 EXPECT_EQ(nullptr, other.get_event().get()); 96 EXPECT_FALSE(other.get_prepare()); 97 98 expect_base_destruct(mover.get_event(), mover.get()); 99 } 100 101 void expect_base_destruct(const Event& event, sd_event_source* source) 102 { 103 { 104 testing::InSequence seq; 105 EXPECT_CALL(mock, sd_event_source_set_enabled(source, SD_EVENT_OFF)) 106 .WillOnce(Return(0)); 107 EXPECT_CALL(mock, sd_event_source_unref(source)) 108 .WillOnce(Return(nullptr)); 109 } 110 EXPECT_CALL(mock, sd_event_unref(event.get())) 111 .WillOnce(Return(nullptr)); 112 } 113 }; 114 115 TEST_F(BaseTest, NewBaseRef) 116 { 117 EXPECT_CALL(mock, sd_event_ref(expected_event)) 118 .WillOnce(Return(expected_event)); 119 EXPECT_CALL(mock, sd_event_source_ref(expected_source)) 120 .WillOnce(Return(expected_source)); 121 void* userdata; 122 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 123 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 124 BaseImpl source(*event, expected_source); 125 EXPECT_EQ(&source, userdata); 126 EXPECT_EQ(expected_source, source.get()); 127 EXPECT_NE(event.get(), &source.get_event()); 128 EXPECT_EQ(expected_event, source.get_event().get()); 129 EXPECT_FALSE(source.get_prepare()); 130 131 expect_base_destruct(*event, expected_source); 132 } 133 134 TEST_F(BaseTest, NewBaseNoRef) 135 { 136 EXPECT_CALL(mock, sd_event_ref(expected_event)) 137 .WillOnce(Return(expected_event)); 138 void* userdata; 139 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 140 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 141 BaseImpl source(*event, expected_source, std::false_type()); 142 EXPECT_EQ(&source, userdata); 143 EXPECT_EQ(expected_source, source.get()); 144 EXPECT_NE(event.get(), &source.get_event()); 145 EXPECT_EQ(expected_event, source.get_event().get()); 146 EXPECT_FALSE(source.get_prepare()); 147 148 expect_base_destruct(*event, expected_source); 149 } 150 151 TEST_F(BaseTest, MoveConstruct) 152 { 153 std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source); 154 set_prepare_placeholder(*source1); 155 156 void* userdata; 157 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 158 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 159 BaseImpl source2(std::move(*source1)); 160 EXPECT_EQ(&source2, userdata); 161 EXPECT_EQ(nullptr, source1->get()); 162 EXPECT_EQ(nullptr, source1->get_event().get()); 163 EXPECT_FALSE(source1->get_prepare()); 164 EXPECT_EQ(expected_source, source2.get()); 165 EXPECT_EQ(expected_event, source2.get_event().get()); 166 EXPECT_TRUE(source2.get_prepare()); 167 168 expect_base_destruct(*event, expected_source); 169 } 170 171 TEST_F(BaseTest, MoveAssignSelf) 172 { 173 std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source); 174 set_prepare_placeholder(*source1); 175 176 *source1 = std::move(*source1); 177 EXPECT_EQ(expected_source, source1->get()); 178 EXPECT_EQ(expected_event, source1->get_event().get()); 179 EXPECT_TRUE(source1->get_prepare()); 180 181 expect_base_destruct(*event, expected_source); 182 } 183 184 TEST_F(BaseTest, MoveAssignEmpty) 185 { 186 std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source); 187 set_prepare_placeholder(*source1); 188 189 std::unique_ptr<BaseImpl> source2 = make_base(*event, expected_source); 190 empty_base(std::move(*source2)); 191 192 { 193 void* userdata; 194 EXPECT_CALL(mock, 195 sd_event_source_set_userdata(expected_source, testing::_)) 196 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 197 *source2 = std::move(*source1); 198 EXPECT_EQ(source2.get(), userdata); 199 } 200 EXPECT_EQ(nullptr, source1->get()); 201 EXPECT_EQ(nullptr, source1->get_event().get()); 202 EXPECT_FALSE(source1->get_prepare()); 203 EXPECT_EQ(expected_source, source2->get()); 204 EXPECT_EQ(expected_event, source2->get_event().get()); 205 EXPECT_TRUE(source2->get_prepare()); 206 207 // Make sure source1 is deleted to ensure it isn't holding a reference 208 source1.reset(); 209 expect_base_destruct(*event, expected_source); 210 } 211 212 TEST_F(BaseTest, MoveAssignExisting) 213 { 214 sd_event_source* const expected_source2 = 215 reinterpret_cast<sd_event_source*>(3456); 216 sd_event* const expected_event2 = reinterpret_cast<sd_event*>(4567); 217 218 std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source); 219 set_prepare_placeholder(*source1); 220 221 UniqueEvent event2 = make_event(expected_event2); 222 std::unique_ptr<BaseImpl> source2 = make_base(*event2, expected_source2); 223 224 { 225 expect_base_destruct(*event2, expected_source2); 226 void* userdata; 227 EXPECT_CALL(mock, 228 sd_event_source_set_userdata(expected_source, testing::_)) 229 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 230 *source2 = std::move(*source1); 231 EXPECT_EQ(source2.get(), userdata); 232 } 233 EXPECT_EQ(nullptr, source1->get()); 234 EXPECT_EQ(nullptr, source1->get_event().get()); 235 EXPECT_FALSE(source1->get_prepare()); 236 EXPECT_EQ(expected_source, source2->get()); 237 EXPECT_EQ(expected_event, source2->get_event().get()); 238 EXPECT_TRUE(source2->get_prepare()); 239 240 // Make sure source1 is deleted to ensure it isn't holding a reference 241 source1.reset(); 242 expect_base_destruct(*event, expected_source); 243 } 244 245 class BaseMethodTest : public BaseTest 246 { 247 protected: 248 std::unique_ptr<BaseImpl> base = make_base(*event, expected_source); 249 250 void TearDown() 251 { 252 expect_base_destruct(base->get_event(), base->get()); 253 base.reset(); 254 } 255 }; 256 257 TEST_F(BaseMethodTest, GetDescriptionSuccess) 258 { 259 const char* expected = "test_desc"; 260 EXPECT_CALL(mock, 261 sd_event_source_get_description(expected_source, testing::_)) 262 .WillOnce(DoAll(SetArgPointee<1>(expected), Return(0))); 263 // Intentionally comparing pointers to make sure no copying is happening 264 EXPECT_EQ(expected, base->get_description()); 265 } 266 267 TEST_F(BaseMethodTest, GetDescriptionError) 268 { 269 EXPECT_CALL(mock, 270 sd_event_source_get_description(expected_source, testing::_)) 271 .WillOnce(Return(-EINVAL)); 272 EXPECT_THROW(base->get_description(), SdEventError); 273 } 274 275 TEST_F(BaseMethodTest, SetDescriptionSuccess) 276 { 277 const char* expected = "test desc"; 278 // Intentionally comparing pointers to make sure no copying is happening 279 EXPECT_CALL(mock, 280 sd_event_source_set_description(expected_source, expected)) 281 .WillOnce(Return(0)); 282 base->set_description(expected); 283 } 284 285 TEST_F(BaseMethodTest, SetDescriptionError) 286 { 287 const char* expected = "test desc"; 288 // Intentionally comparing pointers to make sure no copying is happening 289 EXPECT_CALL(mock, 290 sd_event_source_set_description(expected_source, expected)) 291 .WillOnce(Return(-EINVAL)); 292 EXPECT_THROW(base->set_description(expected), SdEventError); 293 } 294 295 TEST_F(BaseMethodTest, SetPrepareCallback) 296 { 297 bool completed = false; 298 Base::Callback callback = [&completed](Base&) { completed = true; }; 299 sd_event_handler_t event_handler; 300 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_)) 301 .WillOnce(DoAll(SaveArg<1>(&event_handler), Return(0))); 302 base->set_prepare(std::move(callback)); 303 EXPECT_TRUE(base->get_prepare()); 304 EXPECT_FALSE(callback); 305 EXPECT_FALSE(completed); 306 307 EXPECT_EQ(0, event_handler(nullptr, base.get())); 308 EXPECT_TRUE(completed); 309 } 310 311 TEST_F(BaseMethodTest, SetPrepareCallbackNoUserdata) 312 { 313 Base::Callback callback = [](Base&) {}; 314 sd_event_handler_t event_handler; 315 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_)) 316 .WillOnce(DoAll(SaveArg<1>(&event_handler), Return(0))); 317 base->set_prepare(std::move(callback)); 318 EXPECT_TRUE(base->get_prepare()); 319 EXPECT_FALSE(callback); 320 321 EXPECT_EQ(-EINVAL, event_handler(nullptr, nullptr)); 322 } 323 324 TEST_F(BaseMethodTest, SetPrepareError) 325 { 326 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_)) 327 .WillOnce(Return(0)); 328 base->set_prepare(std::move([](Base&) {})); 329 EXPECT_TRUE(base->get_prepare()); 330 331 Base::Callback callback = [](Base&) {}; 332 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_)) 333 .WillOnce(Return(-EINVAL)); 334 EXPECT_THROW(base->set_prepare(std::move(callback)), SdEventError); 335 EXPECT_FALSE(base->get_prepare()); 336 EXPECT_TRUE(callback); 337 } 338 339 TEST_F(BaseMethodTest, SetPrepareNull) 340 { 341 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_)) 342 .WillOnce(Return(0)); 343 base->set_prepare(std::move([](Base&) {})); 344 EXPECT_TRUE(base->get_prepare()); 345 346 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, nullptr)) 347 .WillOnce(Return(0)); 348 base->set_prepare(nullptr); 349 EXPECT_FALSE(base->get_prepare()); 350 } 351 352 TEST_F(BaseMethodTest, GetPendingSuccess) 353 { 354 EXPECT_CALL(mock, sd_event_source_get_pending(expected_source)) 355 .WillOnce(Return(0)); 356 EXPECT_EQ(0, base->get_pending()); 357 EXPECT_CALL(mock, sd_event_source_get_pending(expected_source)) 358 .WillOnce(Return(4)); 359 EXPECT_EQ(4, base->get_pending()); 360 } 361 362 TEST_F(BaseMethodTest, GetPendingError) 363 { 364 EXPECT_CALL(mock, sd_event_source_get_pending(expected_source)) 365 .WillOnce(Return(-EINVAL)); 366 EXPECT_THROW(base->get_pending(), SdEventError); 367 } 368 369 TEST_F(BaseMethodTest, GetPrioritySuccess) 370 { 371 EXPECT_CALL(mock, sd_event_source_get_priority(expected_source, testing::_)) 372 .WillOnce(DoAll(SetArgPointee<1>(1024), Return(0))); 373 EXPECT_EQ(1024, base->get_priority()); 374 } 375 376 TEST_F(BaseMethodTest, GetPriorityError) 377 { 378 EXPECT_CALL(mock, sd_event_source_get_priority(expected_source, testing::_)) 379 .WillOnce(Return(-EINVAL)); 380 EXPECT_THROW(base->get_priority(), SdEventError); 381 } 382 383 TEST_F(BaseMethodTest, SetPrioritySuccess) 384 { 385 EXPECT_CALL(mock, sd_event_source_set_priority(expected_source, 1024)) 386 .WillOnce(Return(0)); 387 base->set_priority(1024); 388 } 389 390 TEST_F(BaseMethodTest, SetPriorityError) 391 { 392 EXPECT_CALL(mock, sd_event_source_set_priority(expected_source, 1024)) 393 .WillOnce(Return(-EINVAL)); 394 EXPECT_THROW(base->set_priority(1024), SdEventError); 395 } 396 397 TEST_F(BaseMethodTest, GetEnabledSuccess) 398 { 399 EXPECT_CALL(mock, sd_event_source_get_enabled(expected_source, testing::_)) 400 .WillOnce(DoAll(SetArgPointee<1>(SD_EVENT_ON), Return(0))); 401 EXPECT_EQ(SD_EVENT_ON, base->get_enabled()); 402 } 403 404 TEST_F(BaseMethodTest, GetEnabledError) 405 { 406 EXPECT_CALL(mock, sd_event_source_get_enabled(expected_source, testing::_)) 407 .WillOnce(Return(-EINVAL)); 408 EXPECT_THROW(base->get_enabled(), SdEventError); 409 } 410 411 TEST_F(BaseMethodTest, SetEnabledSuccess) 412 { 413 EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, SD_EVENT_ON)) 414 .WillOnce(Return(0)); 415 base->set_enabled(SD_EVENT_ON); 416 } 417 418 TEST_F(BaseMethodTest, SetEnabledError) 419 { 420 EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, SD_EVENT_ON)) 421 .WillOnce(Return(-EINVAL)); 422 EXPECT_THROW(base->set_enabled(SD_EVENT_ON), SdEventError); 423 } 424 425 } // namespace 426 } // namespace source 427 } // namespace sdeventplus 428