Added reading Sentinel configuration from environment variables.
Sentinel address is configured via 'DBAAS_SERVICE_HOST' and
'DBAAS_SERVICE_SENTINEL_PORT' environment variables.
Sentinel master name is configured via 'DBAAS_MASTER_NAME' environment
variable.
Sentinel support is now activated.
Using Sentinel is optional. If Sentinel related environment variables
are not set, then static address for Redis server is used as before
(i.e. this change is backward compatible).
Signed-off-by: Rolf Badorek <rolf.badorek@nokia.com>
Change-Id: I34031ac56268673996c6fecb00eeed6e5dda8b9a
include/private/redis/asyncdatabasediscovery.hpp \
include/private/redis/asyncredisreply.hpp \
include/private/redis/asyncredisstorage.hpp \
+ include/private/redis/asyncsentineldatabasediscovery.hpp \
include/private/redis/contents.hpp \
include/private/redis/contentsbuilder.hpp \
include/private/redis/databaseinfo.hpp \
src/redis/asyncdatabasediscovery.cpp \
src/redis/asyncredisreply.cpp \
src/redis/asyncredisstorage.cpp \
+ src/redis/asyncsentineldatabasediscovery.cpp \
src/redis/contentsbuilder.cpp
endif
if HIREDIS
src/redis/hiredisclusterepolladapter.cpp \
src/redis/hiredisclustersystem.cpp
endif
-if SENTINEL
-libsdl_la_SOURCES += \
- include/private/redis/asyncsentineldatabasediscovery.hpp \
- src/redis/asyncsentineldatabasediscovery.cpp
-endif
libsdl_la_CPPFLAGS = \
$(BASE_CPPFLAGS) \
$(HIREDIS_CFLAGS) \
tst/asynccommanddispatcher_test.cpp \
tst/asyncdatabasediscovery_test.cpp \
tst/asyncredisstorage_test.cpp \
+ tst/asyncsentineldatabasediscovery_test.cpp \
tst/asyncstorageimpl_test.cpp \
tst/contents_test.cpp \
tst/contentsbuilder_test.cpp \
tst/hiredisclusterepolladapter_test.cpp \
tst/hiredisclustersystem_test.cpp
endif
-if SENTINEL
-testrunner_SOURCES += \
- tst/asyncsentineldatabasediscovery_test.cpp
-endif
testrunner_CPPFLAGS = \
$(BASE_CPPFLAGS) \
-I$(top_srcdir)/3rdparty/googletest/googlemock/include \
m4_define([SDL_MAJOR], [1])
m4_define([SDL_MINOR], [0])
-m4_define([SDL_MICRO], [0])
+m4_define([SDL_MICRO], [1])
# SDL ABI version with libtool
#
# Change the numbers just before release.
m4_define([SDL_CURRENT], [1])
-m4_define([SDL_REVISION], [0])
+m4_define([SDL_REVISION], [1])
m4_define([SDL_AGE], [0])
AC_INIT([shareddatalayer], [SDL_MAJOR.SDL_MINOR.SDL_MICRO], [], [], [https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/sdl])
AC_DEFINE(HAVE_REDIS, [1], [Have redis])
AM_CONDITIONAL([REDIS], [test xtrue])
-# @TODO Change to true when Redis HA support is activated.
-AC_DEFINE(HAVE_SENTINEL, [0], [Have sentinel])
-AM_CONDITIONAL([SENTINEL], [test "xyes" = "xno"])
-
PKG_CHECK_MODULES([HIREDIS], [hiredis])
AC_DEFINE(HAVE_HIREDIS, [1], [Have hiredis])
AM_CONDITIONAL([HIREDIS], [test xtrue])
#define DB_HOST_ENV_VAR_NAME "DBAAS_SERVICE_HOST"
#define DB_PORT_ENV_VAR_NAME "DBAAS_SERVICE_PORT"
+#define SENTINEL_PORT_ENV_VAR_NAME "DBAAS_SERVICE_SENTINEL_PORT"
+#define SENTINEL_MASTER_NAME_ENV_VAR_NAME "DBAAS_MASTER_NAME"
#include <iosfwd>
#include <string>
std::string dbHostEnvVariableValue;
const std::string dbPortEnvVariableName;
std::string dbPortEnvVariableValue;
+ const std::string sentinelPortEnvVariableName;
+ std::string sentinelPortEnvVariableValue;
+ const std::string sentinelMasterNameEnvVariableName;
+ std::string sentinelMasterNameEnvVariableValue;
boost::optional<boost::property_tree::ptree> jsonDatabaseConfiguration;
std::string sourceForDatabaseConfiguration;
std::unordered_map<std::string, std::pair<boost::property_tree::ptree, std::string>> jsonNamespaceConfigurations;
#include <string>
#include <vector>
+#include <boost/optional.hpp>
#include "private/hostandport.hpp"
namespace shareddatalayer
{
UNKNOWN = 0,
REDIS_STANDALONE,
- REDIS_CLUSTER
+ REDIS_CLUSTER,
+ REDIS_SENTINEL
};
virtual ~DatabaseConfiguration() = default;
virtual void checkAndApplyDbType(const std::string& type) = 0;
virtual void checkAndApplyServerAddress(const std::string& address) = 0;
+ virtual void checkAndApplySentinelAddress(const std::string& address) = 0;
+ virtual void checkAndApplySentinelMasterName(const std::string& name) = 0;
virtual DatabaseConfiguration::DbType getDbType() const = 0;
virtual DatabaseConfiguration::Addresses getServerAddresses() const = 0;
virtual DatabaseConfiguration::Addresses getDefaultServerAddresses() const = 0;
+ virtual boost::optional<HostAndPort> getSentinelAddress() const = 0; // Optional return value, because empty HostAndPort can't be created.
+ virtual std::string getSentinelMasterName() const = 0;
virtual bool isEmpty() const = 0;
DatabaseConfiguration(DatabaseConfiguration&&) = delete;
void checkAndApplyServerAddress(const std::string& address) override;
+ void checkAndApplySentinelAddress(const std::string& address) override;
+
+ void checkAndApplySentinelMasterName(const std::string& name) override;
+
DatabaseConfiguration::DbType getDbType() const override;
DatabaseConfigurationImpl::Addresses getServerAddresses() const override;
DatabaseConfiguration::Addresses getDefaultServerAddresses() const override;
+ boost::optional<HostAndPort> getSentinelAddress() const override;
+
+ std::string getSentinelMasterName() const override;
+
bool isEmpty() const override;
private:
DbType dbType;
Addresses serverAddresses;
+ boost::optional<HostAndPort> sentinelAddress;
+ std::string sentinelMasterName;
};
}
#include <string>
#include <stdint.h>
#include <sdl/exception.hpp>
+#include <iosfwd>
namespace shareddatalayer
{
public:
EmptyHost();
};
+
+ std::ostream& operator << (std::ostream& os, const HostAndPort& hostAndPort);
}
#endif
AsyncSentinelDatabaseDiscovery& operator = (const AsyncSentinelDatabaseDiscovery&) = delete;
AsyncSentinelDatabaseDiscovery(std::shared_ptr<Engine> engine,
- std::shared_ptr<Logger> logger);
+ std::shared_ptr<Logger> logger,
+ const HostAndPort& sentinelAddress,
+ const std::string& sentinelMasterName);
AsyncSentinelDatabaseDiscovery(std::shared_ptr<Engine> engine,
std::shared_ptr<Logger> logger,
+ const HostAndPort& sentinelAddress,
+ const std::string& sentinelMasterName,
const AsyncCommandDispatcherCreator& asyncCommandDispatcherCreator,
std::shared_ptr<redis::ContentsBuilder> contentsBuilder);
std::shared_ptr<Logger> logger;
StateChangedCb stateChangedCb;
DatabaseInfo databaseInfo;
+ std::string sentinelMasterName;
std::shared_ptr<redis::AsyncCommandDispatcher> subscriber;
std::shared_ptr<redis::AsyncCommandDispatcher> dispatcher;
std::shared_ptr<redis::ContentsBuilder> contentsBuilder;
public:
MOCK_METHOD1(checkAndApplyDbType, void(const std::string& type));
MOCK_METHOD1(checkAndApplyServerAddress, void(const std::string& address));
+ MOCK_METHOD1(checkAndApplySentinelAddress, void(const std::string& address));
+ MOCK_METHOD1(checkAndApplySentinelMasterName, void(const std::string& name));
MOCK_CONST_METHOD0(getDbType, DatabaseConfiguration::DbType());
MOCK_CONST_METHOD0(getServerAddresses, DatabaseConfiguration::Addresses());
MOCK_CONST_METHOD0(getDefaultServerAddresses, DatabaseConfiguration::Addresses());
MOCK_CONST_METHOD0(isEmpty, bool());
+ MOCK_CONST_METHOD0(getSentinelAddress, boost::optional<HostAndPort>());
+ MOCK_CONST_METHOD0(getSentinelMasterName, std::string());
};
}
}
return ports;
}
+ void PrintEnvironmentVariable(std::ostream& out, std::string name)
+ {
+ const auto var(name.c_str());
+ const auto conf(getenv(var));
+ if (conf != nullptr)
+ out << var << ": " << conf << std::endl;
+ }
+
void PrintStaticConfiguration(std::ostream& out)
{
auto engine(std::make_shared<EngineImpl>());
out << "Static DB type: redis-cluster" << std::endl;
else if (staticDbType == DatabaseConfiguration::DbType::REDIS_STANDALONE)
out << "Static DB type: redis-standalone" << std::endl;
+ else if (staticDbType == DatabaseConfiguration::DbType::REDIS_SENTINEL)
+ out << "Static DB type: redis-sentinel" << std::endl;
else
out << "Static DB type not defined" << std::endl;
}
out << "Default Host: " << getHosts(defaultAddresses) << std::endl;
out << "Default Port: " << getPorts(defaultAddresses) << std::endl;
}
- const auto var(DB_HOST_ENV_VAR_NAME);
- const auto conf(getenv(var));
- if (conf != nullptr)
- out << var << ": " << conf << std::endl;
+ PrintEnvironmentVariable(out, DB_HOST_ENV_VAR_NAME);
+ PrintEnvironmentVariable(out, DB_PORT_ENV_VAR_NAME);
+ PrintEnvironmentVariable(out, SENTINEL_PORT_ENV_VAR_NAME);
+ PrintEnvironmentVariable(out, SENTINEL_MASTER_NAME_ENV_VAR_NAME);
}
void PrintDatabaseInfo(const DatabaseInfo& databaseInfo, std::ostream& out)
ConfigurationReader::ConfigurationReader(const Directories& directories,
System& system,
std::shared_ptr<Logger> logger):
- dbHostEnvVariableName(DB_HOST_ENV_VAR_NAME),
- dbHostEnvVariableValue({}),
- dbPortEnvVariableName(DB_PORT_ENV_VAR_NAME),
- dbPortEnvVariableValue({}),
+ dbHostEnvVariableName(DB_HOST_ENV_VAR_NAME),
+ dbHostEnvVariableValue({}),
+ dbPortEnvVariableName(DB_PORT_ENV_VAR_NAME),
+ dbPortEnvVariableValue({}),
+ sentinelPortEnvVariableName(SENTINEL_PORT_ENV_VAR_NAME),
+ sentinelPortEnvVariableValue({}),
+ sentinelMasterNameEnvVariableName(SENTINEL_MASTER_NAME_ENV_VAR_NAME),
+ sentinelMasterNameEnvVariableValue({}),
jsonDatabaseConfiguration(boost::none),
logger(logger)
{
auto envStr = system.getenv(dbPortEnvVariableName.c_str());
if (envStr)
dbPortEnvVariableValue = envStr;
+ envStr = system.getenv(sentinelPortEnvVariableName.c_str());
+ if (envStr)
+ sentinelPortEnvVariableValue = envStr;
+ envStr = system.getenv(sentinelMasterNameEnvVariableName.c_str());
+ if (envStr)
+ sentinelMasterNameEnvVariableValue = envStr;
}
readConfigurationFromDirectories(directories);
{
if (sourceForDatabaseConfiguration == dbHostEnvVariableName)
{
- // Currently hard coded to redis-standalone, because RIC dbaas does not support Redis cluster configuration.
- validateAndSetDbType("redis-standalone", databaseConfiguration, sourceForDatabaseConfiguration);
- if (dbPortEnvVariableValue.empty())
- parseDatabaseServersConfigurationFromString(databaseConfiguration, dbHostEnvVariableValue, sourceForDatabaseConfiguration);
- else
- parseDatabaseServersConfigurationFromString(databaseConfiguration, dbHostEnvVariableValue + ":" + dbPortEnvVariableValue, sourceForDatabaseConfiguration);
+ // NOTE: Redis cluster is not currently configurable via environment variables.
+ if (sentinelPortEnvVariableValue.empty())
+ {
+ validateAndSetDbType("redis-standalone", databaseConfiguration, sourceForDatabaseConfiguration);
+ if (dbPortEnvVariableValue.empty())
+ parseDatabaseServersConfigurationFromString(databaseConfiguration, dbHostEnvVariableValue, sourceForDatabaseConfiguration);
+ else
+ parseDatabaseServersConfigurationFromString(databaseConfiguration, dbHostEnvVariableValue + ":" + dbPortEnvVariableValue, sourceForDatabaseConfiguration);
+ }
+ else
+ {
+ validateAndSetDbType("redis-sentinel", databaseConfiguration, sourceForDatabaseConfiguration);
+ databaseConfiguration.checkAndApplySentinelAddress(dbHostEnvVariableValue + ":" + sentinelPortEnvVariableValue);
+ databaseConfiguration.checkAndApplySentinelMasterName(sentinelMasterNameEnvVariableValue);
+ }
}
else
parseDatabaseConfigurationTree(databaseConfiguration, jsonDatabaseConfiguration, sourceForDatabaseConfiguration);
}
const uint16_t DEFAULT_PORT(6379U);
+ const uint16_t DEFAULT_SENTINEL_PORT(26379U);
}
DatabaseConfigurationImpl::DatabaseConfigurationImpl():
dbType = DatabaseConfiguration::DbType::REDIS_STANDALONE;
else if (type == "redis-cluster")
dbType = DatabaseConfiguration::DbType::REDIS_CLUSTER;
+ else if (type == "redis-sentinel")
+ dbType = DatabaseConfiguration::DbType::REDIS_SENTINEL;
else
throw DatabaseConfiguration::InvalidDbType(type);
}
{
return { HostAndPort(getDefaultHost(), htons(DEFAULT_PORT)) };
}
+
+void DatabaseConfigurationImpl::checkAndApplySentinelAddress(const std::string& address)
+{
+ sentinelAddress = HostAndPort(address, htons(DEFAULT_SENTINEL_PORT));
+}
+
+boost::optional<HostAndPort> DatabaseConfigurationImpl::getSentinelAddress() const
+{
+ return sentinelAddress;
+}
+
+void DatabaseConfigurationImpl::checkAndApplySentinelMasterName(const std::string& name)
+{
+ sentinelMasterName = name;
+}
+
+std::string DatabaseConfigurationImpl::getSentinelMasterName() const
+{
+ return sentinelMasterName;
+}
#include <netinet/in.h>
#include <arpa/inet.h>
#include <boost/lexical_cast.hpp>
+#include <ostream>
using namespace shareddatalayer;
else
return this->getHost() < hp.getHost();
}
+
+std::ostream& shareddatalayer::operator << (std::ostream& os, const HostAndPort& hostAndPort)
+{
+ os << hostAndPort.getHost() << ":" << hostAndPort.getPort();
+ return os;
+}
limitations under the License.
*/
-#include "private/redis/asyncdatabasediscovery.hpp"
-#include "private/databaseconfiguration.hpp"
-#include "private/logger.hpp"
#include <cstdlib>
#include "config.h"
+#include "private/abort.hpp"
+#include "private/databaseconfiguration.hpp"
+#include "private/logger.hpp"
+#include "private/redis/asyncdatabasediscovery.hpp"
#if HAVE_HIREDIS
#include "private/redis/asynchiredisdatabasediscovery.hpp"
#endif
-#if HAVE_SENTINEL
#include "private/redis/asyncsentineldatabasediscovery.hpp"
-#endif
-#include "private/abort.hpp"
using namespace shareddatalayer::redis;
else
{
#if HAVE_HIREDIS
-#if HAVE_SENTINEL
- static_cast<void>(ns);
- return std::make_shared<AsyncSentinelDatabaseDiscovery>(engine,
- logger);
-#else
- return std::make_shared<AsyncHiredisDatabaseDiscovery>(engine,
- ns,
- DatabaseInfo::Type::SINGLE,
- staticAddresses,
- logger);
-#endif
+ if (staticDbType == DatabaseConfiguration::DbType::REDIS_SENTINEL)
+ {
+ static_cast<void>(ns);
+ auto sentinelAddress(staticDatabaseConfiguration.getSentinelAddress());
+ if (sentinelAddress)
+ return std::make_shared<AsyncSentinelDatabaseDiscovery>(engine,
+ logger,
+ *sentinelAddress,
+ staticDatabaseConfiguration.getSentinelMasterName());
+ else
+ SHAREDDATALAYER_ABORT("Sentinel address not configured.");
+ }
+ else
+ {
+ return std::make_shared<AsyncHiredisDatabaseDiscovery>(engine,
+ ns,
+ DatabaseInfo::Type::SINGLE,
+ staticAddresses,
+ logger);
+ }
#else
static_cast<void>(logger);
SHAREDDATALAYER_ABORT("No Hiredis");
}
AsyncSentinelDatabaseDiscovery::AsyncSentinelDatabaseDiscovery(std::shared_ptr<Engine> engine,
- std::shared_ptr<Logger> logger):
+ std::shared_ptr<Logger> logger,
+ const HostAndPort& sentinelAddress,
+ const std::string& sentinelMasterName):
AsyncSentinelDatabaseDiscovery(engine,
logger,
+ sentinelAddress,
+ sentinelMasterName,
::asyncCommandDispatcherCreator,
std::make_shared<redis::ContentsBuilder>(AsyncStorage::SEPARATOR))
{
AsyncSentinelDatabaseDiscovery::AsyncSentinelDatabaseDiscovery(std::shared_ptr<Engine> engine,
std::shared_ptr<Logger> logger,
+ const HostAndPort& sentinelAddress,
+ const std::string& sentinelMasterName,
const AsyncCommandDispatcherCreator& asyncCommandDispatcherCreator,
std::shared_ptr<redis::ContentsBuilder> contentsBuilder):
engine(engine),
logger(logger),
- // @TODO Make configurable.
- databaseInfo(DatabaseInfo({DatabaseConfiguration::Addresses({HostAndPort("dbaas-ha", htons(26379U))}),
+ databaseInfo(DatabaseInfo({DatabaseConfiguration::Addresses({sentinelAddress}),
DatabaseInfo::Type::SINGLE,
boost::none,
DatabaseInfo::Discovery::SENTINEL})),
+ sentinelMasterName(sentinelMasterName),
contentsBuilder(contentsBuilder),
subscribeRetryTimer(*engine),
subscribeRetryTimerDuration(std::chrono::seconds(1)),
std::placeholders::_1,
std::placeholders::_2),
"dummyNamespace", // Not meaningful for Sentinel
- contentsBuilder->build("SENTINEL", "get-master-addr-by-name", "mymaster")); //@TODO Make master name configurable
+ contentsBuilder->build("SENTINEL", "get-master-addr-by-name", sentinelMasterName));
}
void AsyncSentinelDatabaseDiscovery::masterInquiryAck(const std::error_code& error,
new AsyncSentinelDatabaseDiscovery(
engineMock,
logger,
+ HostAndPort(someHost, somePort),
+ "mymaster",
std::bind(&AsyncSentinelDatabaseDiscoveryBaseTest::asyncCommandDispatcherCreator,
this),
contentsBuilderMock));
EXPECT_CALL(databaseConfigurationMock, checkAndApplyServerAddress(address));
}
+ void expectSentinelAddressConfigurationCheckAndApply(const std::string& address)
+ {
+ EXPECT_CALL(databaseConfigurationMock, checkAndApplySentinelAddress(address));
+ }
+
+ void expectSentinelMasterNameConfigurationCheckAndApply(const std::string& address)
+ {
+ EXPECT_CALL(databaseConfigurationMock, checkAndApplySentinelMasterName(address));
+ }
+
void expectDatabaseConfigurationIsEmpty_returnFalse()
{
EXPECT_CALL(databaseConfigurationMock, isEmpty()).
public:
std::string dbHostEnvVariableValue;
std::string dbPortEnvVariableValue;
+ std::string sentinelPortEnvVariableValue;
+ std::string sentinelMasterNameEnvVariableValue;
std::istringstream is{R"JSON(
{
"database":
try
{
EXPECT_CALL(systemMock, getenv(_))
- .Times(2)
+ .Times(4)
.WillOnce(Return(dbHostEnvVariableValue.c_str()))
.WillOnce(Return(nullptr));
initializeReaderWithoutDirectories();
expectGetEnvironmentString(dbHostEnvVariableValue.c_str());
dbPortEnvVariableValue = "12345";
expectGetEnvironmentString(dbPortEnvVariableValue.c_str());
+ expectGetEnvironmentString(nullptr); //SENTINEL_PORT_ENV_VAR_NAME
+ expectGetEnvironmentString(nullptr); //SENTINEL_MASTER_NAME_ENV_VAR_NAME
expectDbTypeConfigurationCheckAndApply("redis-standalone");
expectDBServerAddressConfigurationCheckAndApply("unknownAddress.local:12345");
InSequence dummy;
dbHostEnvVariableValue = "server.local";
expectGetEnvironmentString(dbHostEnvVariableValue.c_str());
- expectGetEnvironmentString(nullptr);
+ expectGetEnvironmentString(nullptr); //DB_PORT_ENV_VAR_NAME
+ expectGetEnvironmentString(nullptr); //SENTINEL_PORT_ENV_VAR_NAME
+ expectGetEnvironmentString(nullptr); //SENTINEL_MASTER_NAME_ENV_VAR_NAME
expectDbTypeConfigurationCheckAndApply("redis-standalone");
expectDBServerAddressConfigurationCheckAndApply("server.local");
InSequence dummy;
dbHostEnvVariableValue = "[2001::123]:12345";
expectGetEnvironmentString(dbHostEnvVariableValue.c_str());
- expectGetEnvironmentString(nullptr);
+ expectGetEnvironmentString(nullptr); //DB_PORT_ENV_VAR_NAME
+ expectGetEnvironmentString(nullptr); //SENTINEL_PORT_ENV_VAR_NAME
+ expectGetEnvironmentString(nullptr); //SENTINEL_MASTER_NAME_ENV_VAR_NAME
expectDbTypeConfigurationCheckAndApply("redis-standalone");
expectDBServerAddressConfigurationCheckAndApply("[2001::123]:12345");
initializeReaderWithoutDirectories();
configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
}
+
+TEST_F(ConfigurationReaderEnvironmentVariableTest, EnvironmentConfigurationWithSentinel)
+{
+ InSequence dummy;
+ dbHostEnvVariableValue = "sentinelAddress.local";
+ expectGetEnvironmentString(dbHostEnvVariableValue.c_str());
+ dbPortEnvVariableValue = "1111";
+ expectGetEnvironmentString(dbPortEnvVariableValue.c_str());
+ sentinelPortEnvVariableValue = "2222";
+ expectGetEnvironmentString(sentinelPortEnvVariableValue.c_str());
+ sentinelMasterNameEnvVariableValue = "mymaster";
+ expectGetEnvironmentString(sentinelMasterNameEnvVariableValue.c_str());
+
+ expectDbTypeConfigurationCheckAndApply("redis-sentinel");
+ expectSentinelAddressConfigurationCheckAndApply("sentinelAddress.local:2222");
+ expectSentinelMasterNameConfigurationCheckAndApply(sentinelMasterNameEnvVariableValue);
+ initializeReaderWithoutDirectories();
+ configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
+}
EXPECT_EQ(DatabaseConfiguration::DbType::REDIS_CLUSTER, retDbType);
}
+TEST_F(DatabaseConfigurationImplTest, CanApplyRedisSentinelDbTypeStringAndReturnType)
+{
+ databaseConfigurationImpl->checkAndApplyDbType("redis-sentinel");
+ const auto retDbType(databaseConfigurationImpl->getDbType());
+ EXPECT_EQ(DatabaseConfiguration::DbType::REDIS_SENTINEL, retDbType);
+}
+
TEST_F(DatabaseConfigurationImplTest, CanApplyNewAddressesOneByOneAndReturnAllAddresses)
{
databaseConfigurationImpl->checkAndApplyServerAddress("dummydatabaseaddress.local");
databaseConfigurationImpl->checkAndApplyServerAddress("[2001::123]:12345");
EXPECT_FALSE(databaseConfigurationImpl->isEmpty());
}
+
+TEST_F(DatabaseConfigurationImplTest, DefaultSentinelAddressIsNone)
+{
+ EXPECT_EQ(boost::none, databaseConfigurationImpl->getSentinelAddress());
+}
+
+TEST_F(DatabaseConfigurationImplTest, CanApplyAndReturnSentinelAddress)
+{
+ databaseConfigurationImpl->checkAndApplySentinelAddress("dummydatabaseaddress.local:1234");
+ auto address = databaseConfigurationImpl->getSentinelAddress();
+ EXPECT_NE(boost::none, databaseConfigurationImpl->getSentinelAddress());
+ EXPECT_EQ("dummydatabaseaddress.local", address->getHost());
+ EXPECT_EQ(1234, ntohs(address->getPort()));
+}
+
+TEST_F(DatabaseConfigurationImplTest, DefaultSentinelMasterNameIsEmpty)
+{
+ EXPECT_EQ("", databaseConfigurationImpl->getSentinelMasterName());
+}
+
+TEST_F(DatabaseConfigurationImplTest, CanApplyAndReturnSentinelMasterName)
+{
+ databaseConfigurationImpl->checkAndApplySentinelMasterName("mymaster");
+ EXPECT_EQ("mymaster", databaseConfigurationImpl->getSentinelMasterName());
+}
#include <arpa/inet.h>
#include <gtest/gtest.h>
#include "private/hostandport.hpp"
+#include <sstream>
using namespace shareddatalayer;
using namespace testing;
{
EXPECT_THROW(HostAndPort(":1234", htons(100)), HostAndPort::EmptyHost);
}
+
+TEST(HostAndPortTest, CanOutput)
+{
+ std::string expectedOutput("somehost.somesubdomain.somedomain:1234");
+ std::stringstream ss;
+ HostAndPort hostAndPort("somehost.somesubdomain.somedomain", 1234);
+ ss << hostAndPort;
+ EXPECT_EQ(expectedOutput, ss.str());
+}