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