#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/config_backend_dhcp4_mgr.h>
#include <dhcpsrv/db_type.h>
+#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/parsers/client_class_def_parser.h>
#include <dhcpsrv/parsers/dhcp_parsers.h>
#include <dhcpsrv/parsers/expiration_config_parser.h>
// for option definitions. This is equivalent to committing empty container.
LibDHCP::setRuntimeOptionDefs(OptionDefSpaceContainer());
- // Print the list of known backends.
- HostDataSourceFactory::printRegistered();
-
// Answer will hold the result.
ConstElementPtr answer;
}
}
+ // Print the list of known backends.
+ LeaseMgrFactory::printRegistered();
+
+ // Print the list of known backends.
+ HostDataSourceFactory::printRegistered();
+
// Moved from the commit block to add the config backend indication.
if (status_code == CONTROL_RESULT_SUCCESS && (!check_only || extra_checks)) {
+
try {
// If there are config backends, fetch and merge into staging config
server.getCBControl()->databaseConfigFetch(srv_config,
ConstElementPtr json;
try {
json = parseJSON(config);
- } catch (const std::exception& ex){
+ } catch (const std::exception& ex) {
// Fatal failure on parsing error
FAIL() << "parsing failure:"
<< "config:" << config << std::endl
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/db_type.h>
+#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/parsers/client_class_def_parser.h>
#include <dhcpsrv/parsers/dhcp_parsers.h>
#include <dhcpsrv/parsers/duid_config_parser.h>
// for option definitions. This is equivalent to committing empty container.
LibDHCP::setRuntimeOptionDefs(OptionDefSpaceContainer());
- // Print the list of known backends.
- HostDataSourceFactory::printRegistered();
-
// Answer will hold the result.
ConstElementPtr answer;
}
}
+ // Print the list of known backends.
+ LeaseMgrFactory::printRegistered();
+
+ // Print the list of known backends.
+ HostDataSourceFactory::printRegistered();
+
// Moved from the commit block to add the config backend indication.
if (status_code == CONTROL_RESULT_SUCCESS && (!check_only || extra_checks)) {
try {
// Revert to original data directory.
CfgMgr::instance().setDataDir(original_datadir_);
- // Revert to unit test logging in case the test reconfigured logging.
+ // Revert to unit test logging, in case the test reconfigured it.
isc::log::initLogger();
}
ObservationPtr stat = StatsMgr::instance().getObservation(name);
ASSERT_TRUE(stat);
- uint64_t before = stat->getInteger().first;
// Let's create a RELEASE
Pkt6Ptr rel = createMessage(DHCPV6_RELEASE, type, release_addr, prefix_len,
}
TEST_F(Lease4CmdsTest, lease4AddReleasedLeases) {
- testLease4AddDeclinedLeases();
+ testLease4AddReleasedLeases();
}
TEST_F(Lease4CmdsTest, lease4AddReleasedLeasesMultiThreading) {
MultiThreadingTest mt(true);
- testLease4AddDeclinedLeases();
+ testLease4AddReleasedLeases();
}
TEST_F(Lease4CmdsTest, lease4AddExisting) {
extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED = "DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED";
extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL = "DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL";
extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED = "DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED";
+extern const isc::log::MessageID DHCPSRV_LEASE_MGR_BACKENDS_REGISTERED = "DHCPSRV_LEASE_MGR_BACKENDS_REGISTERED";
+extern const isc::log::MessageID DHCPSRV_LEASE_MGR_BACKEND_DEREGISTER = "DHCPSRV_LEASE_MGR_BACKEND_DEREGISTER";
+extern const isc::log::MessageID DHCPSRV_LEASE_MGR_BACKEND_REGISTER = "DHCPSRV_LEASE_MGR_BACKEND_REGISTER";
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION = "DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION";
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION = "DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION";
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED = "DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED";
"DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED", "extended info for lease %1 was upgraded",
"DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL", "extended info for lease %1 failed checks (%2)",
"DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED", "extended info for lease %1 was upgraded",
+ "DHCPSRV_LEASE_MGR_BACKENDS_REGISTERED", "the following lease backend types are available: %1",
+ "DHCPSRV_LEASE_MGR_BACKEND_DEREGISTER", "deregistered lease backend type: %1",
+ "DHCPSRV_LEASE_MGR_BACKEND_REGISTER", "registered lease backend type: %1",
"DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION", "exception occurred in a lease manager callback for callback type %1, subnet id %2, and lease %3: %4",
"DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION", "unknown exception occurred in a lease manager callback for callback type %1, subnet id %2, and lease %3",
"DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED", "Failed to connect to database: %1 with error: %2",
extern const isc::log::MessageID DHCPSRV_LEASE4_EXTENDED_INFO_UPGRADED;
extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_SANITY_FAIL;
extern const isc::log::MessageID DHCPSRV_LEASE6_EXTENDED_INFO_UPGRADED;
+extern const isc::log::MessageID DHCPSRV_LEASE_MGR_BACKENDS_REGISTERED;
+extern const isc::log::MessageID DHCPSRV_LEASE_MGR_BACKEND_DEREGISTER;
+extern const isc::log::MessageID DHCPSRV_LEASE_MGR_BACKEND_REGISTER;
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_EXCEPTION;
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_CALLBACK_UNKNOWN_EXCEPTION;
extern const isc::log::MessageID DHCPSRV_LEASE_MGR_DB_OPEN_CONNECTION_WITH_RETRY_FAILED;
The database access string with password redacted is logged, along with the
error and details for the reconnect procedure.
+% DHCPSRV_LEASE_MGR_BACKENDS_REGISTERED the following lease backend types are available: %1
+This informational message lists all possible lease backends that could
+be used in lease-database.
+
+% DHCPSRV_LEASE_MGR_BACKEND_DEREGISTER deregistered lease backend type: %1
+Logged at debug log level 40.
+This debug message is issued when a backend factory was deregistered.
+It is no longer possible to use lease backend of this type.
+
+% DHCPSRV_LEASE_MGR_BACKEND_REGISTER registered lease backend type: %1
+Logged at debug log level 40.
+This debug message is issued when a backend factory was successfully
+registered. It is now possible to use lease backend of this type.
+
% DHCPSRV_LEASE_SANITY_FAIL The lease %1 with subnet-id %2 failed subnet-id checks (%3).
This warning message is printed when the lease being loaded does not match the
configuration. Due to lease-checks value, the lease will be loaded, but
namespace {
+// Code will be moved to appropriate hook library.
#ifdef HAVE_MYSQL
struct MySqlHostDataSourceInit {
// Constructor registers
MySqlHostDataSourceInit mysql_init_;
#endif
+// Code will be moved to appropriate hook library.
#ifdef HAVE_PGSQL
struct PgSqlHostDataSourceInit {
// Constructor registers
namespace isc {
namespace dhcp {
-boost::scoped_ptr<TrackingLeaseMgr>&
+map<string, LeaseMgrFactory::Factory> LeaseMgrFactory::map_;
+
+TrackingLeaseMgrPtr&
LeaseMgrFactory::getLeaseMgrPtr() {
- static boost::scoped_ptr<TrackingLeaseMgr> lease_mgr_ptr;
+ static TrackingLeaseMgrPtr lease_mgr_ptr;
return (lease_mgr_ptr);
}
DatabaseConnection::ParameterMap parameters = DatabaseConnection::parse(dbaccess);
std::string redacted = DatabaseConnection::redactedAccessString(parameters);
- // Is "type" present?
- if (parameters.find(type) == parameters.end()) {
+ // Get the database type and open the corresponding database
+ DatabaseConnection::ParameterMap::iterator it = parameters.find(type);
+ if (it == parameters.end()) {
LOG_ERROR(dhcpsrv_logger, DHCPSRV_NOTYPE_DB).arg(dbaccess);
isc_throw(InvalidParameter, "Database configuration parameters do not "
"contain the 'type' keyword");
}
- // Yes, check what it is.
- if (parameters[type] == string("mysql")) {
+ // Code will be moved to appropriate hook library.
#ifdef HAVE_MYSQL
- LOG_INFO(dhcpsrv_logger, DHCPSRV_MYSQL_DB).arg(redacted);
- getLeaseMgrPtr().reset(new MySqlLeaseMgr(parameters));
- return;
-#else
- LOG_ERROR(dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg("mysql");
- isc_throw(InvalidType, "The Kea server has not been compiled with "
- "support for database type: mysql");
+ // Factory method
+ auto mysql_factory = [](const DatabaseConnection::ParameterMap& parameters) -> TrackingLeaseMgrPtr {
+ LOG_INFO(dhcpsrv_logger, DHCPSRV_MYSQL_DB)
+ .arg(DatabaseConnection::redactedAccessString(parameters));
+ return (TrackingLeaseMgrPtr(new MySqlLeaseMgr(parameters)));
+ };
+ LeaseMgrFactory::registerFactory("mysql", mysql_factory, true);
#endif
- }
- if (parameters[type] == string("postgresql")) {
+ // Code will be moved to appropriate hook library.
#ifdef HAVE_PGSQL
- LOG_INFO(dhcpsrv_logger, DHCPSRV_PGSQL_DB).arg(redacted);
- getLeaseMgrPtr().reset(new PgSqlLeaseMgr(parameters));
- return;
-#else
- LOG_ERROR(dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg("postgresql");
- isc_throw(InvalidType, "The Kea server has not been compiled with "
- "support for database type: postgresql");
+ // Factory method
+ auto pgsql_factory = [](const DatabaseConnection::ParameterMap& parameters) -> TrackingLeaseMgrPtr {
+ LOG_INFO(dhcpsrv_logger, DHCPSRV_PGSQL_DB)
+ .arg(DatabaseConnection::redactedAccessString(parameters));
+ return (TrackingLeaseMgrPtr(new PgSqlLeaseMgr(parameters)));
+ };
+ LeaseMgrFactory::registerFactory("postgresql", pgsql_factory, true);
#endif
- }
+
if (parameters[type] == string("memfile")) {
LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_DB).arg(redacted);
getLeaseMgrPtr().reset(new Memfile_LeaseMgr(parameters));
return;
}
- // Get here on no match
- LOG_ERROR(dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg(parameters[type]);
- isc_throw(InvalidType, "Database access parameter 'type' does "
- "not specify a supported database backend: " << parameters[type]);
+ string db_type = it->second;
+ auto index = map_.find(db_type);
+
+ // No match?
+ if (index == map_.end()) {
+ if ((db_type == "mysql") ||
+ (db_type == "postgresql")) {
+ LOG_ERROR(dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg(db_type);
+ string with = (db_type == "postgresql" ? "pgsql" : db_type);
+ isc_throw(InvalidType, "The Kea server has not been compiled with "
+ "support for database type: " << db_type
+ << ". Did you forget to use --with-"
+ << with << " during compilation?");
+ }
+ // Get here on no match
+ LOG_ERROR(dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg(parameters[type]);
+ isc_throw(InvalidType, "Database access parameter 'type' does "
+ "not specify a supported database backend: " << parameters[type]);
+ }
+
+ // Call the factory.
+ getLeaseMgrPtr() = index->second(parameters);
+
+ // Check the factory did not return NULL.
+ if (!getLeaseMgrPtr()) {
+ isc_throw(Unexpected, "Lease database " << db_type <<
+ " factory returned NULL");
+ }
}
void
.arg(getLeaseMgrPtr()->getType());
}
getLeaseMgrPtr().reset();
+ // Code will be moved to appropriate hook library.
+#ifdef HAVE_MYSQL
+ LeaseMgrFactory::deregisterFactory("mysql", true);
+#endif
+ // Code will be moved to appropriate hook library.
+#ifdef HAVE_PGSQL
+ LeaseMgrFactory::deregisterFactory("postgresql", true);
+#endif
}
void
return (*lmptr);
}
+bool
+LeaseMgrFactory::registerFactory(const string& db_type,
+ const Factory& factory,
+ bool no_log) {
+ if (map_.count(db_type)) {
+ return (false);
+ }
+ map_.insert(pair<string, Factory>(db_type, factory));
+
+ // We are dealing here with static logger initialization fiasco.
+ // registerFactory may be called from constructors of static global
+ // objects for built in backends. The logging is not initialized yet,
+ // so the LOG_DEBUG would throw.
+ if (!no_log) {
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_LEASE_MGR_BACKEND_REGISTER)
+ .arg(db_type);
+ }
+ return (true);
+}
+
+bool
+LeaseMgrFactory::deregisterFactory(const string& db_type, bool no_log) {
+ auto index = map_.find(db_type);
+ if (index != map_.end()) {
+ map_.erase(index);
+ if (!no_log) {
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
+ DHCPSRV_LEASE_MGR_BACKEND_DEREGISTER)
+ .arg(db_type);
+ }
+ return (true);
+ } else {
+ return (false);
+ }
+}
+
+bool
+LeaseMgrFactory::registeredFactory(const std::string& db_type) {
+ auto index = map_.find(db_type);
+ return (index != map_.end());
+}
+
+void
+LeaseMgrFactory::printRegistered() {
+ std::stringstream txt;
+
+ for (auto const& x : map_) {
+ txt << x.first << " ";
+ }
+
+ LOG_INFO(dhcpsrv_logger, DHCPSRV_LEASE_MGR_BACKENDS_REGISTERED).arg(txt.str());
+}
+
} // namespace dhcp
} // namespace isc
/// @return True if the lease manager instance exists, false otherwise.
static bool haveInstance();
+ /// @brief Type of lease mgr factory
+ ///
+ /// A factory takes a parameter map and returns a pointer to a lease mgr.
+ /// In case of failure it must throw and not return NULL.
+ typedef std::function<TrackingLeaseMgrPtr (const db::DatabaseConnection::ParameterMap&)> Factory;
+
+ /// @brief Register a lease mgr factory
+ ///
+ /// Associate the factory to a database type in the map.
+ /// The no_log is to avoid logging before the logger is initialized
+ /// as when called at global object initialization.
+ ///
+ /// @param db_type database type
+ /// @param factory lease mgr factory
+ /// @param no_log do not log (default false)
+ /// @return true if the factory was successfully added to the map, false
+ /// if it already exists.
+ static bool registerFactory(const std::string& db_type,
+ const Factory& factory, bool no_log = false);
+
+ /// @brief Deregister a lease mgr factory
+ ///
+ /// Disassociate the factory to a database type in the map.
+ /// The no_log is to avoid logging during global object deinitialization.
+ ///
+ /// @param db_type database type
+ /// @param no_log do not log (default false)
+ /// @return true if the factory was successfully removed from the map,
+ /// false if it was not found.
+ static bool deregisterFactory(const std::string& db_type,
+ bool no_log = false);
+
+ /// @brief Check if a lease mgr factory was registered
+ ///
+ /// @param db_type database type
+ /// @return true if a factory was registered for db_type, false if not.
+ static bool registeredFactory(const std::string& db_type);
+
+ /// @brief Prints out all registered backends.
+ ///
+ /// We need a dedicated method for this, because we sometimes can't log
+ /// the backend type when doing early initialization for backends
+ /// initialized statically.
+ static void printRegistered();
+
private:
/// @brief Hold pointer to lease manager
///
/// Holds a pointer to the singleton lease manager. The singleton
/// is encapsulated in this method to avoid a "static initialization
/// fiasco" if defined in an external static variable.
- static boost::scoped_ptr<TrackingLeaseMgr>& getLeaseMgrPtr();
+ static TrackingLeaseMgrPtr& getLeaseMgrPtr();
+ /// @brief Factory map
+ static std::map<std::string, Factory> map_;
};
} // end of isc::dhcp namespace
cumulative, subnet_->getID()));
glbl_cumulative += 1;
EXPECT_TRUE(testStatistics("cumulative-assigned-nas", glbl_cumulative));
+ EXPECT_FALSE(testStatistics("cumulative-assigned-nas",
+ other_cumulative, other_subnetid, false));
EXPECT_TRUE(testStatistics("reclaimed-leases", 1));
EXPECT_TRUE(testStatistics("reclaimed-leases", 0, subnet_->getID()));
EXPECT_TRUE(testStatistics("reclaimed-leases", 1, other_subnetid));
// Add a host with two addresses.
IOAddress address1("2001:db8:1::1");
IOAddress address2("2001:db8:2::2");
- size_t host_count = 10;
SubnetID subnet_id(42);
HostPtr host = HostPtr(new Host(duids_[0]->toText(), "duid",
// Add a host with two addresses.
IOAddress address1("2001:db8:1::1");
IOAddress address2("2001:db8:2::");
- size_t host_count = 10;
SubnetID subnet_id(42);
HostPtr host = HostPtr(new Host(duids_[0]->toText(), "duid",
#include <config.h>
#include <asiolink/io_address.h>
+#include <database/database_connection.h>
#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/memfile_lease_mgr.h>
+#include <dhcpsrv/tracking_lease_mgr.h>
#include <exceptions/exceptions.h>
#include <gtest/gtest.h>
#include <sstream>
using namespace std;
+using namespace isc;
+using namespace isc::db;
using namespace isc::dhcp;
// This set of tests only check the parsing functions of LeaseMgrFactory.
namespace {
-}; // end of anonymous namespace
+TrackingLeaseMgrPtr
+memFactory(const DatabaseConnection::ParameterMap& parameters) {
+ return (TrackingLeaseMgrPtr(new Memfile_LeaseMgr(parameters)));
+}
+
+// @brief Register memFactory
+bool registerFactory() {
+ return (LeaseMgrFactory::registerFactory("mem", memFactory));
+}
+
+// @brief Derive mem1 class
+class Mem1LeaseMgr : public Memfile_LeaseMgr {
+public:
+ Mem1LeaseMgr(const DatabaseConnection::ParameterMap& parameters) :
+ Memfile_LeaseMgr(parameters) {
+ }
+ virtual ~Mem1LeaseMgr() = default;
+ virtual string getType() const {
+ return ("mem1");
+ }
+};
+
+// @brief Factory of mem1
+TrackingLeaseMgrPtr
+mem1Factory(const DatabaseConnection::ParameterMap& parameters) {
+ return (TrackingLeaseMgrPtr(new Mem1LeaseMgr(parameters)));
+}
+
+// @brief Register mem1Factory
+bool registerFactory1() {
+ return (LeaseMgrFactory::registerFactory("mem1", mem1Factory));
+}
+
+// @brief Derive mem2 class
+class Mem2LeaseMgr : public Memfile_LeaseMgr {
+public:
+ Mem2LeaseMgr(const DatabaseConnection::ParameterMap& parameters) :
+ Memfile_LeaseMgr(parameters) {
+ }
+ virtual ~Mem2LeaseMgr() = default;
+ virtual string getType() const {
+ return ("mem2");
+ }
+};
+
+// @brief Factory of mem2
+TrackingLeaseMgrPtr
+mem2Factory(const DatabaseConnection::ParameterMap& parameters) {
+ return (TrackingLeaseMgrPtr(new Mem2LeaseMgr(parameters)));
+}
+
+// @brief Register mem2Factory
+bool registerFactory2() {
+ return (LeaseMgrFactory::registerFactory("mem2", mem2Factory));
+}
+
+// @brief Factory function returning 0
+TrackingLeaseMgrPtr
+factory0(const DatabaseConnection::ParameterMap&) {
+ return (TrackingLeaseMgrPtr());
+}
+
+// @brief Test fixture class
+class LeaseMgrFactoryTest : public ::testing::Test {
+public:
+ /// @brief Constructor
+ LeaseMgrFactoryTest() = default;
+
+ /// @brief Destructor
+ virtual ~LeaseMgrFactoryTest() = default;
+
+private:
+ // @brief Prepares the class for a test.
+ virtual void SetUp() {
+ LeaseMgrFactory::destroy();
+ }
+
+ // @brief Cleans up after the test.
+ virtual void TearDown() {
+ LeaseMgrFactory::destroy();
+ LeaseMgrFactory::deregisterFactory("mem");
+ LeaseMgrFactory::deregisterFactory("mem1");
+ LeaseMgrFactory::deregisterFactory("mem2");
+ }
+};
+
+// Verify a factory can be registered and only once.
+TEST_F(LeaseMgrFactoryTest, registerFactory) {
+ EXPECT_TRUE(registerFactory());
+
+ // Only once
+ EXPECT_FALSE(registerFactory());
+}
+
+// Verify a factory registration can be checked.
+TEST_F(LeaseMgrFactoryTest, registeredFactory) {
+ // Not yet registered
+ EXPECT_FALSE(LeaseMgrFactory::registeredFactory("mem"));
+ EXPECT_FALSE(LeaseMgrFactory::registeredFactory("mem1"));
+
+ // Register mem
+ EXPECT_TRUE(registerFactory());
+
+ // Now mem is registered but not mem1
+ EXPECT_TRUE(LeaseMgrFactory::registeredFactory("mem"));
+ EXPECT_FALSE(LeaseMgrFactory::registeredFactory("mem1"));
+}
+
+// Verify a factory can be registered and deregistered
+TEST_F(LeaseMgrFactoryTest, deregisterFactory) {
+ // Does not exist at the beginning
+ EXPECT_FALSE(LeaseMgrFactory::deregisterFactory("mem"));
+
+ // Register and deregister
+ EXPECT_TRUE(registerFactory());
+ EXPECT_TRUE(LeaseMgrFactory::deregisterFactory("mem"));
+ EXPECT_FALSE(LeaseMgrFactory::registeredFactory("mem"));
+
+ // No longer exists
+ EXPECT_FALSE(LeaseMgrFactory::deregisterFactory("mem"));
+}
+
+// Verify a registered factory can be called
+TEST_F(LeaseMgrFactoryTest, create) {
+ EXPECT_TRUE(registerFactory());
+ EXPECT_NO_THROW(LeaseMgrFactory::create("type=mem persist=false universe=4"));
+ EXPECT_TRUE(LeaseMgrFactory::haveInstance());
+ EXPECT_EQ(LeaseMgrFactory::instance().getType(), "memfile");
+}
+
+// Verify that type is required
+TEST_F(LeaseMgrFactoryTest, notype) {
+ EXPECT_THROW(LeaseMgrFactory::create("tp=mem"),
+ InvalidParameter);
+ EXPECT_FALSE(LeaseMgrFactory::haveInstance());
+ EXPECT_THROW(LeaseMgrFactory::create("type=mem"),
+ InvalidType);
+ EXPECT_FALSE(LeaseMgrFactory::haveInstance());
+}
+
+// Verify that factory must not return NULL
+TEST_F(LeaseMgrFactoryTest, null) {
+ EXPECT_TRUE(LeaseMgrFactory::registerFactory("mem", factory0));
+ EXPECT_THROW(LeaseMgrFactory::create("type=mem"),
+ Unexpected);
+ EXPECT_FALSE(LeaseMgrFactory::haveInstance());
+}
+
+// Verify destroy class method
+TEST_F(LeaseMgrFactoryTest, destroy) {
+ // No sources at the beginning
+ EXPECT_FALSE(LeaseMgrFactory::haveInstance());
+ EXPECT_NO_THROW(LeaseMgrFactory::destroy());
+ EXPECT_FALSE(LeaseMgrFactory::haveInstance());
+
+ // Add mem
+ EXPECT_TRUE(registerFactory());
+ EXPECT_NO_THROW(LeaseMgrFactory::create("type=mem persist=false universe=6"));
+ EXPECT_TRUE(LeaseMgrFactory::haveInstance());
+
+ EXPECT_NO_THROW(LeaseMgrFactory::destroy());
+ EXPECT_FALSE(LeaseMgrFactory::haveInstance());
+}
+
+// Verify create and destroy class method on multiple backends
+TEST_F(LeaseMgrFactoryTest, multiple) {
+ // Add foo twice
+ EXPECT_TRUE(registerFactory1());
+ EXPECT_NO_THROW(LeaseMgrFactory::create("type=mem1 persist=false universe=4"));
+ EXPECT_NO_THROW(LeaseMgrFactory::create("type=mem1 persist=false universe=6"));
+ EXPECT_TRUE(LeaseMgrFactory::haveInstance());
+ EXPECT_EQ(LeaseMgrFactory::instance().getType(), "mem1");
+
+ // Add mem2 once
+ EXPECT_TRUE(registerFactory2());
+ EXPECT_NO_THROW(LeaseMgrFactory::create("type=mem2 persist=false universe=6"));
+ EXPECT_TRUE(LeaseMgrFactory::haveInstance());
+ EXPECT_EQ(LeaseMgrFactory::instance().getType(), "mem2");
+
+ // Delete them
+ EXPECT_NO_THROW(LeaseMgrFactory::destroy());
+ EXPECT_FALSE(LeaseMgrFactory::haveInstance());
+}
+
+} // end of anonymous namespace
ASSERT_NO_THROW_LOG(client_class = cbptr_->getClientClass4(ServerSelector::ALL(), class1->getName()));
ASSERT_TRUE(client_class);
+ // Verify lifetime values.
+ EXPECT_EQ(30, client_class->getValid().getMin());
+ EXPECT_EQ(60, client_class->getValid().get());
+ EXPECT_EQ(90, client_class->getValid().getMax());
+
// Validate options belonging to the class.
ASSERT_TRUE(client_class->getCfgOption());
OptionDescriptor returned_opt_boot_file_name =
ASSERT_NO_THROW_LOG(client_class = cbptr_->getClientClass4(ServerSelector::ALL(), class1->getName()));
ASSERT_TRUE(client_class);
+ // Re-check lifetime values. This ensure bindings line up.
+ EXPECT_EQ(30, client_class->getValid().getMin());
+ EXPECT_EQ(60, client_class->getValid().get());
+ EXPECT_EQ(90, client_class->getValid().getMax());
+
// Ensure that the first option definition is gone.
ASSERT_TRUE(client_class->getCfgOptionDef());
returned_def_foo = client_class->getCfgOptionDef()->get(test_option_defs_[0]->getOptionSpaceName(),
ASSERT_NO_THROW_LOG(client_class = cbptr_->getClientClass6(ServerSelector::ALL(), class1->getName()));
ASSERT_TRUE(client_class);
- // Verify lifetime values.
+ // Verify lifetime values.
EXPECT_EQ(30, client_class->getValid().getMin());
EXPECT_EQ(60, client_class->getValid().get());
EXPECT_EQ(90, client_class->getValid().getMax());
ASSERT_NO_THROW_LOG(client_class = cbptr_->getClientClass6(ServerSelector::ALL(), class1->getName()));
ASSERT_TRUE(client_class);
- // Re-check lifetime values. This ensure bindings line up.
+ // Re-check lifetime values. This ensure bindings line up.
EXPECT_EQ(30, client_class->getValid().getMin());
EXPECT_EQ(60, client_class->getValid().get());
EXPECT_EQ(90, client_class->getValid().getMax());
std::unordered_set<asiolink::IOAddress, asiolink::IOAddress::Hash> locked_leases_;
};
+/// @brief TrackingLeaseMgr pointer
+typedef boost::shared_ptr<TrackingLeaseMgr> TrackingLeaseMgrPtr;
+
} // end of namespace isc::dhcp
} // end of namespace isc