Add extra line about src files are part of RIC platform project
[ric-plt/sdl.git] / tst / syncstorageimpl_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 <gtest/gtest.h>
23 #include "private/error.hpp"
24 #include "private/redis/asyncredisstorage.hpp"
25 #include "private/syncstorageimpl.hpp"
26 #include "private/tst/asyncstoragemock.hpp"
27 #include "private/tst/systemmock.hpp"
28 #include <sdl/backenderror.hpp>
29 #include <sdl/invalidnamespace.hpp>
30 #include <sdl/notconnected.hpp>
31 #include <sdl/operationinterrupted.hpp>
32 #include <sdl/rejectedbybackend.hpp>
33
34 using namespace shareddatalayer;
35 using namespace shareddatalayer::redis;
36 using namespace shareddatalayer::tst;
37 using namespace testing;
38
39 namespace
40 {
41     class SyncStorageImplTest: public testing::Test
42     {
43     public:
44         std::unique_ptr<SyncStorageImpl> syncStorage;
45         /* AsyncStorageMock ownership will be passed to implementation. To be able to do verification
46          * with the mock object also here after its ownership is passed we take raw pointer to
47          * AsyncStorageMock before passing it to implementation. Works fine, as implementation will
48          * not release injected mock object before test case execution finishes
49          */
50         std::unique_ptr<StrictMock<AsyncStorageMock>> asyncStorageMockPassedToImplementation;
51         StrictMock<AsyncStorageMock>* asyncStorageMockRawPtr;
52         StrictMock<SystemMock> systemMock;
53         AsyncStorage::ModifyAck savedModifyAck;
54         AsyncStorage::ModifyIfAck savedModifyIfAck;
55         AsyncStorage::GetAck savedGetAck;
56         AsyncStorage::FindKeysAck savedFindKeysAck;
57         AsyncStorage::ReadyAck savedReadyAck;
58         int pFd;
59         SyncStorage::DataMap dataMap;
60         SyncStorage::Keys keys;
61         const SyncStorage::Namespace ns;
62         SyncStorageImplTest():
63             asyncStorageMockPassedToImplementation(new StrictMock<AsyncStorageMock>()),
64             asyncStorageMockRawPtr(asyncStorageMockPassedToImplementation.get()),
65             pFd(10),
66             dataMap({{ "key1", { 0x0a, 0x0b, 0x0c } }, { "key2", { 0x0d, 0x0e, 0x0f, 0xff } }}),
67             keys({ "key1", "key2" }),
68             ns("someKnownNamespace")
69         {
70             expectConstructorCalls();
71             syncStorage.reset(new SyncStorageImpl(std::move(asyncStorageMockPassedToImplementation), systemMock));
72         }
73
74         void expectConstructorCalls()
75         {
76             InSequence dummy;
77             EXPECT_CALL(*asyncStorageMockRawPtr, fd())
78                 .Times(1)
79                 .WillOnce(Return(pFd));
80         }
81
82         void expectSdlReadinessCheck()
83         {
84             InSequence dummy;
85             expectWaitReadyAsync();
86             expectPollWait();
87             expectHandleEvents();
88         }
89
90         void expectPollWait()
91         {
92             EXPECT_CALL(systemMock, poll( _, 1, -1))
93                 .Times(1)
94                 .WillOnce(Invoke([](struct pollfd *fds, nfds_t, int)
95                                  {
96                                      fds->revents = POLLIN;
97                                      return 1;
98                                  }));
99         }
100
101         void expectPollError()
102         {
103             EXPECT_CALL(systemMock, poll( _, 1, -1))
104                 .Times(1)
105                 .WillOnce(Invoke([](struct pollfd *fds, nfds_t, int)
106                                  {
107                                      fds->revents = POLLIN;
108                                      return -1;
109                                  }));
110         }
111
112         void expectPollExceptionalCondition()
113         {
114             EXPECT_CALL(systemMock, poll( _, 1, -1))
115                 .Times(1)
116                 .WillOnce(Invoke([](struct pollfd *fds, nfds_t, int)
117                                  {
118                                      fds->revents = POLLPRI;
119                                      return 1;
120                                  }));
121         }
122
123         void expectHandleEvents()
124         {
125             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
126                 .Times(1)
127                 .WillOnce(Invoke([this]()
128                                  {
129                                     savedReadyAck(std::error_code());
130                                  }));
131         }
132
133         void expectWaitReadyAsync()
134         {
135             EXPECT_CALL(*asyncStorageMockRawPtr, waitReadyAsync(ns,_))
136                 .Times(1)
137                 .WillOnce(SaveArg<1>(&savedReadyAck));
138         }
139
140
141         void expectModifyAckWithError()
142         {
143             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
144                 .Times(1)
145                 .WillOnce(Invoke([this]()
146                                  {
147                                     savedModifyAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY);
148                                  }));
149         }
150
151         void expectModifyIfAck(const std::error_code& error, bool status)
152         {
153             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
154                 .Times(1)
155                 .WillOnce(Invoke([this, error, status]()
156                                  {
157                                     savedModifyIfAck(error, status);
158                                  }));
159         }
160
161         void expectGetAckWithError()
162         {
163             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
164                 .Times(1)
165                 .WillOnce(Invoke([this]()
166                                  {
167                                     savedGetAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, dataMap);
168                                  }));
169         }
170
171         void expectGetAck()
172         {
173             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
174                 .Times(1)
175                 .WillOnce(Invoke([this]()
176                                  {
177                                     savedGetAck(std::error_code(), dataMap);
178                                  }));
179         }
180
181         void expectFindKeysAck()
182         {
183             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
184                 .Times(1)
185                 .WillOnce(Invoke([this]()
186                                  {
187                                     savedFindKeysAck(std::error_code(), keys);
188                                  }));
189         }
190
191         void expectFindKeysAckWithError()
192         {
193             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
194                 .Times(1)
195                 .WillOnce(Invoke([this]()
196                                  {
197                                     savedFindKeysAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, keys);
198                                  }));
199         }
200
201         void expectSetAsync(const SyncStorage::DataMap& dataMap)
202         {
203             EXPECT_CALL(*asyncStorageMockRawPtr, setAsync(ns, dataMap, _))
204                 .Times(1)
205                 .WillOnce(SaveArg<2>(&savedModifyAck));
206         }
207
208         void expectSetIfAsync(const SyncStorage::Key& key, const SyncStorage::Data& oldData, const SyncStorage::Data& newData)
209         {
210             EXPECT_CALL(*asyncStorageMockRawPtr, setIfAsync(ns, key, oldData, newData, _))
211                 .Times(1)
212                 .WillOnce(SaveArg<4>(&savedModifyIfAck));
213         }
214
215         void expectGetAsync(const SyncStorage::Keys& keys)
216         {
217             EXPECT_CALL(*asyncStorageMockRawPtr, getAsync(ns, keys, _))
218                 .Times(1)
219                 .WillOnce(SaveArg<2>(&savedGetAck));
220         }
221
222         void expectFindKeysAsync()
223         {
224             EXPECT_CALL(*asyncStorageMockRawPtr, findKeysAsync(ns, _, _))
225                 .Times(1)
226                 .WillOnce(SaveArg<2>(&savedFindKeysAck));
227         }
228
229         void expectRemoveAsync(const SyncStorage::Keys& keys)
230         {
231             EXPECT_CALL(*asyncStorageMockRawPtr, removeAsync(ns, keys, _))
232                 .Times(1)
233                 .WillOnce(SaveArg<2>(&savedModifyAck));
234         }
235
236         void expectRemoveIfAsync(const SyncStorage::Key& key, const SyncStorage::Data& data)
237         {
238             EXPECT_CALL(*asyncStorageMockRawPtr, removeIfAsync(ns, key, data, _))
239                 .Times(1)
240                 .WillOnce(SaveArg<3>(&savedModifyIfAck));
241         }
242
243         void expectRemoveAllAsync()
244         {
245             EXPECT_CALL(*asyncStorageMockRawPtr, removeAllAsync(ns, _))
246                 .Times(1)
247                 .WillOnce(SaveArg<1>(&savedModifyAck));
248         }
249
250         void expectSetIfNotExistsAsync(const SyncStorage::Key& key, const SyncStorage::Data& data)
251         {
252             EXPECT_CALL(*asyncStorageMockRawPtr, setIfNotExistsAsync(ns, key, data, _))
253                 .Times(1)
254                 .WillOnce(SaveArg<3>(&savedModifyIfAck));
255         }
256     };
257 }
258
259 TEST_F(SyncStorageImplTest, IsNotCopyable)
260 {
261     InSequence dummy;
262     EXPECT_FALSE(std::is_copy_constructible<SyncStorageImpl>::value);
263     EXPECT_FALSE(std::is_copy_assignable<SyncStorageImpl>::value);
264 }
265
266 TEST_F(SyncStorageImplTest, ImplementssyncStorage)
267 {
268     InSequence dummy;
269     EXPECT_TRUE((std::is_base_of<SyncStorage, SyncStorageImpl>::value));
270 }
271
272 TEST_F(SyncStorageImplTest, EventsAreNotHandledWhenPollReturnsError)
273 {
274     InSequence dummy;
275     expectSdlReadinessCheck();
276     expectSetAsync(dataMap);
277     expectPollError();
278     expectPollWait();
279     expectHandleEvents();
280     syncStorage->set(ns, dataMap);
281 }
282
283 TEST_F(SyncStorageImplTest, EventsAreNotHandledWhenThereIsAnExceptionalConditionOnTheFd)
284 {
285     InSequence dummy;
286     expectSdlReadinessCheck();
287     expectSetAsync(dataMap);
288     expectPollExceptionalCondition();
289     expectPollWait();
290     expectHandleEvents();
291     syncStorage->set(ns, dataMap);
292 }
293
294 TEST_F(SyncStorageImplTest, SetSuccessfully)
295 {
296     InSequence dummy;
297     expectSdlReadinessCheck();
298     expectSetAsync(dataMap);
299     expectPollWait();
300     expectHandleEvents();
301     syncStorage->set(ns, dataMap);
302 }
303
304 TEST_F(SyncStorageImplTest, SetCanThrowBackendError)
305 {
306     InSequence dummy;
307     expectSdlReadinessCheck();
308     expectSetAsync(dataMap);
309     expectPollWait();
310     expectModifyAckWithError();
311     EXPECT_THROW(syncStorage->set(ns, dataMap), BackendError);
312 }
313
314 TEST_F(SyncStorageImplTest, SetIfSuccessfully)
315 {
316     InSequence dummy;
317     expectSdlReadinessCheck();
318     expectSetAsync(dataMap);
319     expectPollWait();
320     expectHandleEvents();
321     syncStorage->set(ns, dataMap);
322     expectSdlReadinessCheck();
323     expectSetIfAsync("key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
324     expectPollWait();
325     expectHandleEvents();
326     syncStorage->setIf(ns, "key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
327 }
328
329 TEST_F(SyncStorageImplTest, SetIfCanThrowBackendError)
330 {
331     InSequence dummy;
332     expectSdlReadinessCheck();
333     expectSetAsync(dataMap);
334     expectPollWait();
335     expectHandleEvents();
336     syncStorage->set(ns, dataMap);
337     expectSdlReadinessCheck();
338     expectSetIfAsync("key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
339     expectPollWait();
340     expectModifyIfAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, false);
341     EXPECT_THROW(syncStorage->setIf(ns, "key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f }), BackendError);
342 }
343
344 TEST_F(SyncStorageImplTest, SetIfNotExistsSuccessfully)
345 {
346     InSequence dummy;
347     expectSdlReadinessCheck();
348     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
349     expectPollWait();
350     expectModifyIfAck(std::error_code(), true);
351     EXPECT_TRUE(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }));
352 }
353
354 TEST_F(SyncStorageImplTest, SetIfNotExistsReturnsFalseIfKeyAlreadyExists)
355 {
356     InSequence dummy;
357     expectSdlReadinessCheck();
358     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
359     expectPollWait();
360     expectModifyIfAck(std::error_code(), false);
361     EXPECT_FALSE(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }));
362 }
363
364 TEST_F(SyncStorageImplTest, SetIfNotExistsCanThrowBackendError)
365 {
366     InSequence dummy;
367     expectSdlReadinessCheck();
368     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
369     expectPollWait();
370     expectModifyIfAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, false);
371     EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
372 }
373
374 TEST_F(SyncStorageImplTest, GetSuccessfully)
375 {
376     InSequence dummy;
377     expectSdlReadinessCheck();
378     expectGetAsync(keys);
379     expectPollWait();
380     expectGetAck();
381     auto map(syncStorage->get(ns, keys));
382     EXPECT_EQ(map, dataMap);
383 }
384
385 TEST_F(SyncStorageImplTest, GetCanThrowBackendError)
386 {
387     InSequence dummy;
388     expectSdlReadinessCheck();
389     expectGetAsync(keys);
390     expectPollWait();
391     expectGetAckWithError();
392     EXPECT_THROW(syncStorage->get(ns, keys), BackendError);
393 }
394
395 TEST_F(SyncStorageImplTest, RemoveSuccessfully)
396 {
397     InSequence dummy;
398     expectSdlReadinessCheck();
399     expectRemoveAsync(keys);
400     expectPollWait();
401     expectHandleEvents();
402     syncStorage->remove(ns, keys);
403 }
404
405 TEST_F(SyncStorageImplTest, RemoveCanThrowBackendError)
406 {
407     InSequence dummy;
408     expectSdlReadinessCheck();
409     expectRemoveAsync(keys);
410     expectPollWait();
411     expectModifyAckWithError();
412     EXPECT_THROW(syncStorage->remove(ns, keys), BackendError);
413 }
414
415 TEST_F(SyncStorageImplTest, RemoveIfSuccessfully)
416 {
417     InSequence dummy;
418     expectSdlReadinessCheck();
419     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
420     expectPollWait();
421     expectModifyIfAck(std::error_code(), true);
422     EXPECT_TRUE(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }));
423 }
424
425 TEST_F(SyncStorageImplTest, RemoveIfReturnsFalseIfKeyDoesnotMatch)
426 {
427     InSequence dummy;
428     expectSdlReadinessCheck();
429     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
430     expectPollWait();
431     expectModifyIfAck(std::error_code(), false);
432     EXPECT_FALSE(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }));
433 }
434
435 TEST_F(SyncStorageImplTest, RemoveIfCanThrowBackendError)
436 {
437     InSequence dummy;
438     expectSdlReadinessCheck();
439     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
440     expectPollWait();
441     expectModifyIfAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, false);
442     EXPECT_THROW(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
443 }
444
445 TEST_F(SyncStorageImplTest, FindKeysSuccessfully)
446 {
447     InSequence dummy;
448     expectSdlReadinessCheck();
449     expectFindKeysAsync();
450     expectPollWait();
451     expectFindKeysAck();
452     auto ids(syncStorage->findKeys(ns, "*"));
453     EXPECT_EQ(ids, keys);
454 }
455
456 TEST_F(SyncStorageImplTest, FindKeysAckCanThrowBackendError)
457 {
458     InSequence dummy;
459     expectSdlReadinessCheck();
460     expectFindKeysAsync();
461     expectPollWait();
462     expectFindKeysAckWithError();
463     EXPECT_THROW(syncStorage->findKeys(ns, "*"), BackendError);
464 }
465
466 TEST_F(SyncStorageImplTest, RemoveAllSuccessfully)
467 {
468     InSequence dummy;
469     expectSdlReadinessCheck();
470     expectRemoveAllAsync();
471     expectPollWait();
472     expectHandleEvents();
473     syncStorage->removeAll(ns);
474 }
475
476 TEST_F(SyncStorageImplTest, RemoveAllCanThrowBackendError)
477 {
478     InSequence dummy;
479     expectSdlReadinessCheck();
480     expectRemoveAllAsync();
481     expectPollWait();
482     expectModifyAckWithError();
483     EXPECT_THROW(syncStorage->removeAll(ns), BackendError);
484 }
485
486 TEST_F(SyncStorageImplTest, AllAsyncRedisStorageErrorCodesThrowCorrectException)
487 {
488     InSequence dummy;
489     std::error_code ec;
490
491     for (AsyncRedisStorage::ErrorCode arsec = AsyncRedisStorage::ErrorCode::SUCCESS; arsec < AsyncRedisStorage::ErrorCode::END_MARKER; ++arsec)
492     {
493         if (arsec != AsyncRedisStorage::ErrorCode::SUCCESS)
494         {
495             expectSdlReadinessCheck();
496             expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
497             expectPollWait();
498         }
499
500         switch (arsec)
501         {
502             case AsyncRedisStorage::ErrorCode::SUCCESS:
503                 break;
504             case AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE:
505                 expectModifyIfAck(arsec, false);
506                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), InvalidNamespace);
507                 break;
508             case AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED:
509                 expectModifyIfAck(arsec, false);
510                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), NotConnected);
511                 break;
512             default:
513                 FAIL() << "No mapping for AsyncRedisStorage::ErrorCode value: " << arsec;
514                 break;
515         }
516     }
517 }
518
519 TEST_F(SyncStorageImplTest, AllDispatcherErrorCodesThrowCorrectException)
520 {
521     InSequence dummy;
522     std::error_code ec;
523
524     for (AsyncRedisCommandDispatcherErrorCode aec = AsyncRedisCommandDispatcherErrorCode::SUCCESS; aec < AsyncRedisCommandDispatcherErrorCode::END_MARKER; ++aec)
525     {
526         if (aec != AsyncRedisCommandDispatcherErrorCode::SUCCESS)
527         {
528             expectSdlReadinessCheck();
529             expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
530             expectPollWait();
531         }
532
533         switch (aec)
534         {
535             case AsyncRedisCommandDispatcherErrorCode::SUCCESS:
536                 break;
537             case AsyncRedisCommandDispatcherErrorCode::UNKNOWN_ERROR:
538                 expectModifyIfAck(aec, false);
539                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
540                 break;
541             case AsyncRedisCommandDispatcherErrorCode::CONNECTION_LOST:
542                 expectModifyIfAck(aec, false);
543                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), OperationInterrupted);
544                 break;
545             case AsyncRedisCommandDispatcherErrorCode::PROTOCOL_ERROR:
546                 expectModifyIfAck(aec, false);
547                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), RejectedByBackend);
548                 break;
549             case AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY:
550                 expectModifyIfAck(aec, false);
551                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
552                 break;
553             case AsyncRedisCommandDispatcherErrorCode::DATASET_LOADING:
554                 expectModifyIfAck(aec, false);
555                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), NotConnected);
556                 break;
557             case AsyncRedisCommandDispatcherErrorCode::NOT_CONNECTED:
558                 expectModifyIfAck(aec, false);
559                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), NotConnected);
560                 break;
561             case AsyncRedisCommandDispatcherErrorCode::IO_ERROR:
562                 expectModifyIfAck(aec, false);
563                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
564                 break;
565             case AsyncRedisCommandDispatcherErrorCode::WRITING_TO_SLAVE:
566                 expectModifyIfAck(aec, false);
567                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
568                 break;
569             default:
570                 FAIL() << "No mapping for AsyncRedisCommandDispatcherErrorCode value: " << aec;
571                 break;
572         }
573     }
574 }
575
576 TEST_F(SyncStorageImplTest, CanThrowStdExceptionIfDispatcherErrorCodeCannotBeMappedToSdlException)
577 {
578     InSequence dummy;
579     expectSdlReadinessCheck();
580     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
581     expectPollWait();
582     expectModifyIfAck(std::error_code(1, std::system_category()), false);
583     EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), std::range_error);
584 }