xref: /openbmc/sdeventplus/test/source/base.cpp (revision 7c24e057)
1 #include <cerrno>
2 #include <gmock/gmock.h>
3 #include <gtest/gtest.h>
4 #include <memory>
5 #include <sdeventplus/event.hpp>
6 #include <sdeventplus/exception.hpp>
7 #include <sdeventplus/internal/sdevent.hpp>
8 #include <sdeventplus/source/base.hpp>
9 #include <sdeventplus/test/sdevent.hpp>
10 #include <string>
11 #include <system_error>
12 #include <systemd/sd-event.h>
13 #include <type_traits>
14 
15 namespace sdeventplus
16 {
17 namespace source
18 {
19 namespace
20 {
21 
22 using testing::DoAll;
23 using testing::Return;
24 using testing::SaveArg;
25 using testing::SetArgPointee;
26 
27 class BaseImpl : public Base
28 {
29   public:
30     BaseImpl(const Event& event, sd_event_source* source) : Base(event, source)
31     {
32     }
33     BaseImpl(const Event& event, sd_event_source* source, std::false_type) :
34         Base(event, source, std::false_type())
35     {
36     }
37 };
38 
39 class BaseTest : public testing::Test
40 {
41   protected:
42     testing::StrictMock<test::SdEventMock> mock;
43     sd_event_source* expected_source = reinterpret_cast<sd_event_source*>(1234);
44     sd_event* expected_event = reinterpret_cast<sd_event*>(2345);
45     std::unique_ptr<Event> event;
46 
47     virtual void SetUp()
48     {
49         event =
50             std::make_unique<Event>(expected_event, std::false_type(), &mock);
51     }
52     virtual void TearDown()
53     {
54         EXPECT_CALL(mock, sd_event_unref(expected_event))
55             .WillOnce(Return(nullptr));
56         event.reset();
57     }
58 };
59 
60 TEST_F(BaseTest, NewBaseRef)
61 {
62     EXPECT_CALL(mock, sd_event_ref(expected_event))
63         .WillOnce(Return(expected_event));
64     EXPECT_CALL(mock, sd_event_source_ref(expected_source))
65         .WillOnce(Return(expected_source));
66     BaseImpl source(*event, expected_source);
67 
68     {
69         testing::InSequence seq;
70         EXPECT_CALL(mock,
71                     sd_event_source_set_enabled(expected_source, SD_EVENT_OFF))
72             .WillOnce(Return(0));
73         EXPECT_CALL(mock, sd_event_source_unref(expected_source))
74             .WillOnce(Return(nullptr));
75     }
76     EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
77 }
78 
79 TEST_F(BaseTest, NewBaseNoRef)
80 {
81     EXPECT_CALL(mock, sd_event_ref(expected_event))
82         .WillOnce(Return(expected_event));
83     BaseImpl source(*event, expected_source, std::false_type());
84 
85     {
86         testing::InSequence seq;
87         EXPECT_CALL(mock,
88                     sd_event_source_set_enabled(expected_source, SD_EVENT_OFF))
89             .WillOnce(Return(0));
90         EXPECT_CALL(mock, sd_event_source_unref(expected_source))
91             .WillOnce(Return(nullptr));
92     }
93     EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
94 }
95 
96 TEST_F(BaseTest, NoSource)
97 {
98     EXPECT_CALL(mock, sd_event_ref(expected_event))
99         .WillOnce(Return(expected_event));
100     BaseImpl source(*event, nullptr, std::false_type());
101 
102     EXPECT_CALL(mock, sd_event_source_unref(nullptr)).WillOnce(Return(nullptr));
103     EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
104 }
105 
106 class BaseMethodTest : public BaseTest
107 {
108   protected:
109     std::unique_ptr<BaseImpl> base;
110 
111     void SetUp() override
112     {
113         BaseTest::SetUp();
114         EXPECT_CALL(mock, sd_event_ref(expected_event))
115             .WillOnce(Return(expected_event));
116         base = std::make_unique<BaseImpl>(*event, expected_source,
117                                           std::false_type());
118     }
119 
120     void TearDown() override
121     {
122         {
123             testing::InSequence seq;
124             EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source,
125                                                           SD_EVENT_OFF))
126                 .WillOnce(Return(0));
127             EXPECT_CALL(mock, sd_event_source_unref(expected_source))
128                 .WillOnce(Return(nullptr));
129         }
130         EXPECT_CALL(mock, sd_event_unref(expected_event))
131             .WillOnce(Return(nullptr));
132         base.reset();
133         BaseTest::TearDown();
134     }
135 };
136 
137 TEST_F(BaseMethodTest, GetEvent)
138 {
139     EXPECT_NE(event.get(), &base->get_event());
140     EXPECT_EQ(event->get(), base->get_event().get());
141 }
142 
143 TEST_F(BaseMethodTest, GetDescriptionSuccess)
144 {
145     const char* expected = "test_desc";
146     EXPECT_CALL(mock,
147                 sd_event_source_get_description(expected_source, testing::_))
148         .WillOnce(DoAll(SetArgPointee<1>(expected), Return(0)));
149     // Intentionally comparing pointers to make sure no copying is happening
150     EXPECT_EQ(expected, base->get_description());
151 }
152 
153 TEST_F(BaseMethodTest, GetDescriptionError)
154 {
155     EXPECT_CALL(mock,
156                 sd_event_source_get_description(expected_source, testing::_))
157         .WillOnce(Return(-EINVAL));
158     EXPECT_THROW(base->get_description(), SdEventError);
159 }
160 
161 TEST_F(BaseMethodTest, SetDescriptionSuccess)
162 {
163     const char* expected = "test desc";
164     // Intentionally comparing pointers to make sure no copying is happening
165     EXPECT_CALL(mock,
166                 sd_event_source_set_description(expected_source, expected))
167         .WillOnce(Return(0));
168     base->set_description(expected);
169 }
170 
171 TEST_F(BaseMethodTest, SetDescriptionError)
172 {
173     const char* expected = "test desc";
174     // Intentionally comparing pointers to make sure no copying is happening
175     EXPECT_CALL(mock,
176                 sd_event_source_set_description(expected_source, expected))
177         .WillOnce(Return(-EINVAL));
178     EXPECT_THROW(base->set_description(expected), SdEventError);
179 }
180 
181 TEST_F(BaseMethodTest, SetPrepareCallback)
182 {
183     bool completed = false;
184     Base::Callback callback = [&completed](Base&) { completed = true; };
185     sd_event_handler_t event_handler;
186     EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
187         .WillOnce(DoAll(SaveArg<1>(&event_handler), Return(0)));
188     base->set_prepare(std::move(callback));
189     EXPECT_FALSE(callback);
190     EXPECT_FALSE(completed);
191 
192     EXPECT_EQ(0, event_handler(nullptr, base.get()));
193     EXPECT_TRUE(completed);
194 }
195 
196 TEST_F(BaseMethodTest, SetPrepareCallbackNoUserdata)
197 {
198     Base::Callback callback = [](Base&) {};
199     sd_event_handler_t event_handler;
200     EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
201         .WillOnce(DoAll(SaveArg<1>(&event_handler), Return(0)));
202     base->set_prepare(std::move(callback));
203     EXPECT_FALSE(callback);
204 
205     EXPECT_EQ(-EINVAL, event_handler(nullptr, nullptr));
206 }
207 
208 TEST_F(BaseMethodTest, SetPrepareNull)
209 {
210     EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, nullptr))
211         .WillOnce(Return(0));
212     base->set_prepare(nullptr);
213     EXPECT_EQ(-ENOSYS, base->prepareCallback());
214 }
215 
216 TEST_F(BaseMethodTest, SetPrepareSystemError)
217 {
218     Base::Callback callback = [](Base&) {
219         throw std::system_error(EBUSY, std::generic_category());
220     };
221     EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
222         .WillOnce(Return(0));
223     base->set_prepare(std::move(callback));
224     EXPECT_FALSE(callback);
225     EXPECT_EQ(-EBUSY, base->prepareCallback());
226 }
227 
228 TEST_F(BaseMethodTest, SetPrepareUnknownException)
229 {
230     Base::Callback callback = [](Base&) { throw static_cast<int>(1); };
231     EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
232         .WillOnce(Return(0));
233     base->set_prepare(std::move(callback));
234     EXPECT_FALSE(callback);
235     EXPECT_EQ(-ENOSYS, base->prepareCallback());
236 }
237 
238 TEST_F(BaseMethodTest, SetPrepareError)
239 {
240     Base::Callback callback = [](Base&) {};
241     EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_))
242         .WillOnce(Return(-EINVAL));
243     EXPECT_THROW(base->set_prepare(std::move(callback)), SdEventError);
244     EXPECT_TRUE(callback);
245     EXPECT_EQ(-ENOSYS, base->prepareCallback());
246 }
247 
248 TEST_F(BaseMethodTest, GetPendingSuccess)
249 {
250     EXPECT_CALL(mock, sd_event_source_get_pending(expected_source))
251         .WillOnce(Return(0));
252     EXPECT_EQ(0, base->get_pending());
253     EXPECT_CALL(mock, sd_event_source_get_pending(expected_source))
254         .WillOnce(Return(4));
255     EXPECT_EQ(4, base->get_pending());
256 }
257 
258 TEST_F(BaseMethodTest, GetPendingError)
259 {
260     EXPECT_CALL(mock, sd_event_source_get_pending(expected_source))
261         .WillOnce(Return(-EINVAL));
262     EXPECT_THROW(base->get_pending(), SdEventError);
263 }
264 
265 TEST_F(BaseMethodTest, GetPrioritySuccess)
266 {
267     EXPECT_CALL(mock, sd_event_source_get_priority(expected_source, testing::_))
268         .WillOnce(DoAll(SetArgPointee<1>(1024), Return(0)));
269     EXPECT_EQ(1024, base->get_priority());
270 }
271 
272 TEST_F(BaseMethodTest, GetPriorityError)
273 {
274     EXPECT_CALL(mock, sd_event_source_get_priority(expected_source, testing::_))
275         .WillOnce(Return(-EINVAL));
276     EXPECT_THROW(base->get_priority(), SdEventError);
277 }
278 
279 TEST_F(BaseMethodTest, SetPrioritySuccess)
280 {
281     EXPECT_CALL(mock, sd_event_source_set_priority(expected_source, 1024))
282         .WillOnce(Return(0));
283     base->set_priority(1024);
284 }
285 
286 TEST_F(BaseMethodTest, SetPriorityError)
287 {
288     EXPECT_CALL(mock, sd_event_source_set_priority(expected_source, 1024))
289         .WillOnce(Return(-EINVAL));
290     EXPECT_THROW(base->set_priority(1024), SdEventError);
291 }
292 
293 TEST_F(BaseMethodTest, GetEnabledSuccess)
294 {
295     EXPECT_CALL(mock, sd_event_source_get_enabled(expected_source, testing::_))
296         .WillOnce(DoAll(SetArgPointee<1>(SD_EVENT_ON), Return(0)));
297     EXPECT_EQ(SD_EVENT_ON, base->get_enabled());
298 }
299 
300 TEST_F(BaseMethodTest, GetEnabledError)
301 {
302     EXPECT_CALL(mock, sd_event_source_get_enabled(expected_source, testing::_))
303         .WillOnce(Return(-EINVAL));
304     EXPECT_THROW(base->get_enabled(), SdEventError);
305 }
306 
307 TEST_F(BaseMethodTest, SetEnabledSuccess)
308 {
309     EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, SD_EVENT_ON))
310         .WillOnce(Return(0));
311     base->set_enabled(SD_EVENT_ON);
312 }
313 
314 TEST_F(BaseMethodTest, SetEnabledError)
315 {
316     EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, SD_EVENT_ON))
317         .WillOnce(Return(-EINVAL));
318     EXPECT_THROW(base->set_enabled(SD_EVENT_ON), SdEventError);
319 }
320 
321 } // namespace
322 } // namespace source
323 } // namespace sdeventplus
324