blob: bafdeb8e15fa3800f238a835adfc0f1a799d7fdd [file] [log] [blame]
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -07001#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/io.hpp>
9#include <sdeventplus/test/sdevent.hpp>
10#include <systemd/sd-event.h>
11#include <type_traits>
12#include <utility>
13
14namespace sdeventplus
15{
16namespace source
17{
18namespace
19{
20
21using testing::DoAll;
22using testing::Return;
William A. Kennington III5320b1f2019-03-29 20:00:37 -070023using testing::ReturnPointee;
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -070024using testing::SaveArg;
25using testing::SetArgPointee;
26
27using UniqueEvent = std::unique_ptr<Event, std::function<void(Event*)>>;
28
29class IOTest : 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](Event* e) {
41 EXPECT_CALL(this->mock, sd_event_unref(event))
42 .WillOnce(Return(nullptr));
43 delete e;
44 };
45 return UniqueEvent(new Event(event, std::false_type(), &mock), deleter);
46 }
47
48 void expect_destruct()
49 {
William A. Kennington III5320b1f2019-03-29 20:00:37 -070050 EXPECT_CALL(mock, sd_event_source_unref(expected_source))
51 .WillOnce(Return(nullptr));
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -070052 EXPECT_CALL(mock, sd_event_unref(expected_event))
53 .WillOnce(Return(nullptr));
54 }
55};
56
57TEST_F(IOTest, ConstructSuccess)
58{
59 const int fd = 10;
60 const uint32_t events = EPOLLIN | EPOLLET;
61
62 EXPECT_CALL(mock, sd_event_ref(expected_event))
63 .WillOnce(Return(expected_event));
64 sd_event_io_handler_t handler;
65 EXPECT_CALL(mock, sd_event_add_io(expected_event, testing::_, fd, events,
66 testing::_, nullptr))
67 .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<4>(&handler),
68 Return(0)));
William A. Kennington III5320b1f2019-03-29 20:00:37 -070069 sd_event_destroy_t destroy;
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -070070 void* userdata;
William A. Kennington III5320b1f2019-03-29 20:00:37 -070071 {
72 testing::InSequence seq;
73 EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
74 testing::_))
75 .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
76 EXPECT_CALL(mock,
77 sd_event_source_set_userdata(expected_source, testing::_))
78 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
79 EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
80 .WillRepeatedly(ReturnPointee(&userdata));
81 }
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -070082 int completions = 0;
83 int return_fd;
84 uint32_t return_revents;
85 IO::Callback callback = [&](IO&, int fd, uint32_t revents) {
86 return_fd = fd;
87 return_revents = revents;
88 completions++;
89 };
90 IO io(*event, fd, events, std::move(callback));
91 EXPECT_FALSE(callback);
William A. Kennington III5320b1f2019-03-29 20:00:37 -070092 EXPECT_NE(&io, userdata);
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -070093 EXPECT_EQ(0, completions);
94
William A. Kennington III5320b1f2019-03-29 20:00:37 -070095 EXPECT_EQ(0, handler(nullptr, 5, EPOLLIN, userdata));
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -070096 EXPECT_EQ(1, completions);
97 EXPECT_EQ(5, return_fd);
98 EXPECT_EQ(EPOLLIN, return_revents);
99
William A. Kennington IIIb53ef902018-10-29 20:06:45 -0700100 io.set_callback(std::bind([]() {}));
William A. Kennington III5320b1f2019-03-29 20:00:37 -0700101 EXPECT_EQ(0, handler(nullptr, 5, EPOLLIN, userdata));
William A. Kennington IIIb53ef902018-10-29 20:06:45 -0700102 EXPECT_EQ(1, completions);
103
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -0700104 expect_destruct();
William A. Kennington III5320b1f2019-03-29 20:00:37 -0700105 destroy(userdata);
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -0700106}
107
108TEST_F(IOTest, ConstructError)
109{
110 const int fd = 10;
111 const uint32_t events = EPOLLIN | EPOLLET;
112
113 EXPECT_CALL(mock, sd_event_add_io(expected_event, testing::_, fd, events,
114 testing::_, nullptr))
115 .WillOnce(Return(-EINVAL));
116 int completions = 0;
117 IO::Callback callback = [&completions](IO&, int, uint32_t) {
118 completions++;
119 };
120 EXPECT_THROW(IO(*event, fd, events, std::move(callback)), SdEventError);
121 EXPECT_TRUE(callback);
122 EXPECT_EQ(0, completions);
123}
124
125class IOMethodTest : public IOTest
126{
127 protected:
128 std::unique_ptr<IO> io;
William A. Kennington III5320b1f2019-03-29 20:00:37 -0700129 sd_event_destroy_t destroy;
130 void* userdata;
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -0700131
132 void SetUp()
133 {
134 const int fd = 7;
135 const int events = EPOLLOUT;
136
137 EXPECT_CALL(mock, sd_event_ref(expected_event))
138 .WillOnce(Return(expected_event));
139 EXPECT_CALL(mock, sd_event_add_io(expected_event, testing::_, fd,
140 events, testing::_, nullptr))
141 .WillOnce(DoAll(SetArgPointee<1>(expected_source), Return(0)));
William A. Kennington III5320b1f2019-03-29 20:00:37 -0700142 {
143 testing::InSequence seq;
144 EXPECT_CALL(mock, sd_event_source_set_destroy_callback(
145 expected_source, testing::_))
146 .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
147 EXPECT_CALL(
148 mock, sd_event_source_set_userdata(expected_source, testing::_))
149 .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
150 EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
151 .WillRepeatedly(ReturnPointee(&userdata));
152 }
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -0700153 io =
154 std::make_unique<IO>(*event, fd, events, [](IO&, int, uint32_t) {});
155 }
156
157 void TearDown()
158 {
159 expect_destruct();
160 io.reset();
William A. Kennington III5320b1f2019-03-29 20:00:37 -0700161 destroy(userdata);
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -0700162 }
163};
164
165TEST_F(IOMethodTest, GetFdSuccess)
166{
167 const int fd = 5;
168 EXPECT_CALL(mock, sd_event_source_get_io_fd(expected_source))
169 .WillOnce(Return(fd));
170 EXPECT_EQ(fd, io->get_fd());
171}
172
173TEST_F(IOMethodTest, GetFdError)
174{
175 EXPECT_CALL(mock, sd_event_source_get_io_fd(expected_source))
176 .WillOnce(Return(-EINVAL));
177 EXPECT_THROW(io->get_fd(), SdEventError);
178}
179
180TEST_F(IOMethodTest, SetFdSuccess)
181{
182 const int fd = 5;
183 EXPECT_CALL(mock, sd_event_source_set_io_fd(expected_source, fd))
184 .WillOnce(Return(0));
185 io->set_fd(fd);
186}
187
188TEST_F(IOMethodTest, SetFdError)
189{
190 const int fd = 3;
191 EXPECT_CALL(mock, sd_event_source_set_io_fd(expected_source, fd))
192 .WillOnce(Return(-EINVAL));
193 EXPECT_THROW(io->set_fd(fd), SdEventError);
194}
195
William A. Kennington IIIce80c3f2018-07-22 14:59:13 -0700196TEST_F(IOMethodTest, GetEventsSuccess)
197{
198 const uint32_t events = EPOLLIN | EPOLLOUT;
199 EXPECT_CALL(mock,
200 sd_event_source_get_io_events(expected_source, testing::_))
201 .WillOnce(DoAll(SetArgPointee<1>(events), Return(0)));
202 EXPECT_EQ(events, io->get_events());
203}
204
205TEST_F(IOMethodTest, GetEventsError)
206{
207 EXPECT_CALL(mock,
208 sd_event_source_get_io_events(expected_source, testing::_))
209 .WillOnce(Return(-EINVAL));
210 EXPECT_THROW(io->get_events(), SdEventError);
211}
212
213TEST_F(IOMethodTest, SetEventsSuccess)
214{
215 const uint32_t events = EPOLLIN | EPOLLOUT;
216 EXPECT_CALL(mock, sd_event_source_set_io_events(expected_source, events))
217 .WillOnce(Return(0));
218 io->set_events(events);
219}
220
221TEST_F(IOMethodTest, SetEventsError)
222{
223 const uint32_t events = EPOLLIN | EPOLLOUT;
224 EXPECT_CALL(mock, sd_event_source_set_io_events(expected_source, events))
225 .WillOnce(Return(-EINVAL));
226 EXPECT_THROW(io->set_events(events), SdEventError);
227}
228
229TEST_F(IOMethodTest, GetREventsSuccess)
230{
231 const uint32_t revents = EPOLLOUT;
232 EXPECT_CALL(mock,
233 sd_event_source_get_io_revents(expected_source, testing::_))
234 .WillOnce(DoAll(SetArgPointee<1>(revents), Return(0)));
235 EXPECT_EQ(revents, io->get_revents());
236}
237
238TEST_F(IOMethodTest, GetREventsError)
239{
240 EXPECT_CALL(mock,
241 sd_event_source_get_io_revents(expected_source, testing::_))
242 .WillOnce(Return(-EINVAL));
243 EXPECT_THROW(io->get_revents(), SdEventError);
244}
245
246} // namespace
247} // namespace source
248} // namespace sdeventplus