blob: 4cb6f86504c3f7f39f1a3f4575cbf61c0b4f89f6 [file] [log] [blame]
Rolf Badorekef2bf512019-08-20 11:17:15 +03001/*
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
Timo Tietavainena0745d22019-11-28 09:55:22 +020017/*
18 * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19 * platform project (RICP).
20*/
21
Rolf Badorekef2bf512019-08-20 11:17:15 +030022#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
29using namespace shareddatalayer;
30using namespace shareddatalayer::tst;
31using namespace testing;
32
33namespace
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
126TEST_F(EngineImplTest, HandleEventsWithoutAnyAddedFDsDoesNothing)
127{
128 EXPECT_CALL(systemMock, epoll_wait(_, _, _, _))
129 .Times(0);
130 services->handleEvents();
131}
132
133TEST_F(EngineImplTest, FDReturnsTheEpollFD)
134{
135 EXPECT_EQ(epfd, services->fd());
136}
137
138TEST_F(EngineImplTest, AddingFDAddsTheFDToEpoll)
139{
140 expectEpollCtl(epfd, EPOLL_CTL_ADD, fd1, Engine::EVENT_IN);
141 addMonitoredFD(fd1, Engine::EVENT_IN);
142}
143
144TEST_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
156TEST_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
164TEST_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
171TEST_F(EngineImplDeathTest, ModifyingNonExistingFDCallsSHAREDDATALAYER_ABORT)
172{
173 EXPECT_EXIT(modifyMonitoredFD(fd1, 0U),
174 KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
175}
176
177TEST_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
187TEST_F(EngineImplDeathTest, DellingNonExistingFDCallsSHAREDDATALAYER_ABORT)
188{
189 EXPECT_EXIT(deleteMonitoredFD(fd1),
190 KilledBySignal(SIGABRT), "ABORT.*engineimpl\\.cpp");
191}
192
193TEST_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
215TEST_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}