Add SDL developer and user guides
[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 /*
18  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19  * platform project (RICP).
20 */
21
22 #include <memory>
23 #include <sys/epoll.h>
24 #include <gmock/gmock.h>
25 #include "private/filedescriptor.hpp"
26 #include "private/engineimpl.hpp"
27 #include "private/tst/systemmock.hpp"
28
29 using namespace shareddatalayer;
30 using namespace shareddatalayer::tst;
31 using namespace testing;
32
33 namespace
34 {
35     class EventHandlerMock
36     {
37     public:
38         MOCK_METHOD1(handleEvents, void(unsigned int events));
39     };
40
41     class EngineImplTest: public testing::Test
42     {
43     public:
44         const int fd1;
45         const int fd2;
46         const int epfd;
47         NiceMock<SystemMock> systemMock;
48         std::shared_ptr<EngineImpl> services;
49         EventHandlerMock eventHandlerMock1;
50         EventHandlerMock eventHandlerMock2;
51
52         EngineImplTest(): fd1(100), fd2(200), epfd(300)
53         {
54             EXPECT_CALL(systemMock, epoll_create1(EPOLL_CLOEXEC))
55                 .Times(1)
56                 .WillOnce(Return(epfd));
57             services.reset(new EngineImpl(systemMock));
58             Mock::VerifyAndClear(&systemMock);
59         }
60
61         ~EngineImplTest()
62         {
63             stopEngineImpl();
64         }
65
66         void addMonitoredFD(int fd, unsigned int events)
67         {
68             services->addMonitoredFD(fd, events, [] (unsigned int) { });
69         }
70
71         void addMonitoredFD(int fd, unsigned int events, EventHandlerMock& eventHandlerMock)
72         {
73             services->addMonitoredFD(fd, events, std::bind(&EventHandlerMock::handleEvents, &eventHandlerMock, std::placeholders::_1));
74         }
75
76         void modifyMonitoredFD(int fd, unsigned int events)
77         {
78             services->modifyMonitoredFD(fd, events);
79         }
80
81         void deleteMonitoredFD(int fd)
82         {
83             services->deleteMonitoredFD(fd);
84         }
85
86         void expectEpollCtl(int epfd, int op, int fd, unsigned int events)
87         {
88             EXPECT_CALL(systemMock, epoll_ctl(epfd, op, fd, NotNull()))
89                 .Times(1)
90                 .WillOnce(Invoke([fd, events] (int, int, int, epoll_event* event)
91                                  {
92                                      epoll_data data = { };
93                                      data.fd = fd;
94                                      EXPECT_EQ(data.fd, event->data.fd);
95                                      EXPECT_EQ(data.u64, event->data.u64);
96                                      EXPECT_EQ(data.ptr, event->data.ptr);
97                                      EXPECT_EQ(events, event->events);
98                                  }));
99         }
100
101         void expectAtLeastOneEpollCtl(int epfd, int op, int fd, unsigned int events)
102         {
103             EXPECT_CALL(systemMock, epoll_ctl(epfd, op, fd, NotNull()))
104                 .Times(AtLeast(1))
105                 .WillOnce(Invoke([fd, events] (int, int, int, epoll_event* event)
106                                  {
107                                      EXPECT_EQ(fd, event->data.fd);
108                                      EXPECT_EQ(events, event->events);
109                                  }));
110         }
111
112         void stopEngineImpl()
113         {
114             if (!services)
115                 return;
116
117             EXPECT_CALL(systemMock, close(epfd)).Times(1);
118             services.reset();
119             Mock::VerifyAndClear(&systemMock);
120         }
121     };
122
123     using EngineImplDeathTest = EngineImplTest;
124 }
125
126 TEST_F(EngineImplTest, HandleEventsWithoutAnyAddedFDsDoesNothing)
127 {
128     EXPECT_CALL(systemMock, epoll_wait(_, _, _, _))
129         .Times(0);
130     services->handleEvents();
131 }
132
133 TEST_F(EngineImplTest, FDReturnsTheEpollFD)
134 {
135     EXPECT_EQ(epfd, services->fd());
136 }
137
138 TEST_F(EngineImplTest, AddingFDAddsTheFDToEpoll)
139 {
140     expectEpollCtl(epfd, EPOLL_CTL_ADD, fd1, Engine::EVENT_IN);
141     addMonitoredFD(fd1, Engine::EVENT_IN);
142 }
143
144 TEST_F(EngineImplTest, AddingFileDescriptorSetsAtCloseCallback)
145 {
146     FileDescriptor fd(systemMock, fd1);
147     expectEpollCtl(epfd, EPOLL_CTL_ADD, fd1, Engine::EVENT_IN);
148     services->addMonitoredFD(fd, Engine::EVENT_IN, Engine::EventHandler());
149
150     InSequence dummy;
151     EXPECT_CALL(systemMock, epoll_ctl(epfd, EPOLL_CTL_DEL, fd1, nullptr))
152         .Times(1);
153     EXPECT_CALL(systemMock, close(fd1)).Times(1);
154 }
155
156 TEST_F(EngineImplDeathTest, AddingAlreadyAddedFDCallsSHAREDDATALAYER_ABORT)
157 {
158     expectAtLeastOneEpollCtl(epfd, EPOLL_CTL_ADD, fd1, Engine::EVENT_IN);
159     addMonitoredFD(fd1, Engine::EVENT_IN);
160     EXPECT_EXIT(addMonitoredFD(fd1, Engine::EVENT_IN),
161         KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
162 }
163
164 TEST_F(EngineImplTest, ModifyingFDModifiesTheFDInEpoll)
165 {
166     addMonitoredFD(fd1, Engine::EVENT_IN);
167     expectEpollCtl(epfd, EPOLL_CTL_MOD, fd1, Engine::EVENT_OUT);
168     modifyMonitoredFD(fd1, Engine::EVENT_OUT);
169 }
170
171 TEST_F(EngineImplDeathTest, ModifyingNonExistingFDCallsSHAREDDATALAYER_ABORT)
172 {
173     EXPECT_EXIT(modifyMonitoredFD(fd1, 0U),
174         KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
175 }
176
177 TEST_F(EngineImplDeathTest, DellingFDDelsTheFDFromEpollAndFromTheMap)
178 {
179     addMonitoredFD(fd1, Engine::EVENT_IN);
180     EXPECT_CALL(systemMock, epoll_ctl(epfd, EPOLL_CTL_DEL, fd1, nullptr))
181         .Times(1);
182     deleteMonitoredFD(fd1);
183     EXPECT_EXIT(modifyMonitoredFD(fd1, 0U),
184         KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
185 }
186
187 TEST_F(EngineImplDeathTest, DellingNonExistingFDCallsSHAREDDATALAYER_ABORT)
188 {
189     EXPECT_EXIT(deleteMonitoredFD(fd1),
190         KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
191 }
192
193 TEST_F(EngineImplTest, HandleEventsCallsAddedEventHandlersAccordingToEpollReturnValue)
194 {
195     addMonitoredFD(fd1, Engine::EVENT_IN, eventHandlerMock1);
196     addMonitoredFD(fd2, Engine::EVENT_IN, eventHandlerMock2);
197     InSequence dummy;
198     EXPECT_CALL(systemMock, epoll_wait(epfd, NotNull(), 2, 0))
199         .Times(1)
200         .WillOnce(Invoke([this] (int, epoll_event* events, int, int) -> int
201                          {
202                              events[0].events = EPOLLIN;
203                              events[0].data.fd = fd1;
204                              events[1].events = EPOLLOUT;
205                              events[1].data.fd = fd2;
206                              return 2;
207                          }));
208     EXPECT_CALL(eventHandlerMock1, handleEvents(Engine::EVENT_IN))
209         .Times(1);
210     EXPECT_CALL(eventHandlerMock2, handleEvents(Engine::EVENT_OUT))
211         .Times(1);
212     services->handleEvents();
213 }
214
215 TEST_F(EngineImplTest, PendingEventsOfDeletedFileDescriptorAreForgotten)
216 {
217     addMonitoredFD(fd1, Engine::EVENT_IN, eventHandlerMock1);
218     addMonitoredFD(fd2, Engine::EVENT_IN, eventHandlerMock2);
219     InSequence dummy;
220     EXPECT_CALL(eventHandlerMock2, handleEvents(_))
221         .Times(0);
222     EXPECT_CALL(systemMock, epoll_wait(epfd, NotNull(), 2, 0))
223         .Times(1)
224         .WillOnce(Invoke([this] (int, epoll_event* events, int, int) -> int
225                          {
226                              events[0].events = EPOLLIN;
227                              events[0].data.fd = fd1;
228                              events[1].events = EPOLLIN;
229                              events[1].data.fd = fd2;
230                              return 2;
231                          }));
232     EXPECT_CALL(eventHandlerMock1, handleEvents(_))
233         .Times(1)
234         .WillOnce(Invoke([this](unsigned int)
235                          {
236                              deleteMonitoredFD(fd2);
237                              addMonitoredFD(fd2, Engine::EVENT_IN, eventHandlerMock2);
238                          }));
239     services->handleEvents();
240 }