Add Redis Sentinel based database discovery
[ric-plt/sdl.git] / tst / engineimpl_test.cpp
1 /*
2    Copyright (c) 2018-2019 Nokia.
3
4    Licensed under the Apache License, Version 2.0 (the "License");
5    you may not use this file except in compliance with the License.
6    You may obtain a copy of the License at
7
8        http://www.apache.org/licenses/LICENSE-2.0
9
10    Unless required by applicable law or agreed to in writing, software
11    distributed under the License is distributed on an "AS IS" BASIS,
12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    See the License for the specific language governing permissions and
14    limitations under the License.
15 */
16
17 #include <memory>
18 #include <sys/epoll.h>
19 #include <gmock/gmock.h>
20 #include "private/filedescriptor.hpp"
21 #include "private/engineimpl.hpp"
22 #include "private/tst/systemmock.hpp"
23
24 using namespace shareddatalayer;
25 using namespace shareddatalayer::tst;
26 using namespace testing;
27
28 namespace
29 {
30     class EventHandlerMock
31     {
32     public:
33         MOCK_METHOD1(handleEvents, void(unsigned int events));
34     };
35
36     class EngineImplTest: public testing::Test
37     {
38     public:
39         const int fd1;
40         const int fd2;
41         const int epfd;
42         NiceMock<SystemMock> systemMock;
43         std::shared_ptr<EngineImpl> services;
44         EventHandlerMock eventHandlerMock1;
45         EventHandlerMock eventHandlerMock2;
46
47         EngineImplTest(): fd1(100), fd2(200), epfd(300)
48         {
49             EXPECT_CALL(systemMock, epoll_create1(EPOLL_CLOEXEC))
50                 .Times(1)
51                 .WillOnce(Return(epfd));
52             services.reset(new EngineImpl(systemMock));
53             Mock::VerifyAndClear(&systemMock);
54         }
55
56         ~EngineImplTest()
57         {
58             stopEngineImpl();
59         }
60
61         void addMonitoredFD(int fd, unsigned int events)
62         {
63             services->addMonitoredFD(fd, events, [] (unsigned int) { });
64         }
65
66         void addMonitoredFD(int fd, unsigned int events, EventHandlerMock& eventHandlerMock)
67         {
68             services->addMonitoredFD(fd, events, std::bind(&EventHandlerMock::handleEvents, &eventHandlerMock, std::placeholders::_1));
69         }
70
71         void modifyMonitoredFD(int fd, unsigned int events)
72         {
73             services->modifyMonitoredFD(fd, events);
74         }
75
76         void deleteMonitoredFD(int fd)
77         {
78             services->deleteMonitoredFD(fd);
79         }
80
81         void expectEpollCtl(int epfd, int op, int fd, unsigned int events)
82         {
83             EXPECT_CALL(systemMock, epoll_ctl(epfd, op, fd, NotNull()))
84                 .Times(1)
85                 .WillOnce(Invoke([fd, events] (int, int, int, epoll_event* event)
86                                  {
87                                      epoll_data data = { };
88                                      data.fd = fd;
89                                      EXPECT_EQ(data.fd, event->data.fd);
90                                      EXPECT_EQ(data.u64, event->data.u64);
91                                      EXPECT_EQ(data.ptr, event->data.ptr);
92                                      EXPECT_EQ(events, event->events);
93                                  }));
94         }
95
96         void expectAtLeastOneEpollCtl(int epfd, int op, int fd, unsigned int events)
97         {
98             EXPECT_CALL(systemMock, epoll_ctl(epfd, op, fd, NotNull()))
99                 .Times(AtLeast(1))
100                 .WillOnce(Invoke([fd, events] (int, int, int, epoll_event* event)
101                                  {
102                                      EXPECT_EQ(fd, event->data.fd);
103                                      EXPECT_EQ(events, event->events);
104                                  }));
105         }
106
107         void stopEngineImpl()
108         {
109             if (!services)
110                 return;
111
112             EXPECT_CALL(systemMock, close(epfd)).Times(1);
113             services.reset();
114             Mock::VerifyAndClear(&systemMock);
115         }
116     };
117
118     using EngineImplDeathTest = EngineImplTest;
119 }
120
121 TEST_F(EngineImplTest, HandleEventsWithoutAnyAddedFDsDoesNothing)
122 {
123     EXPECT_CALL(systemMock, epoll_wait(_, _, _, _))
124         .Times(0);
125     services->handleEvents();
126 }
127
128 TEST_F(EngineImplTest, FDReturnsTheEpollFD)
129 {
130     EXPECT_EQ(epfd, services->fd());
131 }
132
133 TEST_F(EngineImplTest, AddingFDAddsTheFDToEpoll)
134 {
135     expectEpollCtl(epfd, EPOLL_CTL_ADD, fd1, Engine::EVENT_IN);
136     addMonitoredFD(fd1, Engine::EVENT_IN);
137 }
138
139 TEST_F(EngineImplTest, AddingFileDescriptorSetsAtCloseCallback)
140 {
141     FileDescriptor fd(systemMock, fd1);
142     expectEpollCtl(epfd, EPOLL_CTL_ADD, fd1, Engine::EVENT_IN);
143     services->addMonitoredFD(fd, Engine::EVENT_IN, Engine::EventHandler());
144
145     InSequence dummy;
146     EXPECT_CALL(systemMock, epoll_ctl(epfd, EPOLL_CTL_DEL, fd1, nullptr))
147         .Times(1);
148     EXPECT_CALL(systemMock, close(fd1)).Times(1);
149 }
150
151 TEST_F(EngineImplDeathTest, AddingAlreadyAddedFDCallsSHAREDDATALAYER_ABORT)
152 {
153     expectAtLeastOneEpollCtl(epfd, EPOLL_CTL_ADD, fd1, Engine::EVENT_IN);
154     addMonitoredFD(fd1, Engine::EVENT_IN);
155     EXPECT_EXIT(addMonitoredFD(fd1, Engine::EVENT_IN),
156         KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
157 }
158
159 TEST_F(EngineImplTest, ModifyingFDModifiesTheFDInEpoll)
160 {
161     addMonitoredFD(fd1, Engine::EVENT_IN);
162     expectEpollCtl(epfd, EPOLL_CTL_MOD, fd1, Engine::EVENT_OUT);
163     modifyMonitoredFD(fd1, Engine::EVENT_OUT);
164 }
165
166 TEST_F(EngineImplDeathTest, ModifyingNonExistingFDCallsSHAREDDATALAYER_ABORT)
167 {
168     EXPECT_EXIT(modifyMonitoredFD(fd1, 0U),
169         KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
170 }
171
172 TEST_F(EngineImplDeathTest, DellingFDDelsTheFDFromEpollAndFromTheMap)
173 {
174     addMonitoredFD(fd1, Engine::EVENT_IN);
175     EXPECT_CALL(systemMock, epoll_ctl(epfd, EPOLL_CTL_DEL, fd1, nullptr))
176         .Times(1);
177     deleteMonitoredFD(fd1);
178     EXPECT_EXIT(modifyMonitoredFD(fd1, 0U),
179         KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
180 }
181
182 TEST_F(EngineImplDeathTest, DellingNonExistingFDCallsSHAREDDATALAYER_ABORT)
183 {
184     EXPECT_EXIT(deleteMonitoredFD(fd1),
185         KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
186 }
187
188 TEST_F(EngineImplTest, HandleEventsCallsAddedEventHandlersAccordingToEpollReturnValue)
189 {
190     addMonitoredFD(fd1, Engine::EVENT_IN, eventHandlerMock1);
191     addMonitoredFD(fd2, Engine::EVENT_IN, eventHandlerMock2);
192     InSequence dummy;
193     EXPECT_CALL(systemMock, epoll_wait(epfd, NotNull(), 2, 0))
194         .Times(1)
195         .WillOnce(Invoke([this] (int, epoll_event* events, int, int) -> int
196                          {
197                              events[0].events = EPOLLIN;
198                              events[0].data.fd = fd1;
199                              events[1].events = EPOLLOUT;
200                              events[1].data.fd = fd2;
201                              return 2;
202                          }));
203     EXPECT_CALL(eventHandlerMock1, handleEvents(Engine::EVENT_IN))
204         .Times(1);
205     EXPECT_CALL(eventHandlerMock2, handleEvents(Engine::EVENT_OUT))
206         .Times(1);
207     services->handleEvents();
208 }
209
210 TEST_F(EngineImplTest, PendingEventsOfDeletedFileDescriptorAreForgotten)
211 {
212     addMonitoredFD(fd1, Engine::EVENT_IN, eventHandlerMock1);
213     addMonitoredFD(fd2, Engine::EVENT_IN, eventHandlerMock2);
214     InSequence dummy;
215     EXPECT_CALL(eventHandlerMock2, handleEvents(_))
216         .Times(0);
217     EXPECT_CALL(systemMock, epoll_wait(epfd, NotNull(), 2, 0))
218         .Times(1)
219         .WillOnce(Invoke([this] (int, epoll_event* events, int, int) -> int
220                          {
221                              events[0].events = EPOLLIN;
222                              events[0].data.fd = fd1;
223                              events[1].events = EPOLLIN;
224                              events[1].data.fd = fd2;
225                              return 2;
226                          }));
227     EXPECT_CALL(eventHandlerMock1, handleEvents(_))
228         .Times(1)
229         .WillOnce(Invoke([this](unsigned int)
230                          {
231                              deleteMonitoredFD(fd2);
232                              addMonitoredFD(fd2, Engine::EVENT_IN, eventHandlerMock2);
233                          }));
234     services->handleEvents();
235 }