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<sdeventplus::Event, 27 std::function<void(sdeventplus::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](sdeventplus::Event* e) { 41 EXPECT_CALL(this->mock, sd_event_unref(event)) 42 .WillOnce(Return(nullptr)); 43 delete e; 44 }; 45 return UniqueEvent( 46 new sdeventplus::Event(event, std::false_type(), &mock), deleter); 47 } 48 49 void expect_destruct() 50 { 51 { 52 testing::InSequence sequence; 53 EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, 54 SD_EVENT_OFF)) 55 .WillOnce(Return(0)); 56 EXPECT_CALL(mock, sd_event_source_unref(expected_source)) 57 .WillOnce(Return(nullptr)); 58 } 59 EXPECT_CALL(mock, sd_event_unref(expected_event)) 60 .WillOnce(Return(nullptr)); 61 } 62 }; 63 64 TEST_F(EventTest, DeferConstruct) 65 { 66 EXPECT_CALL(mock, sd_event_ref(expected_event)) 67 .WillOnce(Return(expected_event)); 68 void* userdata; 69 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 70 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 71 sd_event_handler_t handler; 72 EXPECT_CALL(mock, sd_event_add_defer(expected_event, testing::_, testing::_, 73 nullptr)) 74 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 75 Return(0))); 76 int completions = 0; 77 Event::Callback callback = [&completions](Event&) { completions++; }; 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 Event::Callback callback = [&completions](Event&) { completions++; }; 103 Post post(*event, std::move(callback)); 104 EXPECT_EQ(&post, userdata); 105 EXPECT_FALSE(callback); 106 EXPECT_EQ(0, completions); 107 108 EXPECT_EQ(0, handler(nullptr, &post)); 109 EXPECT_EQ(1, completions); 110 111 expect_destruct(); 112 } 113 114 TEST_F(EventTest, ExitConstruct) 115 { 116 EXPECT_CALL(mock, sd_event_ref(expected_event)) 117 .WillOnce(Return(expected_event)); 118 void* userdata; 119 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 120 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 121 sd_event_handler_t handler; 122 EXPECT_CALL(mock, sd_event_add_exit(expected_event, testing::_, testing::_, 123 nullptr)) 124 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 125 Return(0))); 126 int completions = 0; 127 Event::Callback callback = [&completions](Event&) { completions++; }; 128 Exit exit(*event, std::move(callback)); 129 EXPECT_EQ(&exit, userdata); 130 EXPECT_FALSE(callback); 131 EXPECT_EQ(0, completions); 132 133 EXPECT_EQ(0, handler(nullptr, &exit)); 134 EXPECT_EQ(1, completions); 135 136 expect_destruct(); 137 } 138 139 TEST_F(EventTest, ConstructFailure) 140 { 141 EXPECT_CALL(mock, sd_event_add_defer(expected_event, testing::_, testing::_, 142 nullptr)) 143 .WillOnce(Return(-EINVAL)); 144 int completions = 0; 145 Event::Callback callback = [&completions](Event&) { completions++; }; 146 EXPECT_THROW(Defer(*event, std::move(callback)), SdEventError); 147 EXPECT_TRUE(callback); 148 EXPECT_EQ(0, completions); 149 } 150 151 } // namespace 152 } // namespace source 153 } // namespace sdeventplus 154