RIC:1060: Change in PTL
[ric-plt/sdl.git] / tst / asyncredisstorage_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 <cstdlib>
25 #include <gtest/gtest.h>
26 #include <arpa/inet.h>
27 #include <sdl/emptynamespace.hpp>
28 #include <sdl/invalidnamespace.hpp>
29 #include <sdl/publisherid.hpp>
30 #include "private/createlogger.hpp"
31 #include "private/error.hpp"
32 #include "private/logger.hpp"
33 #include "private/redis/asyncredisstorage.hpp"
34 #include "private/redis/contents.hpp"
35 #include "private/redis/databaseinfo.hpp"
36 #include "private/redis/reply.hpp"
37 #include "private/tst/asynccommanddispatchermock.hpp"
38 #include "private/tst/asyncdatabasediscoverymock.hpp"
39 #include "private/tst/contentsbuildermock.hpp"
40 #include "private/tst/enginemock.hpp"
41 #include "private/tst/namespaceconfigurationsmock.hpp"
42 #include "private/tst/replymock.hpp"
43 #include "private/tst/wellknownerrorcode.hpp"
44
45 using namespace shareddatalayer;
46 using namespace shareddatalayer::redis;
47 using namespace shareddatalayer::tst;
48 using namespace testing;
49
50 namespace
51 {
52     std::string getErrorCodeMessage(std::error_code ec)
53     {
54         return ec.message();
55     }
56
57     class AsyncRedisStorageErrorCodeTest: public testing::Test
58     {
59     public:
60         AsyncRedisStorageErrorCodeTest()
61         {
62         }
63
64         virtual ~AsyncRedisStorageErrorCodeTest()
65         {
66         }
67     };
68
69     static const std::string defaultAddress = "address";
70     static const uint16_t defaultPort = 3333;
71     class AsyncRedisStorageTestBase: public testing::Test
72     {
73     public:
74         std::shared_ptr<StrictMock<EngineMock>> engineMock;
75         std::shared_ptr<StrictMock<AsyncDatabaseDiscoveryMock>> discoveryMock;
76         std::shared_ptr<StrictMock<AsyncCommandDispatcherMock>> dispatcherMock;
77         std::unique_ptr<AsyncRedisStorage> sdlStorage;
78         AsyncStorage::Namespace ns;
79         std::shared_ptr<StrictMock<ContentsBuilderMock>> contentsBuilderMock;
80         std::shared_ptr<StrictMock<NamespaceConfigurationsMock>> namespaceConfigurationsMock;
81         Contents contents;
82         Contents publishContentsWithoutPubId;
83         int fd;
84         int discoveryFd;
85         int dispatcherFd;
86         Engine::EventHandler savedDiscoveryEventHandler;
87         Engine::EventHandler savedDispatcherEventHandler;
88         AsyncDatabaseDiscovery::StateChangedCb stateChangedCb;
89         AsyncCommandDispatcher::ConnectAck dispatcherConnectAck;
90         Engine::Callback storedCallback;
91         AsyncCommandDispatcher::CommandCb savedCommandCb;
92         AsyncCommandDispatcher::CommandCb savedPublishCommandCb;
93         AsyncCommandDispatcher::CommandCb savedCommandListQueryCb;
94         ReplyMock replyMock;
95         Reply::ReplyVector replyVector;
96         Reply::ReplyVector commandListReplyVector;
97         Reply::ReplyVector commandListReplyElementVector;
98         std::string expectedStr1;
99         std::string expectedStr2;
100         AsyncStorage::Key key1;
101         AsyncStorage::Key key2;
102         AsyncStorage::Keys keys;
103         AsyncStorage::Keys keysWithNonExistKey;
104         AsyncStorage::Data data1;
105         AsyncStorage::Data data2;
106         AsyncStorage::DataMap dataMap;
107         std::string keyPrefix;
108         std::shared_ptr<Logger> logger;
109
110         AsyncRedisStorageTestBase():
111             engineMock(std::make_shared<StrictMock<EngineMock>>()),
112             discoveryMock(std::make_shared<StrictMock<AsyncDatabaseDiscoveryMock>>()),
113             dispatcherMock(std::make_shared<StrictMock<AsyncCommandDispatcherMock>>()),
114             ns("tag1"),
115             contentsBuilderMock(std::make_shared<StrictMock<ContentsBuilderMock>>(AsyncStorage::SEPARATOR)),
116             namespaceConfigurationsMock(std::make_shared<StrictMock<NamespaceConfigurationsMock>>()),
117             contents({{"aaa","bbb"},{3,3}}),
118             publishContentsWithoutPubId({ { "PUBLISH", ns, "shareddatalayer::NO_PUBLISHER" }, { 7, 4, 29 } }),
119             fd(10),
120             discoveryFd(20),
121             dispatcherFd(30),
122             key1("key1"),
123             key2("key2"),
124             keys({key1,key2}),
125             keysWithNonExistKey({key1,"notfound",key2}),
126             data1({1,2,3}),
127             data2({4,5,6}),
128             dataMap({{key1,data1},{key2,data2}}),
129             keyPrefix("{tag1},*"),
130             logger(createLogger(SDL_LOG_PREFIX))
131         {
132         }
133
134         virtual ~AsyncRedisStorageTestBase() = default;
135
136         std::shared_ptr<AsyncCommandDispatcher> asyncCommandDispatcherCreator(Engine&,
137                                                                               const DatabaseInfo&,
138                                                                               std::shared_ptr<ContentsBuilder>)
139         {
140             newDispatcherCreated();
141             return dispatcherMock;
142         }
143
144         MOCK_METHOD0(newDispatcherCreated, void());
145
146         MOCK_METHOD1(readyAck, void(const std::error_code&));
147
148         MOCK_METHOD1(modifyAck, void(const std::error_code&));
149
150         MOCK_METHOD2(modifyIfAck, void(const std::error_code&, bool status));
151
152         MOCK_METHOD2(getAck, void(const std::error_code&, const AsyncStorage::DataMap&));
153
154         MOCK_METHOD2(findKeysAck, void(const std::error_code&, const AsyncStorage::Keys&));
155
156         DatabaseInfo getDatabaseInfo(DatabaseInfo::Type type = DatabaseInfo::Type::SINGLE,
157                                      DatabaseInfo::Discovery discovery = DatabaseInfo::Discovery::HIREDIS,
158                                      std::string address = defaultAddress,
159                                      uint16_t port = defaultPort)
160         {
161             DatabaseInfo databaseInfo;
162             databaseInfo.type = type;
163             databaseInfo.discovery = discovery;
164             databaseInfo.hosts.push_back({address, htons(port)});
165             databaseInfo.ns = ns;
166             return databaseInfo;
167         }
168
169         void expectDiscoverySetStateChangedCb()
170         {
171             EXPECT_CALL(*discoveryMock, setStateChangedCb(_))
172                 .Times(1)
173                 .WillOnce(Invoke([this](const AsyncDatabaseDiscovery::StateChangedCb& cb)
174                         {
175                             stateChangedCb = cb;
176                         }));
177         }
178
179         void expectDispatcherWaitConnectedAsync()
180         {
181             EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
182                 .Times(1)
183                 .WillOnce(Invoke([this](const AsyncCommandDispatcher::ConnectAck& connectAck)
184                         {
185                             dispatcherConnectAck = connectAck;
186                         }));
187         }
188
189         void expectDispatcherCreation()
190         {
191             expectDispatcherWaitConnectedAsync();
192         }
193
194         void expectNewDispatcherCreated()
195         {
196             EXPECT_CALL(*this, newDispatcherCreated)
197                 .Times(1);
198         }
199
200         void expectNewDispatcherNotCreated()
201         {
202             EXPECT_CALL(*this, newDispatcherCreated)
203                 .Times(0);
204         }
205
206         void expectReadyAck(const std::error_code& error)
207         {
208             EXPECT_CALL(*this, readyAck(error))
209                 .Times(1);
210         }
211
212         void expectModifyAck(const std::error_code& error)
213         {
214             EXPECT_CALL(*this, modifyAck(error))
215                 .Times(1);
216         }
217
218         void expectModifyIfAck(const std::error_code& error, bool status)
219         {
220             EXPECT_CALL(*this, modifyIfAck(error, status))
221                 .Times(1);
222         }
223
224         void expectGetAck(const std::error_code& error, const AsyncStorage::DataMap& dataMap)
225         {
226             EXPECT_CALL(*this, getAck(error, dataMap))
227                 .Times(1);
228         }
229
230         void expectFindKeysAck(const std::error_code& error, const AsyncStorage::Keys& keys)
231         {
232             EXPECT_CALL(*this, findKeysAck(error, keys))
233                 .Times(1);
234         }
235
236         void expectPostCallback()
237         {
238             EXPECT_CALL(*engineMock, postCallback(_))
239                 .Times(1)
240                 .WillOnce(SaveArg<0>(&storedCallback));
241         }
242
243         void createAsyncStorageInstance(const boost::optional<PublisherId>& pId)
244         {
245             expectDiscoverySetStateChangedCb();
246             if (sdlStorage)
247                 expectClearStateChangedCb();
248             sdlStorage.reset(new AsyncRedisStorage(engineMock,
249                                                    discoveryMock,
250                                                    pId,
251                                                    namespaceConfigurationsMock,
252                                                    std::bind(&AsyncRedisStorageTestBase::asyncCommandDispatcherCreator,
253                                                              this,
254                                                              std::placeholders::_1,
255                                                              std::placeholders::_2,
256                                                              std::placeholders::_3),
257                                                    contentsBuilderMock,
258                                                    logger));
259         }
260
261         void createAndConnectAsyncStorageInstance(const boost::optional<PublisherId>& pId)
262         {
263             InSequence dummy;
264             createAsyncStorageInstance(pId);
265             sdlStorage->waitReadyAsync(ns, std::bind(&AsyncRedisStorageTestBase::readyAck, this, std::placeholders::_1));
266             expectNewDispatcherCreated();
267             expectDispatcherCreation();
268             stateChangedCb(getDatabaseInfo());
269             EXPECT_CALL(*this, readyAck(std::error_code()))
270                 .Times(1);
271             dispatcherConnectAck();
272         }
273
274         void expectClearStateChangedCb()
275         {
276             EXPECT_CALL(*discoveryMock, clearStateChangedCb())
277                 .Times(1);
278         }
279
280         void expectNoDispatchAsync()
281         {
282             EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, _))
283                 .Times(0);
284         }
285
286         void expectDispatchAsync()
287         {
288             EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, contents))
289                 .Times(1)
290                 .WillOnce(SaveArg<0>(&savedCommandCb));
291         }
292
293         void expectPublishDispatch()
294         {
295             EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, contents))
296                 .Times(1)
297                 .WillOnce(SaveArg<0>(&savedPublishCommandCb));
298         }
299
300         std::shared_ptr<Reply> getMockPtr()
301         {
302             return std::shared_ptr<Reply>(&replyMock, [](Reply*){ });
303         }
304
305         void expectGetType(const Reply::Type& type)
306         {
307             EXPECT_CALL(replyMock, getType())
308                 .Times(1)
309                 .WillOnce(Return(type));
310         }
311
312         void expectGetDataString(const Reply::DataItem& item)
313         {
314             expectGetType(Reply::Type::STRING);
315             EXPECT_CALL(replyMock, getString())
316                 .Times(1)
317                 .WillOnce(Return(&item));
318         }
319
320         void expectGetArray()
321         {
322             EXPECT_CALL(replyMock, getArray())
323                 .Times(1)
324                 .WillOnce(Return(&replyVector));
325         }
326
327         void expectGetInteger(int value)
328         {
329             EXPECT_CALL(replyMock, getInteger())
330                 .Times(1)
331                 .WillOnce(Return(value));
332         }
333
334         void expectContentsBuild(const std::string& string,
335                                  const AsyncStorage::Key& key,
336                                  const AsyncStorage::Data& data)
337         {
338             EXPECT_CALL(*contentsBuilderMock, build(string, ns, key, data))
339                 .Times(1)
340                 .WillOnce(Return(contents));
341         }
342
343
344         void expectContentsBuild(const std::string& string,
345                                  const AsyncStorage::Key& key,
346                                  const AsyncStorage::Data& data,
347                                  const std::string& string2,
348                                  const std::string& string3)
349         {
350             EXPECT_CALL(*contentsBuilderMock, build(string, ns, key, data, string2, string3))
351                 .Times(1)
352                 .WillOnce(Return(contents));
353         }
354
355         void expectContentsBuild(const std::string& string,
356                                  const std::string& string2,
357                                  const std::string& string3)
358         {
359             EXPECT_CALL(*contentsBuilderMock, build(string, string2, string3))
360                 .Times(1)
361                 .WillOnce(Return(contents));
362         }
363
364         void expectContentsBuild(const std::string& string,
365                                  const AsyncStorage::DataMap& dataMap)
366         {
367             EXPECT_CALL(*contentsBuilderMock, build(string, ns, dataMap))
368                 .Times(1)
369                 .WillOnce(Return(contents));
370         }
371
372         void expectContentsBuild(const std::string& string,
373                                  const AsyncStorage::DataMap& dataMap,
374                                  const std::string& string2,
375                                  const std::string& string3)
376         {
377             EXPECT_CALL(*contentsBuilderMock, build(string, ns, dataMap, string2, string3))
378                 .Times(1)
379                 .WillOnce(Return(contents));
380         }
381
382         void expectContentsBuild(const std::string& string,
383                                  const AsyncStorage::Keys& keys)
384         {
385             EXPECT_CALL(*contentsBuilderMock, build(string, ns, keys))
386                 .Times(1)
387                 .WillOnce(Return(contents));
388         }
389
390         void expectContentsBuild(const std::string& string,
391                                  const AsyncStorage::Keys& keys,
392                                  const std::string& string2,
393                                  const std::string& string3)
394         {
395             EXPECT_CALL(*contentsBuilderMock, build(string, ns, keys, string2, string3))
396                 .Times(1)
397                 .WillOnce(Return(contents));
398         }
399
400         void expectContentsBuild(const std::string& string,
401                                  const std::string& string2)
402         {
403             EXPECT_CALL(*contentsBuilderMock, build(string, string2))
404                 .Times(1)
405                 .WillOnce(Return(contents));
406         }
407     };
408
409     class AsyncRedisStorageTest: public AsyncRedisStorageTestBase
410     {
411     public:
412         AsyncRedisStorageTest()
413         {
414             InSequence dummy;
415             for (auto i(0U); i < 3; ++i)
416                 replyVector.push_back(getMockPtr());
417             createAndConnectAsyncStorageInstance(boost::none);
418             EXPECT_CALL(*namespaceConfigurationsMock, areNotificationsEnabled(_)).WillRepeatedly(Return(true));
419         }
420
421         ~AsyncRedisStorageTest()
422         {
423             expectClearStateChangedCb();
424             EXPECT_CALL(*dispatcherMock, disableCommandCallbacks())
425                 .Times(1);
426         }
427     };
428
429
430     class AsyncRedisStorageTestNotificationsDisabled: public AsyncRedisStorageTestBase
431     {
432     public:
433         AsyncRedisStorageTestNotificationsDisabled()
434         {
435             InSequence dummy;
436             for (auto i(0U); i < 3; ++i)
437                 replyVector.push_back(getMockPtr());
438             createAndConnectAsyncStorageInstance(boost::none);
439             EXPECT_CALL(*namespaceConfigurationsMock, areNotificationsEnabled(_)).WillRepeatedly(Return(false));
440         }
441
442         ~AsyncRedisStorageTestNotificationsDisabled()
443         {
444             expectClearStateChangedCb();
445             EXPECT_CALL(*dispatcherMock, disableCommandCallbacks())
446                 .Times(1);
447         }
448     };
449
450
451     class AsyncRedisStorageTestDispatcherNotCreated: public AsyncRedisStorageTestBase
452     {
453     public:
454         AsyncRedisStorageTestDispatcherNotCreated()
455         {
456             InSequence dummy;
457             for (auto i(0U); i < 3; ++i)
458                 replyVector.push_back(getMockPtr());
459             createAsyncStorageInstance(boost::none);
460         }
461
462         ~AsyncRedisStorageTestDispatcherNotCreated()
463         {
464             expectClearStateChangedCb();
465         }
466     };
467
468     class AsyncRedisStorageDeathTest: public AsyncRedisStorageTestBase
469     {
470     public:
471         AsyncRedisStorageDeathTest()
472         {
473         }
474     };
475 }
476
477 TEST_F(AsyncRedisStorageErrorCodeTest, AllErrorCodeEnumsHaveCorrectDescriptionMessage)
478 {
479     std::error_code ec;
480
481     for (AsyncRedisStorage::ErrorCode aec = AsyncRedisStorage::ErrorCode::SUCCESS; aec != AsyncRedisStorage::ErrorCode::END_MARKER; ++aec)
482     {
483         switch (aec)
484         {
485             case AsyncRedisStorage::ErrorCode::SUCCESS:
486                 ec = aec;
487                 EXPECT_EQ(std::error_code().message(), getErrorCodeMessage(ec));
488                 break;
489             case AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED:
490                 ec = aec;
491                 EXPECT_EQ("connection to the underlying data storage not yet available", getErrorCodeMessage(ec));
492                 break;
493             case AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE:
494                 ec = aec;
495                 EXPECT_EQ("invalid namespace identifier passed to SDL API", getErrorCodeMessage(ec));
496                 break;
497             case AsyncRedisStorage::ErrorCode::END_MARKER:
498                 ec = aec;
499                 EXPECT_EQ("unsupported error code for message()", getErrorCodeMessage(ec));
500                 break;
501             default:
502                 FAIL() << "No mapping for AsyncRedisStorage value: " << aec;
503                 break;
504         }
505     }
506 }
507
508 TEST_F(AsyncRedisStorageErrorCodeTest, AllErrorCodeEnumsAreMappedToCorrectSDLInternalError)
509 {
510     /* If this test case detects missing error code, remember to add new error code also to AllErrorCodeEnumsAreMappedToCorrectClientErrorCode
511      * test case (and add also mapping implementation from InternalError to Error if needed).
512      */
513     std::error_code ec;
514
515     for (AsyncRedisStorage::ErrorCode aec = AsyncRedisStorage::ErrorCode::SUCCESS; aec != AsyncRedisStorage::ErrorCode::END_MARKER; ++aec)
516     {
517         switch (aec)
518         {
519             case AsyncRedisStorage::ErrorCode::SUCCESS:
520                 ec = aec;
521                 EXPECT_TRUE(ec == InternalError::SUCCESS);
522                 break;
523             case AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED:
524                 ec = aec;
525                 EXPECT_TRUE(ec == InternalError::SDL_NOT_READY);
526                 break;
527             case AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE:
528                 ec = aec;
529                 EXPECT_TRUE(ec == InternalError::SDL_RECEIVED_INVALID_PARAMETER);
530                 break;
531             case AsyncRedisStorage::ErrorCode::END_MARKER:
532                 ec = aec;
533                 EXPECT_TRUE(ec == InternalError::SDL_ERROR_CODE_LOGIC_ERROR);
534                 break;
535             default:
536                 FAIL() << "No mapping for AsyncRedisStorage value: " << aec;
537                 break;
538         }
539     }
540 }
541
542 TEST_F(AsyncRedisStorageErrorCodeTest, AllErrorCodeEnumsAreMappedToCorrectClientErrorCode)
543 {
544     std::error_code ec;
545
546     ec = AsyncRedisStorage::ErrorCode::SUCCESS;
547     EXPECT_TRUE(ec == shareddatalayer::Error::SUCCESS);
548     ec = AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED;
549     EXPECT_TRUE(ec == shareddatalayer::Error::NOT_CONNECTED);
550     ec = AsyncRedisStorage::ErrorCode::END_MARKER;
551     EXPECT_TRUE(ec == shareddatalayer::Error::BACKEND_FAILURE);
552 }
553
554 TEST_F(AsyncRedisStorageTest, IsNotCopyable)
555 {
556     EXPECT_FALSE(std::is_copy_constructible<AsyncRedisStorage>::value);
557     EXPECT_FALSE(std::is_copy_assignable<AsyncRedisStorage>::value);
558 }
559 TEST_F(AsyncRedisStorageTest, ImplementsAsyncStorage)
560 {
561     EXPECT_TRUE((std::is_base_of<AsyncStorage, AsyncRedisStorage>::value));
562 }
563
564 TEST_F(AsyncRedisStorageTest, CanGetFd)
565 {
566     EXPECT_CALL(*engineMock, fd())
567         .Times(1)
568         .WillOnce(Return(fd));
569     EXPECT_EQ(fd, sdlStorage->fd());
570 }
571
572 TEST_F(AsyncRedisStorageTest, CanHandleEvents)
573 {
574     EXPECT_CALL(*engineMock, handleEvents())
575         .Times(1);
576     sdlStorage->handleEvents();
577 }
578
579 TEST_F(AsyncRedisStorageTest, ReadyAckIsPassedToAsyncRedisCommandDispatcher)
580 {
581     InSequence dummy;
582     EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
583         .Times(1)
584         .WillOnce(SaveArg<0>(&dispatcherConnectAck));
585     sdlStorage->waitReadyAsync(ns, std::bind(&AsyncRedisStorageTest::readyAck, this, std::placeholders::_1));
586     expectReadyAck(std::error_code());
587     dispatcherConnectAck();
588 }
589
590 TEST_F(AsyncRedisStorageTest, PassingEmptyPublisherIdThrows)
591 {
592     EXPECT_THROW(sdlStorage.reset(new AsyncRedisStorage(
593                      engineMock,
594                      discoveryMock,
595                      std::string(""),
596                      namespaceConfigurationsMock,
597                      std::bind(&AsyncRedisStorageTest::asyncCommandDispatcherCreator,
598                          this,
599                          std::placeholders::_1,
600                          std::placeholders::_2,
601                          std::placeholders::_3),
602                      contentsBuilderMock,
603                      logger)),
604                  std::invalid_argument);
605 }
606
607 TEST_F(AsyncRedisStorageTest, PassingInvalidNamespaceToSetAsyncNacks)
608 {
609     InSequence dummy;
610     expectPostCallback();
611     sdlStorage->setAsync("ns1,2",
612                          { { key1, { } } },
613                          std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
614                                    this,
615                                    std::placeholders::_1));
616     expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE));
617     storedCallback();
618 }
619
620 TEST_F(AsyncRedisStorageTest, PassingEmptyNamespaceToSetAsyncNacks)
621 {
622     InSequence dummy;
623     expectPostCallback();
624     sdlStorage->setAsync("",
625                          { { key1, { } } },
626                          std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
627                                    this,
628                                    std::placeholders::_1));
629     expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE));
630     storedCallback();
631 }
632
633 TEST_F(AsyncRedisStorageTest, SetAsyncSuccessfullyAndErrorIsForwarded)
634 {
635     InSequence dummy;
636     expectContentsBuild("MSETPUB", dataMap, ns, shareddatalayer::NO_PUBLISHER);
637     expectDispatchAsync();
638     sdlStorage->setAsync(ns,
639                          dataMap,
640                          std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
641     expectModifyAck(std::error_code());
642     savedCommandCb(std::error_code(), replyMock);
643     expectModifyAck(getWellKnownErrorCode());
644     savedCommandCb(getWellKnownErrorCode(), replyMock);
645 }
646
647 TEST_F(AsyncRedisStorageTestNotificationsDisabled, SetAsyncSuccessfullyAndErrorIsForwardedNoPublish)
648 {
649     InSequence dummy;
650     expectContentsBuild("MSET", dataMap);
651     expectDispatchAsync();
652     sdlStorage->setAsync(ns,
653                          dataMap,
654                          std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
655     expectModifyAck(std::error_code());
656     savedCommandCb(std::error_code(), replyMock);
657     expectModifyAck(getWellKnownErrorCode());
658     savedCommandCb(getWellKnownErrorCode(), replyMock);
659 }
660
661 TEST_F(AsyncRedisStorageTest, EmptyMapIsCheckedInSetAsyncAndAckIsScheduled)
662 {
663     InSequence dummy;
664     expectNoDispatchAsync();
665     expectPostCallback();
666     sdlStorage->setAsync(ns,
667                          { },
668                          std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
669     expectModifyAck(std::error_code());
670     storedCallback();
671 }
672
673 TEST_F(AsyncRedisStorageTest, GetAsyncSuccessfullyAndErrorIsForwarded)
674 {
675     InSequence dummy;
676     expectContentsBuild("MGET", keysWithNonExistKey);
677     expectDispatchAsync();
678     sdlStorage->getAsync(ns,
679                          keysWithNonExistKey,
680                          std::bind(&AsyncRedisStorageTest::getAck,
681                                    this,
682                                    std::placeholders::_1,
683                                    std::placeholders::_2));
684     expectGetArray();
685     auto expectedDataItem1(Reply::DataItem { std::string(data1.begin(),data1.end()), ReplyStringLength(data1.size()) });
686     auto expectedDataItem2(Reply::DataItem { std::string(data2.begin(),data2.end()), ReplyStringLength(data2.size()) });
687     expectGetDataString(expectedDataItem1);
688     expectGetDataString(expectedDataItem2);
689     expectGetType(Reply::Type::NIL);
690     expectGetAck(std::error_code(), { { key1, data1 }, { key2, data2 } });
691     savedCommandCb(std::error_code(), replyMock);
692     expectGetAck(getWellKnownErrorCode(), { });
693     savedCommandCb(getWellKnownErrorCode(), replyMock);
694 }
695
696 TEST_F(AsyncRedisStorageTest, EmptyEntriesIsCheckedInGetAsyncAndAckIsScheduled)
697 {
698     InSequence dummy;
699     expectNoDispatchAsync();
700     expectPostCallback();
701     sdlStorage->getAsync(ns,
702                          { },
703                          std::bind(&AsyncRedisStorageTest::getAck,
704                                    this,
705                                    std::placeholders::_1,
706                                    std::placeholders::_2));
707     expectGetAck(std::error_code(), { });
708     storedCallback();
709 }
710
711 TEST_F(AsyncRedisStorageTest, RemoveAsyncSuccessfullyAndErrorIsForwarded)
712 {
713     InSequence dummy;
714     expectContentsBuild("DELPUB", keys, ns, shareddatalayer::NO_PUBLISHER);
715     expectDispatchAsync();
716     sdlStorage->removeAsync(ns,
717                             keys,
718                             std::bind(&AsyncRedisStorageTest::modifyAck,
719                                       this,
720                                       std::placeholders::_1));
721     expectModifyAck(std::error_code());
722     savedCommandCb(std::error_code(), replyMock);
723     expectModifyAck(getWellKnownErrorCode());
724     savedCommandCb(getWellKnownErrorCode(), replyMock);
725 }
726
727 TEST_F(AsyncRedisStorageTestNotificationsDisabled, RemoveAsyncSuccessfullyAndErrorIsForwardedNoPublish)
728 {
729     InSequence dummy;
730     expectContentsBuild("DEL", keys);
731     expectDispatchAsync();
732     sdlStorage->removeAsync(ns,
733                             keys,
734                             std::bind(&AsyncRedisStorageTest::modifyAck,
735                                       this,
736                                       std::placeholders::_1));
737     expectModifyAck(std::error_code());
738     savedCommandCb(std::error_code(), replyMock);
739     expectModifyAck(getWellKnownErrorCode());
740     savedCommandCb(getWellKnownErrorCode(), replyMock);
741 }
742
743 TEST_F(AsyncRedisStorageTest, EmptyEntriesIsCheckedInRemoveAsyncAndAckIsScheduled)
744 {
745     InSequence dummy;
746     expectNoDispatchAsync();
747     expectPostCallback();
748     sdlStorage->removeAsync(ns,
749                             { },
750                             std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
751     expectModifyAck(std::error_code());
752     storedCallback();
753 }
754
755 TEST_F(AsyncRedisStorageTest, FindKeysAsyncSuccessfullyAndErrorIsTranslated)
756 {
757     InSequence dummy;
758     expectContentsBuild("KEYS", keyPrefix);
759     expectDispatchAsync();
760     sdlStorage->findKeysAsync(ns,
761                               "",
762                               std::bind(&AsyncRedisStorageTest::findKeysAck,
763                                         this,
764                                         std::placeholders::_1,
765                                         std::placeholders::_2));
766     expectGetArray();
767     auto expectedDataItem1(Reply::DataItem { key1, ReplyStringLength(key1.size()) });
768     auto expectedDataItem2(Reply::DataItem { key2, ReplyStringLength(key2.size()) });
769     expectGetDataString(expectedDataItem1);
770     expectGetType(Reply::Type::NIL);
771     expectGetDataString(expectedDataItem2);
772     expectFindKeysAck(std::error_code(), { key1, key2 });
773     savedCommandCb(std::error_code(), replyMock);
774     expectFindKeysAck(getWellKnownErrorCode(), { });
775     savedCommandCb(getWellKnownErrorCode(), replyMock);
776 }
777
778 TEST_F(AsyncRedisStorageTest, ListKeysPatternSuccessfullyAndErrorIsTranslated)
779 {
780     InSequence dummy;
781     expectContentsBuild("KEYS", "{tag1},key[12]");
782     expectDispatchAsync();
783     sdlStorage->listKeys(ns,
784                          "key[12]",
785                          std::bind(&AsyncRedisStorageTest::findKeysAck,
786                                    this,
787                                    std::placeholders::_1,
788                                    std::placeholders::_2));
789     expectGetArray();
790     auto expectedDataItem1(Reply::DataItem { key1, ReplyStringLength(key1.size()) });
791     auto expectedDataItem2(Reply::DataItem { key2, ReplyStringLength(key2.size()) });
792     expectGetDataString(expectedDataItem1);
793     expectGetType(Reply::Type::NIL);
794     expectGetDataString(expectedDataItem2);
795     expectFindKeysAck(std::error_code(), { key1, key2 });
796     savedCommandCb(std::error_code(), replyMock);
797     expectFindKeysAck(getWellKnownErrorCode(), { });
798     savedCommandCb(getWellKnownErrorCode(), replyMock);
799 }
800
801 TEST_F(AsyncRedisStorageTest, RemoveAllAsyncSuccessfully)
802 {
803     InSequence dummy;
804     expectContentsBuild("KEYS", keyPrefix);
805     expectDispatchAsync();
806     sdlStorage->removeAllAsync(ns,
807                                std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
808     expectGetArray();
809     auto expectedDataItem1(Reply::DataItem { key1, ReplyStringLength(key1.size()) });
810     auto expectedDataItem2(Reply::DataItem { key2, ReplyStringLength(key2.size()) });
811     expectGetDataString(expectedDataItem1);
812     expectGetType(Reply::Type::NIL);
813     expectGetDataString(expectedDataItem2);
814     expectContentsBuild("DELPUB", keys, ns, shareddatalayer::NO_PUBLISHER);
815     expectDispatchAsync();
816     savedCommandCb(std::error_code(), replyMock);
817     expectModifyAck(std::error_code());
818     savedCommandCb(std::error_code(), replyMock);
819 }
820
821 TEST_F(AsyncRedisStorageTestNotificationsDisabled, RemoveAllAsyncSuccessfullyNoPublish)
822 {
823     InSequence dummy;
824     expectContentsBuild("KEYS", keyPrefix);
825     expectDispatchAsync();
826     sdlStorage->removeAllAsync(ns,
827                                std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
828     expectGetArray();
829     auto expectedDataItem1(Reply::DataItem { key1, ReplyStringLength(key1.size()) });
830     auto expectedDataItem2(Reply::DataItem { key2, ReplyStringLength(key2.size()) });
831     expectGetDataString(expectedDataItem1);
832     expectGetType(Reply::Type::NIL);
833     expectGetDataString(expectedDataItem2);
834     expectContentsBuild("DEL", keys);
835     expectDispatchAsync();
836     savedCommandCb(std::error_code(), replyMock);
837 }
838
839 TEST_F(AsyncRedisStorageTest, NothingIsIssuedToBeRemovedIfNoKeysAreFoundUnderNamespace)
840 {
841     InSequence dummy;
842     Reply::ReplyVector empty;
843     expectContentsBuild("KEYS", keyPrefix);
844     expectDispatchAsync();
845     sdlStorage->removeAllAsync(ns,
846                                std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
847     EXPECT_CALL(replyMock, getArray())
848         .Times(1)
849         .WillOnce(Return(&empty));
850     EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, _))
851         .Times(0);
852     expectModifyAck(std::error_code());
853     savedCommandCb(std::error_code(), replyMock);
854 }
855
856 TEST_F(AsyncRedisStorageTest, RemoveAllAsyncErrorIsForwarded)
857 {
858     InSequence dummy;
859     expectContentsBuild("KEYS", keyPrefix);
860     expectDispatchAsync();
861     sdlStorage->removeAllAsync(ns,
862                                std::bind(&AsyncRedisStorageTest::modifyAck,
863                                          this,
864                                          std::placeholders::_1));
865     expectModifyAck(getWellKnownErrorCode());
866     savedCommandCb(getWellKnownErrorCode(), replyMock);
867 }
868
869 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncSuccess)
870 {
871     InSequence dummy;
872     expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
873     expectDispatchAsync();
874     sdlStorage->setIfNotExistsAsync(ns,
875                                     key1,
876                                     data1,
877                                     std::bind(&AsyncRedisStorageTest::modifyIfAck,
878                                               this, std::placeholders::_1,  std::placeholders::_2));
879     expectGetType(Reply::Type::INTEGER);
880     expectGetInteger(1);
881     expectModifyIfAck(std::error_code(), true);
882     savedCommandCb(std::error_code(), replyMock);
883 }
884
885 TEST_F(AsyncRedisStorageTestNotificationsDisabled, SetIfNotExistsAsyncSuccessNoPublish)
886 {
887     InSequence dummy;
888     expectContentsBuild("SETNX", key1, data1);
889     expectDispatchAsync();
890     sdlStorage->setIfNotExistsAsync(ns,
891                                     key1,
892                                     data1,
893                                     std::bind(&AsyncRedisStorageTest::modifyIfAck,
894                                               this, std::placeholders::_1,  std::placeholders::_2));
895     expectGetType(Reply::Type::INTEGER);
896     expectGetInteger(1);
897     expectModifyIfAck(std::error_code(), true);
898     savedCommandCb(std::error_code(), replyMock);
899 }
900
901 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncKeyAlreadyExists)
902 {
903     InSequence dummy;
904     expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
905     expectDispatchAsync();
906     sdlStorage->setIfNotExistsAsync(ns,
907                                     key1,
908                                     data1,
909                                     std::bind(&AsyncRedisStorageTest::modifyIfAck,
910                                               this, std::placeholders::_1,  std::placeholders::_2));
911     expectGetType(Reply::Type::INTEGER);
912     expectGetInteger(0);
913     expectModifyIfAck(std::error_code(), false);
914     savedCommandCb(std::error_code(), replyMock);
915 }
916
917 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncErrorResponse)
918 {
919     InSequence dummy;
920     expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
921     expectDispatchAsync();
922     sdlStorage->setIfNotExistsAsync(ns,
923                                     key1,
924                                     data1,
925                                     std::bind(&AsyncRedisStorageTest::modifyIfAck,
926                                               this, std::placeholders::_1,  std::placeholders::_2));
927     expectGetType(Reply::Type::INTEGER);
928     expectModifyIfAck(getWellKnownErrorCode(), false);
929     savedCommandCb(getWellKnownErrorCode(), replyMock);
930 }
931
932 TEST_F(AsyncRedisStorageTest, RedisSearchPatternCharactersAreCorrectlyEscapedInKeyPrefixSearch)
933 {
934     InSequence dummy;
935     const std::string keyPrefixSearchPatternPrefix = '{' + ns + '}' + AsyncStorage::SEPARATOR;
936     std::string builtKeyPrefixSearchPattern;
937     std::string expectedKeyPrefixSearchPattern;
938
939     // empty prefix will not be escaped and it will search all keys
940     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + '*';
941     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "");
942     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
943
944     // prefix without search characters is not escaped
945     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + "someKnownKeyPrefix" + '*';
946     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "someKnownKeyPrefix");
947     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
948
949     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"("someKnownKeyPrefix")" + '*';
950     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, R"("someKnownKeyPrefix")");
951     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
952
953     // all search characters are correctly escaped with backslash
954     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"(someKnownKeyPrefix\*)" + '*';
955     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "someKnownKeyPrefix*");
956     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
957
958     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"(\?some\]Known\[Key\\Prefix\*)" + '*';
959     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "?some]Known[Key\\Prefix*");
960     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
961
962     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"(\?\*some\[\]Known\[\*\?\\\]Key\\\*Prefix\*\*\*\*)" + '*';
963     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "?*some[]Known[*?\\]Key\\*Prefix****");
964     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
965 }
966
967 TEST_F(AsyncRedisStorageTest, BuildNamespaceKeySearchPatternIsCorrect)
968 {
969     InSequence dummy;
970     const std::string nsPrefix = '{' + ns + '}' + AsyncStorage::SEPARATOR;
971     std::string buildPattern;
972     std::string expectedPattern;
973
974     expectedPattern = nsPrefix;
975     buildPattern = sdlStorage->buildNamespaceKeySearchPattern(ns, "");
976     ASSERT_STREQ(expectedPattern.c_str(), buildPattern.c_str());
977
978     expectedPattern = nsPrefix + '*';
979     buildPattern = sdlStorage->buildNamespaceKeySearchPattern(ns, "*");
980     ASSERT_STREQ(expectedPattern.c_str(), buildPattern.c_str());
981
982     expectedPattern = nsPrefix + "h?llo";
983     buildPattern = sdlStorage->buildNamespaceKeySearchPattern(ns, "h?llo");
984     ASSERT_STREQ(expectedPattern.c_str(), buildPattern.c_str());
985 }
986
987 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, ReadyAckNotForwardedIfDispatcherNotYetCreated)
988 {
989     InSequence dummy;
990     EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
991         .Times(0);
992     sdlStorage->waitReadyAsync(ns, std::bind(&AsyncRedisStorageTestDispatcherNotCreated::readyAck, this, std::placeholders::_1));
993 }
994
995 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
996 {
997     InSequence dummy;
998     expectPostCallback();
999     sdlStorage->setAsync(ns,
1000                          { { key1, { } } },
1001                          std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
1002                                    this,
1003                                    std::placeholders::_1));
1004     expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
1005     storedCallback();
1006 }
1007
1008 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1009 {
1010     InSequence dummy;
1011     expectPostCallback();
1012     sdlStorage->setIfAsync(ns,
1013                            key1,
1014                            data1,
1015                            data2,
1016                            std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyIfAck,
1017                                      this, std::placeholders::_1,  std::placeholders::_2));
1018     expectModifyIfAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), false);
1019     storedCallback();
1020 }
1021
1022 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfNotExistsAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1023 {
1024     InSequence dummy;
1025     expectPostCallback();
1026     sdlStorage->setIfNotExistsAsync(ns,
1027                                     key1,
1028                                     data1,
1029                                     std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyIfAck,
1030                                               this, std::placeholders::_1,  std::placeholders::_2));
1031     expectModifyIfAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), false);
1032     storedCallback();
1033 }
1034
1035 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, GetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1036 {
1037     InSequence dummy;
1038     expectPostCallback();
1039     sdlStorage->getAsync(ns,
1040                          {key1},
1041                          std::bind(&AsyncRedisStorageTestDispatcherNotCreated::getAck,
1042                                    this,
1043                                    std::placeholders::_1,
1044                                    std::placeholders::_2));
1045     expectGetAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1046     storedCallback();
1047 }
1048
1049 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1050 {
1051     InSequence dummy;
1052     expectPostCallback();
1053     sdlStorage->removeAsync(ns,
1054                             {key1},
1055                             std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck, this, std::placeholders::_1));
1056     expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
1057     storedCallback();
1058 }
1059
1060 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, FindKeysAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1061 {
1062     InSequence dummy;
1063     expectPostCallback();
1064     sdlStorage->findKeysAsync(ns,
1065                               "*",
1066                               std::bind(&AsyncRedisStorageTestDispatcherNotCreated::findKeysAck,
1067                                         this,
1068                                         std::placeholders::_1,
1069                                         std::placeholders::_2));
1070     expectFindKeysAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1071     storedCallback();
1072 }
1073
1074 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAllAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1075 {
1076     InSequence dummy;
1077     expectPostCallback();
1078     sdlStorage->removeAllAsync(ns,
1079                                std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck, this, std::placeholders::_1));
1080     expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
1081     storedCallback();
1082 }