2 Copyright (c) 2018-2019 Nokia.
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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
18 * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19 * platform project (RICP).
22 #include <type_traits>
24 #include <sys/epoll.h>
25 #include <gtest/gtest.h>
26 #include "private/redis/hiredisclusterepolladapter.hpp"
27 #include "private/tst/enginemock.hpp"
28 #include "private/tst/hiredisclustersystemmock.hpp"
30 using namespace shareddatalayer;
31 using namespace shareddatalayer::redis;
32 using namespace shareddatalayer::tst;
33 using namespace testing;
37 class HiredisClusterEpollAdapterTest: public testing::Test
40 StrictMock<EngineMock> engineMock;
41 StrictMock<HiredisClusterSystemMock> hiredisClusterSystemMock;
42 redisClusterAsyncContext acc;
43 std::unique_ptr<HiredisClusterEpollAdapter> adapter;
45 redisAsyncContext secondAc;
48 Engine::EventHandler savedEventHandler;
49 Engine::EventHandler anotherSavedEventHandler;
51 HiredisClusterEpollAdapterTest():
53 adapter(new HiredisClusterEpollAdapter(engineMock, hiredisClusterSystemMock)),
64 ~HiredisClusterEpollAdapterTest()
68 void expectAddMonitoredFD(int fd, unsigned int events)
70 EXPECT_CALL(engineMock, addMonitoredFD(fd,events,_))
72 .WillOnce(SaveArg<2>(&savedEventHandler));
75 void expectAddMonitoredFD2(int fd, unsigned int events)
77 EXPECT_CALL(engineMock, addMonitoredFD(fd,events,_))
79 .WillOnce(SaveArg<2>(&anotherSavedEventHandler));
82 void expectModifyMonitoredFD(int fd, unsigned int events)
84 EXPECT_CALL(engineMock, modifyMonitoredFD(fd,events))
88 void expectDeleteMonitoredFD(int fd)
90 EXPECT_CALL(engineMock, deleteMonitoredFD(fd))
95 class HiredisClusterEpollAdapterAttachedTest: public HiredisClusterEpollAdapterTest
98 HiredisClusterEpollAdapterAttachedTest()
100 expectAddMonitoredFD(ac.c.fd, 0);
101 acc.attach_fn(&ac, adapter.get());
104 ~HiredisClusterEpollAdapterAttachedTest()
106 expectDeleteMonitoredFD(ac.c.fd);
111 TEST_F(HiredisClusterEpollAdapterTest, IsNotCopyableAndIsNotMovable)
113 EXPECT_FALSE(std::is_copy_constructible<HiredisClusterEpollAdapter>::value);
114 EXPECT_FALSE(std::is_copy_assignable<HiredisClusterEpollAdapter>::value);
115 EXPECT_FALSE(std::is_move_constructible<HiredisClusterEpollAdapter>::value);
116 EXPECT_FALSE(std::is_move_assignable<HiredisClusterEpollAdapter>::value);
119 TEST_F(HiredisClusterEpollAdapterTest, HasVirtualDestructor)
121 EXPECT_TRUE(std::has_virtual_destructor<HiredisClusterEpollAdapter>::value);
124 TEST_F(HiredisClusterEpollAdapterAttachedTest, EventStateChangedIdempotently)
127 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
128 ac.ev.addRead(ac.ev.data);
129 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT);
130 ac.ev.addWrite(ac.ev.data);
131 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
132 ac.ev.delRead(ac.ev.data);
133 expectModifyMonitoredFD(ac.c.fd, 0);
134 ac.ev.delWrite(ac.ev.data);
135 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
136 ac.ev.addRead(ac.ev.data);
137 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT);
138 ac.ev.addWrite(ac.ev.data);
141 TEST_F(HiredisClusterEpollAdapterAttachedTest, InputEventIsSetOnce)
144 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
145 ac.ev.addRead(ac.ev.data);
146 ac.ev.addRead(ac.ev.data);
149 TEST_F(HiredisClusterEpollAdapterAttachedTest, OutputEventIsSetOnce)
152 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
153 ac.ev.addWrite(ac.ev.data);
154 ac.ev.addWrite(ac.ev.data);
157 TEST_F(HiredisClusterEpollAdapterAttachedTest, CanHandleInputEvent)
160 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
161 ac.ev.addRead(ac.ev.data);
162 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
164 savedEventHandler(EngineMock::EVENT_IN);
167 TEST_F(HiredisClusterEpollAdapterAttachedTest, DoesNotHandleInputEventIfNotReading)
170 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
172 savedEventHandler(EngineMock::EVENT_IN);
175 TEST_F(HiredisClusterEpollAdapterAttachedTest, CanHandleOutputEvent)
178 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
179 ac.ev.addWrite(ac.ev.data);
180 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleWrite(&ac))
182 savedEventHandler(EngineMock::EVENT_OUT);
185 TEST_F(HiredisClusterEpollAdapterAttachedTest, DoesNotHandleOutputEventIfNotWriting)
188 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleWrite(&ac))
190 savedEventHandler(EngineMock::EVENT_OUT);
193 TEST_F(HiredisClusterEpollAdapterAttachedTest, FurtherAttachementsResetEventStateAndWritingAndReading)
196 expectDeleteMonitoredFD(ac.c.fd);
197 expectAddMonitoredFD(ac.c.fd, 0);
198 acc.attach_fn(&ac, adapter.get());
199 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
200 ac.ev.addRead(ac.ev.data);
201 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT);
202 ac.ev.addWrite(ac.ev.data);
203 expectDeleteMonitoredFD(ac.c.fd);
204 expectAddMonitoredFD(ac.c.fd, 0);
205 acc.attach_fn(&ac, adapter.get());
206 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
207 ac.ev.addRead(ac.ev.data);
208 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT);
209 ac.ev.addWrite(ac.ev.data);
212 TEST_F(HiredisClusterEpollAdapterAttachedTest, CanHandleTwoConnections)
215 expectAddMonitoredFD2(secondAc.c.fd, 0);
216 acc.attach_fn(&secondAc, adapter.get());
217 // Read event in first fd:
218 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
219 ac.ev.addRead(ac.ev.data);
220 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
222 savedEventHandler(EngineMock::EVENT_IN);
224 // Read event in second fd:
225 expectModifyMonitoredFD(secondAc.c.fd, EngineMock::EVENT_IN);
226 ac.ev.addRead(secondAc.ev.data);
227 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&secondAc))
229 anotherSavedEventHandler(EngineMock::EVENT_IN);
231 // Cleanup for extra ac
232 expectDeleteMonitoredFD(secondAc.c.fd);
233 adapter->detach(&secondAc);
236 TEST_F(HiredisClusterEpollAdapterAttachedTest, CleanupWillRemoveOngoingEventsAndDeregisterFdFromEpoll)
239 expectDeleteMonitoredFD(acFd);
240 ac.ev.cleanup(ac.ev.data);
241 expectAddMonitoredFD(ac.c.fd, 0);
242 acc.attach_fn(&ac, adapter.get());
245 TEST_F(HiredisClusterEpollAdapterAttachedTest, DetachMakesCleanupIfNotYetDone)
248 expectDeleteMonitoredFD(ac.c.fd);
249 adapter->detach(&ac);
250 expectAddMonitoredFD(ac.c.fd, 0);
251 acc.attach_fn(&ac, adapter.get());
254 TEST_F(HiredisClusterEpollAdapterAttachedTest, InputEventRemovedByCleanupIsNotHandled)
257 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
258 ac.ev.addRead(ac.ev.data);
259 expectDeleteMonitoredFD(ac.c.fd);
260 ac.ev.cleanup(ac.ev.data);
261 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
263 savedEventHandler(EngineMock::EVENT_IN);
264 expectAddMonitoredFD(ac.c.fd, 0);
265 acc.attach_fn(&ac, adapter.get());
268 TEST_F(HiredisClusterEpollAdapterAttachedTest, OutputEventRemovedByCleanupIsNotHandled)
271 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
272 ac.ev.addWrite(ac.ev.data);
273 // Read is deleted first during cleanup handling so write (EPOLLOUT) still exists for the first EPOLL_CTL_MOD
274 expectDeleteMonitoredFD(ac.c.fd);
275 ac.ev.cleanup(ac.ev.data);
276 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleWrite(&ac))
278 savedEventHandler(EngineMock::EVENT_OUT);
279 expectAddMonitoredFD(ac.c.fd, 0);
280 acc.attach_fn(&ac, adapter.get());