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 <utility> 12 13 namespace sdeventplus 14 { 15 namespace source 16 { 17 namespace 18 { 19 20 using testing::DoAll; 21 using testing::Return; 22 using testing::SaveArg; 23 using testing::SetArgPointee; 24 25 using UniqueEvent = std::unique_ptr<sdeventplus::Event, 26 std::function<void(sdeventplus::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](sdeventplus::Event* e) { 40 EXPECT_CALL(this->mock, sd_event_unref(event)) 41 .WillOnce(Return(nullptr)); 42 delete e; 43 }; 44 return UniqueEvent( 45 new sdeventplus::Event(event, std::false_type(), &mock), deleter); 46 } 47 48 void expect_destruct() 49 { 50 { 51 testing::InSequence sequence; 52 EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, 53 SD_EVENT_OFF)) 54 .WillOnce(Return(0)); 55 EXPECT_CALL(mock, sd_event_source_unref(expected_source)) 56 .WillOnce(Return(nullptr)); 57 } 58 EXPECT_CALL(mock, sd_event_unref(expected_event)) 59 .WillOnce(Return(nullptr)); 60 } 61 }; 62 63 TEST_F(EventTest, DeferConstruct) 64 { 65 EXPECT_CALL(mock, sd_event_ref(expected_event)) 66 .WillOnce(Return(expected_event)); 67 void* userdata; 68 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 69 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 70 sd_event_handler_t handler; 71 EXPECT_CALL(mock, sd_event_add_defer(expected_event, testing::_, testing::_, 72 nullptr)) 73 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 74 Return(0))); 75 int completions = 0; 76 Event::Callback callback = [&completions](Event&) { completions++; }; 77 Defer defer(*event, std::move(callback)); 78 EXPECT_EQ(&defer, userdata); 79 EXPECT_FALSE(callback); 80 EXPECT_EQ(0, completions); 81 82 EXPECT_EQ(0, handler(nullptr, &defer)); 83 EXPECT_EQ(1, completions); 84 85 expect_destruct(); 86 } 87 88 TEST_F(EventTest, PostConstruct) 89 { 90 EXPECT_CALL(mock, sd_event_ref(expected_event)) 91 .WillOnce(Return(expected_event)); 92 void* userdata; 93 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 94 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 95 sd_event_handler_t handler; 96 EXPECT_CALL(mock, sd_event_add_post(expected_event, testing::_, testing::_, 97 nullptr)) 98 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 99 Return(0))); 100 int completions = 0; 101 Event::Callback callback = [&completions](Event&) { completions++; }; 102 Post post(*event, std::move(callback)); 103 EXPECT_EQ(&post, userdata); 104 EXPECT_FALSE(callback); 105 EXPECT_EQ(0, completions); 106 107 EXPECT_EQ(0, handler(nullptr, &post)); 108 EXPECT_EQ(1, completions); 109 110 expect_destruct(); 111 } 112 113 TEST_F(EventTest, ExitConstruct) 114 { 115 EXPECT_CALL(mock, sd_event_ref(expected_event)) 116 .WillOnce(Return(expected_event)); 117 void* userdata; 118 EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_)) 119 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr))); 120 sd_event_handler_t handler; 121 EXPECT_CALL(mock, sd_event_add_exit(expected_event, testing::_, testing::_, 122 nullptr)) 123 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler), 124 Return(0))); 125 int completions = 0; 126 Event::Callback callback = [&completions](Event&) { completions++; }; 127 Exit exit(*event, std::move(callback)); 128 EXPECT_EQ(&exit, userdata); 129 EXPECT_FALSE(callback); 130 EXPECT_EQ(0, completions); 131 132 EXPECT_EQ(0, handler(nullptr, &exit)); 133 EXPECT_EQ(1, completions); 134 135 expect_destruct(); 136 } 137 138 TEST_F(EventTest, ConstructFailure) 139 { 140 EXPECT_CALL(mock, sd_event_add_defer(expected_event, testing::_, testing::_, 141 nullptr)) 142 .WillOnce(Return(-EINVAL)); 143 int completions = 0; 144 Event::Callback callback = [&completions](Event&) { completions++; }; 145 EXPECT_THROW(Defer(*event, std::move(callback)), SdEventError); 146 EXPECT_TRUE(callback); 147 EXPECT_EQ(0, completions); 148 } 149 150 } // namespace 151 } // namespace source 152 } // namespace sdeventplus 153