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.
18 * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19 * platform project (RICP).
22 #include <type_traits>
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"
45 using namespace shareddatalayer;
46 using namespace shareddatalayer::redis;
47 using namespace shareddatalayer::tst;
48 using namespace testing;
52 std::string getErrorCodeMessage(std::error_code ec)
57 class AsyncRedisStorageErrorCodeTest: public testing::Test
60 AsyncRedisStorageErrorCodeTest()
64 virtual ~AsyncRedisStorageErrorCodeTest()
69 static const std::string defaultAddress = "address";
70 static const uint16_t defaultPort = 3333;
71 class AsyncRedisStorageTestBase: public testing::Test
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;
82 Contents publishContentsWithoutPubId;
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;
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;
110 AsyncRedisStorageTestBase():
111 engineMock(std::make_shared<StrictMock<EngineMock>>()),
112 discoveryMock(std::make_shared<StrictMock<AsyncDatabaseDiscoveryMock>>()),
113 dispatcherMock(std::make_shared<StrictMock<AsyncCommandDispatcherMock>>()),
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 } }),
125 keysWithNonExistKey({key1,"notfound",key2}),
128 dataMap({{key1,data1},{key2,data2}}),
129 keyPrefix("{tag1},*"),
130 logger(createLogger(SDL_LOG_PREFIX))
134 virtual ~AsyncRedisStorageTestBase() = default;
136 std::shared_ptr<AsyncCommandDispatcher> asyncCommandDispatcherCreator(Engine&,
138 std::shared_ptr<ContentsBuilder>)
140 newDispatcherCreated();
141 return dispatcherMock;
144 MOCK_METHOD0(newDispatcherCreated, void());
146 MOCK_METHOD1(readyAck, void(const std::error_code&));
148 MOCK_METHOD1(modifyAck, void(const std::error_code&));
150 MOCK_METHOD2(modifyIfAck, void(const std::error_code&, bool status));
152 MOCK_METHOD2(getAck, void(const std::error_code&, const AsyncStorage::DataMap&));
154 MOCK_METHOD2(findKeysAck, void(const std::error_code&, const AsyncStorage::Keys&));
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)
161 DatabaseInfo databaseInfo;
162 databaseInfo.type = type;
163 databaseInfo.discovery = discovery;
164 databaseInfo.hosts.push_back({address, htons(port)});
165 databaseInfo.ns = ns;
169 void expectDiscoverySetStateChangedCb()
171 EXPECT_CALL(*discoveryMock, setStateChangedCb(_))
173 .WillOnce(Invoke([this](const AsyncDatabaseDiscovery::StateChangedCb& cb)
179 void expectDispatcherWaitConnectedAsync()
181 EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
183 .WillOnce(Invoke([this](const AsyncCommandDispatcher::ConnectAck& connectAck)
185 dispatcherConnectAck = connectAck;
189 void expectDispatcherCreation()
191 expectDispatcherWaitConnectedAsync();
194 void expectNewDispatcherCreated()
196 EXPECT_CALL(*this, newDispatcherCreated)
200 void expectNewDispatcherNotCreated()
202 EXPECT_CALL(*this, newDispatcherCreated)
206 void expectReadyAck(const std::error_code& error)
208 EXPECT_CALL(*this, readyAck(error))
212 void expectModifyAck(const std::error_code& error)
214 EXPECT_CALL(*this, modifyAck(error))
218 void expectModifyIfAck(const std::error_code& error, bool status)
220 EXPECT_CALL(*this, modifyIfAck(error, status))
224 void expectGetAck(const std::error_code& error, const AsyncStorage::DataMap& dataMap)
226 EXPECT_CALL(*this, getAck(error, dataMap))
230 void expectFindKeysAck(const std::error_code& error, const AsyncStorage::Keys& keys)
232 EXPECT_CALL(*this, findKeysAck(error, keys))
236 void expectPostCallback()
238 EXPECT_CALL(*engineMock, postCallback(_))
240 .WillOnce(SaveArg<0>(&storedCallback));
243 void createAsyncStorageInstance(const boost::optional<PublisherId>& pId)
245 expectDiscoverySetStateChangedCb();
247 expectClearStateChangedCb();
248 sdlStorage.reset(new AsyncRedisStorage(engineMock,
251 namespaceConfigurationsMock,
252 std::bind(&AsyncRedisStorageTestBase::asyncCommandDispatcherCreator,
254 std::placeholders::_1,
255 std::placeholders::_2,
256 std::placeholders::_3),
261 void createAndConnectAsyncStorageInstance(const boost::optional<PublisherId>& pId)
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()))
271 dispatcherConnectAck();
274 void expectClearStateChangedCb()
276 EXPECT_CALL(*discoveryMock, clearStateChangedCb())
280 void expectNoDispatchAsync()
282 EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, _))
286 void expectDispatchAsync()
288 EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, contents))
290 .WillOnce(SaveArg<0>(&savedCommandCb));
293 void expectPublishDispatch()
295 EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, contents))
297 .WillOnce(SaveArg<0>(&savedPublishCommandCb));
300 std::shared_ptr<Reply> getMockPtr()
302 return std::shared_ptr<Reply>(&replyMock, [](Reply*){ });
305 void expectGetType(const Reply::Type& type)
307 EXPECT_CALL(replyMock, getType())
309 .WillOnce(Return(type));
312 void expectGetDataString(const Reply::DataItem& item)
314 expectGetType(Reply::Type::STRING);
315 EXPECT_CALL(replyMock, getString())
317 .WillOnce(Return(&item));
320 void expectGetArray()
322 EXPECT_CALL(replyMock, getArray())
324 .WillOnce(Return(&replyVector));
327 void expectGetInteger(int value)
329 EXPECT_CALL(replyMock, getInteger())
331 .WillOnce(Return(value));
334 void expectContentsBuild(const std::string& string,
335 const AsyncStorage::Key& key,
336 const AsyncStorage::Data& data)
338 EXPECT_CALL(*contentsBuilderMock, build(string, ns, key, data))
340 .WillOnce(Return(contents));
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)
350 EXPECT_CALL(*contentsBuilderMock, build(string, ns, key, data, string2, string3))
352 .WillOnce(Return(contents));
355 void expectContentsBuild(const std::string& string,
356 const std::string& string2,
357 const std::string& string3)
359 EXPECT_CALL(*contentsBuilderMock, build(string, string2, string3))
361 .WillOnce(Return(contents));
364 void expectContentsBuild(const std::string& string,
365 const AsyncStorage::DataMap& dataMap)
367 EXPECT_CALL(*contentsBuilderMock, build(string, ns, dataMap))
369 .WillOnce(Return(contents));
372 void expectContentsBuild(const std::string& string,
373 const AsyncStorage::DataMap& dataMap,
374 const std::string& string2,
375 const std::string& string3)
377 EXPECT_CALL(*contentsBuilderMock, build(string, ns, dataMap, string2, string3))
379 .WillOnce(Return(contents));
382 void expectContentsBuild(const std::string& string,
383 const AsyncStorage::Keys& keys)
385 EXPECT_CALL(*contentsBuilderMock, build(string, ns, keys))
387 .WillOnce(Return(contents));
390 void expectContentsBuild(const std::string& string,
391 const AsyncStorage::Keys& keys,
392 const std::string& string2,
393 const std::string& string3)
395 EXPECT_CALL(*contentsBuilderMock, build(string, ns, keys, string2, string3))
397 .WillOnce(Return(contents));
400 void expectContentsBuild(const std::string& string,
401 const std::string& string2)
403 EXPECT_CALL(*contentsBuilderMock, build(string, string2))
405 .WillOnce(Return(contents));
409 class AsyncRedisStorageTest: public AsyncRedisStorageTestBase
412 AsyncRedisStorageTest()
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));
421 ~AsyncRedisStorageTest()
423 expectClearStateChangedCb();
424 EXPECT_CALL(*dispatcherMock, disableCommandCallbacks())
430 class AsyncRedisStorageTestNotificationsDisabled: public AsyncRedisStorageTestBase
433 AsyncRedisStorageTestNotificationsDisabled()
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));
442 ~AsyncRedisStorageTestNotificationsDisabled()
444 expectClearStateChangedCb();
445 EXPECT_CALL(*dispatcherMock, disableCommandCallbacks())
451 class AsyncRedisStorageTestDispatcherNotCreated: public AsyncRedisStorageTestBase
454 AsyncRedisStorageTestDispatcherNotCreated()
457 for (auto i(0U); i < 3; ++i)
458 replyVector.push_back(getMockPtr());
459 createAsyncStorageInstance(boost::none);
462 ~AsyncRedisStorageTestDispatcherNotCreated()
464 expectClearStateChangedCb();
468 class AsyncRedisStorageDeathTest: public AsyncRedisStorageTestBase
471 AsyncRedisStorageDeathTest()
477 TEST_F(AsyncRedisStorageErrorCodeTest, AllErrorCodeEnumsHaveCorrectDescriptionMessage)
481 for (AsyncRedisStorage::ErrorCode aec = AsyncRedisStorage::ErrorCode::SUCCESS; aec != AsyncRedisStorage::ErrorCode::END_MARKER; ++aec)
485 case AsyncRedisStorage::ErrorCode::SUCCESS:
487 EXPECT_EQ(std::error_code().message(), getErrorCodeMessage(ec));
489 case AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED:
491 EXPECT_EQ("connection to the underlying data storage not yet available", getErrorCodeMessage(ec));
493 case AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE:
495 EXPECT_EQ("invalid namespace identifier passed to SDL API", getErrorCodeMessage(ec));
497 case AsyncRedisStorage::ErrorCode::END_MARKER:
499 EXPECT_EQ("unsupported error code for message()", getErrorCodeMessage(ec));
502 FAIL() << "No mapping for AsyncRedisStorage value: " << aec;
508 TEST_F(AsyncRedisStorageErrorCodeTest, AllErrorCodeEnumsAreMappedToCorrectSDLInternalError)
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).
515 for (AsyncRedisStorage::ErrorCode aec = AsyncRedisStorage::ErrorCode::SUCCESS; aec != AsyncRedisStorage::ErrorCode::END_MARKER; ++aec)
519 case AsyncRedisStorage::ErrorCode::SUCCESS:
521 EXPECT_TRUE(ec == InternalError::SUCCESS);
523 case AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED:
525 EXPECT_TRUE(ec == InternalError::SDL_NOT_READY);
527 case AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE:
529 EXPECT_TRUE(ec == InternalError::SDL_RECEIVED_INVALID_PARAMETER);
531 case AsyncRedisStorage::ErrorCode::END_MARKER:
533 EXPECT_TRUE(ec == InternalError::SDL_ERROR_CODE_LOGIC_ERROR);
536 FAIL() << "No mapping for AsyncRedisStorage value: " << aec;
542 TEST_F(AsyncRedisStorageErrorCodeTest, AllErrorCodeEnumsAreMappedToCorrectClientErrorCode)
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);
554 TEST_F(AsyncRedisStorageTest, IsNotCopyable)
556 EXPECT_FALSE(std::is_copy_constructible<AsyncRedisStorage>::value);
557 EXPECT_FALSE(std::is_copy_assignable<AsyncRedisStorage>::value);
559 TEST_F(AsyncRedisStorageTest, ImplementsAsyncStorage)
561 EXPECT_TRUE((std::is_base_of<AsyncStorage, AsyncRedisStorage>::value));
564 TEST_F(AsyncRedisStorageTest, CanGetFd)
566 EXPECT_CALL(*engineMock, fd())
568 .WillOnce(Return(fd));
569 EXPECT_EQ(fd, sdlStorage->fd());
572 TEST_F(AsyncRedisStorageTest, CanHandleEvents)
574 EXPECT_CALL(*engineMock, handleEvents())
576 sdlStorage->handleEvents();
579 TEST_F(AsyncRedisStorageTest, ReadyAckIsPassedToAsyncRedisCommandDispatcher)
582 EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
584 .WillOnce(SaveArg<0>(&dispatcherConnectAck));
585 sdlStorage->waitReadyAsync(ns, std::bind(&AsyncRedisStorageTest::readyAck, this, std::placeholders::_1));
586 expectReadyAck(std::error_code());
587 dispatcherConnectAck();
590 TEST_F(AsyncRedisStorageTest, PassingEmptyPublisherIdThrows)
592 EXPECT_THROW(sdlStorage.reset(new AsyncRedisStorage(
596 namespaceConfigurationsMock,
597 std::bind(&AsyncRedisStorageTest::asyncCommandDispatcherCreator,
599 std::placeholders::_1,
600 std::placeholders::_2,
601 std::placeholders::_3),
604 std::invalid_argument);
607 TEST_F(AsyncRedisStorageTest, PassingInvalidNamespaceToSetAsyncNacks)
610 expectPostCallback();
611 sdlStorage->setAsync("ns1,2",
613 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
615 std::placeholders::_1));
616 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE));
620 TEST_F(AsyncRedisStorageTest, PassingEmptyNamespaceToSetAsyncNacks)
623 expectPostCallback();
624 sdlStorage->setAsync("",
626 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
628 std::placeholders::_1));
629 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE));
633 TEST_F(AsyncRedisStorageTest, SetAsyncSuccessfullyAndErrorIsForwarded)
636 expectContentsBuild("MSETPUB", dataMap, ns, shareddatalayer::NO_PUBLISHER);
637 expectDispatchAsync();
638 sdlStorage->setAsync(ns,
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);
647 TEST_F(AsyncRedisStorageTestNotificationsDisabled, SetAsyncSuccessfullyAndErrorIsForwardedNoPublish)
650 expectContentsBuild("MSET", dataMap);
651 expectDispatchAsync();
652 sdlStorage->setAsync(ns,
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);
661 TEST_F(AsyncRedisStorageTest, EmptyMapIsCheckedInSetAsyncAndAckIsScheduled)
664 expectNoDispatchAsync();
665 expectPostCallback();
666 sdlStorage->setAsync(ns,
668 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
669 expectModifyAck(std::error_code());
673 TEST_F(AsyncRedisStorageTest, GetAsyncSuccessfullyAndErrorIsForwarded)
676 expectContentsBuild("MGET", keysWithNonExistKey);
677 expectDispatchAsync();
678 sdlStorage->getAsync(ns,
680 std::bind(&AsyncRedisStorageTest::getAck,
682 std::placeholders::_1,
683 std::placeholders::_2));
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);
696 TEST_F(AsyncRedisStorageTest, EmptyEntriesIsCheckedInGetAsyncAndAckIsScheduled)
699 expectNoDispatchAsync();
700 expectPostCallback();
701 sdlStorage->getAsync(ns,
703 std::bind(&AsyncRedisStorageTest::getAck,
705 std::placeholders::_1,
706 std::placeholders::_2));
707 expectGetAck(std::error_code(), { });
711 TEST_F(AsyncRedisStorageTest, RemoveAsyncSuccessfullyAndErrorIsForwarded)
714 expectContentsBuild("DELPUB", keys, ns, shareddatalayer::NO_PUBLISHER);
715 expectDispatchAsync();
716 sdlStorage->removeAsync(ns,
718 std::bind(&AsyncRedisStorageTest::modifyAck,
720 std::placeholders::_1));
721 expectModifyAck(std::error_code());
722 savedCommandCb(std::error_code(), replyMock);
723 expectModifyAck(getWellKnownErrorCode());
724 savedCommandCb(getWellKnownErrorCode(), replyMock);
727 TEST_F(AsyncRedisStorageTestNotificationsDisabled, RemoveAsyncSuccessfullyAndErrorIsForwardedNoPublish)
730 expectContentsBuild("DEL", keys);
731 expectDispatchAsync();
732 sdlStorage->removeAsync(ns,
734 std::bind(&AsyncRedisStorageTest::modifyAck,
736 std::placeholders::_1));
737 expectModifyAck(std::error_code());
738 savedCommandCb(std::error_code(), replyMock);
739 expectModifyAck(getWellKnownErrorCode());
740 savedCommandCb(getWellKnownErrorCode(), replyMock);
743 TEST_F(AsyncRedisStorageTest, EmptyEntriesIsCheckedInRemoveAsyncAndAckIsScheduled)
746 expectNoDispatchAsync();
747 expectPostCallback();
748 sdlStorage->removeAsync(ns,
750 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
751 expectModifyAck(std::error_code());
755 TEST_F(AsyncRedisStorageTest, FindKeysAsyncSuccessfullyAndErrorIsTranslated)
758 expectContentsBuild("KEYS", keyPrefix);
759 expectDispatchAsync();
760 sdlStorage->findKeysAsync(ns,
762 std::bind(&AsyncRedisStorageTest::findKeysAck,
764 std::placeholders::_1,
765 std::placeholders::_2));
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);
778 TEST_F(AsyncRedisStorageTest, ListKeysPatternSuccessfullyAndErrorIsTranslated)
781 expectContentsBuild("KEYS", "{tag1},key[12]");
782 expectDispatchAsync();
783 sdlStorage->listKeys(ns,
785 std::bind(&AsyncRedisStorageTest::findKeysAck,
787 std::placeholders::_1,
788 std::placeholders::_2));
790 auto expectedDataItem1(Reply::DataItem { key1, ReplyStringLength(key1.size()) });
791 auto expectedDataItem2(Reply::DataItem { key2, ReplyStringLength(key2.size()) });
792 expectGetDataString(expectedDataItem1);
793 expectGetType(Reply::Type::NIL);
794 expectGetDataString(expectedDataItem2);
795 expectFindKeysAck(std::error_code(), { key1, key2 });
796 savedCommandCb(std::error_code(), replyMock);
797 expectFindKeysAck(getWellKnownErrorCode(), { });
798 savedCommandCb(getWellKnownErrorCode(), replyMock);
801 TEST_F(AsyncRedisStorageTest, RemoveAllAsyncSuccessfully)
804 expectContentsBuild("KEYS", keyPrefix);
805 expectDispatchAsync();
806 sdlStorage->removeAllAsync(ns,
807 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
809 auto expectedDataItem1(Reply::DataItem { key1, ReplyStringLength(key1.size()) });
810 auto expectedDataItem2(Reply::DataItem { key2, ReplyStringLength(key2.size()) });
811 expectGetDataString(expectedDataItem1);
812 expectGetType(Reply::Type::NIL);
813 expectGetDataString(expectedDataItem2);
814 expectContentsBuild("DELPUB", keys, ns, shareddatalayer::NO_PUBLISHER);
815 expectDispatchAsync();
816 savedCommandCb(std::error_code(), replyMock);
817 expectModifyAck(std::error_code());
818 savedCommandCb(std::error_code(), replyMock);
821 TEST_F(AsyncRedisStorageTestNotificationsDisabled, RemoveAllAsyncSuccessfullyNoPublish)
824 expectContentsBuild("KEYS", keyPrefix);
825 expectDispatchAsync();
826 sdlStorage->removeAllAsync(ns,
827 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
829 auto expectedDataItem1(Reply::DataItem { key1, ReplyStringLength(key1.size()) });
830 auto expectedDataItem2(Reply::DataItem { key2, ReplyStringLength(key2.size()) });
831 expectGetDataString(expectedDataItem1);
832 expectGetType(Reply::Type::NIL);
833 expectGetDataString(expectedDataItem2);
834 expectContentsBuild("DEL", keys);
835 expectDispatchAsync();
836 savedCommandCb(std::error_code(), replyMock);
839 TEST_F(AsyncRedisStorageTest, NothingIsIssuedToBeRemovedIfNoKeysAreFoundUnderNamespace)
842 Reply::ReplyVector empty;
843 expectContentsBuild("KEYS", keyPrefix);
844 expectDispatchAsync();
845 sdlStorage->removeAllAsync(ns,
846 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
847 EXPECT_CALL(replyMock, getArray())
849 .WillOnce(Return(&empty));
850 EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, _))
852 expectModifyAck(std::error_code());
853 savedCommandCb(std::error_code(), replyMock);
856 TEST_F(AsyncRedisStorageTest, RemoveAllAsyncErrorIsForwarded)
859 expectContentsBuild("KEYS", keyPrefix);
860 expectDispatchAsync();
861 sdlStorage->removeAllAsync(ns,
862 std::bind(&AsyncRedisStorageTest::modifyAck,
864 std::placeholders::_1));
865 expectModifyAck(getWellKnownErrorCode());
866 savedCommandCb(getWellKnownErrorCode(), replyMock);
869 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncSuccess)
872 expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
873 expectDispatchAsync();
874 sdlStorage->setIfNotExistsAsync(ns,
877 std::bind(&AsyncRedisStorageTest::modifyIfAck,
878 this, std::placeholders::_1, std::placeholders::_2));
879 expectGetType(Reply::Type::INTEGER);
881 expectModifyIfAck(std::error_code(), true);
882 savedCommandCb(std::error_code(), replyMock);
885 TEST_F(AsyncRedisStorageTestNotificationsDisabled, SetIfNotExistsAsyncSuccessNoPublish)
888 expectContentsBuild("SETNX", key1, data1);
889 expectDispatchAsync();
890 sdlStorage->setIfNotExistsAsync(ns,
893 std::bind(&AsyncRedisStorageTest::modifyIfAck,
894 this, std::placeholders::_1, std::placeholders::_2));
895 expectGetType(Reply::Type::INTEGER);
897 expectModifyIfAck(std::error_code(), true);
898 savedCommandCb(std::error_code(), replyMock);
901 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncKeyAlreadyExists)
904 expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
905 expectDispatchAsync();
906 sdlStorage->setIfNotExistsAsync(ns,
909 std::bind(&AsyncRedisStorageTest::modifyIfAck,
910 this, std::placeholders::_1, std::placeholders::_2));
911 expectGetType(Reply::Type::INTEGER);
913 expectModifyIfAck(std::error_code(), false);
914 savedCommandCb(std::error_code(), replyMock);
917 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncErrorResponse)
920 expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
921 expectDispatchAsync();
922 sdlStorage->setIfNotExistsAsync(ns,
925 std::bind(&AsyncRedisStorageTest::modifyIfAck,
926 this, std::placeholders::_1, std::placeholders::_2));
927 expectGetType(Reply::Type::INTEGER);
928 expectModifyIfAck(getWellKnownErrorCode(), false);
929 savedCommandCb(getWellKnownErrorCode(), replyMock);
932 TEST_F(AsyncRedisStorageTest, RedisSearchPatternCharactersAreCorrectlyEscapedInKeyPrefixSearch)
935 const std::string keyPrefixSearchPatternPrefix = '{' + ns + '}' + AsyncStorage::SEPARATOR;
936 std::string builtKeyPrefixSearchPattern;
937 std::string expectedKeyPrefixSearchPattern;
939 // empty prefix will not be escaped and it will search all keys
940 expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + '*';
941 builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "");
942 ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
944 // prefix without search characters is not escaped
945 expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + "someKnownKeyPrefix" + '*';
946 builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "someKnownKeyPrefix");
947 ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
949 expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"("someKnownKeyPrefix")" + '*';
950 builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, R"("someKnownKeyPrefix")");
951 ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
953 // all search characters are correctly escaped with backslash
954 expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"(someKnownKeyPrefix\*)" + '*';
955 builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "someKnownKeyPrefix*");
956 ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
958 expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"(\?some\]Known\[Key\\Prefix\*)" + '*';
959 builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "?some]Known[Key\\Prefix*");
960 ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
962 expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"(\?\*some\[\]Known\[\*\?\\\]Key\\\*Prefix\*\*\*\*)" + '*';
963 builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, "?*some[]Known[*?\\]Key\\*Prefix****");
964 ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
967 TEST_F(AsyncRedisStorageTest, BuildNamespaceKeySearchPatternIsCorrect)
970 const std::string nsPrefix = '{' + ns + '}' + AsyncStorage::SEPARATOR;
971 std::string buildPattern;
972 std::string expectedPattern;
974 expectedPattern = nsPrefix;
975 buildPattern = sdlStorage->buildNamespaceKeySearchPattern(ns, "");
976 ASSERT_STREQ(expectedPattern.c_str(), buildPattern.c_str());
978 expectedPattern = nsPrefix + '*';
979 buildPattern = sdlStorage->buildNamespaceKeySearchPattern(ns, "*");
980 ASSERT_STREQ(expectedPattern.c_str(), buildPattern.c_str());
982 expectedPattern = nsPrefix + "h?llo";
983 buildPattern = sdlStorage->buildNamespaceKeySearchPattern(ns, "h?llo");
984 ASSERT_STREQ(expectedPattern.c_str(), buildPattern.c_str());
987 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, ReadyAckNotForwardedIfDispatcherNotYetCreated)
990 EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
992 sdlStorage->waitReadyAsync(ns, std::bind(&AsyncRedisStorageTestDispatcherNotCreated::readyAck, this, std::placeholders::_1));
995 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
998 expectPostCallback();
999 sdlStorage->setAsync(ns,
1001 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
1003 std::placeholders::_1));
1004 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
1008 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1011 expectPostCallback();
1012 sdlStorage->setIfAsync(ns,
1016 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyIfAck,
1017 this, std::placeholders::_1, std::placeholders::_2));
1018 expectModifyIfAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), false);
1022 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfNotExistsAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1025 expectPostCallback();
1026 sdlStorage->setIfNotExistsAsync(ns,
1029 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyIfAck,
1030 this, std::placeholders::_1, std::placeholders::_2));
1031 expectModifyIfAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), false);
1035 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, GetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1038 expectPostCallback();
1039 sdlStorage->getAsync(ns,
1041 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::getAck,
1043 std::placeholders::_1,
1044 std::placeholders::_2));
1045 expectGetAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1049 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1052 expectPostCallback();
1053 sdlStorage->removeAsync(ns,
1055 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck, this, std::placeholders::_1));
1056 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
1060 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, FindKeysAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1063 expectPostCallback();
1064 sdlStorage->findKeysAsync(ns,
1066 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::findKeysAck,
1068 std::placeholders::_1,
1069 std::placeholders::_2));
1070 expectFindKeysAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1074 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAllAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1077 expectPostCallback();
1078 sdlStorage->removeAllAsync(ns,
1079 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck, this, std::placeholders::_1));
1080 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));