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