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, RemoveAllAsyncSuccessfully)
781 expectContentsBuild("KEYS", keyPrefix);
782 expectDispatchAsync();
783 sdlStorage->removeAllAsync(ns,
784 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
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);
798 TEST_F(AsyncRedisStorageTestNotificationsDisabled, RemoveAllAsyncSuccessfullyNoPublish)
801 expectContentsBuild("KEYS", keyPrefix);
802 expectDispatchAsync();
803 sdlStorage->removeAllAsync(ns,
804 std::bind(&AsyncRedisStorageTest::modifyAck, this, std::placeholders::_1));
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);
816 TEST_F(AsyncRedisStorageTest, NothingIsIssuedToBeRemovedIfNoKeysAreFoundUnderNamespace)
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())
826 .WillOnce(Return(&empty));
827 EXPECT_CALL(*dispatcherMock, dispatchAsync(_, ns, _))
829 expectModifyAck(std::error_code());
830 savedCommandCb(std::error_code(), replyMock);
833 TEST_F(AsyncRedisStorageTest, RemoveAllAsyncErrorIsForwarded)
836 expectContentsBuild("KEYS", keyPrefix);
837 expectDispatchAsync();
838 sdlStorage->removeAllAsync(ns,
839 std::bind(&AsyncRedisStorageTest::modifyAck,
841 std::placeholders::_1));
842 expectModifyAck(getWellKnownErrorCode());
843 savedCommandCb(getWellKnownErrorCode(), replyMock);
846 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncSuccess)
849 expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
850 expectDispatchAsync();
851 sdlStorage->setIfNotExistsAsync(ns,
854 std::bind(&AsyncRedisStorageTest::modifyIfAck,
855 this, std::placeholders::_1, std::placeholders::_2));
856 expectGetType(Reply::Type::INTEGER);
858 expectModifyIfAck(std::error_code(), true);
859 savedCommandCb(std::error_code(), replyMock);
862 TEST_F(AsyncRedisStorageTestNotificationsDisabled, SetIfNotExistsAsyncSuccessNoPublish)
865 expectContentsBuild("SETNX", key1, data1);
866 expectDispatchAsync();
867 sdlStorage->setIfNotExistsAsync(ns,
870 std::bind(&AsyncRedisStorageTest::modifyIfAck,
871 this, std::placeholders::_1, std::placeholders::_2));
872 expectGetType(Reply::Type::INTEGER);
874 expectModifyIfAck(std::error_code(), true);
875 savedCommandCb(std::error_code(), replyMock);
878 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncKeyAlreadyExists)
881 expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
882 expectDispatchAsync();
883 sdlStorage->setIfNotExistsAsync(ns,
886 std::bind(&AsyncRedisStorageTest::modifyIfAck,
887 this, std::placeholders::_1, std::placeholders::_2));
888 expectGetType(Reply::Type::INTEGER);
890 expectModifyIfAck(std::error_code(), false);
891 savedCommandCb(std::error_code(), replyMock);
894 TEST_F(AsyncRedisStorageTest, SetIfNotExistsAsyncErrorResponse)
897 expectContentsBuild("SETNXPUB", key1, data1, ns, shareddatalayer::NO_PUBLISHER);
898 expectDispatchAsync();
899 sdlStorage->setIfNotExistsAsync(ns,
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);
909 TEST_F(AsyncRedisStorageTest, RedisSearchPatternCharactersAreCorrectlyEscapedInKeyPrefixSearch)
912 const std::string keyPrefixSearchPatternPrefix = '{' + ns + '}' + AsyncStorage::SEPARATOR;
913 std::string builtKeyPrefixSearchPattern;
914 std::string expectedKeyPrefixSearchPattern;
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());
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());
926 expectedKeyPrefixSearchPattern = keyPrefixSearchPatternPrefix + R"("someKnownKeyPrefix")" + '*';
927 builtKeyPrefixSearchPattern = sdlStorage->buildKeyPrefixSearchPattern(ns, R"("someKnownKeyPrefix")");
928 ASSERT_STREQ(expectedKeyPrefixSearchPattern.c_str(), builtKeyPrefixSearchPattern.c_str());
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());
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());
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());
944 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, ReadyAckNotForwardedIfDispatcherNotYetCreated)
947 EXPECT_CALL(*dispatcherMock, waitConnectedAsync(_))
949 sdlStorage->waitReadyAsync(ns, std::bind(&AsyncRedisStorageTestDispatcherNotCreated::readyAck, this, std::placeholders::_1));
952 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
955 expectPostCallback();
956 sdlStorage->setAsync(ns,
958 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck,
960 std::placeholders::_1));
961 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
965 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
968 expectPostCallback();
969 sdlStorage->setIfAsync(ns,
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);
979 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, SetIfNotExistsAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
982 expectPostCallback();
983 sdlStorage->setIfNotExistsAsync(ns,
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);
992 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, GetAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
995 expectPostCallback();
996 sdlStorage->getAsync(ns,
998 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::getAck,
1000 std::placeholders::_1,
1001 std::placeholders::_2));
1002 expectGetAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1006 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1009 expectPostCallback();
1010 sdlStorage->removeAsync(ns,
1012 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::modifyAck, this, std::placeholders::_1));
1013 expectModifyAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED));
1017 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, FindKeysAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
1020 expectPostCallback();
1021 sdlStorage->findKeysAsync(ns,
1023 std::bind(&AsyncRedisStorageTestDispatcherNotCreated::findKeysAck,
1025 std::placeholders::_1,
1026 std::placeholders::_2));
1027 expectFindKeysAck(std::error_code(AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED), { });
1031 TEST_F(AsyncRedisStorageTestDispatcherNotCreated, RemoveAllAsyncWithoutDispatcherInstanceNacksWithREDIS_NOT_YET_DISCOVERED)
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));