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