Add SDL developer and user guides
[ric-plt/sdl.git] / tst / hiredisclusterepolladapter_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 <type_traits>
23 #include <memory>
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"
29
30 using namespace shareddatalayer;
31 using namespace shareddatalayer::redis;
32 using namespace shareddatalayer::tst;
33 using namespace testing;
34
35 namespace
36 {
37     class HiredisClusterEpollAdapterTest: public testing::Test
38     {
39     public:
40         StrictMock<EngineMock> engineMock;
41         StrictMock<HiredisClusterSystemMock> hiredisClusterSystemMock;
42         redisClusterAsyncContext acc;
43         std::unique_ptr<HiredisClusterEpollAdapter> adapter;
44         redisAsyncContext ac;
45         redisAsyncContext secondAc;
46         int acFd;
47         int secondAcFd;
48         Engine::EventHandler savedEventHandler;
49         Engine::EventHandler anotherSavedEventHandler;
50
51         HiredisClusterEpollAdapterTest():
52             acc { },
53             adapter(new HiredisClusterEpollAdapter(engineMock, hiredisClusterSystemMock)),
54             ac { },
55             secondAc { },
56             acFd(20),
57             secondAcFd(30)
58         {
59             InSequence dummy;
60             ac.c.fd = acFd;
61             adapter->setup(&acc);
62         }
63
64         ~HiredisClusterEpollAdapterTest()
65         {
66         }
67
68         void expectAddMonitoredFD(int fd, unsigned int events)
69         {
70             EXPECT_CALL(engineMock, addMonitoredFD(fd,events,_))
71                 .Times(1)
72                 .WillOnce(SaveArg<2>(&savedEventHandler));
73         }
74
75         void expectAddMonitoredFD2(int fd, unsigned int events)
76         {
77             EXPECT_CALL(engineMock, addMonitoredFD(fd,events,_))
78                 .Times(1)
79                 .WillOnce(SaveArg<2>(&anotherSavedEventHandler));
80         }
81
82         void expectModifyMonitoredFD(int fd, unsigned int events)
83         {
84             EXPECT_CALL(engineMock, modifyMonitoredFD(fd,events))
85                 .Times(1);
86         }
87
88         void expectDeleteMonitoredFD(int fd)
89         {
90             EXPECT_CALL(engineMock, deleteMonitoredFD(fd))
91                 .Times(1);
92         }
93     };
94
95     class HiredisClusterEpollAdapterAttachedTest: public HiredisClusterEpollAdapterTest
96     {
97     public:
98         HiredisClusterEpollAdapterAttachedTest()
99         {
100             expectAddMonitoredFD(ac.c.fd, 0);
101             acc.attach_fn(&ac, adapter.get());
102         }
103
104         ~HiredisClusterEpollAdapterAttachedTest()
105         {
106             expectDeleteMonitoredFD(ac.c.fd);
107         }
108     };
109 }
110
111 TEST_F(HiredisClusterEpollAdapterTest, IsNotCopyableAndIsNotMovable)
112 {
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);
117 }
118
119 TEST_F(HiredisClusterEpollAdapterTest, HasVirtualDestructor)
120 {
121     EXPECT_TRUE(std::has_virtual_destructor<HiredisClusterEpollAdapter>::value);
122 }
123
124 TEST_F(HiredisClusterEpollAdapterAttachedTest, EventStateChangedIdempotently)
125 {
126     InSequence dummy;
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);
139 }
140
141 TEST_F(HiredisClusterEpollAdapterAttachedTest, InputEventIsSetOnce)
142 {
143     InSequence dummy;
144     expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
145     ac.ev.addRead(ac.ev.data);
146     ac.ev.addRead(ac.ev.data);
147 }
148
149 TEST_F(HiredisClusterEpollAdapterAttachedTest, OutputEventIsSetOnce)
150 {
151     InSequence dummy;
152     expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
153     ac.ev.addWrite(ac.ev.data);
154     ac.ev.addWrite(ac.ev.data);
155 }
156
157 TEST_F(HiredisClusterEpollAdapterAttachedTest, CanHandleInputEvent)
158 {
159     InSequence dummy;
160     expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN);
161     ac.ev.addRead(ac.ev.data);
162     EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
163         .Times(1);
164     savedEventHandler(EngineMock::EVENT_IN);
165 }
166
167 TEST_F(HiredisClusterEpollAdapterAttachedTest, DoesNotHandleInputEventIfNotReading)
168 {
169     InSequence dummy;
170     EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleRead(&ac))
171         .Times(0);
172     savedEventHandler(EngineMock::EVENT_IN);
173 }
174
175 TEST_F(HiredisClusterEpollAdapterAttachedTest, CanHandleOutputEvent)
176 {
177     InSequence dummy;
178     expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT);
179     ac.ev.addWrite(ac.ev.data);
180     EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleWrite(&ac))
181         .Times(1);
182     savedEventHandler(EngineMock::EVENT_OUT);
183 }
184
185 TEST_F(HiredisClusterEpollAdapterAttachedTest, DoesNotHandleOutputEventIfNotWriting)
186 {
187     InSequence dummy;
188     EXPECT_CALL(hiredisClusterSystemMock, redisAsyncHandleWrite(&ac))
189         .Times(0);
190     savedEventHandler(EngineMock::EVENT_OUT);
191 }
192
193 TEST_F(HiredisClusterEpollAdapterAttachedTest, FurtherAttachementsResetEventStateAndWritingAndReading)
194 {
195     InSequence dummy;
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);
210 }
211
212 TEST_F(HiredisClusterEpollAdapterAttachedTest, CanHandleTwoConnections)
213 {
214     InSequence dummy;
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))
221         .Times(1);
222     savedEventHandler(EngineMock::EVENT_IN);
223
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))
228         .Times(1);
229     anotherSavedEventHandler(EngineMock::EVENT_IN);
230
231     // Cleanup for extra ac
232     expectDeleteMonitoredFD(secondAc.c.fd);
233     adapter->detach(&secondAc);
234 }
235
236 TEST_F(HiredisClusterEpollAdapterAttachedTest, CleanupWillRemoveOngoingEventsAndDeregisterFdFromEpoll)
237 {
238     InSequence dummy;
239     expectDeleteMonitoredFD(acFd);
240     ac.ev.cleanup(ac.ev.data);
241     expectAddMonitoredFD(ac.c.fd, 0);
242     acc.attach_fn(&ac, adapter.get());
243 }
244
245 TEST_F(HiredisClusterEpollAdapterAttachedTest, DetachMakesCleanupIfNotYetDone)
246 {
247     InSequence dummy;
248     expectDeleteMonitoredFD(ac.c.fd);
249     adapter->detach(&ac);
250     expectAddMonitoredFD(ac.c.fd, 0);
251     acc.attach_fn(&ac, adapter.get());
252 }
253
254 TEST_F(HiredisClusterEpollAdapterAttachedTest, InputEventRemovedByCleanupIsNotHandled)
255 {
256     InSequence dummy;
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))
262         .Times(0);
263     savedEventHandler(EngineMock::EVENT_IN);
264     expectAddMonitoredFD(ac.c.fd, 0);
265     acc.attach_fn(&ac, adapter.get());
266 }
267
268 TEST_F(HiredisClusterEpollAdapterAttachedTest, OutputEventRemovedByCleanupIsNotHandled)
269 {
270     InSequence dummy;
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))
277         .Times(0);
278     savedEventHandler(EngineMock::EVENT_OUT);
279     expectAddMonitoredFD(ac.c.fd, 0);
280     acc.attach_fn(&ac, adapter.get());
281 }