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