summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc2
-rw-r--r--src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc2
-rw-r--r--src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc521
-rw-r--r--src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc521
-rw-r--r--src/lib/dhcpsrv/tests/Makefile.am1
-rw-r--r--src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/alloc_engine_utils.cc2
-rw-r--r--src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/host_mgr_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/lease_mgr_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/tests/sanity_checks_unittest.cc2
-rw-r--r--src/lib/dhcpsrv/testutils/Makefile.am1
-rw-r--r--src/lib/dhcpsrv/testutils/test_utils.cc (renamed from src/lib/dhcpsrv/tests/test_utils.cc)0
-rw-r--r--src/lib/dhcpsrv/testutils/test_utils.h (renamed from src/lib/dhcpsrv/tests/test_utils.h)0
-rw-r--r--src/lib/process/config_ctl_info.cc6
-rw-r--r--src/lib/process/config_ctl_info.h55
26 files changed, 1094 insertions, 47 deletions
diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
index 693898c663..6deb393966 100644
--- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
+++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
@@ -2329,7 +2329,7 @@ public:
// Iterate over the configured DBs and instantiate them.
for (auto db : config_ctl->getConfigDatabases()) {
const std::string& access = db.getAccessString();
- auto parameters = DatabaseConnection::parse(access);
+ auto parameters = db.getParameters();
if (ConfigBackendDHCPv4Mgr::instance().delBackend(parameters["type"], access, true)) {
ConfigBackendDHCPv4Mgr::instance().addBackend(db.getAccessString());
}
diff --git a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc
index 0fa4fb4e86..f59ff7f576 100644
--- a/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc
+++ b/src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc
@@ -2772,7 +2772,7 @@ public:
// Iterate over the configured DBs and instantiate them.
for (auto db : config_ctl->getConfigDatabases()) {
const std::string& access = db.getAccessString();
- auto parameters = DatabaseConnection::parse(access);
+ auto parameters = db.getParameters();
if (ConfigBackendDHCPv6Mgr::instance().delBackend(parameters["type"], access, true)) {
ConfigBackendDHCPv6Mgr::instance().addBackend(db.getAccessString());
}
diff --git a/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc b/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc
index 43da6cef8c..5cc98f1a49 100644
--- a/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc
+++ b/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc
@@ -7,6 +7,7 @@
#include <config.h>
#include <mysql_cb_dhcp4.h>
#include <mysql_cb_impl.h>
+#include <database/database_connection.h>
#include <database/db_exceptions.h>
#include <database/server.h>
#include <database/testutils/schema.h>
@@ -16,22 +17,31 @@
#include <dhcp/option_int.h>
#include <dhcp/option_space.h>
#include <dhcp/option_string.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/config_backend_dhcp4_mgr.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/testutils/mysql_generic_backend_unittest.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <mysql/testutils/mysql_schema.h>
+#include <testutils/multi_threading_utils.h>
+
#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>
#include <mysql.h>
#include <map>
#include <sstream>
+using namespace isc;
using namespace isc::asiolink;
using namespace isc::db;
using namespace isc::db::test;
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
+using namespace isc::process;
+using namespace isc::test;
+namespace ph = std::placeholders;
namespace {
@@ -4153,4 +4163,515 @@ TEST_F(MySqlConfigBackendDHCPv4Test, multipleAuditEntries) {
}
}
+class MySqlConfigBackendDHCPv4DbLostCallbackTest : public ::testing::Test {
+public:
+ MySqlConfigBackendDHCPv4DbLostCallbackTest()
+ : db_lost_callback_called_(0), db_recovered_callback_called_(0),
+ db_failed_callback_called_(0),
+ io_service_(boost::make_shared<isc::asiolink::IOService>()) {
+ isc::db::DatabaseConnection::db_lost_callback_ = 0;
+ isc::db::DatabaseConnection::db_recovered_callback_ = 0;
+ isc::db::DatabaseConnection::db_failed_callback_ = 0;
+ isc::dhcp::MySqlConfigBackendImpl::setIOService(io_service_);
+ isc::dhcp::TimerMgr::instance()->setIOService(io_service_);
+ isc::dhcp::CfgMgr::instance().clear();
+ }
+
+ ~MySqlConfigBackendDHCPv4DbLostCallbackTest() {
+ isc::db::DatabaseConnection::db_lost_callback_ = 0;
+ isc::db::DatabaseConnection::db_recovered_callback_ = 0;
+ isc::db::DatabaseConnection::db_failed_callback_ = 0;
+ isc::dhcp::MySqlConfigBackendImpl::setIOService(isc::asiolink::IOServicePtr());
+ isc::dhcp::TimerMgr::instance()->unregisterTimers();
+ isc::dhcp::CfgMgr::instance().clear();
+ }
+
+ /// @brief Prepares the class for a test.
+ ///
+ /// Invoked by gtest prior test entry, we create the
+ /// appropriate schema and create a basic DB manager to
+ /// wipe out any prior instance
+ virtual void SetUp() {
+ isc::dhcp::MySqlConfigBackendImpl::setIOService(io_service_);
+ isc::db::DatabaseConnection::db_lost_callback_ = 0;
+ isc::db::DatabaseConnection::db_recovered_callback_ = 0;
+ isc::db::DatabaseConnection::db_failed_callback_ = 0;
+ // Ensure we have the proper schema with no transient data.
+ createMySQLSchema();
+ isc::dhcp::CfgMgr::instance().clear();
+ isc::dhcp::MySqlConfigBackendDHCPv4::registerBackendType();
+ }
+
+ /// @brief Pre-text exit clean up
+ ///
+ /// Invoked by gtest upon test exit, we destroy the schema
+ /// we created.
+ virtual void TearDown() {
+ isc::dhcp::MySqlConfigBackendImpl::setIOService(isc::asiolink::IOServicePtr());
+ isc::db::DatabaseConnection::db_lost_callback_ = 0;
+ isc::db::DatabaseConnection::db_recovered_callback_ = 0;
+ isc::db::DatabaseConnection::db_failed_callback_ = 0;
+ // If data wipe enabled, delete transient data otherwise destroy the schema
+ destroyMySQLSchema();
+ isc::dhcp::CfgMgr::instance().clear();
+ isc::dhcp::MySqlConfigBackendDHCPv4::unregisterBackendType();
+ }
+
+ /// @brief Method which returns the back end specific connection
+ /// string
+ virtual std::string validConnectString() {
+ return (validMySQLConnectionString());
+ }
+
+ /// @brief Method which returns invalid back end specific connection
+ /// string
+ virtual std::string invalidConnectString() {
+ return (connectionString(MYSQL_VALID_TYPE, INVALID_NAME, VALID_HOST,
+ VALID_USER, VALID_PASSWORD));
+ }
+
+ /// @brief Verifies open failures do NOT invoke db lost callback
+ ///
+ /// The db lost callback should only be invoked after successfully
+ /// opening the DB and then subsequently losing it. Failing to
+ /// open should be handled directly by the application layer.
+ void testNoCallbackOnOpenFailure();
+
+ /// @brief Verifies the CB manager's behavior if DB connection is lost
+ ///
+ /// This function creates a CB manager with an back end that
+ /// supports connectivity lost callback (currently only MySQL and
+ /// PostgreSQL currently). It verifies connectivity by issuing a known
+ /// valid query. Next it simulates connectivity lost by identifying and
+ /// closing the socket connection to the CB backend. It then reissues
+ /// the query and verifies that:
+ /// -# The Query throws DbOperationError (rather than exiting)
+ /// -# The registered DbLostCallback was invoked
+ /// -# The registered DbRecoveredCallback was invoked
+ void testDbLostAndRecoveredCallback();
+
+ /// @brief Verifies the CB manager's behavior if DB connection is lost
+ ///
+ /// This function creates a CB manager with an back end that
+ /// supports connectivity lost callback (currently only MySQL and
+ /// PostgreSQL currently). It verifies connectivity by issuing a known
+ /// valid query. Next it simulates connectivity lost by identifying and
+ /// closing the socket connection to the CB backend. It then reissues
+ /// the query and verifies that:
+ /// -# The Query throws DbOperationError (rather than exiting)
+ /// -# The registered DbLostCallback was invoked
+ /// -# The registered DbFailedCallback was invoked
+ void testDbLostAndFailedCallback();
+
+ /// @brief Verifies the CB manager's behavior if DB connection is lost
+ ///
+ /// This function creates a CB manager with an back end that
+ /// supports connectivity lost callback (currently only MySQL and
+ /// PostgreSQL currently). It verifies connectivity by issuing a known
+ /// valid query. Next it simulates connectivity lost by identifyingLost and
+ /// closing the socket connection to the CB backend. It then reissues
+ /// the query and verifies that:
+ /// -# The Query throws DbOperationError (rather than exiting)
+ /// -# The registered DbLostCallback was invoked
+ /// -# The registered DbRecoveredCallback was invoked after two reconnect
+ /// attempts (once failing and second triggered by timer)
+ void testDbLostAndRecoveredAfterTimeoutCallback();
+
+ /// @brief Verifies the CB manager's behavior if DB connection is lost
+ ///
+ /// This function creates a CB manager with an back end that
+ /// supports connectivity lost callback (currently only MySQL and
+ /// PostgreSQL currently). It verifies connectivity by issuing a known
+ /// valid query. Next it simulates connectivity lost by identifyingLost and
+ /// closing the socket connection to the CB backend. It then reissues
+ /// the query and verifies that:
+ /// -# The Query throws DbOperationError (rather than exiting)
+ /// -# The registered DbLostCallback was invoked
+ /// -# The registered DbFailedCallback was invoked after two reconnect
+ /// attempts (once failing and second triggered by timer)
+ void testDbLostAndFailedAfterTimeoutCallback();
+
+ /// @brief Callback function registered with the CB manager
+ bool db_lost_callback(db::ReconnectCtlPtr /* not_used */) {
+ return (++db_lost_callback_called_);
+ }
+
+ /// @brief Flag used to detect calls to db_lost_callback function
+ uint32_t db_lost_callback_called_;
+
+ /// @brief Callback function registered with the CB manager
+ bool db_recovered_callback(db::ReconnectCtlPtr /* not_used */) {
+ return (++db_recovered_callback_called_);
+ }
+
+ /// @brief Flag used to detect calls to db_recovered_callback function
+ uint32_t db_recovered_callback_called_;
+
+ /// @brief Callback function registered with the CB manager
+ bool db_failed_callback(db::ReconnectCtlPtr /* not_used */) {
+ return (++db_failed_callback_called_);
+ }
+
+ /// @brief Flag used to detect calls to db_failed_callback function
+ uint32_t db_failed_callback_called_;
+
+ /// The IOService object, used for all ASIO operations.
+ isc::asiolink::IOServicePtr io_service_;
+};
+
+void
+MySqlConfigBackendDHCPv4DbLostCallbackTest::testNoCallbackOnOpenFailure() {
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = invalidConnectString();
+
+ // Connect to the CB backend.
+ ASSERT_THROW(ConfigBackendDHCPv4Mgr::instance().addBackend(access), DbOpenError);
+
+ io_service_->poll();
+
+ EXPECT_EQ(0, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+}
+
+void
+MySqlConfigBackendDHCPv4DbLostCallbackTest::testDbLostAndRecoveredCallback() {
+ // Set the connectivity lost callback.
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = validConnectString();
+
+ ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ // Find the most recently opened socket. Our SQL client's socket should
+ // be the next one.
+ int last_open_socket = findLastSocketFd();
+
+ // Fill holes.
+ FillFdHoles holes(last_open_socket);
+
+ // Connect to the CB backend.
+ ASSERT_NO_THROW(ConfigBackendDHCPv4Mgr::instance().addBackend(access));
+
+ // Find the SQL client socket.
+ int sql_socket = findLastSocketFd();
+ ASSERT_TRUE(sql_socket > last_open_socket);
+
+ // Verify we can execute a query. We don't care about the answer.
+ ServerCollection servers;
+ ASSERT_NO_THROW(servers = ConfigBackendDHCPv4Mgr::instance().getPool()->getAllServers4(BackendSelector()));
+
+ // Now close the sql socket out from under backend client
+ ASSERT_EQ(0, close(sql_socket));
+
+ // A query should fail with DbConnectionUnusable.
+ ASSERT_THROW(servers = ConfigBackendDHCPv4Mgr::instance().getPool()->getAllServers4(BackendSelector()),
+ DbConnectionUnusable);
+
+ io_service_->poll();
+
+ // Our lost and recovered connectivity callback should have been invoked.
+ EXPECT_EQ(1, db_lost_callback_called_);
+ EXPECT_EQ(1, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+}
+
+void
+MySqlConfigBackendDHCPv4DbLostCallbackTest::testDbLostAndFailedCallback() {
+ // Set the connectivity lost callback.
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = validConnectString();
+ ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ // Find the most recently opened socket. Our SQL client's socket should
+ // be the next one.
+ int last_open_socket = findLastSocketFd();
+
+ // Fill holes.
+ FillFdHoles holes(last_open_socket);
+
+ // Connect to the CB backend.
+ ASSERT_NO_THROW(ConfigBackendDHCPv4Mgr::instance().addBackend(access));
+
+ // Find the SQL client socket.
+ int sql_socket = findLastSocketFd();
+ ASSERT_TRUE(sql_socket > last_open_socket);
+
+ // Verify we can execute a query. We don't care about the answer.
+ ServerCollection servers;
+ ASSERT_NO_THROW(servers = ConfigBackendDHCPv4Mgr::instance().getPool()->getAllServers4(BackendSelector()));
+
+ access = invalidConnectString();
+ CfgMgr::instance().clear();
+ // by adding an extra space in the access string will cause the DatabaseConnection::parse
+ // to throw resulting in failure to recreate the manager
+ config_ctl_info.reset(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+ const ConfigDbInfoList& cfg = CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases();
+ (const_cast<ConfigDbInfoList&>(cfg))[0].setAccessString(access + " ", true);
+
+ // Now close the sql socket out from under backend client
+ ASSERT_EQ(0, close(sql_socket));
+
+ // A query should fail with DbConnectionUnusable.
+ ASSERT_THROW(servers = ConfigBackendDHCPv4Mgr::instance().getPool()->getAllServers4(BackendSelector()),
+ DbConnectionUnusable);
+
+ io_service_->poll();
+
+ // Our lost and recovered connectivity callback should have been invoked.
+ EXPECT_EQ(1, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(1, db_failed_callback_called_);
+}
+
+void
+MySqlConfigBackendDHCPv4DbLostCallbackTest::testDbLostAndRecoveredAfterTimeoutCallback() {
+ // Set the connectivity lost callback.
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = validConnectString();
+ std::string extra = " max-reconnect-tries=2 reconnect-wait-time=1";
+ access += extra;
+ ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ // Find the most recently opened socket. Our SQL client's socket should
+ // be the next one.
+ int last_open_socket = findLastSocketFd();
+
+ // Fill holes.
+ FillFdHoles holes(last_open_socket);
+
+ // Connect to the CB backend.
+ ASSERT_NO_THROW(ConfigBackendDHCPv4Mgr::instance().addBackend(access));
+
+ // Find the SQL client socket.
+ int sql_socket = findLastSocketFd();
+ ASSERT_TRUE(sql_socket > last_open_socket);
+
+ // Verify we can execute a query. We don't care about the answer.
+ ServerCollection servers;
+ ASSERT_NO_THROW(servers = ConfigBackendDHCPv4Mgr::instance().getPool()->getAllServers4(BackendSelector()));
+
+ access = invalidConnectString();
+ access += extra;
+ CfgMgr::instance().clear();
+ // by adding an extra space in the access string will cause the DatabaseConnection::parse
+ // to throw resulting in failure to recreate the manager
+ config_ctl_info.reset(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+ const ConfigDbInfoList& cfg = CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases();
+ (const_cast<ConfigDbInfoList&>(cfg))[0].setAccessString(access + " ", true);
+
+ // Now close the sql socket out from under backend client
+ ASSERT_EQ(0, close(sql_socket));
+
+ // A query should fail with DbConnectionUnusable.
+ ASSERT_THROW(servers = ConfigBackendDHCPv4Mgr::instance().getPool()->getAllServers4(BackendSelector()),
+ DbConnectionUnusable);
+
+ io_service_->poll();
+
+ // Our lost and recovered connectivity callback should have been invoked.
+ EXPECT_EQ(1, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+
+ access = validConnectString();
+ access += extra;
+ CfgMgr::instance().clear();
+ config_ctl_info.reset(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ sleep(1);
+
+ io_service_->poll();
+
+ // Our recovered connectivity callback should have been invoked.
+ EXPECT_EQ(2, db_lost_callback_called_);
+ EXPECT_EQ(1, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+}
+
+void
+MySqlConfigBackendDHCPv4DbLostCallbackTest::testDbLostAndFailedAfterTimeoutCallback() {
+ // Set the connectivity lost callback.
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv4DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = validConnectString();
+ std::string extra = " max-reconnect-tries=2 reconnect-wait-time=1";
+ access += extra;
+ ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ // Find the most recently opened socket. Our SQL client's socket should
+ // be the next one.
+ int last_open_socket = findLastSocketFd();
+
+ // Fill holes.
+ FillFdHoles holes(last_open_socket);
+
+ // Connect to the CB backend.
+ ASSERT_NO_THROW(ConfigBackendDHCPv4Mgr::instance().addBackend(access));
+
+ // Find the SQL client socket.
+ int sql_socket = findLastSocketFd();
+ ASSERT_TRUE(sql_socket > last_open_socket);
+
+ // Verify we can execute a query. We don't care about the answer.
+ ServerCollection servers;
+ ASSERT_NO_THROW(servers = ConfigBackendDHCPv4Mgr::instance().getPool()->getAllServers4(BackendSelector()));
+
+ access = invalidConnectString();
+ access += extra;
+ CfgMgr::instance().clear();
+ // by adding an extra space in the access string will cause the DatabaseConnection::parse
+ // to throw resulting in failure to recreate the manager
+ config_ctl_info.reset(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+ const ConfigDbInfoList& cfg = CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases();
+ (const_cast<ConfigDbInfoList&>(cfg))[0].setAccessString(access + " ", true);
+
+ // Now close the sql socket out from under backend client
+ ASSERT_EQ(0, close(sql_socket));
+
+ // A query should fail with DbConnectionUnusable.
+ ASSERT_THROW(servers = ConfigBackendDHCPv4Mgr::instance().getPool()->getAllServers4(BackendSelector()),
+ DbConnectionUnusable);
+
+ io_service_->poll();
+
+ // Our lost and recovered connectivity callback should have been invoked.
+ EXPECT_EQ(1, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+
+ sleep(1);
+
+ io_service_->poll();
+
+ // Our recovered connectivity callback should have been invoked.
+ EXPECT_EQ(2, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(1, db_failed_callback_called_);
+}
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testNoCallbackOnOpenFailure) {
+ MultiThreadingTest mt(false);
+ testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testNoCallbackOnOpenFailureMultiThreading) {
+ MultiThreadingTest mt(true);
+ testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testDbLostAndRecoveredCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testDbLostAndRecoveredCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testDbLostAndFailedCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testDbLostAndFailedCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndFailedAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv4DbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndFailedAfterTimeoutCallback();
+}
+
}
diff --git a/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc b/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc
index 1ce871302b..f07fba3f4f 100644
--- a/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc
+++ b/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc
@@ -7,6 +7,7 @@
#include <config.h>
#include <mysql_cb_dhcp6.h>
#include <asiolink/addr_utilities.h>
+#include <database/database_connection.h>
#include <database/db_exceptions.h>
#include <database/testutils/schema.h>
#include <dhcp/dhcp6.h>
@@ -15,22 +16,31 @@
#include <dhcp/option_int.h>
#include <dhcp/option_space.h>
#include <dhcp/option_string.h>
+#include <dhcpsrv/cfgmgr.h>
+#include <dhcpsrv/config_backend_dhcp6_mgr.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/testutils/mysql_generic_backend_unittest.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <mysql/testutils/mysql_schema.h>
+#include <testutils/multi_threading_utils.h>
+
#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>
#include <mysql.h>
#include <map>
#include <sstream>
+using namespace isc;
using namespace isc::asiolink;
using namespace isc::db;
using namespace isc::db::test;
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
+using namespace isc::process;
+using namespace isc::test;
+namespace ph = std::placeholders;
namespace {
@@ -4328,4 +4338,515 @@ TEST_F(MySqlConfigBackendDHCPv6Test, multipleAuditEntries) {
}
}
+class MySqlConfigBackendDHCPv6DbLostCallbackTest : public ::testing::Test {
+public:
+ MySqlConfigBackendDHCPv6DbLostCallbackTest()
+ : db_lost_callback_called_(0), db_recovered_callback_called_(0),
+ db_failed_callback_called_(0),
+ io_service_(boost::make_shared<isc::asiolink::IOService>()) {
+ isc::db::DatabaseConnection::db_lost_callback_ = 0;
+ isc::db::DatabaseConnection::db_recovered_callback_ = 0;
+ isc::db::DatabaseConnection::db_failed_callback_ = 0;
+ isc::dhcp::MySqlConfigBackendImpl::setIOService(io_service_);
+ isc::dhcp::TimerMgr::instance()->setIOService(io_service_);
+ isc::dhcp::CfgMgr::instance().clear();
+ }
+
+ ~MySqlConfigBackendDHCPv6DbLostCallbackTest() {
+ isc::db::DatabaseConnection::db_lost_callback_ = 0;
+ isc::db::DatabaseConnection::db_recovered_callback_ = 0;
+ isc::db::DatabaseConnection::db_failed_callback_ = 0;
+ isc::dhcp::MySqlConfigBackendImpl::setIOService(isc::asiolink::IOServicePtr());
+ isc::dhcp::TimerMgr::instance()->unregisterTimers();
+ isc::dhcp::CfgMgr::instance().clear();
+ }
+
+ /// @brief Prepares the class for a test.
+ ///
+ /// Invoked by gtest prior test entry, we create the
+ /// appropriate schema and create a basic DB manager to
+ /// wipe out any prior instance
+ virtual void SetUp() {
+ isc::dhcp::MySqlConfigBackendImpl::setIOService(io_service_);
+ isc::db::DatabaseConnection::db_lost_callback_ = 0;
+ isc::db::DatabaseConnection::db_recovered_callback_ = 0;
+ isc::db::DatabaseConnection::db_failed_callback_ = 0;
+ // Ensure we have the proper schema with no transient data.
+ createMySQLSchema();
+ isc::dhcp::CfgMgr::instance().clear();
+ isc::dhcp::MySqlConfigBackendDHCPv6::registerBackendType();
+ }
+
+ /// @brief Pre-text exit clean up
+ ///
+ /// Invoked by gtest upon test exit, we destroy the schema
+ /// we created.
+ virtual void TearDown() {
+ isc::dhcp::MySqlConfigBackendImpl::setIOService(isc::asiolink::IOServicePtr());
+ isc::db::DatabaseConnection::db_lost_callback_ = 0;
+ isc::db::DatabaseConnection::db_recovered_callback_ = 0;
+ isc::db::DatabaseConnection::db_failed_callback_ = 0;
+ // If data wipe enabled, delete transient data otherwise destroy the schema
+ destroyMySQLSchema();
+ isc::dhcp::CfgMgr::instance().clear();
+ isc::dhcp::MySqlConfigBackendDHCPv6::unregisterBackendType();
+ }
+
+ /// @brief Method which returns the back end specific connection
+ /// string
+ virtual std::string validConnectString() {
+ return (validMySQLConnectionString());
+ }
+
+ /// @brief Method which returns invalid back end specific connection
+ /// string
+ virtual std::string invalidConnectString() {
+ return (connectionString(MYSQL_VALID_TYPE, INVALID_NAME, VALID_HOST,
+ VALID_USER, VALID_PASSWORD));
+ }
+
+ /// @brief Verifies open failures do NOT invoke db lost callback
+ ///
+ /// The db lost callback should only be invoked after successfully
+ /// opening the DB and then subsequently losing it. Failing to
+ /// open should be handled directly by the application layer.
+ void testNoCallbackOnOpenFailure();
+
+ /// @brief Verifies the CB manager's behavior if DB connection is lost
+ ///
+ /// This function creates a CB manager with an back end that
+ /// supports connectivity lost callback (currently only MySQL and
+ /// PostgreSQL currently). It verifies connectivity by issuing a known
+ /// valid query. Next it simulates connectivity lost by identifying and
+ /// closing the socket connection to the CB backend. It then reissues
+ /// the query and verifies that:
+ /// -# The Query throws DbOperationError (rather than exiting)
+ /// -# The registered DbLostCallback was invoked
+ /// -# The registered DbRecoveredCallback was invoked
+ void testDbLostAndRecoveredCallback();
+
+ /// @brief Verifies the CB manager's behavior if DB connection is lost
+ ///
+ /// This function creates a CB manager with an back end that
+ /// supports connectivity lost callback (currently only MySQL and
+ /// PostgreSQL currently). It verifies connectivity by issuing a known
+ /// valid query. Next it simulates connectivity lost by identifying and
+ /// closing the socket connection to the CB backend. It then reissues
+ /// the query and verifies that:
+ /// -# The Query throws DbOperationError (rather than exiting)
+ /// -# The registered DbLostCallback was invoked
+ /// -# The registered DbFailedCallback was invoked
+ void testDbLostAndFailedCallback();
+
+ /// @brief Verifies the CB manager's behavior if DB connection is lost
+ ///
+ /// This function creates a CB manager with an back end that
+ /// supports connectivity lost callback (currently only MySQL and
+ /// PostgreSQL currently). It verifies connectivity by issuing a known
+ /// valid query. Next it simulates connectivity lost by identifyingLost and
+ /// closing the socket connection to the CB backend. It then reissues
+ /// the query and verifies that:
+ /// -# The Query throws DbOperationError (rather than exiting)
+ /// -# The registered DbLostCallback was invoked
+ /// -# The registered DbRecoveredCallback was invoked after two reconnect
+ /// attempts (once failing and second triggered by timer)
+ void testDbLostAndRecoveredAfterTimeoutCallback();
+
+ /// @brief Verifies the CB manager's behavior if DB connection is lost
+ ///
+ /// This function creates a CB manager with an back end that
+ /// supports connectivity lost callback (currently only MySQL and
+ /// PostgreSQL currently). It verifies connectivity by issuing a known
+ /// valid query. Next it simulates connectivity lost by identifyingLost and
+ /// closing the socket connection to the CB backend. It then reissues
+ /// the query and verifies that:
+ /// -# The Query throws DbOperationError (rather than exiting)
+ /// -# The registered DbLostCallback was invoked
+ /// -# The registered DbFailedCallback was invoked after two reconnect
+ /// attempts (once failing and second triggered by timer)
+ void testDbLostAndFailedAfterTimeoutCallback();
+
+ /// @brief Callback function registered with the CB manager
+ bool db_lost_callback(db::ReconnectCtlPtr /* not_used */) {
+ return (++db_lost_callback_called_);
+ }
+
+ /// @brief Flag used to detect calls to db_lost_callback function
+ uint32_t db_lost_callback_called_;
+
+ /// @brief Callback function registered with the CB manager
+ bool db_recovered_callback(db::ReconnectCtlPtr /* not_used */) {
+ return (++db_recovered_callback_called_);
+ }
+
+ /// @brief Flag used to detect calls to db_recovered_callback function
+ uint32_t db_recovered_callback_called_;
+
+ /// @brief Callback function registered with the CB manager
+ bool db_failed_callback(db::ReconnectCtlPtr /* not_used */) {
+ return (++db_failed_callback_called_);
+ }
+
+ /// @brief Flag used to detect calls to db_failed_callback function
+ uint32_t db_failed_callback_called_;
+
+ /// The IOService object, used for all ASIO operations.
+ isc::asiolink::IOServicePtr io_service_;
+};
+
+void
+MySqlConfigBackendDHCPv6DbLostCallbackTest::testNoCallbackOnOpenFailure() {
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = invalidConnectString();
+
+ // Connect to the CB backend.
+ ASSERT_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access), DbOpenError);
+
+ io_service_->poll();
+
+ EXPECT_EQ(0, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+}
+
+void
+MySqlConfigBackendDHCPv6DbLostCallbackTest::testDbLostAndRecoveredCallback() {
+ // Set the connectivity lost callback.
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = validConnectString();
+
+ ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ // Find the most recently opened socket. Our SQL client's socket should
+ // be the next one.
+ int last_open_socket = findLastSocketFd();
+
+ // Fill holes.
+ FillFdHoles holes(last_open_socket);
+
+ // Connect to the CB backend.
+ ASSERT_NO_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access));
+
+ // Find the SQL client socket.
+ int sql_socket = findLastSocketFd();
+ ASSERT_TRUE(sql_socket > last_open_socket);
+
+ // Verify we can execute a query. We don't care about the answer.
+ ServerCollection servers;
+ ASSERT_NO_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector()));
+
+ // Now close the sql socket out from under backend client
+ ASSERT_EQ(0, close(sql_socket));
+
+ // A query should fail with DbConnectionUnusable.
+ ASSERT_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector()),
+ DbConnectionUnusable);
+
+ io_service_->poll();
+
+ // Our lost and recovered connectivity callback should have been invoked.
+ EXPECT_EQ(1, db_lost_callback_called_);
+ EXPECT_EQ(1, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+}
+
+void
+MySqlConfigBackendDHCPv6DbLostCallbackTest::testDbLostAndFailedCallback() {
+ // Set the connectivity lost callback.
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = validConnectString();
+ ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ // Find the most recently opened socket. Our SQL client's socket should
+ // be the next one.
+ int last_open_socket = findLastSocketFd();
+
+ // Fill holes.
+ FillFdHoles holes(last_open_socket);
+
+ // Connect to the CB backend.
+ ASSERT_NO_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access));
+
+ // Find the SQL client socket.
+ int sql_socket = findLastSocketFd();
+ ASSERT_TRUE(sql_socket > last_open_socket);
+
+ // Verify we can execute a query. We don't care about the answer.
+ ServerCollection servers;
+ ASSERT_NO_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector()));
+
+ access = invalidConnectString();
+ CfgMgr::instance().clear();
+ // by adding an extra space in the access string will cause the DatabaseConnection::parse
+ // to throw resulting in failure to recreate the manager
+ config_ctl_info.reset(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+ const ConfigDbInfoList& cfg = CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases();
+ (const_cast<ConfigDbInfoList&>(cfg))[0].setAccessString(access + " ", true);
+
+ // Now close the sql socket out from under backend client
+ ASSERT_EQ(0, close(sql_socket));
+
+ // A query should fail with DbConnectionUnusable.
+ ASSERT_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector()),
+ DbConnectionUnusable);
+
+ io_service_->poll();
+
+ // Our lost and recovered connectivity callback should have been invoked.
+ EXPECT_EQ(1, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(1, db_failed_callback_called_);
+}
+
+void
+MySqlConfigBackendDHCPv6DbLostCallbackTest::testDbLostAndRecoveredAfterTimeoutCallback() {
+ // Set the connectivity lost callback.
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = validConnectString();
+ std::string extra = " max-reconnect-tries=2 reconnect-wait-time=1";
+ access += extra;
+ ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ // Find the most recently opened socket. Our SQL client's socket should
+ // be the next one.
+ int last_open_socket = findLastSocketFd();
+
+ // Fill holes.
+ FillFdHoles holes(last_open_socket);
+
+ // Connect to the CB backend.
+ ASSERT_NO_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access));
+
+ // Find the SQL client socket.
+ int sql_socket = findLastSocketFd();
+ ASSERT_TRUE(sql_socket > last_open_socket);
+
+ // Verify we can execute a query. We don't care about the answer.
+ ServerCollection servers;
+ ASSERT_NO_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector()));
+
+ access = invalidConnectString();
+ access += extra;
+ CfgMgr::instance().clear();
+ // by adding an extra space in the access string will cause the DatabaseConnection::parse
+ // to throw resulting in failure to recreate the manager
+ config_ctl_info.reset(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+ const ConfigDbInfoList& cfg = CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases();
+ (const_cast<ConfigDbInfoList&>(cfg))[0].setAccessString(access + " ", true);
+
+ // Now close the sql socket out from under backend client
+ ASSERT_EQ(0, close(sql_socket));
+
+ // A query should fail with DbConnectionUnusable.
+ ASSERT_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector()),
+ DbConnectionUnusable);
+
+ io_service_->poll();
+
+ // Our lost and recovered connectivity callback should have been invoked.
+ EXPECT_EQ(1, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+
+ access = validConnectString();
+ access += extra;
+ CfgMgr::instance().clear();
+ config_ctl_info.reset(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ sleep(1);
+
+ io_service_->poll();
+
+ // Our recovered connectivity callback should have been invoked.
+ EXPECT_EQ(2, db_lost_callback_called_);
+ EXPECT_EQ(1, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+}
+
+void
+MySqlConfigBackendDHCPv6DbLostCallbackTest::testDbLostAndFailedAfterTimeoutCallback() {
+ // Set the connectivity lost callback.
+ isc::db::DatabaseConnection::db_lost_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+ // Set the connectivity recovered callback.
+ isc::db::DatabaseConnection::db_recovered_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+ // Set the connectivity failed callback.
+ isc::db::DatabaseConnection::db_failed_callback_ =
+ std::bind(&MySqlConfigBackendDHCPv6DbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+ std::string access = validConnectString();
+ std::string extra = " max-reconnect-tries=2 reconnect-wait-time=1";
+ access += extra;
+ ConfigControlInfoPtr config_ctl_info(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+
+ // Find the most recently opened socket. Our SQL client's socket should
+ // be the next one.
+ int last_open_socket = findLastSocketFd();
+
+ // Fill holes.
+ FillFdHoles holes(last_open_socket);
+
+ // Connect to the CB backend.
+ ASSERT_NO_THROW(ConfigBackendDHCPv6Mgr::instance().addBackend(access));
+
+ // Find the SQL client socket.
+ int sql_socket = findLastSocketFd();
+ ASSERT_TRUE(sql_socket > last_open_socket);
+
+ // Verify we can execute a query. We don't care about the answer.
+ ServerCollection servers;
+ ASSERT_NO_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector()));
+
+ access = invalidConnectString();
+ access += extra;
+ CfgMgr::instance().clear();
+ // by adding an extra space in the access string will cause the DatabaseConnection::parse
+ // to throw resulting in failure to recreate the manager
+ config_ctl_info.reset(new ConfigControlInfo());
+ config_ctl_info->addConfigDatabase(access);
+ CfgMgr::instance().getCurrentCfg()->setConfigControlInfo(config_ctl_info);
+ const ConfigDbInfoList& cfg = CfgMgr::instance().getCurrentCfg()->getConfigControlInfo()->getConfigDatabases();
+ (const_cast<ConfigDbInfoList&>(cfg))[0].setAccessString(access + " ", true);
+
+ // Now close the sql socket out from under backend client
+ ASSERT_EQ(0, close(sql_socket));
+
+ // A query should fail with DbConnectionUnusable.
+ ASSERT_THROW(servers = ConfigBackendDHCPv6Mgr::instance().getPool()->getAllServers6(BackendSelector()),
+ DbConnectionUnusable);
+
+ io_service_->poll();
+
+ // Our lost and recovered connectivity callback should have been invoked.
+ EXPECT_EQ(1, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(0, db_failed_callback_called_);
+
+ sleep(1);
+
+ io_service_->poll();
+
+ // Our recovered connectivity callback should have been invoked.
+ EXPECT_EQ(2, db_lost_callback_called_);
+ EXPECT_EQ(0, db_recovered_callback_called_);
+ EXPECT_EQ(1, db_failed_callback_called_);
+}
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testNoCallbackOnOpenFailure) {
+ MultiThreadingTest mt(false);
+ testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testNoCallbackOnOpenFailureMultiThreading) {
+ MultiThreadingTest mt(true);
+ testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndRecoveredCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndRecoveredCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndFailedCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndFailedCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndFailedAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlConfigBackendDHCPv6DbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndFailedAfterTimeoutCallback();
+}
+
}
diff --git a/src/lib/dhcpsrv/tests/Makefile.am b/src/lib/dhcpsrv/tests/Makefile.am
index 8aad886da0..c7d8bf2aa4 100644
--- a/src/lib/dhcpsrv/tests/Makefile.am
+++ b/src/lib/dhcpsrv/tests/Makefile.am
@@ -131,7 +131,6 @@ libdhcpsrv_unittests_SOURCES += srv_config_unittest.cc
libdhcpsrv_unittests_SOURCES += subnet_unittest.cc
libdhcpsrv_unittests_SOURCES += test_get_callout_handle.cc test_get_callout_handle.h
libdhcpsrv_unittests_SOURCES += triplet_unittest.cc
-libdhcpsrv_unittests_SOURCES += test_utils.cc test_utils.h
libdhcpsrv_unittests_SOURCES += timer_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += network_state_unittest.cc
libdhcpsrv_unittests_SOURCES += network_unittest.cc
diff --git a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc
index 6ffd1d54ec..ffb2696f62 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc
@@ -11,7 +11,7 @@
#include <dhcpsrv/shared_network.h>
#include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/tests/alloc_engine_utils.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <testutils/gtest_utils.h>
#include <hooks/hooks_manager.h>
#include <hooks/callout_handle.h>
diff --git a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc
index ff2ab7c656..b1c9f855af 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc
@@ -9,7 +9,7 @@
#include <dhcp/pkt6.h>
#include <dhcpsrv/host_mgr.h>
#include <dhcpsrv/tests/alloc_engine_utils.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <stats/stats_mgr.h>
#include <testutils/gtest_utils.h>
diff --git a/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc
index be89802b7a..c758e476c0 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine_expiration_unittest.cc
@@ -9,7 +9,7 @@
#include <dhcp/option_data_types.h>
#include <dhcp_ddns/ncr_msg.h>
#include <dhcpsrv/tests/alloc_engine_utils.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <hooks/hooks_manager.h>
#include <stats/stats_mgr.h>
#include <gtest/gtest.h>
diff --git a/src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc
index 682e64aa4c..935296dcba 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc
@@ -6,7 +6,7 @@
#include <config.h>
#include <dhcpsrv/tests/alloc_engine_utils.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <hooks/server_hooks.h>
#include <hooks/callout_manager.h>
diff --git a/src/lib/dhcpsrv/tests/alloc_engine_utils.cc b/src/lib/dhcpsrv/tests/alloc_engine_utils.cc
index 9de1ea6990..03d224bfcb 100644
--- a/src/lib/dhcpsrv/tests/alloc_engine_utils.cc
+++ b/src/lib/dhcpsrv/tests/alloc_engine_utils.cc
@@ -18,7 +18,7 @@
#include <hooks/callout_handle.h>
#include <stats/stats_mgr.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/tests/alloc_engine_utils.h>
#include <hooks/hooks_manager.h>
diff --git a/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc
index ec2b80b2ef..17b084c748 100644
--- a/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc
+++ b/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc
@@ -18,7 +18,7 @@
#include <config.h>
#include <asiolink/io_address.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <exceptions/exceptions.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/cql_host_data_source.h>
diff --git a/src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc
index d79dd8bb69..38f4455e43 100644
--- a/src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/cql_lease_mgr_unittest.cc
@@ -23,7 +23,7 @@
#include <cql/testutils/cql_schema.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/cql_lease_mgr.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <exceptions/exceptions.h>
diff --git a/src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc
index cc8966fdf8..1d3524819c 100644
--- a/src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc
@@ -13,7 +13,7 @@
#include <dhcpsrv/dhcpsrv_exceptions.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <exceptions/exceptions.h>
#include <stats/stats_mgr.h>
diff --git a/src/lib/dhcpsrv/tests/host_mgr_unittest.cc b/src/lib/dhcpsrv/tests/host_mgr_unittest.cc
index 014a1b8b18..564f863407 100644
--- a/src/lib/dhcpsrv/tests/host_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/host_mgr_unittest.cc
@@ -11,7 +11,7 @@
#include <dhcpsrv/host.h>
#include <dhcpsrv/host_data_source_factory.h>
#include <dhcpsrv/host_mgr.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <testutils/multi_threading_utils.h>
#include <util/multi_threading_mgr.h>
diff --git a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
index a430c789c0..01dadd931a 100644
--- a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
@@ -9,7 +9,7 @@
#include <asiolink/io_address.h>
#include <dhcpsrv/lease_mgr.h>
#include <dhcpsrv/memfile_lease_mgr.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <gtest/gtest.h>
diff --git a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
index 25d4a5541b..937f8a3b4e 100644
--- a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
@@ -16,7 +16,7 @@
#include <dhcpsrv/memfile_lease_mgr.h>
#include <dhcpsrv/timer_mgr.h>
#include <dhcpsrv/testutils/lease_file_io.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <util/multi_threading_mgr.h>
#include <util/pid_file.h>
diff --git a/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc
index c28417e708..677a0679bd 100644
--- a/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc
+++ b/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc
@@ -7,7 +7,7 @@
#include <config.h>
#include <asiolink/io_address.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <exceptions/exceptions.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/mysql_host_data_source.h>
diff --git a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
index 82f2185a55..d740b64430 100644
--- a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
@@ -9,7 +9,7 @@
#include <asiolink/io_address.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/mysql_lease_mgr.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <exceptions/exceptions.h>
#include <mysql/mysql_connection.h>
diff --git a/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc
index c7e5546831..6f6985037b 100644
--- a/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc
+++ b/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc
@@ -7,7 +7,7 @@
#include <config.h>
#include <asiolink/io_address.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <exceptions/exceptions.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/pgsql_host_data_source.h>
diff --git a/src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc
index f5433d01ba..393c0d36e3 100644
--- a/src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc
@@ -9,7 +9,7 @@
#include <asiolink/io_address.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/pgsql_lease_mgr.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <exceptions/exceptions.h>
#include <pgsql/pgsql_connection.h>
diff --git a/src/lib/dhcpsrv/tests/sanity_checks_unittest.cc b/src/lib/dhcpsrv/tests/sanity_checks_unittest.cc
index a7231e1baa..6831d308a2 100644
--- a/src/lib/dhcpsrv/tests/sanity_checks_unittest.cc
+++ b/src/lib/dhcpsrv/tests/sanity_checks_unittest.cc
@@ -13,7 +13,7 @@
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/sanity_checker.h>
-#include <dhcpsrv/tests/test_utils.h>
+#include <dhcpsrv/testutils/test_utils.h>
#include <util/range_utilities.h>
#include <cc/data.h>
#include <gtest/gtest.h>
diff --git a/src/lib/dhcpsrv/testutils/Makefile.am b/src/lib/dhcpsrv/testutils/Makefile.am
index 18ec74d9fa..cef0020f29 100644
--- a/src/lib/dhcpsrv/testutils/Makefile.am
+++ b/src/lib/dhcpsrv/testutils/Makefile.am
@@ -16,6 +16,7 @@ libdhcpsrvtest_la_SOURCES = config_result_check.cc config_result_check.h
libdhcpsrvtest_la_SOURCES += dhcp4o6_test_ipc.cc dhcp4o6_test_ipc.h
libdhcpsrvtest_la_SOURCES += host_data_source_utils.cc host_data_source_utils.h
libdhcpsrvtest_la_SOURCES += memory_host_data_source.cc memory_host_data_source.h
+libdhcpsrvtest_la_SOURCES += test_utils.cc test_utils.h
libdhcpsrvtest_la_SOURCES += generic_backend_unittest.cc generic_backend_unittest.h
libdhcpsrvtest_la_SOURCES += generic_host_data_source_unittest.cc generic_host_data_source_unittest.h
libdhcpsrvtest_la_SOURCES += lease_file_io.cc lease_file_io.h
diff --git a/src/lib/dhcpsrv/tests/test_utils.cc b/src/lib/dhcpsrv/testutils/test_utils.cc
index 4fe7d86d93..4fe7d86d93 100644
--- a/src/lib/dhcpsrv/tests/test_utils.cc
+++ b/src/lib/dhcpsrv/testutils/test_utils.cc
diff --git a/src/lib/dhcpsrv/tests/test_utils.h b/src/lib/dhcpsrv/testutils/test_utils.h
index 02af9ba467..02af9ba467 100644
--- a/src/lib/dhcpsrv/tests/test_utils.h
+++ b/src/lib/dhcpsrv/testutils/test_utils.h
diff --git a/src/lib/process/config_ctl_info.cc b/src/lib/process/config_ctl_info.cc
index 33edb91c50..7e38994479 100644
--- a/src/lib/process/config_ctl_info.cc
+++ b/src/lib/process/config_ctl_info.cc
@@ -14,10 +14,12 @@ namespace isc {
namespace process {
void
-ConfigDbInfo::setAccessString(const std::string& access_str) {
+ConfigDbInfo::setAccessString(const std::string& access_str, bool test_mode) {
access_str_ = access_str;
access_params_.clear();
- access_params_ = db::DatabaseConnection::parse(access_str_);
+ if (!test_mode) {
+ access_params_ = db::DatabaseConnection::parse(access_str_);
+ }
}
bool
diff --git a/src/lib/process/config_ctl_info.h b/src/lib/process/config_ctl_info.h
index 96f961641a..8440b3a9cc 100644
--- a/src/lib/process/config_ctl_info.h
+++ b/src/lib/process/config_ctl_info.h
@@ -19,34 +19,36 @@ namespace isc {
namespace process {
/// @brief Provides configuration information used during a server's
-/// configuration process
+/// configuration process.
///
class ConfigDbInfo : public isc::data::CfgToElement {
public:
/// @brief Constructor
ConfigDbInfo() {};
- /// @brief Set the access string
+ /// @brief Set the access string.
///
- /// Sest the db's access string to the given value and then parses it
+ /// Sets the db's access string to the given value and then parses it
/// into name-value pairs and storing them internally as a
/// DatabaseConnection::ParameterMap. It discards the existing content
/// of the map first. It does not validate the parameter names of values,
/// ensuring the validity of the string content is placed upon the caller.
///
- /// @param access_str string of name=value pairs seperated by spaces
- void setAccessString(const std::string& access_str);
+ /// @param access_str string of name=value pairs separated by spaces.
+ /// @param test_mode flag used in unittests only to skip parsing the access
+ /// string and storing the parameters.
+ void setAccessString(const std::string& access_str, bool test_mode = false);
/// @brief Retrieves the database access string.
///
- /// @return database access string
+ /// @return database access string.
std::string getAccessString() const {
return (access_str_);
}
/// @brief Retrieves the database access string with password redacted.
///
- /// @return database access string with password redacted
+ /// @return database access string with password redacted.
std::string redactedAccessString() const {
return(db::DatabaseConnection::redactedAccessString(access_params_));
}
@@ -58,9 +60,9 @@ public:
return (access_params_);
}
- /// @brief Fetch the value of a given parmeter
+ /// @brief Fetch the value of a given parameter.
///
- /// @param name name of the parameter value to fetch
+ /// @param name name of the parameter value to fetch.
/// @param[out] value string which will contain the value of the
/// parameter (if found).
///
@@ -69,9 +71,9 @@ public:
bool getParameterValue(const std::string& name,
std::string& value) const;
- /// @brief Unparse a configuration object
+ /// @brief Unparse a configuration object.
///
- /// @return a pointer to unparsed configuration
+ /// @return a pointer to unparsed configuration.
virtual isc::data::ElementPtr toElement() const;
/// @brief Compares two objects for equality.
@@ -100,17 +102,17 @@ public:
}
private:
- /// @brief Access string of parameters used to acces this database
+ /// @brief Access string of parameters used to access this database.
std::string access_str_;
- /// @brief Map of the access parameters and their values
+ /// @brief Map of the access parameters and their values.
db::DatabaseConnection::ParameterMap access_params_;
};
typedef std::vector<ConfigDbInfo> ConfigDbInfoList;
/// @brief Embodies configuration information used during a server's
-/// configuration process
+/// configuration process.
///
/// This is class conveys the configuration control information
/// described by the following JSON text:
@@ -178,24 +180,24 @@ public:
/// in the given access string, or if the access string is invalid.
void addConfigDatabase(const std::string& access_str);
- /// @brief Retrieves the list of databases
+ /// @brief Retrieves the list of databases.
///
/// The entries in the list are stored in the order they were
/// added to it (FIFO).
///
- /// @return a reference to a const list of databases
+ /// @return a reference to a const list of databases.
const ConfigDbInfoList& getConfigDatabases() const {
return (db_infos_);
}
- /// @brief Retrieves the datbase with the given access parameter value
+ /// @brief Retrieves the database with the given access parameter value.
///
/// @return A reference to the matching database or the not-found value
- /// available via @c EMPTY_DB()
+ /// available via @c EMPTY_DB().
const ConfigDbInfo& findConfigDb(const std::string& param_name,
const std::string& param_value);
- /// @brief Empties the contents of the class, including the database list
+ /// @brief Empties the contents of the class, including the database list.
void clear();
/// @brief Merges specified configuration into this configuration.
@@ -207,14 +209,14 @@ public:
/// configuration.
void merge(const ConfigControlInfo& other);
- /// @brief Unparse a configuration object
+ /// @brief Unparse a configuration object.
///
- /// @return a pointer to unparsed configuration
+ /// @return a pointer to unparsed configuration.
virtual isc::data::ElementPtr toElement() const;
- /// @brief Fetches the not-found value returned by database list searches
+ /// @brief Fetches the not-found value returned by database list searches.
///
- /// @return a reference to the empty ConfigDBInfo
+ /// @return a reference to the empty ConfigDBInfo.
static const ConfigDbInfo& EMPTY_DB();
/// @brief Compares two objects for equality.
@@ -229,13 +231,14 @@ private:
/// @brief Configured value of the config-fetch-wait-time.
util::Optional<uint16_t> config_fetch_wait_time_;
- /// @brief List of configuration databases
+ /// @brief List of configuration databases.
ConfigDbInfoList db_infos_;
};
-/// @brief Defines a pointer to a ConfigControlInfo
+/// @brief Defines a pointer to a ConfigControlInfo.
typedef boost::shared_ptr<ConfigControlInfo> ConfigControlInfoPtr;
-/// @brief Defines a pointer to a const ConfigControlInfo
+
+/// @brief Defines a pointer to a const ConfigControlInfo.
typedef boost::shared_ptr<const ConfigControlInfo> ConstConfigControlInfoPtr;
} // namespace process