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