xref: /openbmc/sdeventplus/test/source/event.cpp (revision 5a7365c6e51fe4554b6a24455080974f3eeab4dc)
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