blob: 0ca093b7611868831aa903ce8bb2edce92e45487 [file] [log] [blame]
William A. Kennington III48c42752018-07-17 14:40:14 -07001#include <cerrno>
William A. Kennington III0a816c52018-07-17 14:40:14 -07002#include <gmock/gmock.h>
3#include <gtest/gtest.h>
William A. Kennington III715c72f2018-07-17 14:40:14 -07004#include <memory>
5#include <sdeventplus/event.hpp>
William A. Kennington III65db8632018-07-17 14:40:14 -07006#include <sdeventplus/exception.hpp>
William A. Kennington III0a816c52018-07-17 14:40:14 -07007#include <sdeventplus/internal/sdevent.hpp>
8#include <sdeventplus/source/base.hpp>
9#include <sdeventplus/test/sdevent.hpp>
William A. Kennington III65db8632018-07-17 14:40:14 -070010#include <string>
William A. Kennington III48c42752018-07-17 14:40:14 -070011#include <system_error>
William A. Kennington III715c72f2018-07-17 14:40:14 -070012#include <systemd/sd-event.h>
William A. Kennington III0a816c52018-07-17 14:40:14 -070013#include <type_traits>
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -070014#include <utility>
William A. Kennington III0a816c52018-07-17 14:40:14 -070015
16namespace sdeventplus
17{
18namespace source
19{
20namespace
21{
22
William A. Kennington III65db8632018-07-17 14:40:14 -070023using testing::DoAll;
William A. Kennington III0a816c52018-07-17 14:40:14 -070024using testing::Return;
William A. Kennington III48c42752018-07-17 14:40:14 -070025using testing::SaveArg;
William A. Kennington III65db8632018-07-17 14:40:14 -070026using testing::SetArgPointee;
William A. Kennington III0a816c52018-07-17 14:40:14 -070027
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -070028using UniqueEvent = std::unique_ptr<Event, std::function<void(Event*)>>;
29
William A. Kennington III0a816c52018-07-17 14:40:14 -070030class BaseImpl : public Base
31{
32 public:
William A. Kennington III715c72f2018-07-17 14:40:14 -070033 BaseImpl(const Event& event, sd_event_source* source) : Base(event, source)
William A. Kennington III0a816c52018-07-17 14:40:14 -070034 {
35 }
William A. Kennington III715c72f2018-07-17 14:40:14 -070036 BaseImpl(const Event& event, sd_event_source* source, std::false_type) :
37 Base(event, source, std::false_type())
William A. Kennington III0a816c52018-07-17 14:40:14 -070038 {
39 }
40};
41
42class BaseTest : public testing::Test
43{
44 protected:
45 testing::StrictMock<test::SdEventMock> mock;
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -070046 sd_event_source* const expected_source =
47 reinterpret_cast<sd_event_source*>(1234);
48 sd_event* const expected_event = reinterpret_cast<sd_event*>(2345);
49 UniqueEvent event = make_event(expected_event);
William A. Kennington III715c72f2018-07-17 14:40:14 -070050
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -070051 UniqueEvent make_event(sd_event* event)
William A. Kennington III715c72f2018-07-17 14:40:14 -070052 {
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -070053 auto deleter = [this, event](Event* e) {
54 EXPECT_CALL(this->mock, sd_event_unref(event))
55 .WillOnce(Return(nullptr));
56 delete e;
57 };
58 return UniqueEvent(new Event(event, std::false_type(), &mock), deleter);
William A. Kennington III715c72f2018-07-17 14:40:14 -070059 }
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -070060
61 // Using a unique_ptr to make sure we don't get any superfluous moves or
62 // copies.
63 std::unique_ptr<BaseImpl> make_base(const Event& event,
64 sd_event_source* source)
William A. Kennington III715c72f2018-07-17 14:40:14 -070065 {
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -070066 EXPECT_CALL(mock, sd_event_ref(event.get()))
67 .WillOnce(Return(event.get()));
68 auto ret = std::make_unique<BaseImpl>(event, source, std::false_type());
69 EXPECT_EQ(source, ret->get());
70 EXPECT_NE(&event, &ret->get_event());
71 EXPECT_EQ(event.get(), ret->get_event().get());
72 EXPECT_FALSE(ret->get_prepare());
73 return ret;
74 }
75
76 void set_prepare_placeholder(Base& base)
77 {
78 EXPECT_CALL(mock, sd_event_source_set_prepare(base.get(), testing::_))
79 .WillOnce(Return(0));
80 base.set_prepare([](Base&) {});
81 EXPECT_TRUE(base.get_prepare());
82 }
83
84 void empty_base(BaseImpl&& other)
85 {
86 BaseImpl mover(std::move(other));
87 EXPECT_EQ(nullptr, other.get());
88 EXPECT_EQ(nullptr, other.get_event().get());
89 EXPECT_FALSE(other.get_prepare());
90
91 expect_base_destruct(mover.get_event(), mover.get());
92 }
93
94 void expect_base_destruct(const Event& event, sd_event_source* source)
95 {
96 {
97 testing::InSequence seq;
98 EXPECT_CALL(mock, sd_event_source_set_enabled(source, SD_EVENT_OFF))
99 .WillOnce(Return(0));
100 EXPECT_CALL(mock, sd_event_source_unref(source))
101 .WillOnce(Return(nullptr));
102 }
103 EXPECT_CALL(mock, sd_event_unref(event.get()))
William A. Kennington III715c72f2018-07-17 14:40:14 -0700104 .WillOnce(Return(nullptr));
William A. Kennington III715c72f2018-07-17 14:40:14 -0700105 }
William A. Kennington III0a816c52018-07-17 14:40:14 -0700106};
107
108TEST_F(BaseTest, NewBaseRef)
109{
William A. Kennington III715c72f2018-07-17 14:40:14 -0700110 EXPECT_CALL(mock, sd_event_ref(expected_event))
111 .WillOnce(Return(expected_event));
William A. Kennington III0a816c52018-07-17 14:40:14 -0700112 EXPECT_CALL(mock, sd_event_source_ref(expected_source))
113 .WillOnce(Return(expected_source));
William A. Kennington III715c72f2018-07-17 14:40:14 -0700114 BaseImpl source(*event, expected_source);
William A. Kennington III4863b962018-07-17 14:40:14 -0700115 EXPECT_EQ(expected_source, source.get());
116 EXPECT_NE(event.get(), &source.get_event());
117 EXPECT_EQ(expected_event, source.get_event().get());
William A. Kennington IIIf5285c72018-07-17 14:40:14 -0700118 EXPECT_FALSE(source.get_prepare());
William A. Kennington III0a816c52018-07-17 14:40:14 -0700119
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700120 expect_base_destruct(*event, expected_source);
William A. Kennington III0a816c52018-07-17 14:40:14 -0700121}
122
123TEST_F(BaseTest, NewBaseNoRef)
124{
William A. Kennington III715c72f2018-07-17 14:40:14 -0700125 EXPECT_CALL(mock, sd_event_ref(expected_event))
126 .WillOnce(Return(expected_event));
127 BaseImpl source(*event, expected_source, std::false_type());
William A. Kennington III4863b962018-07-17 14:40:14 -0700128 EXPECT_EQ(expected_source, source.get());
129 EXPECT_NE(event.get(), &source.get_event());
130 EXPECT_EQ(expected_event, source.get_event().get());
William A. Kennington IIIf5285c72018-07-17 14:40:14 -0700131 EXPECT_FALSE(source.get_prepare());
William A. Kennington III0a816c52018-07-17 14:40:14 -0700132
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700133 expect_base_destruct(*event, expected_source);
William A. Kennington III7c24e052018-07-17 14:40:14 -0700134}
135
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700136TEST_F(BaseTest, MoveConstruct)
137{
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700138 std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source);
139 set_prepare_placeholder(*source1);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700140
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700141 BaseImpl source2(std::move(*source1));
142 EXPECT_EQ(nullptr, source1->get());
143 EXPECT_EQ(nullptr, source1->get_event().get());
144 EXPECT_FALSE(source1->get_prepare());
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700145 EXPECT_EQ(expected_source, source2.get());
146 EXPECT_EQ(expected_event, source2.get_event().get());
147 EXPECT_TRUE(source2.get_prepare());
148
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700149 expect_base_destruct(*event, expected_source);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700150}
151
152TEST_F(BaseTest, MoveAssignSelf)
153{
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700154 std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source);
155 set_prepare_placeholder(*source1);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700156
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700157 *source1 = std::move(*source1);
158 EXPECT_EQ(expected_source, source1->get());
159 EXPECT_EQ(expected_event, source1->get_event().get());
160 EXPECT_TRUE(source1->get_prepare());
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700161
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700162 expect_base_destruct(*event, expected_source);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700163}
164
165TEST_F(BaseTest, MoveAssignEmpty)
166{
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700167 std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source);
168 set_prepare_placeholder(*source1);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700169
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700170 std::unique_ptr<BaseImpl> source2 = make_base(*event, expected_source);
171 empty_base(std::move(*source2));
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700172
173 {
174 testing::InSequence seq;
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700175 *source2 = std::move(*source1);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700176 }
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700177 EXPECT_EQ(nullptr, source1->get());
178 EXPECT_EQ(nullptr, source1->get_event().get());
179 EXPECT_FALSE(source1->get_prepare());
180 EXPECT_EQ(expected_source, source2->get());
181 EXPECT_EQ(expected_event, source2->get_event().get());
182 EXPECT_TRUE(source2->get_prepare());
183
184 // Make sure source1 is deleted to ensure it isn't holding a reference
185 source1.reset();
186 expect_base_destruct(*event, expected_source);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700187}
188
189TEST_F(BaseTest, MoveAssignExisting)
190{
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700191 sd_event_source* const expected_source2 =
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700192 reinterpret_cast<sd_event_source*>(3456);
193 sd_event* const expected_event2 = reinterpret_cast<sd_event*>(4567);
194
195 std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source);
196 set_prepare_placeholder(*source1);
197
198 UniqueEvent event2 = make_event(expected_event2);
199 std::unique_ptr<BaseImpl> source2 = make_base(*event2, expected_source2);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700200
201 {
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700202 expect_base_destruct(*event2, expected_source2);
203 *source2 = std::move(*source1);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700204 }
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700205 EXPECT_EQ(nullptr, source1->get());
206 EXPECT_EQ(nullptr, source1->get_event().get());
207 EXPECT_FALSE(source1->get_prepare());
208 EXPECT_EQ(expected_source, source2->get());
209 EXPECT_EQ(expected_event, source2->get_event().get());
210 EXPECT_TRUE(source2->get_prepare());
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700211
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700212 // Make sure source1 is deleted to ensure it isn't holding a reference
213 source1.reset();
214 expect_base_destruct(*event, expected_source);
William A. Kennington IIIcc6b12b2018-07-17 14:40:14 -0700215}
216
William A. Kennington III65db8632018-07-17 14:40:14 -0700217class BaseMethodTest : public BaseTest
218{
219 protected:
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700220 std::unique_ptr<BaseImpl> base = make_base(*event, expected_source);
William A. Kennington III65db8632018-07-17 14:40:14 -0700221
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700222 void TearDown()
William A. Kennington III65db8632018-07-17 14:40:14 -0700223 {
William A. Kennington IIIe3e1df02018-07-17 14:40:14 -0700224 expect_base_destruct(base->get_event(), base->get());
William A. Kennington III715c72f2018-07-17 14:40:14 -0700225 base.reset();
William A. Kennington III65db8632018-07-17 14:40:14 -0700226 }
227};
228
229TEST_F(BaseMethodTest, GetDescriptionSuccess)
230{
231 const char* expected = "test_desc";
232 EXPECT_CALL(mock,
233 sd_event_source_get_description(expected_source, testing::_))
234 .WillOnce(DoAll(SetArgPointee<1>(expected), Return(0)));
235 // Intentionally comparing pointers to make sure no copying is happening
236 EXPECT_EQ(expected, base->get_description());
237}
238
239TEST_F(BaseMethodTest, GetDescriptionError)
240{
241 EXPECT_CALL(mock,
242 sd_event_source_get_description(expected_source, testing::_))
243 .WillOnce(Return(-EINVAL));
244 EXPECT_THROW(base->get_description(), SdEventError);
245}
246
247TEST_F(BaseMethodTest, SetDescriptionSuccess)
248{
249 const char* expected = "test desc";
250 // Intentionally comparing pointers to make sure no copying is happening
251 EXPECT_CALL(mock,
252 sd_event_source_set_description(expected_source, expected))
253 .WillOnce(Return(0));
254 base->set_description(expected);
255}
256
257TEST_F(BaseMethodTest, SetDescriptionError)
258{
259 const char* expected = "test desc";
260 // Intentionally comparing pointers to make sure no copying is happening
261 EXPECT_CALL(mock,
262 sd_event_source_set_description(expected_source, expected))
263 .WillOnce(Return(-EINVAL));
264 EXPECT_THROW(base->set_description(expected), SdEventError);
265}
266
William A. Kennington III48c42752018-07-17 14:40:14 -0700267TEST_F(BaseMethodTest, SetPrepareCallback)
268{
269 bool completed = false;
270 Base::Callback callback = [&completed](Base&) { completed = true; };
271 sd_event_handler_t event_handler;
272 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
273 .WillOnce(DoAll(SaveArg<1>(&event_handler), Return(0)));
274 base->set_prepare(std::move(callback));
William A. Kennington IIIf5285c72018-07-17 14:40:14 -0700275 EXPECT_TRUE(base->get_prepare());
William A. Kennington III48c42752018-07-17 14:40:14 -0700276 EXPECT_FALSE(callback);
277 EXPECT_FALSE(completed);
278
279 EXPECT_EQ(0, event_handler(nullptr, base.get()));
280 EXPECT_TRUE(completed);
281}
282
283TEST_F(BaseMethodTest, SetPrepareCallbackNoUserdata)
284{
285 Base::Callback callback = [](Base&) {};
286 sd_event_handler_t event_handler;
287 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
288 .WillOnce(DoAll(SaveArg<1>(&event_handler), Return(0)));
289 base->set_prepare(std::move(callback));
William A. Kennington IIIf5285c72018-07-17 14:40:14 -0700290 EXPECT_TRUE(base->get_prepare());
William A. Kennington III48c42752018-07-17 14:40:14 -0700291 EXPECT_FALSE(callback);
292
293 EXPECT_EQ(-EINVAL, event_handler(nullptr, nullptr));
294}
295
296TEST_F(BaseMethodTest, SetPrepareNull)
297{
298 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, nullptr))
299 .WillOnce(Return(0));
300 base->set_prepare(nullptr);
301 EXPECT_EQ(-ENOSYS, base->prepareCallback());
302}
303
304TEST_F(BaseMethodTest, SetPrepareSystemError)
305{
306 Base::Callback callback = [](Base&) {
307 throw std::system_error(EBUSY, std::generic_category());
308 };
309 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
310 .WillOnce(Return(0));
311 base->set_prepare(std::move(callback));
William A. Kennington IIIf5285c72018-07-17 14:40:14 -0700312 EXPECT_TRUE(base->get_prepare());
William A. Kennington III48c42752018-07-17 14:40:14 -0700313 EXPECT_FALSE(callback);
314 EXPECT_EQ(-EBUSY, base->prepareCallback());
315}
316
317TEST_F(BaseMethodTest, SetPrepareUnknownException)
318{
319 Base::Callback callback = [](Base&) { throw static_cast<int>(1); };
320 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
321 .WillOnce(Return(0));
322 base->set_prepare(std::move(callback));
William A. Kennington IIIf5285c72018-07-17 14:40:14 -0700323 EXPECT_TRUE(base->get_prepare());
William A. Kennington III48c42752018-07-17 14:40:14 -0700324 EXPECT_FALSE(callback);
325 EXPECT_EQ(-ENOSYS, base->prepareCallback());
326}
327
328TEST_F(BaseMethodTest, SetPrepareError)
329{
330 Base::Callback callback = [](Base&) {};
331 EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
332 .WillOnce(Return(-EINVAL));
333 EXPECT_THROW(base->set_prepare(std::move(callback)), SdEventError);
William A. Kennington IIIf5285c72018-07-17 14:40:14 -0700334 EXPECT_FALSE(base->get_prepare());
William A. Kennington III48c42752018-07-17 14:40:14 -0700335 EXPECT_TRUE(callback);
336 EXPECT_EQ(-ENOSYS, base->prepareCallback());
337}
338
William A. Kennington III65db8632018-07-17 14:40:14 -0700339TEST_F(BaseMethodTest, GetPendingSuccess)
340{
341 EXPECT_CALL(mock, sd_event_source_get_pending(expected_source))
342 .WillOnce(Return(0));
343 EXPECT_EQ(0, base->get_pending());
344 EXPECT_CALL(mock, sd_event_source_get_pending(expected_source))
345 .WillOnce(Return(4));
346 EXPECT_EQ(4, base->get_pending());
347}
348
349TEST_F(BaseMethodTest, GetPendingError)
350{
351 EXPECT_CALL(mock, sd_event_source_get_pending(expected_source))
352 .WillOnce(Return(-EINVAL));
353 EXPECT_THROW(base->get_pending(), SdEventError);
354}
355
356TEST_F(BaseMethodTest, GetPrioritySuccess)
357{
358 EXPECT_CALL(mock, sd_event_source_get_priority(expected_source, testing::_))
359 .WillOnce(DoAll(SetArgPointee<1>(1024), Return(0)));
360 EXPECT_EQ(1024, base->get_priority());
361}
362
363TEST_F(BaseMethodTest, GetPriorityError)
364{
365 EXPECT_CALL(mock, sd_event_source_get_priority(expected_source, testing::_))
366 .WillOnce(Return(-EINVAL));
367 EXPECT_THROW(base->get_priority(), SdEventError);
368}
369
370TEST_F(BaseMethodTest, SetPrioritySuccess)
371{
372 EXPECT_CALL(mock, sd_event_source_set_priority(expected_source, 1024))
373 .WillOnce(Return(0));
374 base->set_priority(1024);
375}
376
377TEST_F(BaseMethodTest, SetPriorityError)
378{
379 EXPECT_CALL(mock, sd_event_source_set_priority(expected_source, 1024))
380 .WillOnce(Return(-EINVAL));
381 EXPECT_THROW(base->set_priority(1024), SdEventError);
382}
383
384TEST_F(BaseMethodTest, GetEnabledSuccess)
385{
386 EXPECT_CALL(mock, sd_event_source_get_enabled(expected_source, testing::_))
387 .WillOnce(DoAll(SetArgPointee<1>(SD_EVENT_ON), Return(0)));
388 EXPECT_EQ(SD_EVENT_ON, base->get_enabled());
389}
390
391TEST_F(BaseMethodTest, GetEnabledError)
392{
393 EXPECT_CALL(mock, sd_event_source_get_enabled(expected_source, testing::_))
394 .WillOnce(Return(-EINVAL));
395 EXPECT_THROW(base->get_enabled(), SdEventError);
396}
397
398TEST_F(BaseMethodTest, SetEnabledSuccess)
399{
400 EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, SD_EVENT_ON))
401 .WillOnce(Return(0));
402 base->set_enabled(SD_EVENT_ON);
403}
404
405TEST_F(BaseMethodTest, SetEnabledError)
406{
407 EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, SD_EVENT_ON))
408 .WillOnce(Return(-EINVAL));
409 EXPECT_THROW(base->set_enabled(SD_EVENT_ON), SdEventError);
William A. Kennington III0a816c52018-07-17 14:40:14 -0700410}
411
412} // namespace
413} // namespace source
414} // namespace sdeventplus