2 Copyright (c) 2018-2019 Nokia.
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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <type_traits>
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"
40 using namespace shareddatalayer;
41 using namespace shareddatalayer::redis;
42 using namespace shareddatalayer::tst;
43 using namespace testing;
47 std::string getErrorCodeMessage(std::error_code ec)
52 class AsyncRedisStorageErrorCodeTest: public testing::Test
55 AsyncRedisStorageErrorCodeTest()
59 virtual ~AsyncRedisStorageErrorCodeTest()
64 static const std::string defaultAddress = "address";
65 static const uint16_t defaultPort = 3333;
66 class AsyncRedisStorageTestBase: public testing::Test
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;
77 Contents publishContentsWithoutPubId;
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;
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;
105 AsyncRedisStorageTestBase():
106 engineMock(std::make_shared<StrictMock<EngineMock>>()),
107 discoveryMock(std::make_shared<StrictMock<AsyncDatabaseDiscoveryMock>>()),
108 dispatcherMock(std::make_shared<StrictMock<AsyncCommandDispatcherMock>>()),
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 } }),
120 keysWithNonExistKey({key1,"notfound",key2}),
123 dataMap({{key1,data1},{key2,data2}}),
124 keyPrefix("{tag1},*"),
125 logger(createLogger(SDL_LOG_PREFIX))
129 virtual ~AsyncRedisStorageTestBase() = default;
131 std::shared_ptr<AsyncCommandDispatcher> asyncCommandDispatcherCreator(Engine&,
133 std::shared_ptr<ContentsBuilder>)
135 newDispatcherCreated();
136 return dispatcherMock;
139 MOCK_METHOD0(newDispatcherCreated, void());
141 MOCK_METHOD1(readyAck, void(const std::error_code&));
143 MOCK_METHOD1(modifyAck, void(const std::error_code&));
145 MOCK_METHOD2(modifyIfAck, void(const std::error_code&, bool status));
147 MOCK_METHOD2(getAck, void(const std::error_code&, const AsyncStorage::DataMap&));
149 MOCK_METHOD2(findKeysAck, void(const std::error_code&, const AsyncStorage::Keys&));
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)
156 DatabaseInfo databaseInfo;
157 databaseInfo.type = type;
158 databaseInfo.discovery = discovery;
159 databaseInfo.hosts.push_back({address, htons(port)});
160 databaseInfo.ns = ns;
164 void expectDiscoverySetStateChangedCb()
166 EXPECT_CALL(*discoveryMock, setStateChangedCb(_))
168 .WillOnce(Invoke([this](const AsyncDatabaseDiscovery::StateChangedCb& cb)
174 void expectDispatcherWaitConnectedAsync()
176 EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
178 .WillOnce(Invoke([this](const AsyncCommandDispatcher::ConnectAck& connectAck)
180 dispatcherConnectAck = connectAck;
184 void expectDispatcherCreation()
186 expectDispatcherWaitConnectedAsync();
189 void expectNewDispatcherCreated()
191 EXPECT_CALL(*this, newDispatcherCreated)
195 void expectNewDispatcherNotCreated()
197 EXPECT_CALL(*this, newDispatcherCreated)
201 void expectReadyAck(const std::error_code& error)
203 EXPECT_CALL(*this, readyAck(error))
207 void expectModifyAck(const std::error_code& error)
209 EXPECT_CALL(*this, modifyAck(error))
213 void expectModifyIfAck(const std::error_code& error, bool status)
215 EXPECT_CALL(*this, modifyIfAck(error, status))
219 void expectGetAck(const std::error_code& error, const AsyncStorage::DataMap& dataMap)
221 EXPECT_CALL(*this, getAck(error, dataMap))
225 void expectFindKeysAck(const std::error_code& error, const AsyncStorage::Keys& keys)
227 EXPECT_CALL(*this, findKeysAck(error, keys))
231 void expectPostCallback()
233 EXPECT_CALL(*engineMock, postCallback(_))
235 .WillOnce(SaveArg<0>(&storedCallback));
238 void createAsyncStorageInstance(const boost::optional<PublisherId>& pId)
240 expectDiscoverySetStateChangedCb();
242 expectClearStateChangedCb();
243 sdlStorage.reset(new AsyncRedisStorage(engineMock,
246 namespaceConfigurationsMock,
247 std::bind(&AsyncRedisStorageTestBase::asyncCommandDispatcherCreator,
249 std::placeholders::_1,
250 std::placeholders::_2,
251 std::placeholders::_3),
256 void createAndConnectAsyncStorageInstance(const boost::optional<PublisherId>& pId)
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()))
266 dispatcherConnectAck();
269 void expectClearStateChangedCb()
271 EXPECT_CALL(*discoveryMock, clearStateChangedCb())
275 void expectNoDispatchAsync()
277 EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, _))
281 void expectDispatchAsync()
283 EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, contents))
285 .WillOnce(SaveArg<0>(&savedCommandCb));
288 void expectPublishDispatch()
290 EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, contents))
292 .WillOnce(SaveArg<0>(&savedPublishCommandCb));
295 std::shared_ptr<Reply> getMockPtr()
297 return std::shared_ptr<Reply>(&replyMock, [](Reply*){ });
300 void expectGetType(const Reply::Type& type)
302 EXPECT_CALL(replyMock, getType())
304 .WillOnce(Return(type));
307 void expectGetDataString(const Reply::DataItem& item)
309 expectGetType(Reply::Type::STRING);
310 EXPECT_CALL(replyMock, getString())
312 .WillOnce(Return(&item));
315 void expectGetArray()
317 EXPECT_CALL(replyMock, getArray())
319 .WillOnce(Return(&replyVector));
322 void expectGetInteger(int value)
324 EXPECT_CALL(replyMock, getInteger())
326 .WillOnce(Return(value));
329 void expectContentsBuild(const std::string& string,
330 const AsyncStorage::Key& key,
331 const AsyncStorage::Data& data)
333 EXPECT_CALL(*contentsBuilderMock, build(string, ns, key, data))
335 .WillOnce(Return(contents));
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)
345 EXPECT_CALL(*contentsBuilderMock, build(string, ns, key, data, string2, string3))
347 .WillOnce(Return(contents));
350 void expectContentsBuild(const std::string& string,
351 const std::string& string2,
352 const std::string& string3)
354 EXPECT_CALL(*contentsBuilderMock, build(string, string2, string3))
356 .WillOnce(Return(contents));
359 void expectContentsBuild(const std::string& string,
360 const AsyncStorage::DataMap& dataMap)
362 EXPECT_CALL(*contentsBuilderMock, build(string, ns, dataMap))
364 .WillOnce(Return(contents));
367 void expectContentsBuild(const std::string& string,
368 const AsyncStorage::DataMap& dataMap,
369 const std::string& string2,
370 const std::string& string3)
372 EXPECT_CALL(*contentsBuilderMock, build(string, ns, dataMap, string2, string3))
374 .WillOnce(Return(contents));
377 void expectContentsBuild(const std::string& string,
378 const AsyncStorage::Keys& keys)
380 EXPECT_CALL(*contentsBuilderMock, build(string, ns, keys))
382 .WillOnce(Return(contents));
385 void expectContentsBuild(const std::string& string,
386 const AsyncStorage::Keys& keys,
387 const std::string& string2,
388 const std::string& string3)
390 EXPECT_CALL(*contentsBuilderMock, build(string, ns, keys, string2, string3))
392 .WillOnce(Return(contents));
395 void expectContentsBuild(const std::string& string,
396 const std::string& string2)
398 EXPECT_CALL(*contentsBuilderMock, build(string, string2))
400 .WillOnce(Return(contents));
404 class AsyncRedisStorageTest: public AsyncRedisStorageTestBase
407 AsyncRedisStorageTest()
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));
416 ~AsyncRedisStorageTest()
418 expectClearStateChangedCb();
419 EXPECT_CALL(*dispatcherMock, disableCommandCallbacks())
425 class AsyncRedisStorageTestNotificationsDisabled: public AsyncRedisStorageTestBase
428 AsyncRedisStorageTestNotificationsDisabled()
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));
437 ~AsyncRedisStorageTestNotificationsDisabled()
439 expectClearStateChangedCb();
440 EXPECT_CALL(*dispatcherMock, disableCommandCallbacks())
446 class AsyncRedisStorageTestDispatcherNotCreated: public AsyncRedisStorageTestBase
449 AsyncRedisStorageTestDispatcherNotCreated()
452 for (auto i(0U); i < 3; ++i)
453 replyVector.push_back(getMockPtr());
454 createAsyncStorageInstance(boost::none);
457 ~AsyncRedisStorageTestDispatcherNotCreated()
459 expectClearStateChangedCb();
463 class AsyncRedisStorageDeathTest: public AsyncRedisStorageTestBase
466 AsyncRedisStorageDeathTest()
472 TEST_F(AsyncRedisStorageErrorCodeTest, AllErrorCodeEnumsHaveCorrectDescriptionMessage)
476 for (AsyncRedisStorage::ErrorCode aec = AsyncRedisStorage::ErrorCode::SUCCESS; aec != AsyncRedisStorage::ErrorCode::END_MARKER; ++aec)
480 case AsyncRedisStorage::ErrorCode::SUCCESS:
482 EXPECT_EQ(std::error_code().message(), getErrorCodeMessage(ec));
484 case AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED:
486 EXPECT_EQ("connection to the underlying data storage not yet available", getErrorCodeMessage(ec));
488 case AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE:
490 EXPECT_EQ("invalid namespace identifier passed to SDL API", getErrorCodeMessage(ec));
492 case AsyncRedisStorage::ErrorCode::END_MARKER:
494 EXPECT_EQ("unsupported error code for message()", getErrorCodeMessage(ec));
497 FAIL() << "No mapping for AsyncRedisStorage value: " << aec;
503 TEST_F(AsyncRedisStorageErrorCodeTest, AllErrorCodeEnumsAreMappedToCorrectSDLInternalError)
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).
510 for (AsyncRedisStorage::ErrorCode aec = AsyncRedisStorage::ErrorCode::SUCCESS; aec != AsyncRedisStorage::ErrorCode::END_MARKER; ++aec)
514 case AsyncRedisStorage::ErrorCode::SUCCESS:
516 EXPECT_TRUE(ec == InternalError::SUCCESS);
518 case AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED:
520 EXPECT_TRUE(ec == InternalError::SDL_NOT_READY);
522 case AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE:
524 EXPECT_TRUE(ec == InternalError::SDL_RECEIVED_INVALID_PARAMETER);
526 case AsyncRedisStorage::ErrorCode::END_MARKER:
528 EXPECT_TRUE(ec == InternalError::SDL_ERROR_CODE_LOGIC_ERROR);
531 FAIL() << "No mapping for AsyncRedisStorage value: " << aec;
537 TEST_F(AsyncRedisStorageErrorCodeTest, AllErrorCodeEnumsAreMappedToCorrectClientErrorCode)
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);
549 TEST_F(AsyncRedisStorageTest, IsNotCopyable)
551 EXPECT_FALSE(std::is_copy_constructible<AsyncRedisStorage>::value);
552 EXPECT_FALSE(std::is_copy_assignable<AsyncRedisStorage>::value);
554 TEST_F(AsyncRedisStorageTest, ImplementsAsyncStorage)
556 EXPECT_TRUE((std::is_base_of<AsyncStorage, AsyncRedisStorage>::value));
559 TEST_F(AsyncRedisStorageTest, CanGetFd)
561 EXPECT_CALL(*engineMock, fd())
563 .WillOnce(Return(fd));
564 EXPECT_EQ(fd, sdlStorage->fd());
567 TEST_F(AsyncRedisStorageTest, CanHandleEvents)
569 EXPECT_CALL(*engineMock, handleEvents())
571 sdlStorage->handleEvents();
574 TEST_F(AsyncRedisStorageTest, ReadyAckIsPassedToAsyncRedisCommandDispatcher)
577 EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
579 .WillOnce(SaveArg<0>(&dispatcherConnectAck));
580 sdlStorage->waitReadyAsync(ns, std::bind(&AsyncRedisStorageTest::readyAck, this, std::placeholders::_1));
581 expectReadyAck(std::error_code());
582 dispatcherConnectAck();
585 TEST_F(AsyncRedisStorageTest, PassingEmptyPublisherIdThrows)
587 EXPECT_THROW(sdlStorage.reset(new AsyncRedisStorage(
591 namespaceConfigurationsMock,
592 std::bind(&AsyncRedisStorageTest::asyncCommandDispatcherCreator,
594 std::placeholders::_1,
595 std::placeholders::_2,
596 std::placeholders::_3),
599 std::invalid_argument);
602 TEST_F(AsyncRedisStorageTest, PassingInvalidNamespaceToSetAsyncNacks)
605 expectPostCallback();
606 sdlStorage->setAsync("ns1,2",
608 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
610 std::placeholders::_1));
611 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE));
615 TEST_F(AsyncRedisStorageTest, PassingEmptyNamespaceToSetAsyncNacks)
618 expectPostCallback();
619 sdlStorage->setAsync("",
621 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
623 std::placeholders::_1));
624 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE));
628 TEST_F(AsyncRedisStorageTest, SetAsyncSuccessfullyAndErrorIsForwarded)
631 expectContentsBuild("MSETPUB", dataMap, ns, shareddatalayer::NO_PUBLISHER);
632 expectDispatchAsync();
633 sdlStorage->setAsync(ns,
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);
642 TEST_F(AsyncRedisStorageTestNotificationsDisabled, SetAsyncSuccessfullyAndErrorIsForwardedNoPublish)
645 expectContentsBuild("MSET", dataMap);
646 expectDispatchAsync();
647 sdlStorage->setAsync(ns,
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);
656 TEST_F(AsyncRedisStorageTest, EmptyMapIsCheckedInSetAsyncAndAckIsScheduled)
659 expectNoDispatchAsync();
660 expectPostCallback();
661 sdlStorage->setAsync(ns,
663 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
664 expectModifyAck(std::error_code());
668 TEST_F(AsyncRedisStorageTest, GetAsyncSuccessfullyAndErrorIsForwarded)
671 expectContentsBuild("MGET", keysWithNonExistKey);
672 expectDispatchAsync();
673 sdlStorage->getAsync(ns,
675 std::bind(&AsyncRedisStorageTest::getAck,
677 std::placeholders::_1,
678 std::placeholders::_2));
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);
691 TEST_F(AsyncRedisStorageTest, EmptyEntriesIsCheckedInGetAsyncAndAckIsScheduled)
694 expectNoDispatchAsync();
695 expectPostCallback();
696 sdlStorage->getAsync(ns,
698 std::bind(&AsyncRedisStorageTest::getAck,
700 std::placeholders::_1,
701 std::placeholders::_2));
702 expectGetAck(std::error_code(), { });
706 TEST_F(AsyncRedisStorageTest, RemoveAsyncSuccessfullyAndErrorIsForwarded)
709 expectContentsBuild("DELPUB", keys, ns, shareddatalayer::NO_PUBLISHER);
710 expectDispatchAsync();
711 sdlStorage->removeAsync(ns,
713 std::bind(&AsyncRedisStorageTest::modifyAck,
715 std::placeholders::_1));
716 expectModifyAck(std::error_code());
717 savedCommandCb(std::error_code(), replyMock);
718 expectModifyAck(getWellKnownErrorCode());
719 savedCommandCb(getWellKnownErrorCode(), replyMock);
722 TEST_F(AsyncRedisStorageTestNotificationsDisabled, RemoveAsyncSuccessfullyAndErrorIsForwardedNoPublish)
725 expectContentsBuild("DEL", keys);
726 expectDispatchAsync();
727 sdlStorage->removeAsync(ns,
729 std::bind(&AsyncRedisStorageTest::modifyAck,
731 std::placeholders::_1));
732 expectModifyAck(std::error_code());
733 savedCommandCb(std::error_code(), replyMock);
734 expectModifyAck(getWellKnownErrorCode());
735 savedCommandCb(getWellKnownErrorCode(), replyMock);
738 TEST_F(AsyncRedisStorageTest, EmptyEntriesIsCheckedInRemoveAsyncAndAckIsScheduled)
741 expectNoDispatchAsync();
742 expectPostCallback();
743 sdlStorage->removeAsync(ns,
745 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
746 expectModifyAck(std::error_code());
750 TEST_F(AsyncRedisStorageTest, FindKeysAsyncSuccessfullyAndErrorIsTranslated)
753 expectContentsBuild("KEYS", keyPrefix);
754 expectDispatchAsync();
755 sdlStorage->findKeysAsync(ns,
757 std::bind(&AsyncRedisStorageTest::findKeysAck,
759 std::placeholders::_1,
760 std::placeholders::_2));
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);
773 TEST_F(AsyncRedisStorageTest, RemoveAllAsyncSuccessfully)
776 expectContentsBuild("KEYS", keyPrefix);
777 expectDispatchAsync();
778 sdlStorage->removeAllAsync(ns,
779 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
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);
793 TEST_F(AsyncRedisStorageTestNotificationsDisabled, RemoveAllAsyncSuccessfullyNoPublish)
796 expectContentsBuild("KEYS", keyPrefix);
797 expectDispatchAsync();
798 sdlStorage->removeAllAsync(ns,
799 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
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);
811 TEST_F(AsyncRedisStorageTest, NothingIsIssuedToBeRemovedIfNoKeysAreFoundUnderNamespace)
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())
821 .WillOnce(Return(&empty));
822 EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, _))
824 expectModifyAck(std::error_code());
825 savedCommandCb(std::error_code(), replyMock);
828 TEST_F(AsyncRedisStorageTest, RemoveAllAsyncErrorIsForwarded)
831 expectContentsBuild("KEYS", keyPrefix);
832 expectDispatchAsync();
833 sdlStorage->removeAllAsync(ns,
834 std::bind(&AsyncRedisStorageTest::modifyAck,
836 std::placeholders::_1));
837 expectModifyAck(getWellKnownErrorCode());
838 savedCommandCb(getWellKnownErrorCode(), replyMock);
841 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncSuccess)
844 expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
845 expectDispatchAsync();
846 sdlStorage->setIfNotExistsAsync(ns,
849 std::bind(&AsyncRedisStorageTest::modifyIfAck,
850 this, std::placeholders::_1, std::placeholders::_2));
851 expectGetType(Reply::Type::INTEGER);
853 expectModifyIfAck(std::error_code(), true);
854 savedCommandCb(std::error_code(), replyMock);
857 TEST_F(AsyncRedisStorageTestNotificationsDisabled, SetIfNotExistsAsyncSuccessNoPublish)
860 expectContentsBuild("SETNX", key1, data1);
861 expectDispatchAsync();
862 sdlStorage->setIfNotExistsAsync(ns,
865 std::bind(&AsyncRedisStorageTest::modifyIfAck,
866 this, std::placeholders::_1, std::placeholders::_2));
867 expectGetType(Reply::Type::INTEGER);
869 expectModifyIfAck(std::error_code(), true);
870 savedCommandCb(std::error_code(), replyMock);
873 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncKeyAlreadyExists)
876 expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
877 expectDispatchAsync();
878 sdlStorage->setIfNotExistsAsync(ns,
881 std::bind(&AsyncRedisStorageTest::modifyIfAck,
882 this, std::placeholders::_1, std::placeholders::_2));
883 expectGetType(Reply::Type::INTEGER);
885 expectModifyIfAck(std::error_code(), false);
886 savedCommandCb(std::error_code(), replyMock);
889 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncErrorResponse)
892 expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
893 expectDispatchAsync();
894 sdlStorage->setIfNotExistsAsync(ns,
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);
904 TEST_F(AsyncRedisStorageTest, RedisSearchPatternCharactersAreCorrectlyEscapedInKeyPrefixSearch)
907 const std::string keyPrefixSearchPatternPrefix = '{' + ns + '}' + AsyncStorage::SEPARATOR;
908 std::string builtKeyPrefixSearchPattern;
909 std::string expectedKeyPrefixSearchPattern;
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());
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());
921 expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"("someKnownKeyPrefix")" + '*';
922 builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, R"("someKnownKeyPrefix")");
923 ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
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());
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());
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());
939 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, ReadyAckNotForwardedIfDispatcherNotYetCreated)
942 EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
944 sdlStorage->waitReadyAsync(ns, std::bind(&AsyncRedisStorageTestDispatcherNotCreated::readyAck, this, std::placeholders::_1));
947 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
950 expectPostCallback();
951 sdlStorage->setAsync(ns,
953 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
955 std::placeholders::_1));
956 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
960 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
963 expectPostCallback();
964 sdlStorage->setIfAsync(ns,
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);
974 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfNotExistsAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
977 expectPostCallback();
978 sdlStorage->setIfNotExistsAsync(ns,
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);
987 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, GetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
990 expectPostCallback();
991 sdlStorage->getAsync(ns,
993 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::getAck,
995 std::placeholders::_1,
996 std::placeholders::_2));
997 expectGetAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1001 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1004 expectPostCallback();
1005 sdlStorage->removeAsync(ns,
1007 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck, this, std::placeholders::_1));
1008 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
1012 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, FindKeysAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1015 expectPostCallback();
1016 sdlStorage->findKeysAsync(ns,
1018 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::findKeysAck,
1020 std::placeholders::_1,
1021 std::placeholders::_2));
1022 expectFindKeysAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1026 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAllAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
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));