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.
17 #include <type_traits>
19 #include <sys/epoll.h>
20 #include <gtest/gtest.h>
21 #include "private/redis/hiredisclusterepolladapter.hpp"
22 #include "private/tst/enginemock.hpp"
23 #include "private/tst/hiredisclustersystemmock.hpp"
25 using namespace shareddatalayer;
26 using namespace shareddatalayer::redis;
27 using namespace shareddatalayer::tst;
28 using namespace testing;
32 class HiredisClusterEpollAdapterTest: public testing::Test
35 StrictMock<EngineMock> engineMock;
36 StrictMock<HiredisClusterSystemMock> hiredisClusterSystemMock;
37 redisClusterAsyncContext acc;
38 std::unique_ptr<HiredisClusterEpollAdapter> adapter;
40 redisAsyncContext secondAc;
43 Engine::EventHandler savedEventHandler;
44 Engine::EventHandler anotherSavedEventHandler;
46 HiredisClusterEpollAdapterTest():
48 adapter(new HiredisClusterEpollAdapter(engineMock, hiredisClusterSystemMock)),
59 ~HiredisClusterEpollAdapterTest()
63 void expectAddMonitoredFD(int fd, unsigned int events)
65 EXPECT_CALL(engineMock, addMonitoredFD(fd,events,_))
67 .WillOnce(SaveArg<2>(&savedEventHandler));
70 void expectAddMonitoredFD2(int fd, unsigned int events)
72 EXPECT_CALL(engineMock, addMonitoredFD(fd,events,_))
74 .WillOnce(SaveArg<2>(&anotherSavedEventHandler));
77 void expectModifyMonitoredFD(int fd, unsigned int events)
79 EXPECT_CALL(engineMock, modifyMonitoredFD(fd,events))
83 void expectDeleteMonitoredFD(int fd)
85 EXPECT_CALL(engineMock, deleteMonitoredFD(fd))
90 class HiredisClusterEpollAdapterAttachedTest: public HiredisClusterEpollAdapterTest
93 HiredisClusterEpollAdapterAttachedTest()
95 expectAddMonitoredFD(ac.c.fd, 0);
96 acc.attach_fn(&ac, adapter.get());
99 ~HiredisClusterEpollAdapterAttachedTest()
101 expectDeleteMonitoredFD(ac.c.fd);
106 TEST_F(HiredisClusterEpollAdapterTest, IsNotCopyableAndIsNotMovable)
108 EXPECT_FALSE(std::is_copy_constructible<HiredisClusterEpollAdapter>::value);
109 EXPECT_FALSE(std::is_copy_assignable<HiredisClusterEpollAdapter>::value);
110 EXPECT_FALSE(std::is_move_constructible<HiredisClusterEpollAdapter>::value);
111 EXPECT_FALSE(std::is_move_assignable<HiredisClusterEpollAdapter>::value);
114 TEST_F(HiredisClusterEpollAdapterTest, HasVirtualDestructor)
116 EXPECT_TRUE(std::has_virtual_destructor<HiredisClusterEpollAdapter>::value);
119 TEST_F(HiredisClusterEpollAdapterAttachedTest, EventStateChangedIdempotently)
122 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
123 ac.ev.addRead(ac.ev.data);
124 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT);
125 ac.ev.addWrite(ac.ev.data);
126 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
127 ac.ev.delRead(ac.ev.data);
128 expectModifyMonitoredFD(ac.c.fd, 0);
129 ac.ev.delWrite(ac.ev.data);
130 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
131 ac.ev.addRead(ac.ev.data);
132 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT);
133 ac.ev.addWrite(ac.ev.data);
136 TEST_F(HiredisClusterEpollAdapterAttachedTest, InputEventIsSetOnce)
139 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
140 ac.ev.addRead(ac.ev.data);
141 ac.ev.addRead(ac.ev.data);
144 TEST_F(HiredisClusterEpollAdapterAttachedTest, OutputEventIsSetOnce)
147 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
148 ac.ev.addWrite(ac.ev.data);
149 ac.ev.addWrite(ac.ev.data);
152 TEST_F(HiredisClusterEpollAdapterAttachedTest, CanHandleInputEvent)
155 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
156 ac.ev.addRead(ac.ev.data);
157 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
159 savedEventHandler(EngineMock::EVENT_IN);
162 TEST_F(HiredisClusterEpollAdapterAttachedTest, DoesNotHandleInputEventIfNotReading)
165 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
167 savedEventHandler(EngineMock::EVENT_IN);
170 TEST_F(HiredisClusterEpollAdapterAttachedTest, CanHandleOutputEvent)
173 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
174 ac.ev.addWrite(ac.ev.data);
175 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleWrite(&ac))
177 savedEventHandler(EngineMock::EVENT_OUT);
180 TEST_F(HiredisClusterEpollAdapterAttachedTest, DoesNotHandleOutputEventIfNotWriting)
183 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleWrite(&ac))
185 savedEventHandler(EngineMock::EVENT_OUT);
188 TEST_F(HiredisClusterEpollAdapterAttachedTest, FurtherAttachementsResetEventStateAndWritingAndReading)
191 expectDeleteMonitoredFD(ac.c.fd);
192 expectAddMonitoredFD(ac.c.fd, 0);
193 acc.attach_fn(&ac, adapter.get());
194 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
195 ac.ev.addRead(ac.ev.data);
196 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT);
197 ac.ev.addWrite(ac.ev.data);
198 expectDeleteMonitoredFD(ac.c.fd);
199 expectAddMonitoredFD(ac.c.fd, 0);
200 acc.attach_fn(&ac, adapter.get());
201 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
202 ac.ev.addRead(ac.ev.data);
203 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT);
204 ac.ev.addWrite(ac.ev.data);
207 TEST_F(HiredisClusterEpollAdapterAttachedTest, CanHandleTwoConnections)
210 expectAddMonitoredFD2(secondAc.c.fd, 0);
211 acc.attach_fn(&secondAc, adapter.get());
212 // Read event in first fd:
213 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
214 ac.ev.addRead(ac.ev.data);
215 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
217 savedEventHandler(EngineMock::EVENT_IN);
219 // Read event in second fd:
220 expectModifyMonitoredFD(secondAc.c.fd, EngineMock::EVENT_IN);
221 ac.ev.addRead(secondAc.ev.data);
222 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&secondAc))
224 anotherSavedEventHandler(EngineMock::EVENT_IN);
226 // Cleanup for extra ac
227 expectDeleteMonitoredFD(secondAc.c.fd);
228 adapter->detach(&secondAc);
231 TEST_F(HiredisClusterEpollAdapterAttachedTest, CleanupWillRemoveOngoingEventsAndDeregisterFdFromEpoll)
234 expectDeleteMonitoredFD(acFd);
235 ac.ev.cleanup(ac.ev.data);
236 expectAddMonitoredFD(ac.c.fd, 0);
237 acc.attach_fn(&ac, adapter.get());
240 TEST_F(HiredisClusterEpollAdapterAttachedTest, DetachMakesCleanupIfNotYetDone)
243 expectDeleteMonitoredFD(ac.c.fd);
244 adapter->detach(&ac);
245 expectAddMonitoredFD(ac.c.fd, 0);
246 acc.attach_fn(&ac, adapter.get());
249 TEST_F(HiredisClusterEpollAdapterAttachedTest, InputEventRemovedByCleanupIsNotHandled)
252 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
253 ac.ev.addRead(ac.ev.data);
254 expectDeleteMonitoredFD(ac.c.fd);
255 ac.ev.cleanup(ac.ev.data);
256 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
258 savedEventHandler(EngineMock::EVENT_IN);
259 expectAddMonitoredFD(ac.c.fd, 0);
260 acc.attach_fn(&ac, adapter.get());
263 TEST_F(HiredisClusterEpollAdapterAttachedTest, OutputEventRemovedByCleanupIsNotHandled)
266 expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
267 ac.ev.addWrite(ac.ev.data);
268 // Read is deleted first during cleanup handling so write (EPOLLOUT) still exists for the first EPOLL_CTL_MOD
269 expectDeleteMonitoredFD(ac.c.fd);
270 ac.ev.cleanup(ac.ev.data);
271 EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleWrite(&ac))
273 savedEventHandler(EngineMock::EVENT_OUT);
274 expectAddMonitoredFD(ac.c.fd, 0);
275 acc.attach_fn(&ac, adapter.get());