Add synchronous SDL readiness waiting API
[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, RemoveAllAsyncSuccessfully)
779 {
780     InSequence dummy;
781     expectContentsBuild("KEYS", keyPrefix);
782     expectDispatchAsync();
783     sdlStorage->removeAllAsync(ns,
784                                std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
785     expectGetArray();
786     auto expectedDataItem1(Reply::DataItem { key1, ReplyStringLength(key1.size()) });
787     auto expectedDataItem2(Reply::DataItem { key2, ReplyStringLength(key2.size()) });
788     expectGetDataString(expectedDataItem1);
789     expectGetType(Reply::Type::NIL);
790     expectGetDataString(expectedDataItem2);
791     expectContentsBuild("DELPUB", keys, ns, shareddatalayer::NO_PUBLISHER);
792     expectDispatchAsync();
793     savedCommandCb(std::error_code(), replyMock);
794     expectModifyAck(std::error_code());
795     savedCommandCb(std::error_code(), replyMock);
796 }
797
798 TEST_F(AsyncRedisStorageTestNotificationsDisabled, RemoveAllAsyncSuccessfullyNoPublish)
799 {
800     InSequence dummy;
801     expectContentsBuild("KEYS", keyPrefix);
802     expectDispatchAsync();
803     sdlStorage->removeAllAsync(ns,
804                                std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
805     expectGetArray();
806     auto expectedDataItem1(Reply::DataItem { key1, ReplyStringLength(key1.size()) });
807     auto expectedDataItem2(Reply::DataItem { key2, ReplyStringLength(key2.size()) });
808     expectGetDataString(expectedDataItem1);
809     expectGetType(Reply::Type::NIL);
810     expectGetDataString(expectedDataItem2);
811     expectContentsBuild("DEL", keys);
812     expectDispatchAsync();
813     savedCommandCb(std::error_code(), replyMock);
814 }
815
816 TEST_F(AsyncRedisStorageTest, NothingIsIssuedToBeRemovedIfNoKeysAreFoundUnderNamespace)
817 {
818     InSequence dummy;
819     Reply::ReplyVector empty;
820     expectContentsBuild("KEYS", keyPrefix);
821     expectDispatchAsync();
822     sdlStorage->removeAllAsync(ns,
823                                std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
824     EXPECT_CALL(replyMock, getArray())
825         .Times(1)
826         .WillOnce(Return(&empty));
827     EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, _))
828         .Times(0);
829     expectModifyAck(std::error_code());
830     savedCommandCb(std::error_code(), replyMock);
831 }
832
833 TEST_F(AsyncRedisStorageTest, RemoveAllAsyncErrorIsForwarded)
834 {
835     InSequence dummy;
836     expectContentsBuild("KEYS", keyPrefix);
837     expectDispatchAsync();
838     sdlStorage->removeAllAsync(ns,
839                                std::bind(&AsyncRedisStorageTest::modifyAck,
840                                          this,
841                                          std::placeholders::_1));
842     expectModifyAck(getWellKnownErrorCode());
843     savedCommandCb(getWellKnownErrorCode(), replyMock);
844 }
845
846 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncSuccess)
847 {
848     InSequence dummy;
849     expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
850     expectDispatchAsync();
851     sdlStorage->setIfNotExistsAsync(ns,
852                                     key1,
853                                     data1,
854                                     std::bind(&AsyncRedisStorageTest::modifyIfAck,
855                                               this, std::placeholders::_1,  std::placeholders::_2));
856     expectGetType(Reply::Type::INTEGER);
857     expectGetInteger(1);
858     expectModifyIfAck(std::error_code(), true);
859     savedCommandCb(std::error_code(), replyMock);
860 }
861
862 TEST_F(AsyncRedisStorageTestNotificationsDisabled, SetIfNotExistsAsyncSuccessNoPublish)
863 {
864     InSequence dummy;
865     expectContentsBuild("SETNX", key1, data1);
866     expectDispatchAsync();
867     sdlStorage->setIfNotExistsAsync(ns,
868                                     key1,
869                                     data1,
870                                     std::bind(&AsyncRedisStorageTest::modifyIfAck,
871                                               this, std::placeholders::_1,  std::placeholders::_2));
872     expectGetType(Reply::Type::INTEGER);
873     expectGetInteger(1);
874     expectModifyIfAck(std::error_code(), true);
875     savedCommandCb(std::error_code(), replyMock);
876 }
877
878 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncKeyAlreadyExists)
879 {
880     InSequence dummy;
881     expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
882     expectDispatchAsync();
883     sdlStorage->setIfNotExistsAsync(ns,
884                                     key1,
885                                     data1,
886                                     std::bind(&AsyncRedisStorageTest::modifyIfAck,
887                                               this, std::placeholders::_1,  std::placeholders::_2));
888     expectGetType(Reply::Type::INTEGER);
889     expectGetInteger(0);
890     expectModifyIfAck(std::error_code(), false);
891     savedCommandCb(std::error_code(), replyMock);
892 }
893
894 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncErrorResponse)
895 {
896     InSequence dummy;
897     expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
898     expectDispatchAsync();
899     sdlStorage->setIfNotExistsAsync(ns,
900                                     key1,
901                                     data1,
902                                     std::bind(&AsyncRedisStorageTest::modifyIfAck,
903                                               this, std::placeholders::_1,  std::placeholders::_2));
904     expectGetType(Reply::Type::INTEGER);
905     expectModifyIfAck(getWellKnownErrorCode(), false);
906     savedCommandCb(getWellKnownErrorCode(), replyMock);
907 }
908
909 TEST_F(AsyncRedisStorageTest, RedisSearchPatternCharactersAreCorrectlyEscapedInKeyPrefixSearch)
910 {
911     InSequence dummy;
912     const std::string keyPrefixSearchPatternPrefix = '{' + ns + '}' + AsyncStorage::SEPARATOR;
913     std::string builtKeyPrefixSearchPattern;
914     std::string expectedKeyPrefixSearchPattern;
915
916     // empty prefix will not be escaped and it will search all keys
917     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + '*';
918     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "");
919     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
920
921     // prefix without search characters is not escaped
922     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + "someKnownKeyPrefix" + '*';
923     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "someKnownKeyPrefix");
924     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
925
926     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"("someKnownKeyPrefix")" + '*';
927     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, R"("someKnownKeyPrefix")");
928     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
929
930     // all search characters are correctly escaped with backslash
931     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"(someKnownKeyPrefix\*)" + '*';
932     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "someKnownKeyPrefix*");
933     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
934
935     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"(\?some\]Known\[Key\\Prefix\*)" + '*';
936     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "?some]Known[Key\\Prefix*");
937     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
938
939     expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"(\?\*some\[\]Known\[\*\?\\\]Key\\\*Prefix\*\*\*\*)" + '*';
940     builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "?*some[]Known[*?\\]Key\\*Prefix****");
941     ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
942 }
943
944 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, ReadyAckNotForwardedIfDispatcherNotYetCreated)
945 {
946     InSequence dummy;
947     EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
948         .Times(0);
949     sdlStorage->waitReadyAsync(ns, std::bind(&AsyncRedisStorageTestDispatcherNotCreated::readyAck, this, std::placeholders::_1));
950 }
951
952 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
953 {
954     InSequence dummy;
955     expectPostCallback();
956     sdlStorage->setAsync(ns,
957                          { { key1, { } } },
958                          std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
959                                    this,
960                                    std::placeholders::_1));
961     expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
962     storedCallback();
963 }
964
965 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
966 {
967     InSequence dummy;
968     expectPostCallback();
969     sdlStorage->setIfAsync(ns,
970                            key1,
971                            data1,
972                            data2,
973                            std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyIfAck,
974                                      this, std::placeholders::_1,  std::placeholders::_2));
975     expectModifyIfAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), false);
976     storedCallback();
977 }
978
979 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfNotExistsAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
980 {
981     InSequence dummy;
982     expectPostCallback();
983     sdlStorage->setIfNotExistsAsync(ns,
984                                     key1,
985                                     data1,
986                                     std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyIfAck,
987                                               this, std::placeholders::_1,  std::placeholders::_2));
988     expectModifyIfAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), false);
989     storedCallback();
990 }
991
992 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, GetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
993 {
994     InSequence dummy;
995     expectPostCallback();
996     sdlStorage->getAsync(ns,
997                          {key1},
998                          std::bind(&AsyncRedisStorageTestDispatcherNotCreated::getAck,
999                                    this,
1000                                    std::placeholders::_1,
1001                                    std::placeholders::_2));
1002     expectGetAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1003     storedCallback();
1004 }
1005
1006 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1007 {
1008     InSequence dummy;
1009     expectPostCallback();
1010     sdlStorage->removeAsync(ns,
1011                             {key1},
1012                             std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck, this, std::placeholders::_1));
1013     expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
1014     storedCallback();
1015 }
1016
1017 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, FindKeysAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1018 {
1019     InSequence dummy;
1020     expectPostCallback();
1021     sdlStorage->findKeysAsync(ns,
1022                               "*",
1023                               std::bind(&AsyncRedisStorageTestDispatcherNotCreated::findKeysAck,
1024                                         this,
1025                                         std::placeholders::_1,
1026                                         std::placeholders::_2));
1027     expectFindKeysAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1028     storedCallback();
1029 }
1030
1031 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAllAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1032 {
1033     InSequence dummy;
1034     expectPostCallback();
1035     sdlStorage->removeAllAsync(ns,
1036                                std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck, this, std::placeholders::_1));
1037     expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
1038     storedCallback();
1039 }