]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1375] moved unittests
authorRazvan Becheriu <razvan@isc.org>
Sat, 14 Nov 2020 17:25:13 +0000 (19:25 +0200)
committerRazvan Becheriu <razvan@isc.org>
Wed, 9 Dec 2020 17:13:19 +0000 (19:13 +0200)
src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.cc
src/lib/dhcpsrv/tests/host_mgr_unittest.cc
src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc
src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc
src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.cc
src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.h

index 17b084c74815e07164e522fa452abf022a2a3315..43c8e12748dd862d04fb8cb7c70d64851fd4f074 100644 (file)
@@ -768,4 +768,141 @@ TEST_F(CqlHostDataSourceTest, testMultipleHosts6) {
     testMultipleHosts6();
 }
 
+/// @brief Test fixture class for validating @c HostMgr using
+/// CQL as alternate host data source.
+class CQLHostMgrTest : public HostMgrTest {
+protected:
+
+    /// @brief Build CQL schema for a test.
+    virtual void SetUp();
+
+    /// @brief Rollback and drop CQL schema after the test.
+    virtual void TearDown();
+};
+
+void
+CQLHostMgrTest::SetUp() {
+    HostMgrTest::SetUp();
+
+    // Ensure we have the proper schema with no transient data.
+    db::test::createCqlSchema();
+
+    // Connect to the database
+    try {
+        HostMgr::addBackend(db::test::validCqlConnectionString());
+    } catch (...) {
+        std::cerr << "*** ERROR: unable to open database. The test\n"
+            "*** environment is broken and must be fixed before\n"
+            "*** the CQL tests will run correctly.\n"
+            "*** The reason for the problem is described in the\n"
+            "*** accompanying exception output.\n";
+        throw;
+    }
+}
+
+void
+CQLHostMgrTest::TearDown() {
+    HostMgr::instance().getHostDataSource()->rollback();
+    HostMgr::delBackend("cql");
+
+    // If data wipe enabled, delete transient data otherwise destroy the schema
+    db::test::destroyCqlSchema();
+}
+
+// This test verifies that reservations for a particular client can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(CQLHostMgrTest, getAll) {
+    testGetAll(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(CQLHostMgrTest, getAll4BySubnet) {
+    testGetAll4BySubnet(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(CQLHostMgrTest, getAll6BySubnet) {
+    testGetAll6BySubnet(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular hostname can be
+// retrieved from the configuration file and a database simultaneously.
+TEST_F(CQLHostMgrTest, getAllbyHostname) {
+    testGetAllbyHostname(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular hostname and
+// DHCPv4 subnet can be retrieved from the configuration file and a
+// database simultaneously.
+TEST_F(CQLHostMgrTest, getAllbyHostnameSubnet4) {
+    testGetAllbyHostnameSubnet4(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular hostname and
+// DHCPv6 subnet can be retrieved from the configuration file and a
+// database simultaneously.
+TEST_F(CQLHostMgrTest, getAllbyHostnameSubnet6) {
+    testGetAllbyHostnameSubnet6(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved by pages from the configuration file and a database
+// simultaneously.
+TEST_F(CQLHostMgrTest, getPage4) {
+    testGetPage4(true);
+}
+
+// This test verifies that all v4 reservations be retrieved by pages
+// from the configuration file and a database simultaneously.
+TEST_F(CQLHostMgrTest, getPage4All) {
+    testGetPage4All(true);
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved by pages from the configuration file and a database
+// simultaneously.
+TEST_F(CQLHostMgrTest, getPage6) {
+    testGetPage6(true);
+}
+
+// This test verifies that all v6 reservations be retrieved by pages
+// from the configuration file and a database simultaneously.
+TEST_F(CQLHostMgrTest, getPage6All) {
+    testGetPage6All(true);
+}
+
+// This test verifies that IPv4 reservations for a particular client can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(CQLHostMgrTest, getAll4) {
+    testGetAll4(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that the IPv4 reservation can be retrieved from a
+// database.
+TEST_F(CQLHostMgrTest, get4) {
+    testGet4(HostMgr::instance());
+}
+
+// This test verifies that the IPv6 reservation can be retrieved from a
+// database.
+TEST_F(CQLHostMgrTest, get6) {
+    testGet6(HostMgr::instance());
+}
+
+// This test verifies that the IPv6 prefix reservation can be retrieved
+// from a configuration file and a database.
+TEST_F(CQLHostMgrTest, get6ByPrefix) {
+    testGet6ByPrefix(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that it is possible to control whether the reserved
+// IP addresses are unique or non unique via the HostMgr.
+TEST_F(CQLHostMgrTest, setIPReservationsUnique) {
+    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(true));
+    // This is currently not supported for Cassandra.
+    EXPECT_FALSE(HostMgr::instance().setIPReservationsUnique(false));
+}
+
 }  // namespace
index 1d3524819c0610c997f0f0f76af8049f7f322ed3..3a58cb7aba9c4b8af1f3bd7704907c2cc05fe991 100644 (file)
@@ -3370,6 +3370,8 @@ LeaseMgrDbLostCallbackTest::testDbLostAndFailedCallback() {
     ASSERT_NO_THROW(lease = lm.getLease4(IOAddress("192.0.1.0")));
 
     access = invalidConnectString();
+    // by adding an invalid access will cause the manager factory to throw
+    // resulting in failure to recreate the manager
     CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setLeaseDbAccessString(access);
 
     // Now close the sql socket out from under backend client
@@ -3422,6 +3424,8 @@ LeaseMgrDbLostCallbackTest::testDbLostAndRecoveredAfterTimeoutCallback() {
 
     access = invalidConnectString();
     access += extra;
+    // by adding an invalid access will cause the manager factory to throw
+    // resulting in failure to recreate the manager
     CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setLeaseDbAccessString(access);
 
     // Now close the sql socket out from under backend client
@@ -3487,6 +3491,8 @@ LeaseMgrDbLostCallbackTest::testDbLostAndFailedAfterTimeoutCallback() {
 
     access = invalidConnectString();
     access += extra;
+    // by adding an invalid access will cause the manager factory to throw
+    // resulting in failure to recreate the manager
     CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setLeaseDbAccessString(access);
 
     // Now close the sql socket out from under backend client
index f030ce7cb79cd7a2ed3ff083278871738427580f..c97205c3c6102aecf1b7a7ada4268db68d1e2ed2 100644 (file)
 #include <dhcpsrv/host.h>
 #include <dhcpsrv/host_data_source_factory.h>
 #include <dhcpsrv/host_mgr.h>
-#include <dhcpsrv/testutils/test_utils.h>
-#include <testutils/multi_threading_utils.h>
-#include <util/multi_threading_mgr.h>
-
-#if defined HAVE_MYSQL
-#include <mysql/testutils/mysql_schema.h>
-#endif
-
-#if defined HAVE_PGSQL
-#include <pgsql/testutils/pgsql_schema.h>
-#endif
-
-#if defined HAVE_CQL
-#include <cql/testutils/cql_schema.h>
-#endif
+#include <dhcpsrv/testutils/generic_host_data_source_unittest.h>
 
 #include <gtest/gtest.h>
 #include <vector>
 
 using namespace isc;
 using namespace isc::db;
-using namespace isc::db::test;
 using namespace isc::dhcp;
 using namespace isc::dhcp::test;
 using namespace isc::asiolink;
-using namespace isc::test;
-namespace ph = std::placeholders;
 
 namespace {
 
-/// @brief Test fixture class for @c HostMgr class.
-class HostMgrTest : public ::testing::Test {
-protected:
-
-    /// @brief Prepares the class for a test.
-    ///
-    /// This method crates a handful of unique HW address and DUID objects
-    /// for use in unit tests. These objects are held in the @c hwaddrs_ and
-    /// @c duids_ members respectively.
-    ///
-    /// This method also resets the @c CfgMgr configuration and re-creates
-    /// the @c HostMgr object.
-    virtual void SetUp();
-
-    /// @brief Convenience method returning a pointer to the @c CfgHosts object
-    /// in the @c CfgMgr.
-    CfgHostsPtr getCfgHosts() const;
-
-    /// @brief Inserts IPv4 reservation into the host data source.
-    ///
-    /// @param data_source Reference to the data source to which the reservation
-    /// should be inserted.
-    /// @param hwaddr Pointer to the hardware address to be associated with the
-    /// reservation.
-    /// @param subnet_id IPv4 subnet id.
-    /// @param address IPv4 address to be reserved.
-    void addHost4(BaseHostDataSource& data_source,
-                  const HWAddrPtr& hwaddr,
-                  const SubnetID& subnet_id,
-                  const IOAddress& address);
-
-    /// @brief Inserts IPv6 reservation into the host data source.
-    ///
-    /// @param data_source Reference to the data source to which the reservation
-    /// should be inserted.
-    /// @param duid Pointer to the DUID to be associated with the reservation.
-    /// @param subnet_id IPv6 subnet id.
-    /// @param address IPv6 address/prefix to be reserved.
-    /// @param prefix_len Prefix length. The default value is 128 which
-    /// indicates that the reservation is for an IPv6 address rather than a
-    /// prefix.
-    void addHost6(BaseHostDataSource& data_source,
-                  const DuidPtr& duid,
-                  const SubnetID& subnet_id,
-                  const IOAddress& address,
-                  const uint8_t prefix_len = 128);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified HW address.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGetAll(BaseHostDataSource& data_source1,
-                    BaseHostDataSource& data_source2);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified DHCPv4 subnet.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGetAll4BySubnet(BaseHostDataSource& data_source1,
-                             BaseHostDataSource& data_source2);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified DHCPv6 subnet.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGetAll6BySubnet(BaseHostDataSource& data_source1,
-                             BaseHostDataSource& data_source2);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified hostname.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGetAllbyHostname(BaseHostDataSource& data_source1,
-                              BaseHostDataSource& data_source2);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified hostname and DHCPv4 subnet.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGetAllbyHostnameSubnet4(BaseHostDataSource& data_source1,
-                                     BaseHostDataSource& data_source2);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified hostname and DHCPv6 subnet.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGetAllbyHostnameSubnet6(BaseHostDataSource& data_source1,
-                                     BaseHostDataSource& data_source2);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified DHCPv4 subnet by pages.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param use_database True when the second reservation is inserted
-    /// in a database.
-    void testGetPage4(bool use_database);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified DHCPv6 subnet by pages.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param use_database True when the second reservation is inserted
-    /// in a database.
-    void testGetPage6(bool use_database);
-
-    /// @brief This test verifies that HostMgr returns all reservations
-    /// by pages.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param use_database True when the second reservation is inserted
-    /// in a database.
-    void testGetPage4All(bool use_database);
-
-    /// @brief This test verifies that HostMgr returns all reservations
-    /// by pages.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param use_database True when the second reservation is inserted
-    /// in a database.
-    void testGetPage6All(bool use_database);
-
-    /// @brief This test verifies that it is possible to retrieve IPv4
-    /// reservation for the particular host using HostMgr.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGetAll4(BaseHostDataSource& data_source1,
-                     BaseHostDataSource& data_source2);
-
-    /// @brief This test verifies that it is possible to retrieve an IPv4
-    /// reservation for the particular host using HostMgr.
-    ///
-    /// @param data_source Host data source to which reservation is inserted and
-    /// from which it will be retrieved.
-    void testGet4(BaseHostDataSource& data_source);
-
-    /// @brief This test verifies that it is possible to retrieve negative
-    /// cached reservation with and only with get4Any.
-    void testGet4Any();
-
-    /// @brief This test verifies that it is possible to retrieve an IPv6
-    /// reservation for the particular host using HostMgr.
-    ///
-    /// @param data_source Host data source to which reservation is inserted and
-    /// from which it will be retrieved.
-    void testGet6(BaseHostDataSource& data_source);
-
-    /// @brief This test verifies that it is possible to retrieve negative
-    /// cached reservation with and only with get6Any.
-    void testGet6Any();
-
-    /// @brief This test verifies that it is possible to retrieve an IPv6
-    /// prefix reservation for the particular host using HostMgr.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGet6ByPrefix(BaseHostDataSource& data_source1,
-                          BaseHostDataSource& data_source2);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified DHCPv4 subnet and IPv4 address.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGetAll4BySubnetIP(BaseHostDataSource& data_source1,
-                               BaseHostDataSource& data_source2);
-
-    /// @brief This test verifies that HostMgr returns all reservations for the
-    /// specified DHCPv6 subnet and IPv6 address.
-    ///
-    /// If reservations are added to different host data sources, it is expected
-    /// that the @c HostMgr will retrieve reservations from both of them.
-    ///
-    /// @param data_source1 Host data source to which first reservation is
-    /// inserted.
-    /// @param data_source2 Host data source to which second reservation is
-    /// inserted.
-    void testGetAll6BySubnetIP(BaseHostDataSource& data_source1,
-                               BaseHostDataSource& data_source2);
-
-
-    /// @brief HW addresses to be used by the tests.
-    std::vector<HWAddrPtr> hwaddrs_;
-    /// @brief DUIDs to be used by the tests.
-    std::vector<DuidPtr> duids_;
-};
-
-void
-// cppcheck-suppress unusedFunction
-HostMgrTest::SetUp() {
-    // Remove all configuration which may be dangling from the previous test.
-    CfgMgr::instance().clear();
-    // Recreate HostMgr instance. It drops any previous state.
-    HostMgr::create();
-    // Create HW addresses from the template.
-    const uint8_t mac_template[] = {
-        0x01, 0x02, 0x0A, 0xBB, 0x03, 0x00
-    };
-    for (uint8_t i = 0; i < 10; ++i) {
-        std::vector<uint8_t> vec(mac_template,
-                                 mac_template + sizeof(mac_template));
-        vec[vec.size() - 1] = i;
-        HWAddrPtr hwaddr(new HWAddr(vec, HTYPE_ETHER));
-        hwaddrs_.push_back(hwaddr);
-    }
-    // Create DUIDs from the template.
-    const uint8_t duid_template[] = {
-        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x00
-    };
-    for (uint8_t i = 0; i < 10; ++i) {
-        std::vector<uint8_t> vec(duid_template,
-                                 duid_template + sizeof(mac_template));
-        vec[vec.size() - 1] = i;
-        DuidPtr duid(new DUID(vec));
-        duids_.push_back(duid);
-    }
-}
-
-CfgHostsPtr
-HostMgrTest::getCfgHosts() const {
-    return (CfgMgr::instance().getStagingCfg()->getCfgHosts());
-}
-
-void
-HostMgrTest::addHost4(BaseHostDataSource& data_source,
-                      const HWAddrPtr& hwaddr,
-                      const SubnetID& subnet_id,
-                      const IOAddress& address) {
-    data_source.add(HostPtr(new Host(hwaddr->toText(false),
-                                     "hw-address", subnet_id, SUBNET_ID_UNUSED,
-                                     address)));
-}
-
-void
-HostMgrTest::addHost6(BaseHostDataSource& data_source,
-                      const DuidPtr& duid,
-                      const SubnetID& subnet_id,
-                      const IOAddress& address,
-                      const uint8_t prefix_len) {
-    HostPtr new_host(new Host(duid->toText(), "duid", SubnetID(1),
-                              subnet_id, IOAddress::IPV4_ZERO_ADDRESS()));
-    new_host->addReservation(IPv6Resrv(prefix_len == 128 ? IPv6Resrv::TYPE_NA :
-                                       IPv6Resrv::TYPE_PD,
-                                       address, prefix_len));
-    data_source.add(new_host);
-}
-
-
-void
-HostMgrTest::testGetAll(BaseHostDataSource& data_source1,
-                        BaseHostDataSource& data_source2) {
-    // Initially, no reservations should be present.
-    ConstHostCollection hosts =
-        HostMgr::instance().getAll(Host::IDENT_HWADDR,
-                                   &hwaddrs_[1]->hwaddr_[0],
-                                   hwaddrs_[1]->hwaddr_.size());
-    ASSERT_TRUE(hosts.empty());
-
-    // Add two reservations for the same HW address. They differ by the IP
-    // address reserved and the IPv4 subnet.
-    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
-    addHost4(data_source2, hwaddrs_[0], SubnetID(10), IOAddress("192.0.3.10"));
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching HW address is specified, nothing should be
-    // returned.
-    hosts = HostMgr::instance().getAll(Host::IDENT_HWADDR,
-                                       &hwaddrs_[1]->hwaddr_[0],
-                                       hwaddrs_[1]->hwaddr_.size());
-    ASSERT_TRUE(hosts.empty());
-
-    // For the correct HW address, there should be two reservations.
-    hosts = HostMgr::instance().getAll(Host::IDENT_HWADDR,
-                                       &hwaddrs_[0]->hwaddr_[0],
-                                       hwaddrs_[0]->hwaddr_.size());
-    ASSERT_EQ(2, hosts.size());
-
-    // We don't know the order in which the reservations are returned so
-    // we have to match with any of the two reservations returned.
-
-    // Look for the first reservation.
-    bool found = false;
-    for (unsigned i = 0; i < 2; ++i) {
-        if (hosts[0]->getIPv4Reservation() == IOAddress("192.0.2.5")) {
-            ASSERT_EQ(1, hosts[0]->getIPv4SubnetID());
-            found = true;
-        }
-    }
-    if (!found) {
-        ADD_FAILURE() << "Reservation for the IPv4 address 192.0.2.5"
-            " not found using getAll method";
-    }
-
-    // Look for the second reservation.
-    found = false;
-    for (unsigned i = 0; i < 2; ++i) {
-        if (hosts[1]->getIPv4Reservation() == IOAddress("192.0.3.10")) {
-            ASSERT_EQ(10, hosts[1]->getIPv4SubnetID());
-            found = true;
-        }
-    }
-    if (!found) {
-        ADD_FAILURE() << "Reservation for the IPv4 address 192.0.3.10"
-            " not found using getAll method";
-    }
-}
-
-void
-HostMgrTest::testGetAll4BySubnet(BaseHostDataSource& data_source1,
-                                 BaseHostDataSource& data_source2) {
-    // Initially, no reservations should be present.
-    ConstHostCollection hosts = HostMgr::instance().getAll4(SubnetID(1));
-    ASSERT_TRUE(hosts.empty());
-
-    // Add two reservations for the same subnet.
-    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
-    addHost4(data_source2, hwaddrs_[1], SubnetID(1), IOAddress("192.0.2.6"));
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching subnet is specified, nothing should be returned.
-    hosts = HostMgr::instance().getAll4(SubnetID(100));
-    ASSERT_TRUE(hosts.empty());
-
-    // For the correct subnet, there should be two reservations.
-    hosts = HostMgr::instance().getAll4(SubnetID(1));
-    ASSERT_EQ(2, hosts.size());
-
-    // Make sure that subnet is correct.
-    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
-    EXPECT_EQ(1, hosts[1]->getIPv4SubnetID());
-
-    // Make sure that two different hosts were returned.
-    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
-    EXPECT_EQ("192.0.2.6", hosts[1]->getIPv4Reservation().toText());
-}
-
-void
-HostMgrTest::testGetAll6BySubnet(BaseHostDataSource& data_source1,
-                                 BaseHostDataSource& data_source2) {
-    // Initially, no reservations should be present.
-    ConstHostCollection hosts = HostMgr::instance().getAll6(SubnetID(1));
-    ASSERT_TRUE(hosts.empty());
-
-    // Add two reservations for the same subnet.
-    addHost6(data_source1, duids_[0], SubnetID(1), IOAddress("2001:db8:1::5"));
-    addHost6(data_source2, duids_[1], SubnetID(1), IOAddress("2001:db8:1::6"));
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching subnet is specified, nothing should be returned.
-    hosts = HostMgr::instance().getAll6(SubnetID(100));
-    ASSERT_TRUE(hosts.empty());
-
-    // For the correct subnet, there should be two reservations.
-    hosts = HostMgr::instance().getAll6(SubnetID(1));
-    ASSERT_EQ(2, hosts.size());
-
-    // Make sure that subnet is correct.
-    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
-    EXPECT_EQ(1, hosts[1]->getIPv6SubnetID());
-
-    // Make sure that two different hosts were returned.
-    EXPECT_TRUE(hosts[0]->hasReservation(
-                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
-    EXPECT_TRUE(hosts[1]->hasReservation(
-                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
-}
-
-void
-HostMgrTest::testGetAllbyHostname(BaseHostDataSource& data_source1,
-                                  BaseHostDataSource& data_source2) {
-    // Initially, no reservations should be present.
-    ConstHostCollection hosts =
-        HostMgr::instance().getAllbyHostname("host");
-    ASSERT_TRUE(hosts.empty());
-
-    // Add two reservations with the same hostname.
-    HostPtr host1(new Host(hwaddrs_[0]->toText(false), "hw-address",
-                           SubnetID(1), SUBNET_ID_UNUSED,
-                           IOAddress("192.0.2.5")));
-    host1->setHostname("Host");
-    data_source1.add(host1);
-    HostPtr host2(new Host(hwaddrs_[1]->toText(false), "hw-address",
-                           SubnetID(10), SUBNET_ID_UNUSED,
-                           IOAddress("192.0.3.10")));
-    host2->setHostname("hosT");
-    data_source2.add(host2);
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching hostname is specified, nothing should be
-    // returned.
-    hosts = HostMgr::instance().getAllbyHostname("foobar");
-    EXPECT_TRUE(hosts.empty());
-
-    // For the correct hostname, there should be two reservations.
-    hosts = HostMgr::instance().getAllbyHostname("host");
-    ASSERT_EQ(2, hosts.size());
-
-    // Make sure that subnet is correct.
-    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
-    EXPECT_EQ(10, hosts[1]->getIPv4SubnetID());
-
-    // Make sure that hostname is correct including its case.
-    EXPECT_EQ("Host", hosts[0]->getHostname());
-    EXPECT_EQ("hosT", hosts[1]->getHostname());
-}
-
-void
-HostMgrTest::testGetAllbyHostnameSubnet4(BaseHostDataSource& data_source1,
-                                         BaseHostDataSource& data_source2) {
-    // Initially, no reservations should be present.
-    ConstHostCollection hosts =
-        HostMgr::instance().getAllbyHostname4("host", SubnetID(1));
-    ASSERT_TRUE(hosts.empty());
-
-    // Add two reservations with the same hostname.
-    HostPtr host1(new Host(hwaddrs_[0]->toText(false), "hw-address",
-                           SubnetID(1), SUBNET_ID_UNUSED,
-                           IOAddress("192.0.2.5")));
-    host1->setHostname("Host");
-    data_source1.add(host1);
-    HostPtr host2(new Host(hwaddrs_[1]->toText(false), "hw-address",
-                           SubnetID(1), SUBNET_ID_UNUSED,
-                           IOAddress("192.0.2.6")));
-    host2->setHostname("hosT");
-    data_source2.add(host2);
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching hostname is specified, nothing should be
-    // returned.
-    hosts = HostMgr::instance().getAllbyHostname4("foobar", SubnetID(1));
-    EXPECT_TRUE(hosts.empty());
-
-    // If there non-matching subnet is specified, nothing should be
-    // returned.
-    hosts = HostMgr::instance().getAllbyHostname4("host", SubnetID(10));
-    EXPECT_TRUE(hosts.empty());
-
-    // For the correct hostname, there should be two reservations.
-    hosts = HostMgr::instance().getAllbyHostname4("host", SubnetID(1));
-    ASSERT_EQ(2, hosts.size());
-
-    // Make sure that subnet is correct.
-    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
-    EXPECT_EQ(1, hosts[1]->getIPv4SubnetID());
-
-    // Make sure that two different hosts were returned.
-    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
-    EXPECT_EQ("192.0.2.6", hosts[1]->getIPv4Reservation().toText());
-
-    // Make sure that hostname is correct including its case.
-    EXPECT_EQ("Host", hosts[0]->getHostname());
-    EXPECT_EQ("hosT", hosts[1]->getHostname());
-}
-
-void
-HostMgrTest::testGetAllbyHostnameSubnet6(BaseHostDataSource& data_source1,
-                                         BaseHostDataSource& data_source2) {
-    // Initially, no reservations should be present.
-    ConstHostCollection hosts =
-        HostMgr::instance().getAllbyHostname6("host", SubnetID(1));
-    ASSERT_TRUE(hosts.empty());
-
-    // Add two reservations with the same hostname.
-    HostPtr host1(new Host(duids_[0]->toText(), "duid",
-                           SubnetID(1), SubnetID(1),
-                           IOAddress::IPV4_ZERO_ADDRESS()));
-    host1->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
-                                    IOAddress("2001:db8:1::5"), 128));
-    host1->setHostname("Host");
-    data_source1.add(host1);
-    HostPtr host2(new Host(duids_[1]->toText(), "duid",
-                           SubnetID(1), SubnetID(1),
-                           IOAddress::IPV4_ZERO_ADDRESS()));
-    host2->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
-                                    IOAddress("2001:db8:1::6"), 128));
-    host2->setHostname("hosT");
-    data_source2.add(host2);
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching hostname is specified, nothing should be
-    // returned.
-    hosts = HostMgr::instance().getAllbyHostname6("foobar", SubnetID(1));
-    EXPECT_TRUE(hosts.empty());
-
-    // If there non-matching subnet is specified, nothing should be
-    // returned.
-    hosts = HostMgr::instance().getAllbyHostname6("host", SubnetID(10));
-    EXPECT_TRUE(hosts.empty());
-
-    // For the correct hostname, there should be two reservations.
-    hosts = HostMgr::instance().getAllbyHostname6("host", SubnetID(1));
-    ASSERT_EQ(2, hosts.size());
-
-    // Make sure that subnet is correct.
-    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
-    EXPECT_EQ(1, hosts[1]->getIPv6SubnetID());
-
-    // Make sure that two different hosts were returned.
-    EXPECT_TRUE(hosts[0]->hasReservation(
-                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
-    EXPECT_TRUE(hosts[1]->hasReservation(
-                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
-
-    // Make sure that hostname is correct including its case.
-    EXPECT_EQ("Host", hosts[0]->getHostname());
-    EXPECT_EQ("hosT", hosts[1]->getHostname());
-}
-
-void
-HostMgrTest::testGetPage4(bool use_database) {
-    BaseHostDataSource& data_source1 = *getCfgHosts();
-    BaseHostDataSource& data_source2 = HostMgr::instance();
-
-    // Initially, no reservations should be present.
-    size_t idx(0);
-    HostPageSize page_size(10);
-    ConstHostCollection hosts =
-        HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
-    ASSERT_TRUE(hosts.empty());
-    if (use_database) {
-        EXPECT_EQ(2, idx);
-    } else {
-        EXPECT_EQ(1, idx);
-    }
-
-    // Add two reservations for the same subnet.
-    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
-    addHost4(use_database ? data_source2 : data_source1,
-             hwaddrs_[1], SubnetID(1), IOAddress("192.0.2.6"));
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching subnet is specified, nothing should be returned.
-    idx = 0;
-    hosts = HostMgr::instance().getPage4(SubnetID(100), idx, 0, page_size);
-    ASSERT_TRUE(hosts.empty());
-
-    // For the correct subnet, there should be two reservations.
-    idx = 0;
-    hosts = HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
-    if (use_database) {
-        ASSERT_EQ(1, hosts.size());
-    } else {
-        ASSERT_EQ(2, hosts.size());
-    }
-
-    // Make sure that returned values are correct.
-    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
-    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
-    if (!use_database) {
-        EXPECT_EQ(1, hosts[1]->getIPv4SubnetID());
-        EXPECT_EQ("192.0.2.6", hosts[1]->getIPv4Reservation().toText());
-
-        // Check it was the last page.
-        uint64_t hid = hosts[1]->getHostId();
-        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, hid, page_size);
-        ASSERT_EQ(0, hosts.size());
-        idx = 1;
-        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
-        ASSERT_EQ(0, hosts.size());
-    }
-
-    if (use_database) {
-        uint64_t hid = hosts[0]->getHostId();
-        ASSERT_NE(0, hid);
-        ASSERT_EQ(0, idx);
-        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, hid, page_size);
-        ASSERT_EQ(1, hosts.size());
-        ASSERT_NE(0, idx);
-        EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
-        EXPECT_EQ("192.0.2.6", hosts[0]->getIPv4Reservation().toText());
-
-        // Alternate way to use the database.
-        idx = 1;
-        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
-        ASSERT_EQ(1, hosts.size());
-        EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
-        EXPECT_EQ("192.0.2.6", hosts[0]->getIPv4Reservation().toText());
-
-        // Check it was the last page.
-        hid = hosts[0]->getHostId();
-        ASSERT_NE(0, hid);
-        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, hid, page_size);
-        ASSERT_EQ(0, hosts.size());
-        idx = 2;
-        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
-        ASSERT_EQ(0, hosts.size());
-    }
-}
-
-void
-HostMgrTest::testGetPage6(bool use_database) {
-    BaseHostDataSource& data_source1 = *getCfgHosts();
-    BaseHostDataSource& data_source2 = HostMgr::instance();
-
-    // Initially, no reservations should be present.
-    size_t idx(0);
-    HostPageSize page_size(10);
-    ConstHostCollection hosts =
-        HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
-    ASSERT_TRUE(hosts.empty());
-    if (use_database) {
-        EXPECT_EQ(2, idx);
-    } else {
-        EXPECT_EQ(1, idx);
-    }
-
-    // Add two reservations for the same subnet.
-    addHost6(data_source1, duids_[0], SubnetID(1), IOAddress("2001:db8:1::5"));
-    addHost6(use_database ? data_source2 : data_source1,
-             duids_[1], SubnetID(1), IOAddress("2001:db8:1::6"));
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching subnet is specified, nothing should be returned.
-    idx = 0;
-    hosts = HostMgr::instance().getPage6(SubnetID(100), idx, 0, page_size);
-    ASSERT_TRUE(hosts.empty());
-
-    // For the correct subnet, there should be two reservations.
-    idx = 0;
-    hosts = HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
-    if (use_database) {
-        ASSERT_EQ(1, hosts.size());
-    } else {
-        ASSERT_EQ(2, hosts.size());
-    }
-
-    // Make sure that returned values are correct.
-    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
-    EXPECT_TRUE(hosts[0]->hasReservation(
-                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
-    if (!use_database) {
-        EXPECT_EQ(1, hosts[1]->getIPv6SubnetID());
-        EXPECT_TRUE(hosts[1]->hasReservation(
-                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
-
-        // Check it was the last page.
-        uint64_t hid = hosts[1]->getHostId();
-        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, hid, page_size);
-        ASSERT_EQ(0, hosts.size());
-        idx = 1;
-        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
-        ASSERT_EQ(0, hosts.size());
-    }
-
-    if (use_database) {
-        uint64_t hid = hosts[0]->getHostId();
-        ASSERT_NE(0, hid);
-        ASSERT_EQ(0, idx);
-        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, hid, page_size);
-        ASSERT_EQ(1, hosts.size());
-        ASSERT_NE(0, idx);
-        EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
-        EXPECT_TRUE(hosts[0]->hasReservation(
-                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
-
-        // Alternate way to use the database.
-        idx = 1;
-        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
-        ASSERT_EQ(1, hosts.size());
-        EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
-        EXPECT_TRUE(hosts[0]->hasReservation(
-                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
-
-        // Check it was the last page.
-        hid = hosts[0]->getHostId();
-        ASSERT_NE(0, hid);
-        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, hid, page_size);
-        ASSERT_EQ(0, hosts.size());
-        idx = 2;
-        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
-        ASSERT_EQ(0, hosts.size());
-    }
-}
-
-void
-HostMgrTest::testGetPage4All(bool use_database) {
-    BaseHostDataSource& data_source1 = *getCfgHosts();
-    BaseHostDataSource& data_source2 = HostMgr::instance();
-
-    // Initially, no reservations should be present.
-    size_t idx(0);
-    HostPageSize page_size(10);
-    ConstHostCollection hosts =
-        HostMgr::instance().getPage4(idx, 0, page_size);
-    ASSERT_TRUE(hosts.empty());
-    if (use_database) {
-        EXPECT_EQ(2, idx);
-    } else {
-        EXPECT_EQ(1, idx);
-    }
-
-    // Add two reservations.
-    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
-    addHost4(use_database ? data_source2 : data_source1,
-             hwaddrs_[1], SubnetID(2), IOAddress("192.0.2.6"));
-
-    CfgMgr::instance().commit();
-
-    // There should be two reservations.
-    idx = 0;
-    hosts = HostMgr::instance().getPage4(idx, 0, page_size);
-    if (use_database) {
-        ASSERT_EQ(1, hosts.size());
-    } else {
-        ASSERT_EQ(2, hosts.size());
-    }
-
-    // Make sure that returned values are correct.
-    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
-    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
-    if (!use_database) {
-        EXPECT_EQ(2, hosts[1]->getIPv4SubnetID());
-        EXPECT_EQ("192.0.2.6", hosts[1]->getIPv4Reservation().toText());
-
-        // Check it was the last page.
-        uint64_t hid = hosts[1]->getHostId();
-        hosts = HostMgr::instance().getPage4(idx, hid, page_size);
-        ASSERT_EQ(0, hosts.size());
-        idx = 1;
-        hosts = HostMgr::instance().getPage4(idx, 0, page_size);
-        ASSERT_EQ(0, hosts.size());
-    }
-
-    if (use_database) {
-        uint64_t hid = hosts[0]->getHostId();
-        ASSERT_NE(0, hid);
-        ASSERT_EQ(0, idx);
-        hosts = HostMgr::instance().getPage4(idx, hid, page_size);
-        ASSERT_EQ(1, hosts.size());
-        ASSERT_NE(0, idx);
-        EXPECT_EQ(2, hosts[0]->getIPv4SubnetID());
-        EXPECT_EQ("192.0.2.6", hosts[0]->getIPv4Reservation().toText());
-
-        // Alternate way to use the database.
-        idx = 1;
-        hosts = HostMgr::instance().getPage4(idx, 0, page_size);
-        ASSERT_EQ(1, hosts.size());
-        EXPECT_EQ(2, hosts[0]->getIPv4SubnetID());
-        EXPECT_EQ("192.0.2.6", hosts[0]->getIPv4Reservation().toText());
-
-        // Check it was the last page.
-        hid = hosts[0]->getHostId();
-        ASSERT_NE(0, hid);
-        hosts = HostMgr::instance().getPage4(idx, hid, page_size);
-        ASSERT_EQ(0, hosts.size());
-        idx = 2;
-        hosts = HostMgr::instance().getPage4(idx, 0, page_size);
-        ASSERT_EQ(0, hosts.size());
-    }
-}
-
-void
-HostMgrTest::testGetPage6All(bool use_database) {
-    BaseHostDataSource& data_source1 = *getCfgHosts();
-    BaseHostDataSource& data_source2 = HostMgr::instance();
-
-    // Initially, no reservations should be present.
-    size_t idx(0);
-    HostPageSize page_size(10);
-    ConstHostCollection hosts =
-        HostMgr::instance().getPage6(idx, 0, page_size);
-    ASSERT_TRUE(hosts.empty());
-    if (use_database) {
-        EXPECT_EQ(2, idx);
-    } else {
-        EXPECT_EQ(1, idx);
-    }
-
-    // Add two reservations.
-    addHost6(data_source1, duids_[0], SubnetID(1), IOAddress("2001:db8:1::5"));
-    addHost6(use_database ? data_source2 : data_source1,
-             duids_[1], SubnetID(2), IOAddress("2001:db8:1::6"));
-
-    CfgMgr::instance().commit();
-
-    // There should be two reservations.
-    idx = 0;
-    hosts = HostMgr::instance().getPage6(idx, 0, page_size);
-    if (use_database) {
-        ASSERT_EQ(1, hosts.size());
-    } else {
-        ASSERT_EQ(2, hosts.size());
-    }
-
-    // Make sure that returned values are correct.
-    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
-    EXPECT_TRUE(hosts[0]->hasReservation(
-                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
-    if (!use_database) {
-        EXPECT_EQ(2, hosts[1]->getIPv6SubnetID());
-        EXPECT_TRUE(hosts[1]->hasReservation(
-                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
-
-        // Check it was the last page.
-        uint64_t hid = hosts[1]->getHostId();
-        hosts = HostMgr::instance().getPage6(idx, hid, page_size);
-        ASSERT_EQ(0, hosts.size());
-        idx = 1;
-        hosts = HostMgr::instance().getPage6(idx, 0, page_size);
-        ASSERT_EQ(0, hosts.size());
-    }
-
-    if (use_database) {
-        uint64_t hid = hosts[0]->getHostId();
-        ASSERT_NE(0, hid);
-        ASSERT_EQ(0, idx);
-        hosts = HostMgr::instance().getPage6(idx, hid, page_size);
-        ASSERT_EQ(1, hosts.size());
-        ASSERT_NE(0, idx);
-        EXPECT_EQ(2, hosts[0]->getIPv6SubnetID());
-        EXPECT_TRUE(hosts[0]->hasReservation(
-                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
-
-        // Alternate way to use the database.
-        idx = 1;
-        hosts = HostMgr::instance().getPage6(idx, 0, page_size);
-        ASSERT_EQ(1, hosts.size());
-        EXPECT_EQ(2, hosts[0]->getIPv6SubnetID());
-        EXPECT_TRUE(hosts[0]->hasReservation(
-                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
-
-        // Check it was the last page.
-        hid = hosts[0]->getHostId();
-        ASSERT_NE(0, hid);
-        hosts = HostMgr::instance().getPage6(idx, hid, page_size);
-        ASSERT_EQ(0, hosts.size());
-        idx = 2;
-        hosts = HostMgr::instance().getPage6(idx, 0, page_size);
-        ASSERT_EQ(0, hosts.size());
-    }
-}
-
-void
-HostMgrTest::testGetAll4(BaseHostDataSource& data_source1,
-                         BaseHostDataSource& data_source2) {
-    // Initially, no hosts should be present.
-    ConstHostCollection hosts =
-        HostMgr::instance().getAll4(IOAddress("192.0.2.5"));
-    ASSERT_TRUE(hosts.empty());
-
-    // Add two hosts to different data sources.
-    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
-    addHost4(data_source2, hwaddrs_[1], SubnetID(10), IOAddress("192.0.2.5"));
-
-    CfgMgr::instance().commit();
-
-    // Retrieve all hosts, This should return hosts from both sources
-    // in a single container.
-    hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5"));
-    ASSERT_EQ(2, hosts.size());
-
-    // Make sure that IPv4 address is correct.
-    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
-    EXPECT_EQ("192.0.2.5", hosts[1]->getIPv4Reservation().toText());
-
-    // Make sure that two different hosts were returned.
-    EXPECT_NE(hosts[0]->getIPv4SubnetID(), hosts[1]->getIPv4SubnetID());
-}
-
-void
-HostMgrTest::testGet4(BaseHostDataSource& data_source) {
-    // Initially, no host should be present.
-    ConstHostPtr host =
-        HostMgr::instance().get4(SubnetID(1), Host::IDENT_HWADDR,
-                                 &hwaddrs_[0]->hwaddr_[0],
-                                 hwaddrs_[0]->hwaddr_.size());
-    ASSERT_FALSE(host);
-
-    // Add new host to the database.
-    addHost4(data_source, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
-
-    CfgMgr::instance().commit();
-
-    // Retrieve the host from the database and expect that the parameters match.
-    host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_HWADDR,
-                                    &hwaddrs_[0]->hwaddr_[0],
-                                    hwaddrs_[0]->hwaddr_.size());
-    ASSERT_TRUE(host);
-    EXPECT_EQ(1, host->getIPv4SubnetID());
-    EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
-}
-
-void
-HostMgrTest::testGet4Any() {
-    // Initially, no host should be present.
-    ConstHostPtr host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
-                                                 &duids_[0]->getDuid()[0],
-                                                 duids_[0]->getDuid().size());
-    ASSERT_FALSE(host);
-    HostMgr::instance().get4Any(SubnetID(1), Host::IDENT_DUID,
-                                &duids_[0]->getDuid()[0],
-                                duids_[0]->getDuid().size());
-    ASSERT_FALSE(host);
-
-    // Add new host to the database.
-    HostPtr new_host(new Host(duids_[0]->toText(), "duid", SubnetID(1),
-                              SUBNET_ID_UNUSED, IOAddress("192.0.2.5")));
-    // Abuse of the server's configuration.
-    getCfgHosts()->add(new_host);
-
-    CfgMgr::instance().commit();
-
-    // Retrieve the host from the database and expect that the parameters match.
-    host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
-                                    &duids_[0]->getDuid()[0],
-                                    duids_[0]->getDuid().size());
-    ASSERT_TRUE(host);
-    EXPECT_EQ(1, host->getIPv4SubnetID());
-    EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
-
-    // Set the negative cache flag on the host.
-    new_host->setNegative(true);
-
-    // get4 is not supposed to get it.
-    host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
-                                    &duids_[0]->getDuid()[0],
-                                    duids_[0]->getDuid().size());
-    EXPECT_FALSE(host);
-
-    // But get4Any should.
-    host = HostMgr::instance().get4Any(SubnetID(1), Host::IDENT_DUID,
-                                       &duids_[0]->getDuid()[0],
-                                       duids_[0]->getDuid().size());
-    ASSERT_TRUE(host);
-    EXPECT_EQ(1, host->getIPv4SubnetID());
-    EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
-    EXPECT_TRUE(host->getNegative());
-
-    // To be sure. Note we use the CfgHosts source so only this
-    // get4 overload works.
-    host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
-                                    &duids_[0]->getDuid()[0],
-                                    duids_[0]->getDuid().size());
-    EXPECT_FALSE(host);
-}
-
-void
-HostMgrTest::testGet6(BaseHostDataSource& data_source) {
-    // Initially, no host should be present.
-    ConstHostPtr host =
-        HostMgr::instance().get6(SubnetID(2), Host::IDENT_DUID,
-                                 &duids_[0]->getDuid()[0],
-                                 duids_[0]->getDuid().size());
-    ASSERT_FALSE(host);
-
-    // Add new host to the database.
-    addHost6(data_source, duids_[0], SubnetID(2), IOAddress("2001:db8:1::1"));
-
-    CfgMgr::instance().commit();
-
-    // Retrieve the host from the database and expect that the parameters match.
-    host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_DUID,
-                                    &duids_[0]->getDuid()[0],
-                                    duids_[0]->getDuid().size());
-    ASSERT_TRUE(host);
-    EXPECT_EQ(2, host->getIPv6SubnetID());
-    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
-                                               IOAddress("2001:db8:1::1"))));
-}
-
-void
-HostMgrTest::testGet6Any() {
-    // Initially, no host should be present.
-    ConstHostPtr host = HostMgr::instance().get6(SubnetID(2),
-                                                 Host::IDENT_HWADDR,
-                                                 &hwaddrs_[0]->hwaddr_[0],
-                                                 hwaddrs_[0]->hwaddr_.size());
-    ASSERT_FALSE(host);
-    host = HostMgr::instance().get6Any(SubnetID(2), Host::IDENT_HWADDR,
-                                       &hwaddrs_[0]->hwaddr_[0],
-                                       hwaddrs_[0]->hwaddr_.size());
-    ASSERT_FALSE(host);
-
-    // Add new host to the database.
-    HostPtr new_host(new Host(hwaddrs_[0]->toText(false), "hw-address",
-                              SubnetID(1), SubnetID(2),
-                              IOAddress::IPV4_ZERO_ADDRESS()));
-    new_host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
-                                       IOAddress("2001:db8:1::1"), 128));
-    // Abuse of the server's configuration.
-    getCfgHosts()->add(new_host);
-
-    CfgMgr::instance().commit();
-
-    // Retrieve the host from the database and expect that the parameters match.
-    host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_HWADDR,
-                                    &hwaddrs_[0]->hwaddr_[0],
-                                    hwaddrs_[0]->hwaddr_.size());
-    ASSERT_TRUE(host);
-    EXPECT_EQ(2, host->getIPv6SubnetID());
-    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
-                                               IOAddress("2001:db8:1::1"))));
-
-    // Set the negative cache flag on the host.
-    new_host->setNegative(true);
-
-    // get6 is not supposed to get it.
-    host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_HWADDR,
-                                    &hwaddrs_[0]->hwaddr_[0],
-                                    hwaddrs_[0]->hwaddr_.size());
-    EXPECT_FALSE(host);
-
-    // But get6Any should.
-    host = HostMgr::instance().get6Any(SubnetID(2), Host::IDENT_HWADDR,
-                                       &hwaddrs_[0]->hwaddr_[0],
-                                       hwaddrs_[0]->hwaddr_.size());
-    ASSERT_TRUE(host);
-    EXPECT_EQ(2, host->getIPv6SubnetID());
-    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
-                                               IOAddress("2001:db8:1::1"))));
-    EXPECT_TRUE(host->getNegative());
-
-    // To be sure. Note we use the CfgHosts source so only this
-    // get6 overload works.
-    host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_HWADDR,
-                                    &hwaddrs_[0]->hwaddr_[0],
-                                    hwaddrs_[0]->hwaddr_.size());
-    EXPECT_FALSE(host);
-}
-
-void
-HostMgrTest::testGet6ByPrefix(BaseHostDataSource& data_source1,
-                              BaseHostDataSource& data_source2) {
-    ConstHostPtr host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 64);
-    ASSERT_FALSE(host);
-
-    // Add a host with a reservation for a prefix 2001:db8:1::/64.
-    addHost6(data_source1, duids_[0], SubnetID(2), IOAddress("2001:db8:1::"), 64);
-
-    // Add another host having a reservation for prefix 2001:db8:1:0:6::/72.
-    addHost6(data_source2, duids_[1], SubnetID(3), IOAddress("2001:db8:1:0:6::"), 72);
-
-    CfgMgr::instance().commit();
-
-    // Retrieve first reservation.
-    host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 64);
-    ASSERT_TRUE(host);
-    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
-                                               IOAddress("2001:db8:1::"), 64)));
-
-    // Make sure the first reservation is not retrieved when the prefix
-    // length is incorrect.
-    host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 72);
-    EXPECT_FALSE(host);
-
-    // Retrieve second reservation.
-    host = HostMgr::instance().get6(IOAddress("2001:db8:1:0:6::"), 72);
-    ASSERT_TRUE(host);
-    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
-                                               IOAddress("2001:db8:1:0:6::"), 72)));
-
-    // Make sure the second reservation is not retrieved when the prefix
-    // length is incorrect.
-    host = HostMgr::instance().get6(IOAddress("2001:db8:1:0:6::"), 64);
-    EXPECT_FALSE(host);
-}
-
-void
-HostMgrTest::testGetAll4BySubnetIP(BaseHostDataSource& data_source1,
-                                   BaseHostDataSource& data_source2) {
-    // Set the mode of operation with multiple reservations for the same
-    // IP address.
-    ASSERT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
-    CfgMgr::instance().getStagingCfg()->getCfgHosts()->setIPReservationsUnique(false);
-
-    // Initially, no reservations should be present.
-    ConstHostCollection hosts = HostMgr::instance().getAll4(SubnetID(1),
-                                                            IOAddress("192.0.2.5"));
-    ASSERT_TRUE(hosts.empty());
-
-    // Add two reservations for the same subnet and IP address.
-    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
-    addHost4(data_source2, hwaddrs_[1], SubnetID(1), IOAddress("192.0.2.5"));
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching subnet is specified, nothing should be returned.
-    hosts = HostMgr::instance().getAll4(SubnetID(100), IOAddress("192.0.2.5"));
-    ASSERT_TRUE(hosts.empty());
-
-    // For the correct subnet, there should be two reservations.
-    hosts = HostMgr::instance().getAll4(SubnetID(1), IOAddress("192.0.2.5"));
-    ASSERT_EQ(2, hosts.size());
-
-    // Make sure that subnet is correct.
-    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
-    EXPECT_EQ(1, hosts[1]->getIPv4SubnetID());
-
-    // Make sure that two hosts were returned with different identifiers
-    // but the same address.
-    EXPECT_NE(hosts[0]->getIdentifierAsText(), hosts[1]->getIdentifierAsText());
-    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
-    EXPECT_EQ("192.0.2.5", hosts[1]->getIPv4Reservation().toText());
-}
-
-void
-HostMgrTest::testGetAll6BySubnetIP(BaseHostDataSource& data_source1,
-                                   BaseHostDataSource& data_source2) {
-    // Set the mode of operation with multiple reservations for the same
-    // IP address.
-    ASSERT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
-    CfgMgr::instance().getStagingCfg()->getCfgHosts()->setIPReservationsUnique(false);
-
-    // Initially, no reservations should be present.
-    ConstHostCollection hosts = HostMgr::instance().getAll6(SubnetID(1),
-                                                            IOAddress("2001:db8:1::5"));
-    ASSERT_TRUE(hosts.empty());
-
-    // Add two reservations for the same subnet.
-    addHost6(data_source1, duids_[0], SubnetID(1), IOAddress("2001:db8:1::5"));
-    addHost6(data_source2, duids_[1], SubnetID(1), IOAddress("2001:db8:1::5"));
-
-    CfgMgr::instance().commit();
-
-    // If there non-matching subnet is specified, nothing should be returned.
-    hosts = HostMgr::instance().getAll6(SubnetID(100), IOAddress("2001:db8:1::5"));
-    ASSERT_TRUE(hosts.empty());
-
-    // For the correct subnet, there should be two reservations.
-    hosts = HostMgr::instance().getAll6(SubnetID(1), IOAddress("2001:db8:1::5"));
-    ASSERT_EQ(2, hosts.size());
-
-    // Make sure that subnet is correct.
-    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
-    EXPECT_EQ(1, hosts[1]->getIPv6SubnetID());
-
-    // Make sure that two hosts were returned with different identifiers
-    // but the same address.
-    EXPECT_NE(hosts[0]->getIdentifierAsText(), hosts[1]->getIdentifierAsText());
-    EXPECT_TRUE(hosts[0]->hasReservation(
-                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
-    EXPECT_TRUE(hosts[1]->hasReservation(
-                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
-}
-
 // This test verifies that HostMgr returns all reservations for the
 // specified HW address. The reservations are defined in the server's
 // configuration.
@@ -1377,1056 +161,4 @@ TEST_F(HostMgrTest, addNoDataSource) {
     EXPECT_THROW(HostMgr::instance().add(host), NoHostDataSourceManager);
 }
 
-class HostMgrDbLostCallbackTest : public ::testing::Test {
-public:
-    HostMgrDbLostCallbackTest()
-        : db_lost_callback_called_(0), db_recovered_callback_called_(0),
-          db_failed_callback_called_(0),
-          io_service_(boost::make_shared<isc::asiolink::IOService>()) {
-        db::DatabaseConnection::db_lost_callback_ = 0;
-        db::DatabaseConnection::db_recovered_callback_ = 0;
-        db::DatabaseConnection::db_failed_callback_ = 0;
-        HostMgr::setIOService(io_service_);
-        TimerMgr::instance()->setIOService(io_service_);
-        CfgMgr::instance().clear();
-    }
-
-    ~HostMgrDbLostCallbackTest() {
-        db::DatabaseConnection::db_lost_callback_ = 0;
-        db::DatabaseConnection::db_recovered_callback_ = 0;
-        db::DatabaseConnection::db_failed_callback_ = 0;
-        HostMgr::setIOService(isc::asiolink::IOServicePtr());
-        TimerMgr::instance()->unregisterTimers();
-        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 host manager to
-    /// wipe out any prior instance
-    virtual void SetUp() {
-        HostMgr::setIOService(io_service_);
-        db::DatabaseConnection::db_lost_callback_ = 0;
-        db::DatabaseConnection::db_recovered_callback_ = 0;
-        db::DatabaseConnection::db_failed_callback_ = 0;
-        // Ensure we have the proper schema with no transient data.
-        createSchema();
-        // Wipe out any pre-existing mgr
-        HostMgr::create();
-        CfgMgr::instance().clear();
-    }
-
-    /// @brief Pre-text exit clean up
-    ///
-    /// Invoked by gtest upon test exit, we destroy the schema
-    /// we created.
-    virtual void TearDown() {
-        HostMgr::setIOService(isc::asiolink::IOServicePtr());
-        db::DatabaseConnection::db_lost_callback_ = 0;
-        db::DatabaseConnection::db_recovered_callback_ = 0;
-        db::DatabaseConnection::db_failed_callback_ = 0;
-        // If data wipe enabled, delete transient data otherwise destroy the schema
-        destroySchema();
-        CfgMgr::instance().clear();
-    }
-
-    /// @brief Abstract method for destroying the back end specific shcema
-    virtual void destroySchema() = 0;
-
-    /// @brief Abstract method for creating the back end specific shcema
-    virtual void createSchema() = 0;
-
-    /// @brief Abstract method which returns the back end specific connection
-    /// string
-    virtual std::string validConnectString() = 0;
-
-    /// @brief Abstract method which returns invalid back end specific connection
-    /// string
-    virtual std::string invalidConnectString() = 0;
-
-#if defined(HAVE_MYSQL) || defined(HAVE_PGSQL)
-    /// @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 host manager's behavior if DB connection is lost
-    ///
-    /// This function creates a host manager with a back end that supports
-    /// connectivity lost callback (currently only MySQL and PostgreSQL). 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 host manager's behavior if DB connection is lost
-    ///
-    /// This function creates a host manager with a back end that supports
-    /// connectivity lost callback (currently only MySQL and PostgreSQL). 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 host manager's behavior if DB connection is lost
-    ///
-    /// This function creates a host manager with a back end that supports
-    /// connectivity lost callback (currently only MySQL and PostgreSQL). 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 after two reconnect
-    /// attempts (once failing and second triggered by timer)
-    void testDbLostAndRecoveredAfterTimeoutCallback();
-
-    /// @brief Verifies the host manager's behavior if DB connection is lost
-    ///
-    /// This function creates a host manager with a back end that supports
-    /// connectivity lost callback (currently only MySQL and PostgreSQL). 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 after two reconnect
-    /// attempts (once failing and second triggered by timer)
-    void testDbLostAndFailedAfterTimeoutCallback();
-#endif
-
-    /// @brief Callback function registered with the host 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 host 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 host 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_;
-};
-
-#if defined(HAVE_MYSQL) || defined(HAVE_PGSQL)
-
-void
-HostMgrDbLostCallbackTest::testNoCallbackOnOpenFailure() {
-    DatabaseConnection::db_lost_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
-
-    // Set the connectivity recovered callback.
-    DatabaseConnection::db_recovered_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
-
-    // Set the connectivity failed callback.
-    DatabaseConnection::db_failed_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
-
-    // Connect to the host backend.
-    ASSERT_THROW(HostMgr::addBackend(invalidConnectString()), 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
-HostMgrDbLostCallbackTest::testDbLostAndRecoveredCallback() {
-    // Set the connectivity lost callback.
-    DatabaseConnection::db_lost_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
-
-    // Set the connectivity recovered callback.
-    DatabaseConnection::db_recovered_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
-
-    // Set the connectivity failed callback.
-    DatabaseConnection::db_failed_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
-
-    std::string access = validConnectString();
-    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
-
-    // Create the HostMgr.
-    HostMgr::create();
-
-    // 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 host backend.
-    ASSERT_NO_THROW(HostMgr::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.
-    ConstHostCollection hosts;
-    ASSERT_NO_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")));
-
-    // Now close the sql socket out from under backend client
-    ASSERT_EQ(0, close(sql_socket));
-
-    // A query should fail with DbConnectionUnusable.
-    ASSERT_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")),
-                 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
-HostMgrDbLostCallbackTest::testDbLostAndFailedCallback() {
-    // Set the connectivity lost callback.
-    DatabaseConnection::db_lost_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
-
-    // Set the connectivity recovered callback.
-    DatabaseConnection::db_recovered_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
-
-    // Set the connectivity failed callback.
-    DatabaseConnection::db_failed_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
-
-    std::string access = validConnectString();
-    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
-
-    // Create the HostMgr.
-    HostMgr::create();
-
-    // 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 host backend.
-    ASSERT_NO_THROW(HostMgr::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.
-    ConstHostCollection hosts;
-    ASSERT_NO_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")));
-
-    access = invalidConnectString();
-    CfgMgr::instance().clear();
-    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access + " ");
-
-    // Now close the sql socket out from under backend client
-    ASSERT_EQ(0, close(sql_socket));
-
-    // A query should fail with DbConnectionUnusable.
-    ASSERT_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")),
-                 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
-HostMgrDbLostCallbackTest::testDbLostAndRecoveredAfterTimeoutCallback() {
-    // Set the connectivity lost callback.
-    DatabaseConnection::db_lost_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
-
-    // Set the connectivity recovered callback.
-    DatabaseConnection::db_recovered_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
-
-    // Set the connectivity failed callback.
-    DatabaseConnection::db_failed_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
-
-    std::string access = validConnectString();
-    std::string extra = " max-reconnect-tries=2 reconnect-wait-time=1";
-    access += extra;
-    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
-
-    // Create the HostMgr.
-    HostMgr::create();
-
-    // 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 host backend.
-    ASSERT_NO_THROW(HostMgr::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.
-    ConstHostCollection hosts;
-    ASSERT_NO_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")));
-
-    access = invalidConnectString();
-    access += extra;
-    CfgMgr::instance().clear();
-    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access + " ");
-
-    // Now close the sql socket out from under backend client
-    ASSERT_EQ(0, close(sql_socket));
-
-    // A query should fail with DbConnectionUnusable.
-    ASSERT_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")),
-                 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();
-    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
-
-    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
-HostMgrDbLostCallbackTest::testDbLostAndFailedAfterTimeoutCallback() {
-    // Set the connectivity lost callback.
-    DatabaseConnection::db_lost_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
-
-    // Set the connectivity recovered callback.
-    DatabaseConnection::db_recovered_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
-
-    // Set the connectivity failed callback.
-    DatabaseConnection::db_failed_callback_ =
-        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
-
-    std::string access = validConnectString();
-    std::string extra = " max-reconnect-tries=2 reconnect-wait-time=1";
-    access += extra;
-    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
-
-    // Create the HostMgr.
-    HostMgr::create();
-
-    // 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 host backend.
-    ASSERT_NO_THROW(HostMgr::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.
-    ConstHostCollection hosts;
-    ASSERT_NO_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")));
-
-    access = invalidConnectString();
-    access += extra;
-    CfgMgr::instance().clear();
-    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access + " ");
-
-    // Now close the sql socket out from under backend client
-    ASSERT_EQ(0, close(sql_socket));
-
-    // A query should fail with DbConnectionUnusable.
-    ASSERT_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")),
-                 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_);
-}
-#endif
-
-// The following tests require MySQL enabled.
-#if defined HAVE_MYSQL
-
-/// @brief Test fixture class for validating @c HostMgr using
-/// MySQL as alternate host data source.
-class MySQLHostMgrTest : public HostMgrTest {
-protected:
-
-    /// @brief Build MySQL schema for a test.
-    virtual void SetUp();
-
-    /// @brief Rollback and drop MySQL schema after the test.
-    virtual void TearDown();
-};
-
-void
-MySQLHostMgrTest::SetUp() {
-    HostMgrTest::SetUp();
-
-    // Ensure we have the proper schema with no transient data.
-    db::test::createMySQLSchema();
-
-    // Connect to the database
-    try {
-        HostMgr::addBackend(db::test::validMySQLConnectionString());
-    } catch (...) {
-        std::cerr << "*** ERROR: unable to open database. The test\n"
-            "*** environment is broken and must be fixed before\n"
-            "*** the MySQL tests will run correctly.\n"
-            "*** The reason for the problem is described in the\n"
-            "*** accompanying exception output.\n";
-        throw;
-    }
-}
-
-void
-MySQLHostMgrTest::TearDown() {
-    HostMgr::instance().getHostDataSource()->rollback();
-    HostMgr::delBackend("mysql");
-
-    // If data wipe enabled, delete transient data otherwise destroy the schema
-    db::test::destroyMySQLSchema();
-}
-
-/// @brief Test fixture class for validating @c HostMgr using
-/// MySQL as alternate host data source and MySQL connectivity loss.
-class MySQLHostMgrDbLostCallbackTest : public HostMgrDbLostCallbackTest {
-public:
-    virtual void destroySchema() {
-        // If data wipe enabled, delete transient data otherwise destroy the schema
-        db::test::destroyMySQLSchema();
-    }
-
-    virtual void createSchema() {
-        // Ensure we have the proper schema with no transient data.
-        db::test::createMySQLSchema();
-    }
-
-    virtual std::string validConnectString() {
-        return (db::test::validMySQLConnectionString());
-    }
-
-    virtual std::string invalidConnectString() {
-        return (connectionString(MYSQL_VALID_TYPE, INVALID_NAME, VALID_HOST,
-                                 VALID_USER, VALID_PASSWORD));
-    }
-};
-
-// This test verifies that reservations for a particular client can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(MySQLHostMgrTest, getAll) {
-    testGetAll(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(MySQLHostMgrTest, getAll4BySubnet) {
-    testGetAll4BySubnet(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(MySQLHostMgrTest, getAll6BySubnet) {
-    testGetAll6BySubnet(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that HostMgr returns all reservations for the specified
-// IPv4 subnet and reserved address.
-TEST_F(MySQLHostMgrTest, getAll4BySubnetIP) {
-    testGetAll4BySubnetIP(*getCfgHosts(), *getCfgHosts());
-}
-
-// This test verifies that HostMgr returns all reservations for the specified
-// IPv6 subnet and reserved address.
-TEST_F(MySQLHostMgrTest, getAll6BySubnetIP) {
-    testGetAll6BySubnetIP(*getCfgHosts(), *getCfgHosts());
-}
-
-// This test verifies that reservations for a particular hostname can be
-// retrieved from the configuration file and a database simultaneously.
-TEST_F(MySQLHostMgrTest, getAllbyHostname) {
-    testGetAllbyHostname(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular hostname and
-// DHCPv4 subnet can be retrieved from the configuration file and a
-// database simultaneously.
-TEST_F(MySQLHostMgrTest, getAllbyHostnameSubnet4) {
-    testGetAllbyHostnameSubnet4(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular hostname and
-// DHCPv6 subnet can be retrieved from the configuration file and a
-// database simultaneously.
-TEST_F(MySQLHostMgrTest, getAllbyHostnameSubnet6) {
-    testGetAllbyHostnameSubnet6(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved by pages from the configuration file and a database
-// simultaneously.
-TEST_F(MySQLHostMgrTest, getPage4) {
-    testGetPage4(true);
-}
-
-// This test verifies that all v4 reservations be retrieved by pages
-// from the configuration file and a database simultaneously.
-TEST_F(MySQLHostMgrTest, getPage4All) {
-    testGetPage4All(true);
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved by pages from the configuration file and a database
-// simultaneously.
-TEST_F(MySQLHostMgrTest, getPage6) {
-    testGetPage6(true);
-}
-
-// This test verifies that all v6 reservations be retrieved by pages
-// from the configuration file and a database simultaneously.
-TEST_F(MySQLHostMgrTest, getPage6All) {
-    testGetPage6All(true);
-}
-
-// This test verifies that IPv4 reservations for a particular client can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(MySQLHostMgrTest, getAll4) {
-    testGetAll4(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that the IPv4 reservation can be retrieved from a
-// database.
-TEST_F(MySQLHostMgrTest, get4) {
-    testGet4(HostMgr::instance());
-}
-
-// This test verifies that the IPv6 reservation can be retrieved from a
-// database.
-TEST_F(MySQLHostMgrTest, get6) {
-    testGet6(HostMgr::instance());
-}
-
-// This test verifies that the IPv6 prefix reservation can be retrieved
-// from a configuration file and a database.
-TEST_F(MySQLHostMgrTest, get6ByPrefix) {
-    testGet6ByPrefix(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that it is possible to control whether the reserved
-// IP addresses are unique or non unique via the HostMgr.
-TEST_F(MySQLHostMgrTest, setIPReservationsUnique) {
-    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(true));
-    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
-}
-
-/// @brief Verifies that db lost callback is not invoked on an open failure
-TEST_F(MySQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) {
-    MultiThreadingTest mt(false);
-    testNoCallbackOnOpenFailure();
-}
-
-/// @brief Verifies that db lost callback is not invoked on an open failure
-TEST_F(MySQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailureMultiThreading) {
-    MultiThreadingTest mt(true);
-    testNoCallbackOnOpenFailure();
-}
-
-/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
-TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredCallback) {
-    MultiThreadingTest mt(false);
-    testDbLostAndRecoveredCallback();
-}
-
-/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
-TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredCallbackMultiThreading) {
-    MultiThreadingTest mt(true);
-    testDbLostAndRecoveredCallback();
-}
-
-/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
-TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndFailedCallback) {
-    MultiThreadingTest mt(false);
-    testDbLostAndFailedCallback();
-}
-
-/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
-TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndFailedCallbackMultiThreading) {
-    MultiThreadingTest mt(true);
-    testDbLostAndFailedCallback();
-}
-
-/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
-TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallback) {
-    MultiThreadingTest mt(false);
-    testDbLostAndRecoveredAfterTimeoutCallback();
-}
-
-/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
-TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
-    MultiThreadingTest mt(true);
-    testDbLostAndRecoveredAfterTimeoutCallback();
-}
-
-/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
-TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallback) {
-    MultiThreadingTest mt(false);
-    testDbLostAndFailedAfterTimeoutCallback();
-}
-
-/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
-TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
-    MultiThreadingTest mt(true);
-    testDbLostAndFailedAfterTimeoutCallback();
-}
-
-
-#endif
-
-
-// The following tests require PostgreSQL enabled.
-#if defined HAVE_PGSQL
-
-/// @brief Test fixture class for validating @c HostMgr using
-/// PostgreSQL as alternate host data source.
-class PostgreSQLHostMgrTest : public HostMgrTest {
-protected:
-
-    /// @brief Build PostgreSQL schema for a test.
-    virtual void SetUp();
-
-    /// @brief Rollback and drop PostgreSQL schema after the test.
-    virtual void TearDown();
-};
-
-void
-PostgreSQLHostMgrTest::SetUp() {
-    HostMgrTest::SetUp();
-
-    // Ensure we have the proper schema with no transient data.
-    db::test::createPgSQLSchema();
-
-    // Connect to the database
-    try {
-        HostMgr::addBackend(db::test::validPgSQLConnectionString());
-    } catch (...) {
-        std::cerr << "*** ERROR: unable to open database. The test\n"
-            "*** environment is broken and must be fixed before\n"
-            "*** the PostgreSQL tests will run correctly.\n"
-            "*** The reason for the problem is described in the\n"
-            "*** accompanying exception output.\n";
-        throw;
-    }
-}
-
-void
-PostgreSQLHostMgrTest::TearDown() {
-    HostMgr::instance().getHostDataSource()->rollback();
-    HostMgr::delBackend("postgresql");
-    // If data wipe enabled, delete transient data otherwise destroy the schema
-    db::test::destroyPgSQLSchema();
-}
-
-/// @brief Test fixture class for validating @c HostMgr using
-/// PostgreSQL as alternate host data source and PostgreSQL connectivity loss.
-class PostgreSQLHostMgrDbLostCallbackTest : public HostMgrDbLostCallbackTest {
-public:
-    virtual void destroySchema() {
-        // If data wipe enabled, delete transient data otherwise destroy the schema
-        db::test::destroyPgSQLSchema();
-    }
-
-    virtual void createSchema() {
-        // Ensure we have the proper schema with no transient data.
-        db::test::createPgSQLSchema();
-    }
-
-    virtual std::string validConnectString() {
-        return (db::test::validPgSQLConnectionString());
-    }
-
-    virtual std::string invalidConnectString() {
-        return (connectionString(PGSQL_VALID_TYPE, INVALID_NAME, VALID_HOST,
-                                 VALID_USER, VALID_PASSWORD));
-    }
-};
-
-// This test verifies that reservations for a particular client can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getAll) {
-    testGetAll(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getAll4BySubnet) {
-    testGetAll4BySubnet(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getAll6BySubnet) {
-    testGetAll6BySubnet(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that HostMgr returns all reservations for the specified
-// IPv4 subnet and reserved address.
-TEST_F(PostgreSQLHostMgrTest, getAll4BySubnetIP) {
-    testGetAll4BySubnetIP(*getCfgHosts(), *getCfgHosts());
-}
-
-// This test verifies that HostMgr returns all reservations for the specified
-// IPv6 subnet and reserved address.
-TEST_F(PostgreSQLHostMgrTest, getAll6BySubnetIP) {
-    testGetAll6BySubnetIP(*getCfgHosts(), *getCfgHosts());
-}
-
-// This test verifies that reservations for a particular hostname can be
-// retrieved from the configuration file and a database simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getAllbyHostname) {
-    testGetAllbyHostname(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular hostname and
-// DHCPv4 subnet can be retrieved from the configuration file and a
-// database simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getAllbyHostnameSubnet4) {
-    testGetAllbyHostnameSubnet4(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular hostname and
-// DHCPv6 subnet can be retrieved from the configuration file and a
-// database simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getAllbyHostnameSubnet6) {
-    testGetAllbyHostnameSubnet6(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved by pages from the configuration file and a database
-// simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getPage4) {
-    testGetPage4(true);
-}
-
-// This test verifies that all v4 reservations be retrieved by pages
-// from the configuration file and a database simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getPage4All) {
-    testGetPage4All(true);
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved by pages from the configuration file and a database
-// simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getPage6) {
-    testGetPage6(true);
-}
-
-// This test verifies that all v6 reservations be retrieved by pages
-// from the configuration file and a database simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getPage6All) {
-    testGetPage6All(true);
-}
-
-// This test verifies that IPv4 reservations for a particular client can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(PostgreSQLHostMgrTest, getAll4) {
-    testGetAll4(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that the IPv4 reservation can be retrieved from a
-// database.
-TEST_F(PostgreSQLHostMgrTest, get4) {
-    testGet4(HostMgr::instance());
-}
-
-// This test verifies that the IPv6 reservation can be retrieved from a
-// database.
-TEST_F(PostgreSQLHostMgrTest, get6) {
-    testGet6(HostMgr::instance());
-}
-
-// This test verifies that the IPv6 prefix reservation can be retrieved
-// from a configuration file and a database.
-TEST_F(PostgreSQLHostMgrTest, get6ByPrefix) {
-    testGet6ByPrefix(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that it is possible to control whether the reserved
-// IP addresses are unique or non unique via the HostMgr.
-TEST_F(PostgreSQLHostMgrTest, setIPReservationUnique) {
-    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(true));
-    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
-}
-
-/// @brief Verifies that db lost callback is not invoked on an open failure
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) {
-    MultiThreadingTest mt(false);
-    testNoCallbackOnOpenFailure();
-}
-
-/// @brief Verifies that db lost callback is not invoked on an open failure
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailureMultiThreading) {
-    MultiThreadingTest mt(true);
-    testNoCallbackOnOpenFailure();
-}
-
-/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredCallback) {
-    MultiThreadingTest mt(false);
-    testDbLostAndRecoveredCallback();
-}
-
-/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredCallbackMultiThreading) {
-    MultiThreadingTest mt(true);
-    testDbLostAndRecoveredCallback();
-}
-
-/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testDbLostAndFailedCallback) {
-    MultiThreadingTest mt(false);
-    testDbLostAndFailedCallback();
-}
-
-/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testDbLostAndFailedCallbackMultiThreading) {
-    MultiThreadingTest mt(true);
-    testDbLostAndFailedCallback();
-}
-
-/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallback) {
-    MultiThreadingTest mt(false);
-    testDbLostAndRecoveredAfterTimeoutCallback();
-}
-
-/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
-    MultiThreadingTest mt(true);
-    testDbLostAndRecoveredAfterTimeoutCallback();
-}
-
-/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallback) {
-    MultiThreadingTest mt(false);
-    testDbLostAndFailedAfterTimeoutCallback();
-}
-
-/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
-TEST_F(PostgreSQLHostMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
-    MultiThreadingTest mt(true);
-    testDbLostAndFailedAfterTimeoutCallback();
-}
-
-
-#endif
-
-// The following tests require Cassandra enabled.
-#if defined HAVE_CQL
-
-/// @brief Test fixture class for validating @c HostMgr using
-/// CQL as alternate host data source.
-class CQLHostMgrTest : public HostMgrTest {
-protected:
-
-    /// @brief Build CQL schema for a test.
-    virtual void SetUp();
-
-    /// @brief Rollback and drop CQL schema after the test.
-    virtual void TearDown();
-};
-
-void
-CQLHostMgrTest::SetUp() {
-    HostMgrTest::SetUp();
-
-    // Ensure we have the proper schema with no transient data.
-    db::test::createCqlSchema();
-
-    // Connect to the database
-    try {
-        HostMgr::addBackend(db::test::validCqlConnectionString());
-    } catch (...) {
-        std::cerr << "*** ERROR: unable to open database. The test\n"
-            "*** environment is broken and must be fixed before\n"
-            "*** the CQL tests will run correctly.\n"
-            "*** The reason for the problem is described in the\n"
-            "*** accompanying exception output.\n";
-        throw;
-    }
-}
-
-void
-CQLHostMgrTest::TearDown() {
-    HostMgr::instance().getHostDataSource()->rollback();
-    HostMgr::delBackend("cql");
-
-    // If data wipe enabled, delete transient data otherwise destroy the schema
-    db::test::destroyCqlSchema();
-}
-
-// This test verifies that reservations for a particular client can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(CQLHostMgrTest, getAll) {
-    testGetAll(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(CQLHostMgrTest, getAll4BySubnet) {
-    testGetAll4BySubnet(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(CQLHostMgrTest, getAll6BySubnet) {
-    testGetAll6BySubnet(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular hostname can be
-// retrieved from the configuration file and a database simultaneously.
-TEST_F(CQLHostMgrTest, getAllbyHostname) {
-    testGetAllbyHostname(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular hostname and
-// DHCPv4 subnet can be retrieved from the configuration file and a
-// database simultaneously.
-TEST_F(CQLHostMgrTest, getAllbyHostnameSubnet4) {
-    testGetAllbyHostnameSubnet4(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular hostname and
-// DHCPv6 subnet can be retrieved from the configuration file and a
-// database simultaneously.
-TEST_F(CQLHostMgrTest, getAllbyHostnameSubnet6) {
-    testGetAllbyHostnameSubnet6(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved by pages from the configuration file and a database
-// simultaneously.
-TEST_F(CQLHostMgrTest, getPage4) {
-    testGetPage4(true);
-}
-
-// This test verifies that all v4 reservations be retrieved by pages
-// from the configuration file and a database simultaneously.
-TEST_F(CQLHostMgrTest, getPage4All) {
-    testGetPage4All(true);
-}
-
-// This test verifies that reservations for a particular subnet can
-// be retrieved by pages from the configuration file and a database
-// simultaneously.
-TEST_F(CQLHostMgrTest, getPage6) {
-    testGetPage6(true);
-}
-
-// This test verifies that all v6 reservations be retrieved by pages
-// from the configuration file and a database simultaneously.
-TEST_F(CQLHostMgrTest, getPage6All) {
-    testGetPage6All(true);
-}
-
-// This test verifies that IPv4 reservations for a particular client can
-// be retrieved from the configuration file and a database simultaneously.
-TEST_F(CQLHostMgrTest, getAll4) {
-    testGetAll4(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that the IPv4 reservation can be retrieved from a
-// database.
-TEST_F(CQLHostMgrTest, get4) {
-    testGet4(HostMgr::instance());
-}
-
-// This test verifies that the IPv6 reservation can be retrieved from a
-// database.
-TEST_F(CQLHostMgrTest, get6) {
-    testGet6(HostMgr::instance());
-}
-
-// This test verifies that the IPv6 prefix reservation can be retrieved
-// from a configuration file and a database.
-TEST_F(CQLHostMgrTest, get6ByPrefix) {
-    testGet6ByPrefix(*getCfgHosts(), HostMgr::instance());
-}
-
-// This test verifies that it is possible to control whether the reserved
-// IP addresses are unique or non unique via the HostMgr.
-TEST_F(CQLHostMgrTest, setIPReservationsUnique) {
-    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(true));
-    // This is currently not supported for Cassandra.
-    EXPECT_FALSE(HostMgr::instance().setIPReservationsUnique(false));
-}
-
-#endif
-
 }  // namespace
index 677a0679bd926d625820497cf4a64815d2a443a7..a0d4ea7bd1234b55c2420ff09983924803612c1f 100644 (file)
@@ -1467,4 +1467,235 @@ TEST_F(MySqlHostDataSourceTest, testMultipleHosts6MultiThreading) {
     testMultipleHosts6();
 }
 
+/// @brief Test fixture class for validating @c HostMgr using
+/// MySQL as alternate host data source.
+class MySQLHostMgrTest : public HostMgrTest {
+protected:
+
+    /// @brief Build MySQL schema for a test.
+    virtual void SetUp();
+
+    /// @brief Rollback and drop MySQL schema after the test.
+    virtual void TearDown();
+};
+
+void
+MySQLHostMgrTest::SetUp() {
+    HostMgrTest::SetUp();
+
+    // Ensure we have the proper schema with no transient data.
+    db::test::createMySQLSchema();
+
+    // Connect to the database
+    try {
+        HostMgr::addBackend(db::test::validMySQLConnectionString());
+    } catch (...) {
+        std::cerr << "*** ERROR: unable to open database. The test\n"
+            "*** environment is broken and must be fixed before\n"
+            "*** the MySQL tests will run correctly.\n"
+            "*** The reason for the problem is described in the\n"
+            "*** accompanying exception output.\n";
+        throw;
+    }
+}
+
+void
+MySQLHostMgrTest::TearDown() {
+    HostMgr::instance().getHostDataSource()->rollback();
+    HostMgr::delBackend("mysql");
+    // If data wipe enabled, delete transient data otherwise destroy the schema
+    db::test::destroyMySQLSchema();
+}
+
+/// @brief Test fixture class for validating @c HostMgr using
+/// MySQL as alternate host data source and MySQL connectivity loss.
+class MySQLHostMgrDbLostCallbackTest : public HostMgrDbLostCallbackTest {
+public:
+    virtual void destroySchema() {
+        // If data wipe enabled, delete transient data otherwise destroy the schema
+        db::test::destroyMySQLSchema();
+    }
+
+    virtual void createSchema() {
+        // Ensure we have the proper schema with no transient data.
+        db::test::createMySQLSchema();
+    }
+
+    virtual std::string validConnectString() {
+        return (db::test::validMySQLConnectionString());
+    }
+
+    virtual std::string invalidConnectString() {
+        return (connectionString(MYSQL_VALID_TYPE, INVALID_NAME, VALID_HOST,
+                                 VALID_USER, VALID_PASSWORD));
+    }
+};
+
+// This test verifies that reservations for a particular client can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(MySQLHostMgrTest, getAll) {
+    testGetAll(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(MySQLHostMgrTest, getAll4BySubnet) {
+    testGetAll4BySubnet(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(MySQLHostMgrTest, getAll6BySubnet) {
+    testGetAll6BySubnet(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that HostMgr returns all reservations for the specified
+// IPv4 subnet and reserved address.
+TEST_F(MySQLHostMgrTest, getAll4BySubnetIP) {
+    testGetAll4BySubnetIP(*getCfgHosts(), *getCfgHosts());
+}
+
+// This test verifies that HostMgr returns all reservations for the specified
+// IPv6 subnet and reserved address.
+TEST_F(MySQLHostMgrTest, getAll6BySubnetIP) {
+    testGetAll6BySubnetIP(*getCfgHosts(), *getCfgHosts());
+}
+
+// This test verifies that reservations for a particular hostname can be
+// retrieved from the configuration file and a database simultaneously.
+TEST_F(MySQLHostMgrTest, getAllbyHostname) {
+    testGetAllbyHostname(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular hostname and
+// DHCPv4 subnet can be retrieved from the configuration file and a
+// database simultaneously.
+TEST_F(MySQLHostMgrTest, getAllbyHostnameSubnet4) {
+    testGetAllbyHostnameSubnet4(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular hostname and
+// DHCPv6 subnet can be retrieved from the configuration file and a
+// database simultaneously.
+TEST_F(MySQLHostMgrTest, getAllbyHostnameSubnet6) {
+    testGetAllbyHostnameSubnet6(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved by pages from the configuration file and a database
+// simultaneously.
+TEST_F(MySQLHostMgrTest, getPage4) {
+    testGetPage4(true);
+}
+
+// This test verifies that all v4 reservations be retrieved by pages
+// from the configuration file and a database simultaneously.
+TEST_F(MySQLHostMgrTest, getPage4All) {
+    testGetPage4All(true);
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved by pages from the configuration file and a database
+// simultaneously.
+TEST_F(MySQLHostMgrTest, getPage6) {
+    testGetPage6(true);
+}
+
+// This test verifies that all v6 reservations be retrieved by pages
+// from the configuration file and a database simultaneously.
+TEST_F(MySQLHostMgrTest, getPage6All) {
+    testGetPage6All(true);
+}
+
+// This test verifies that IPv4 reservations for a particular client can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(MySQLHostMgrTest, getAll4) {
+    testGetAll4(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that the IPv4 reservation can be retrieved from a
+// database.
+TEST_F(MySQLHostMgrTest, get4) {
+    testGet4(HostMgr::instance());
+}
+
+// This test verifies that the IPv6 reservation can be retrieved from a
+// database.
+TEST_F(MySQLHostMgrTest, get6) {
+    testGet6(HostMgr::instance());
+}
+
+// This test verifies that the IPv6 prefix reservation can be retrieved
+// from a configuration file and a database.
+TEST_F(MySQLHostMgrTest, get6ByPrefix) {
+    testGet6ByPrefix(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that it is possible to control whether the reserved
+// IP addresses are unique or non unique via the HostMgr.
+TEST_F(MySQLHostMgrTest, setIPReservationsUnique) {
+    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(true));
+    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
+}
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(MySQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) {
+    MultiThreadingTest mt(false);
+    testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(MySQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailureMultiThreading) {
+    MultiThreadingTest mt(true);
+    testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredCallback) {
+    MultiThreadingTest mt(false);
+    testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredCallbackMultiThreading) {
+    MultiThreadingTest mt(true);
+    testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndFailedCallback) {
+    MultiThreadingTest mt(false);
+    testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndFailedCallbackMultiThreading) {
+    MultiThreadingTest mt(true);
+    testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallback) {
+    MultiThreadingTest mt(false);
+    testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
+    MultiThreadingTest mt(true);
+    testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallback) {
+    MultiThreadingTest mt(false);
+    testDbLostAndFailedAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySQLHostMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
+    MultiThreadingTest mt(true);
+    testDbLostAndFailedAfterTimeoutCallback();
+}
+
 }  // namespace
index 6f6985037b17f07cb7eadaf52979ca1cb0af5918..b832bcf35fb5cacc17ff5cbf88d5c7202afe079c 100644 (file)
@@ -1424,4 +1424,235 @@ TEST_F(PgSqlHostDataSourceTest, testMultipleHosts6MultiThreading) {
     testMultipleHosts6();
 }
 
+/// @brief Test fixture class for validating @c HostMgr using
+/// PostgreSQL as alternate host data source.
+class PgSQLHostMgrTest : public HostMgrTest {
+protected:
+
+    /// @brief Build PostgreSQL schema for a test.
+    virtual void SetUp();
+
+    /// @brief Rollback and drop PostgreSQL schema after the test.
+    virtual void TearDown();
+};
+
+void
+PgSQLHostMgrTest::SetUp() {
+    HostMgrTest::SetUp();
+
+    // Ensure we have the proper schema with no transient data.
+    db::test::createPgSQLSchema();
+
+    // Connect to the database
+    try {
+        HostMgr::addBackend(db::test::validPgSQLConnectionString());
+    } catch (...) {
+        std::cerr << "*** ERROR: unable to open database. The test\n"
+            "*** environment is broken and must be fixed before\n"
+            "*** the PostgreSQL tests will run correctly.\n"
+            "*** The reason for the problem is described in the\n"
+            "*** accompanying exception output.\n";
+        throw;
+    }
+}
+
+void
+PgSQLHostMgrTest::TearDown() {
+    HostMgr::instance().getHostDataSource()->rollback();
+    HostMgr::delBackend("postgresql");
+    // If data wipe enabled, delete transient data otherwise destroy the schema
+    db::test::destroyPgSQLSchema();
+}
+
+/// @brief Test fixture class for validating @c HostMgr using
+/// PostgreSQL as alternate host data source and PostgreSQL connectivity loss.
+class PgSQLHostMgrDbLostCallbackTest : public HostMgrDbLostCallbackTest {
+public:
+    virtual void destroySchema() {
+        // If data wipe enabled, delete transient data otherwise destroy the schema
+        db::test::destroyPgSQLSchema();
+    }
+
+    virtual void createSchema() {
+        // Ensure we have the proper schema with no transient data.
+        db::test::createPgSQLSchema();
+    }
+
+    virtual std::string validConnectString() {
+        return (db::test::validPgSQLConnectionString());
+    }
+
+    virtual std::string invalidConnectString() {
+        return (connectionString(PGSQL_VALID_TYPE, INVALID_NAME, VALID_HOST,
+                                 VALID_USER, VALID_PASSWORD));
+    }
+};
+
+// This test verifies that reservations for a particular client can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(PgSQLHostMgrTest, getAll) {
+    testGetAll(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(PgSQLHostMgrTest, getAll4BySubnet) {
+    testGetAll4BySubnet(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(PgSQLHostMgrTest, getAll6BySubnet) {
+    testGetAll6BySubnet(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that HostMgr returns all reservations for the specified
+// IPv4 subnet and reserved address.
+TEST_F(PgSQLHostMgrTest, getAll4BySubnetIP) {
+    testGetAll4BySubnetIP(*getCfgHosts(), *getCfgHosts());
+}
+
+// This test verifies that HostMgr returns all reservations for the specified
+// IPv6 subnet and reserved address.
+TEST_F(PgSQLHostMgrTest, getAll6BySubnetIP) {
+    testGetAll6BySubnetIP(*getCfgHosts(), *getCfgHosts());
+}
+
+// This test verifies that reservations for a particular hostname can be
+// retrieved from the configuration file and a database simultaneously.
+TEST_F(PgSQLHostMgrTest, getAllbyHostname) {
+    testGetAllbyHostname(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular hostname and
+// DHCPv4 subnet can be retrieved from the configuration file and a
+// database simultaneously.
+TEST_F(PgSQLHostMgrTest, getAllbyHostnameSubnet4) {
+    testGetAllbyHostnameSubnet4(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular hostname and
+// DHCPv6 subnet can be retrieved from the configuration file and a
+// database simultaneously.
+TEST_F(PgSQLHostMgrTest, getAllbyHostnameSubnet6) {
+    testGetAllbyHostnameSubnet6(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved by pages from the configuration file and a database
+// simultaneously.
+TEST_F(PgSQLHostMgrTest, getPage4) {
+    testGetPage4(true);
+}
+
+// This test verifies that all v4 reservations be retrieved by pages
+// from the configuration file and a database simultaneously.
+TEST_F(PgSQLHostMgrTest, getPage4All) {
+    testGetPage4All(true);
+}
+
+// This test verifies that reservations for a particular subnet can
+// be retrieved by pages from the configuration file and a database
+// simultaneously.
+TEST_F(PgSQLHostMgrTest, getPage6) {
+    testGetPage6(true);
+}
+
+// This test verifies that all v6 reservations be retrieved by pages
+// from the configuration file and a database simultaneously.
+TEST_F(PgSQLHostMgrTest, getPage6All) {
+    testGetPage6All(true);
+}
+
+// This test verifies that IPv4 reservations for a particular client can
+// be retrieved from the configuration file and a database simultaneously.
+TEST_F(PgSQLHostMgrTest, getAll4) {
+    testGetAll4(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that the IPv4 reservation can be retrieved from a
+// database.
+TEST_F(PgSQLHostMgrTest, get4) {
+    testGet4(HostMgr::instance());
+}
+
+// This test verifies that the IPv6 reservation can be retrieved from a
+// database.
+TEST_F(PgSQLHostMgrTest, get6) {
+    testGet6(HostMgr::instance());
+}
+
+// This test verifies that the IPv6 prefix reservation can be retrieved
+// from a configuration file and a database.
+TEST_F(PgSQLHostMgrTest, get6ByPrefix) {
+    testGet6ByPrefix(*getCfgHosts(), HostMgr::instance());
+}
+
+// This test verifies that it is possible to control whether the reserved
+// IP addresses are unique or non unique via the HostMgr.
+TEST_F(PgSQLHostMgrTest, setIPReservationsUnique) {
+    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(true));
+    EXPECT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
+}
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) {
+    MultiThreadingTest mt(false);
+    testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testNoCallbackOnOpenFailureMultiThreading) {
+    MultiThreadingTest mt(true);
+    testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredCallback) {
+    MultiThreadingTest mt(false);
+    testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredCallbackMultiThreading) {
+    MultiThreadingTest mt(true);
+    testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testDbLostAndFailedCallback) {
+    MultiThreadingTest mt(false);
+    testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testDbLostAndFailedCallbackMultiThreading) {
+    MultiThreadingTest mt(true);
+    testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallback) {
+    MultiThreadingTest mt(false);
+    testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
+    MultiThreadingTest mt(true);
+    testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallback) {
+    MultiThreadingTest mt(false);
+    testDbLostAndFailedAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to PostgreSQL is handled correctly.
+TEST_F(PgSQLHostMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
+    MultiThreadingTest mt(true);
+    testDbLostAndFailedAfterTimeoutCallback();
+}
+
 }  // namespace
index fd40206423606ecf421a275c359033458ae82078..8bd21b5333d4a951e1f6db8387d28b6913956bee 100644 (file)
@@ -15,8 +15,8 @@
 #include <dhcp/option_int.h>
 #include <dhcp/option_string.h>
 #include <dhcp/option_vendor.h>
-#include <dhcpsrv/host_mgr.h>
 #include <dhcpsrv/host_data_source_factory.h>
+#include <dhcpsrv/tests/test_utils.h>
 #include <dhcpsrv/testutils/generic_host_data_source_unittest.h>
 #include <dhcpsrv/testutils/host_data_source_utils.h>
 #include <database/testutils/schema.h>
@@ -38,6 +38,7 @@ using namespace isc::db;
 using namespace isc::db::test;
 using namespace isc::util;
 using namespace isc::data;
+namespace ph = std::placeholders;
 
 namespace isc {
 namespace dhcp {
@@ -2664,6 +2665,1244 @@ GenericHostDataSourceTest::testMultipleHosts6() {
     ASSERT_NO_THROW(hdsptr_->add(host2));
 }
 
+void
+HostMgrDbLostCallbackTest::testNoCallbackOnOpenFailure() {
+    isc::db::DatabaseConnection::db_lost_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+    // Set the connectivity recovered callback.
+    isc::db::DatabaseConnection::db_recovered_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+    // Set the connectivity failed callback.
+    isc::db::DatabaseConnection::db_failed_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+    // Connect to the host backend.
+    ASSERT_THROW(HostMgr::addBackend(invalidConnectString()), 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
+HostMgrDbLostCallbackTest::testDbLostAndRecoveredCallback() {
+    // Set the connectivity lost callback.
+    isc::db::DatabaseConnection::db_lost_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+    // Set the connectivity recovered callback.
+    isc::db::DatabaseConnection::db_recovered_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+    // Set the connectivity failed callback.
+    isc::db::DatabaseConnection::db_failed_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+    std::string access = validConnectString();
+    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
+
+    // Create the HostMgr.
+    HostMgr::create();
+
+    // 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 host backend.
+    ASSERT_NO_THROW(HostMgr::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.
+    ConstHostCollection hosts;
+    ASSERT_NO_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")));
+
+    // Now close the sql socket out from under backend client
+    ASSERT_EQ(0, close(sql_socket));
+
+    // A query should fail with DbConnectionUnusable.
+    ASSERT_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")),
+                 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
+HostMgrDbLostCallbackTest::testDbLostAndFailedCallback() {
+    // Set the connectivity lost callback.
+    isc::db::DatabaseConnection::db_lost_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+    // Set the connectivity recovered callback.
+    isc::db::DatabaseConnection::db_recovered_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+    // Set the connectivity failed callback.
+    isc::db::DatabaseConnection::db_failed_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+    std::string access = validConnectString();
+    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
+
+    // Create the HostMgr.
+    HostMgr::create();
+
+    // 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 host backend.
+    ASSERT_NO_THROW(HostMgr::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.
+    ConstHostCollection hosts;
+    ASSERT_NO_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")));
+
+    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
+    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access + " ");
+
+    // Now close the sql socket out from under backend client
+    ASSERT_EQ(0, close(sql_socket));
+
+    // A query should fail with DbConnectionUnusable.
+    ASSERT_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")),
+                 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
+HostMgrDbLostCallbackTest::testDbLostAndRecoveredAfterTimeoutCallback() {
+    // Set the connectivity lost callback.
+    isc::db::DatabaseConnection::db_lost_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+    // Set the connectivity recovered callback.
+    isc::db::DatabaseConnection::db_recovered_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+    // Set the connectivity failed callback.
+    isc::db::DatabaseConnection::db_failed_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+    std::string access = validConnectString();
+    std::string extra = " max-reconnect-tries=2 reconnect-wait-time=1";
+    access += extra;
+    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
+
+    // Create the HostMgr.
+    HostMgr::create();
+
+    // 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 host backend.
+    ASSERT_NO_THROW(HostMgr::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.
+    ConstHostCollection hosts;
+    ASSERT_NO_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")));
+
+    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
+    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access + " ");
+
+    // Now close the sql socket out from under backend client
+    ASSERT_EQ(0, close(sql_socket));
+
+    // A query should fail with DbConnectionUnusable.
+    ASSERT_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")),
+                 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();
+    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
+
+    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
+HostMgrDbLostCallbackTest::testDbLostAndFailedAfterTimeoutCallback() {
+    // Set the connectivity lost callback.
+    isc::db::DatabaseConnection::db_lost_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_lost_callback, this, ph::_1);
+
+    // Set the connectivity recovered callback.
+    isc::db::DatabaseConnection::db_recovered_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_recovered_callback, this, ph::_1);
+
+    // Set the connectivity failed callback.
+    isc::db::DatabaseConnection::db_failed_callback_ =
+        std::bind(&HostMgrDbLostCallbackTest::db_failed_callback, this, ph::_1);
+
+    std::string access = validConnectString();
+    std::string extra = " max-reconnect-tries=2 reconnect-wait-time=1";
+    access += extra;
+    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access);
+
+    // Create the HostMgr.
+    HostMgr::create();
+
+    // 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 host backend.
+    ASSERT_NO_THROW(HostMgr::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.
+    ConstHostCollection hosts;
+    ASSERT_NO_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")));
+
+    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
+    CfgMgr::instance().getCurrentCfg()->getCfgDbAccess()->setHostDbAccessString(access + " ");
+
+    // Now close the sql socket out from under backend client
+    ASSERT_EQ(0, close(sql_socket));
+
+    // A query should fail with DbConnectionUnusable.
+    ASSERT_THROW(hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5")),
+                 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_);
+}
+
+void
+// cppcheck-suppress unusedFunction
+HostMgrTest::SetUp() {
+    // Remove all configuration which may be dangling from the previous test.
+    CfgMgr::instance().clear();
+    // Recreate HostMgr instance. It drops any previous state.
+    HostMgr::create();
+    // Create HW addresses from the template.
+    const uint8_t mac_template[] = {
+        0x01, 0x02, 0x0A, 0xBB, 0x03, 0x00
+    };
+    for (uint8_t i = 0; i < 10; ++i) {
+        std::vector<uint8_t> vec(mac_template,
+                                 mac_template + sizeof(mac_template));
+        vec[vec.size() - 1] = i;
+        HWAddrPtr hwaddr(new HWAddr(vec, HTYPE_ETHER));
+        hwaddrs_.push_back(hwaddr);
+    }
+    // Create DUIDs from the template.
+    const uint8_t duid_template[] = {
+        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x00
+    };
+    for (uint8_t i = 0; i < 10; ++i) {
+        std::vector<uint8_t> vec(duid_template,
+                                 duid_template + sizeof(mac_template));
+        vec[vec.size() - 1] = i;
+        DuidPtr duid(new DUID(vec));
+        duids_.push_back(duid);
+    }
+}
+
+CfgHostsPtr
+HostMgrTest::getCfgHosts() const {
+    return (CfgMgr::instance().getStagingCfg()->getCfgHosts());
+}
+
+void
+HostMgrTest::addHost4(BaseHostDataSource& data_source,
+                      const HWAddrPtr& hwaddr,
+                      const SubnetID& subnet_id,
+                      const IOAddress& address) {
+    data_source.add(HostPtr(new Host(hwaddr->toText(false),
+                                     "hw-address", subnet_id, SUBNET_ID_UNUSED,
+                                     address)));
+}
+
+void
+HostMgrTest::addHost6(BaseHostDataSource& data_source,
+                      const DuidPtr& duid,
+                      const SubnetID& subnet_id,
+                      const IOAddress& address,
+                      const uint8_t prefix_len) {
+    HostPtr new_host(new Host(duid->toText(), "duid", SubnetID(1),
+                              subnet_id, IOAddress::IPV4_ZERO_ADDRESS()));
+    new_host->addReservation(IPv6Resrv(prefix_len == 128 ? IPv6Resrv::TYPE_NA :
+                                       IPv6Resrv::TYPE_PD,
+                                       address, prefix_len));
+    data_source.add(new_host);
+}
+
+
+void
+HostMgrTest::testGetAll(BaseHostDataSource& data_source1,
+                        BaseHostDataSource& data_source2) {
+    // Initially, no reservations should be present.
+    ConstHostCollection hosts =
+        HostMgr::instance().getAll(Host::IDENT_HWADDR,
+                                   &hwaddrs_[1]->hwaddr_[0],
+                                   hwaddrs_[1]->hwaddr_.size());
+    ASSERT_TRUE(hosts.empty());
+
+    // Add two reservations for the same HW address. They differ by the IP
+    // address reserved and the IPv4 subnet.
+    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
+    addHost4(data_source2, hwaddrs_[0], SubnetID(10), IOAddress("192.0.3.10"));
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching HW address is specified, nothing should be
+    // returned.
+    hosts = HostMgr::instance().getAll(Host::IDENT_HWADDR,
+                                       &hwaddrs_[1]->hwaddr_[0],
+                                       hwaddrs_[1]->hwaddr_.size());
+    ASSERT_TRUE(hosts.empty());
+
+    // For the correct HW address, there should be two reservations.
+    hosts = HostMgr::instance().getAll(Host::IDENT_HWADDR,
+                                       &hwaddrs_[0]->hwaddr_[0],
+                                       hwaddrs_[0]->hwaddr_.size());
+    ASSERT_EQ(2, hosts.size());
+
+    // We don't know the order in which the reservations are returned so
+    // we have to match with any of the two reservations returned.
+
+    // Look for the first reservation.
+    bool found = false;
+    for (unsigned i = 0; i < 2; ++i) {
+        if (hosts[0]->getIPv4Reservation() == IOAddress("192.0.2.5")) {
+            ASSERT_EQ(1, hosts[0]->getIPv4SubnetID());
+            found = true;
+        }
+    }
+    if (!found) {
+        ADD_FAILURE() << "Reservation for the IPv4 address 192.0.2.5"
+            " not found using getAll method";
+    }
+
+    // Look for the second reservation.
+    found = false;
+    for (unsigned i = 0; i < 2; ++i) {
+        if (hosts[1]->getIPv4Reservation() == IOAddress("192.0.3.10")) {
+            ASSERT_EQ(10, hosts[1]->getIPv4SubnetID());
+            found = true;
+        }
+    }
+    if (!found) {
+        ADD_FAILURE() << "Reservation for the IPv4 address 192.0.3.10"
+            " not found using getAll method";
+    }
+}
+
+void
+HostMgrTest::testGetAll4BySubnet(BaseHostDataSource& data_source1,
+                                 BaseHostDataSource& data_source2) {
+    // Initially, no reservations should be present.
+    ConstHostCollection hosts = HostMgr::instance().getAll4(SubnetID(1));
+    ASSERT_TRUE(hosts.empty());
+
+    // Add two reservations for the same subnet.
+    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
+    addHost4(data_source2, hwaddrs_[1], SubnetID(1), IOAddress("192.0.2.6"));
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching subnet is specified, nothing should be returned.
+    hosts = HostMgr::instance().getAll4(SubnetID(100));
+    ASSERT_TRUE(hosts.empty());
+
+    // For the correct subnet, there should be two reservations.
+    hosts = HostMgr::instance().getAll4(SubnetID(1));
+    ASSERT_EQ(2, hosts.size());
+
+    // Make sure that subnet is correct.
+    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
+    EXPECT_EQ(1, hosts[1]->getIPv4SubnetID());
+
+    // Make sure that two different hosts were returned.
+    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
+    EXPECT_EQ("192.0.2.6", hosts[1]->getIPv4Reservation().toText());
+}
+
+void
+HostMgrTest::testGetAll6BySubnet(BaseHostDataSource& data_source1,
+                                 BaseHostDataSource& data_source2) {
+    // Initially, no reservations should be present.
+    ConstHostCollection hosts = HostMgr::instance().getAll6(SubnetID(1));
+    ASSERT_TRUE(hosts.empty());
+
+    // Add two reservations for the same subnet.
+    addHost6(data_source1, duids_[0], SubnetID(1), IOAddress("2001:db8:1::5"));
+    addHost6(data_source2, duids_[1], SubnetID(1), IOAddress("2001:db8:1::6"));
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching subnet is specified, nothing should be returned.
+    hosts = HostMgr::instance().getAll6(SubnetID(100));
+    ASSERT_TRUE(hosts.empty());
+
+    // For the correct subnet, there should be two reservations.
+    hosts = HostMgr::instance().getAll6(SubnetID(1));
+    ASSERT_EQ(2, hosts.size());
+
+    // Make sure that subnet is correct.
+    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
+    EXPECT_EQ(1, hosts[1]->getIPv6SubnetID());
+
+    // Make sure that two different hosts were returned.
+    EXPECT_TRUE(hosts[0]->hasReservation(
+                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
+    EXPECT_TRUE(hosts[1]->hasReservation(
+                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
+}
+
+void
+HostMgrTest::testGetAllbyHostname(BaseHostDataSource& data_source1,
+                                  BaseHostDataSource& data_source2) {
+    // Initially, no reservations should be present.
+    ConstHostCollection hosts =
+        HostMgr::instance().getAllbyHostname("host");
+    ASSERT_TRUE(hosts.empty());
+
+    // Add two reservations with the same hostname.
+    HostPtr host1(new Host(hwaddrs_[0]->toText(false), "hw-address",
+                           SubnetID(1), SUBNET_ID_UNUSED,
+                           IOAddress("192.0.2.5")));
+    host1->setHostname("Host");
+    data_source1.add(host1);
+    HostPtr host2(new Host(hwaddrs_[1]->toText(false), "hw-address",
+                           SubnetID(10), SUBNET_ID_UNUSED,
+                           IOAddress("192.0.3.10")));
+    host2->setHostname("hosT");
+    data_source2.add(host2);
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching hostname is specified, nothing should be
+    // returned.
+    hosts = HostMgr::instance().getAllbyHostname("foobar");
+    EXPECT_TRUE(hosts.empty());
+
+    // For the correct hostname, there should be two reservations.
+    hosts = HostMgr::instance().getAllbyHostname("host");
+    ASSERT_EQ(2, hosts.size());
+
+    // Make sure that subnet is correct.
+    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
+    EXPECT_EQ(10, hosts[1]->getIPv4SubnetID());
+
+    // Make sure that hostname is correct including its case.
+    EXPECT_EQ("Host", hosts[0]->getHostname());
+    EXPECT_EQ("hosT", hosts[1]->getHostname());
+}
+
+void
+HostMgrTest::testGetAllbyHostnameSubnet4(BaseHostDataSource& data_source1,
+                                         BaseHostDataSource& data_source2) {
+    // Initially, no reservations should be present.
+    ConstHostCollection hosts =
+        HostMgr::instance().getAllbyHostname4("host", SubnetID(1));
+    ASSERT_TRUE(hosts.empty());
+
+    // Add two reservations with the same hostname.
+    HostPtr host1(new Host(hwaddrs_[0]->toText(false), "hw-address",
+                           SubnetID(1), SUBNET_ID_UNUSED,
+                           IOAddress("192.0.2.5")));
+    host1->setHostname("Host");
+    data_source1.add(host1);
+    HostPtr host2(new Host(hwaddrs_[1]->toText(false), "hw-address",
+                           SubnetID(1), SUBNET_ID_UNUSED,
+                           IOAddress("192.0.2.6")));
+    host2->setHostname("hosT");
+    data_source2.add(host2);
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching hostname is specified, nothing should be
+    // returned.
+    hosts = HostMgr::instance().getAllbyHostname4("foobar", SubnetID(1));
+    EXPECT_TRUE(hosts.empty());
+
+    // If there non-matching subnet is specified, nothing should be
+    // returned.
+    hosts = HostMgr::instance().getAllbyHostname4("host", SubnetID(10));
+    EXPECT_TRUE(hosts.empty());
+
+    // For the correct hostname, there should be two reservations.
+    hosts = HostMgr::instance().getAllbyHostname4("host", SubnetID(1));
+    ASSERT_EQ(2, hosts.size());
+
+    // Make sure that subnet is correct.
+    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
+    EXPECT_EQ(1, hosts[1]->getIPv4SubnetID());
+
+    // Make sure that two different hosts were returned.
+    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
+    EXPECT_EQ("192.0.2.6", hosts[1]->getIPv4Reservation().toText());
+
+    // Make sure that hostname is correct including its case.
+    EXPECT_EQ("Host", hosts[0]->getHostname());
+    EXPECT_EQ("hosT", hosts[1]->getHostname());
+}
+
+void
+HostMgrTest::testGetAllbyHostnameSubnet6(BaseHostDataSource& data_source1,
+                                         BaseHostDataSource& data_source2) {
+    // Initially, no reservations should be present.
+    ConstHostCollection hosts =
+        HostMgr::instance().getAllbyHostname6("host", SubnetID(1));
+    ASSERT_TRUE(hosts.empty());
+
+    // Add two reservations with the same hostname.
+    HostPtr host1(new Host(duids_[0]->toText(), "duid",
+                           SubnetID(1), SubnetID(1),
+                           IOAddress::IPV4_ZERO_ADDRESS()));
+    host1->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
+                                    IOAddress("2001:db8:1::5"), 128));
+    host1->setHostname("Host");
+    data_source1.add(host1);
+    HostPtr host2(new Host(duids_[1]->toText(), "duid",
+                           SubnetID(1), SubnetID(1),
+                           IOAddress::IPV4_ZERO_ADDRESS()));
+    host2->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
+                                    IOAddress("2001:db8:1::6"), 128));
+    host2->setHostname("hosT");
+    data_source2.add(host2);
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching hostname is specified, nothing should be
+    // returned.
+    hosts = HostMgr::instance().getAllbyHostname6("foobar", SubnetID(1));
+    EXPECT_TRUE(hosts.empty());
+
+    // If there non-matching subnet is specified, nothing should be
+    // returned.
+    hosts = HostMgr::instance().getAllbyHostname6("host", SubnetID(10));
+    EXPECT_TRUE(hosts.empty());
+
+    // For the correct hostname, there should be two reservations.
+    hosts = HostMgr::instance().getAllbyHostname6("host", SubnetID(1));
+    ASSERT_EQ(2, hosts.size());
+
+    // Make sure that subnet is correct.
+    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
+    EXPECT_EQ(1, hosts[1]->getIPv6SubnetID());
+
+    // Make sure that two different hosts were returned.
+    EXPECT_TRUE(hosts[0]->hasReservation(
+                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
+    EXPECT_TRUE(hosts[1]->hasReservation(
+                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
+
+    // Make sure that hostname is correct including its case.
+    EXPECT_EQ("Host", hosts[0]->getHostname());
+    EXPECT_EQ("hosT", hosts[1]->getHostname());
+}
+
+void
+HostMgrTest::testGetPage4(bool use_database) {
+    BaseHostDataSource& data_source1 = *getCfgHosts();
+    BaseHostDataSource& data_source2 = HostMgr::instance();
+
+    // Initially, no reservations should be present.
+    size_t idx(0);
+    HostPageSize page_size(10);
+    ConstHostCollection hosts =
+        HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
+    ASSERT_TRUE(hosts.empty());
+    if (use_database) {
+        EXPECT_EQ(2, idx);
+    } else {
+        EXPECT_EQ(1, idx);
+    }
+
+    // Add two reservations for the same subnet.
+    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
+    addHost4(use_database ? data_source2 : data_source1,
+             hwaddrs_[1], SubnetID(1), IOAddress("192.0.2.6"));
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching subnet is specified, nothing should be returned.
+    idx = 0;
+    hosts = HostMgr::instance().getPage4(SubnetID(100), idx, 0, page_size);
+    ASSERT_TRUE(hosts.empty());
+
+    // For the correct subnet, there should be two reservations.
+    idx = 0;
+    hosts = HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
+    if (use_database) {
+        ASSERT_EQ(1, hosts.size());
+    } else {
+        ASSERT_EQ(2, hosts.size());
+    }
+
+    // Make sure that returned values are correct.
+    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
+    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
+    if (!use_database) {
+        EXPECT_EQ(1, hosts[1]->getIPv4SubnetID());
+        EXPECT_EQ("192.0.2.6", hosts[1]->getIPv4Reservation().toText());
+
+        // Check it was the last page.
+        uint64_t hid = hosts[1]->getHostId();
+        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, hid, page_size);
+        ASSERT_EQ(0, hosts.size());
+        idx = 1;
+        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
+        ASSERT_EQ(0, hosts.size());
+    }
+
+    if (use_database) {
+        uint64_t hid = hosts[0]->getHostId();
+        ASSERT_NE(0, hid);
+        ASSERT_EQ(0, idx);
+        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, hid, page_size);
+        ASSERT_EQ(1, hosts.size());
+        ASSERT_NE(0, idx);
+        EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
+        EXPECT_EQ("192.0.2.6", hosts[0]->getIPv4Reservation().toText());
+
+        // Alternate way to use the database.
+        idx = 1;
+        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
+        ASSERT_EQ(1, hosts.size());
+        EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
+        EXPECT_EQ("192.0.2.6", hosts[0]->getIPv4Reservation().toText());
+
+        // Check it was the last page.
+        hid = hosts[0]->getHostId();
+        ASSERT_NE(0, hid);
+        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, hid, page_size);
+        ASSERT_EQ(0, hosts.size());
+        idx = 2;
+        hosts = HostMgr::instance().getPage4(SubnetID(1), idx, 0, page_size);
+        ASSERT_EQ(0, hosts.size());
+    }
+}
+
+void
+HostMgrTest::testGetPage6(bool use_database) {
+    BaseHostDataSource& data_source1 = *getCfgHosts();
+    BaseHostDataSource& data_source2 = HostMgr::instance();
+
+    // Initially, no reservations should be present.
+    size_t idx(0);
+    HostPageSize page_size(10);
+    ConstHostCollection hosts =
+        HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
+    ASSERT_TRUE(hosts.empty());
+    if (use_database) {
+        EXPECT_EQ(2, idx);
+    } else {
+        EXPECT_EQ(1, idx);
+    }
+
+    // Add two reservations for the same subnet.
+    addHost6(data_source1, duids_[0], SubnetID(1), IOAddress("2001:db8:1::5"));
+    addHost6(use_database ? data_source2 : data_source1,
+             duids_[1], SubnetID(1), IOAddress("2001:db8:1::6"));
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching subnet is specified, nothing should be returned.
+    idx = 0;
+    hosts = HostMgr::instance().getPage6(SubnetID(100), idx, 0, page_size);
+    ASSERT_TRUE(hosts.empty());
+
+    // For the correct subnet, there should be two reservations.
+    idx = 0;
+    hosts = HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
+    if (use_database) {
+        ASSERT_EQ(1, hosts.size());
+    } else {
+        ASSERT_EQ(2, hosts.size());
+    }
+
+    // Make sure that returned values are correct.
+    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
+    EXPECT_TRUE(hosts[0]->hasReservation(
+                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
+    if (!use_database) {
+        EXPECT_EQ(1, hosts[1]->getIPv6SubnetID());
+        EXPECT_TRUE(hosts[1]->hasReservation(
+                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
+
+        // Check it was the last page.
+        uint64_t hid = hosts[1]->getHostId();
+        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, hid, page_size);
+        ASSERT_EQ(0, hosts.size());
+        idx = 1;
+        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
+        ASSERT_EQ(0, hosts.size());
+    }
+
+    if (use_database) {
+        uint64_t hid = hosts[0]->getHostId();
+        ASSERT_NE(0, hid);
+        ASSERT_EQ(0, idx);
+        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, hid, page_size);
+        ASSERT_EQ(1, hosts.size());
+        ASSERT_NE(0, idx);
+        EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
+        EXPECT_TRUE(hosts[0]->hasReservation(
+                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
+
+        // Alternate way to use the database.
+        idx = 1;
+        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
+        ASSERT_EQ(1, hosts.size());
+        EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
+        EXPECT_TRUE(hosts[0]->hasReservation(
+                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
+
+        // Check it was the last page.
+        hid = hosts[0]->getHostId();
+        ASSERT_NE(0, hid);
+        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, hid, page_size);
+        ASSERT_EQ(0, hosts.size());
+        idx = 2;
+        hosts = HostMgr::instance().getPage6(SubnetID(1), idx, 0, page_size);
+        ASSERT_EQ(0, hosts.size());
+    }
+}
+
+void
+HostMgrTest::testGetPage4All(bool use_database) {
+    BaseHostDataSource& data_source1 = *getCfgHosts();
+    BaseHostDataSource& data_source2 = HostMgr::instance();
+
+    // Initially, no reservations should be present.
+    size_t idx(0);
+    HostPageSize page_size(10);
+    ConstHostCollection hosts =
+        HostMgr::instance().getPage4(idx, 0, page_size);
+    ASSERT_TRUE(hosts.empty());
+    if (use_database) {
+        EXPECT_EQ(2, idx);
+    } else {
+        EXPECT_EQ(1, idx);
+    }
+
+    // Add two reservations.
+    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
+    addHost4(use_database ? data_source2 : data_source1,
+             hwaddrs_[1], SubnetID(2), IOAddress("192.0.2.6"));
+
+    CfgMgr::instance().commit();
+
+    // There should be two reservations.
+    idx = 0;
+    hosts = HostMgr::instance().getPage4(idx, 0, page_size);
+    if (use_database) {
+        ASSERT_EQ(1, hosts.size());
+    } else {
+        ASSERT_EQ(2, hosts.size());
+    }
+
+    // Make sure that returned values are correct.
+    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
+    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
+    if (!use_database) {
+        EXPECT_EQ(2, hosts[1]->getIPv4SubnetID());
+        EXPECT_EQ("192.0.2.6", hosts[1]->getIPv4Reservation().toText());
+
+        // Check it was the last page.
+        uint64_t hid = hosts[1]->getHostId();
+        hosts = HostMgr::instance().getPage4(idx, hid, page_size);
+        ASSERT_EQ(0, hosts.size());
+        idx = 1;
+        hosts = HostMgr::instance().getPage4(idx, 0, page_size);
+        ASSERT_EQ(0, hosts.size());
+    }
+
+    if (use_database) {
+        uint64_t hid = hosts[0]->getHostId();
+        ASSERT_NE(0, hid);
+        ASSERT_EQ(0, idx);
+        hosts = HostMgr::instance().getPage4(idx, hid, page_size);
+        ASSERT_EQ(1, hosts.size());
+        ASSERT_NE(0, idx);
+        EXPECT_EQ(2, hosts[0]->getIPv4SubnetID());
+        EXPECT_EQ("192.0.2.6", hosts[0]->getIPv4Reservation().toText());
+
+        // Alternate way to use the database.
+        idx = 1;
+        hosts = HostMgr::instance().getPage4(idx, 0, page_size);
+        ASSERT_EQ(1, hosts.size());
+        EXPECT_EQ(2, hosts[0]->getIPv4SubnetID());
+        EXPECT_EQ("192.0.2.6", hosts[0]->getIPv4Reservation().toText());
+
+        // Check it was the last page.
+        hid = hosts[0]->getHostId();
+        ASSERT_NE(0, hid);
+        hosts = HostMgr::instance().getPage4(idx, hid, page_size);
+        ASSERT_EQ(0, hosts.size());
+        idx = 2;
+        hosts = HostMgr::instance().getPage4(idx, 0, page_size);
+        ASSERT_EQ(0, hosts.size());
+    }
+}
+
+void
+HostMgrTest::testGetPage6All(bool use_database) {
+    BaseHostDataSource& data_source1 = *getCfgHosts();
+    BaseHostDataSource& data_source2 = HostMgr::instance();
+
+    // Initially, no reservations should be present.
+    size_t idx(0);
+    HostPageSize page_size(10);
+    ConstHostCollection hosts =
+        HostMgr::instance().getPage6(idx, 0, page_size);
+    ASSERT_TRUE(hosts.empty());
+    if (use_database) {
+        EXPECT_EQ(2, idx);
+    } else {
+        EXPECT_EQ(1, idx);
+    }
+
+    // Add two reservations.
+    addHost6(data_source1, duids_[0], SubnetID(1), IOAddress("2001:db8:1::5"));
+    addHost6(use_database ? data_source2 : data_source1,
+             duids_[1], SubnetID(2), IOAddress("2001:db8:1::6"));
+
+    CfgMgr::instance().commit();
+
+    // There should be two reservations.
+    idx = 0;
+    hosts = HostMgr::instance().getPage6(idx, 0, page_size);
+    if (use_database) {
+        ASSERT_EQ(1, hosts.size());
+    } else {
+        ASSERT_EQ(2, hosts.size());
+    }
+
+    // Make sure that returned values are correct.
+    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
+    EXPECT_TRUE(hosts[0]->hasReservation(
+                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
+    if (!use_database) {
+        EXPECT_EQ(2, hosts[1]->getIPv6SubnetID());
+        EXPECT_TRUE(hosts[1]->hasReservation(
+                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
+
+        // Check it was the last page.
+        uint64_t hid = hosts[1]->getHostId();
+        hosts = HostMgr::instance().getPage6(idx, hid, page_size);
+        ASSERT_EQ(0, hosts.size());
+        idx = 1;
+        hosts = HostMgr::instance().getPage6(idx, 0, page_size);
+        ASSERT_EQ(0, hosts.size());
+    }
+
+    if (use_database) {
+        uint64_t hid = hosts[0]->getHostId();
+        ASSERT_NE(0, hid);
+        ASSERT_EQ(0, idx);
+        hosts = HostMgr::instance().getPage6(idx, hid, page_size);
+        ASSERT_EQ(1, hosts.size());
+        ASSERT_NE(0, idx);
+        EXPECT_EQ(2, hosts[0]->getIPv6SubnetID());
+        EXPECT_TRUE(hosts[0]->hasReservation(
+                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
+
+        // Alternate way to use the database.
+        idx = 1;
+        hosts = HostMgr::instance().getPage6(idx, 0, page_size);
+        ASSERT_EQ(1, hosts.size());
+        EXPECT_EQ(2, hosts[0]->getIPv6SubnetID());
+        EXPECT_TRUE(hosts[0]->hasReservation(
+                    IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::6"))));
+
+        // Check it was the last page.
+        hid = hosts[0]->getHostId();
+        ASSERT_NE(0, hid);
+        hosts = HostMgr::instance().getPage6(idx, hid, page_size);
+        ASSERT_EQ(0, hosts.size());
+        idx = 2;
+        hosts = HostMgr::instance().getPage6(idx, 0, page_size);
+        ASSERT_EQ(0, hosts.size());
+    }
+}
+
+void
+HostMgrTest::testGetAll4(BaseHostDataSource& data_source1,
+                         BaseHostDataSource& data_source2) {
+    // Initially, no hosts should be present.
+    ConstHostCollection hosts =
+        HostMgr::instance().getAll4(IOAddress("192.0.2.5"));
+    ASSERT_TRUE(hosts.empty());
+
+    // Add two hosts to different data sources.
+    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
+    addHost4(data_source2, hwaddrs_[1], SubnetID(10), IOAddress("192.0.2.5"));
+
+    CfgMgr::instance().commit();
+
+    // Retrieve all hosts, This should return hosts from both sources
+    // in a single container.
+    hosts = HostMgr::instance().getAll4(IOAddress("192.0.2.5"));
+    ASSERT_EQ(2, hosts.size());
+
+    // Make sure that IPv4 address is correct.
+    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
+    EXPECT_EQ("192.0.2.5", hosts[1]->getIPv4Reservation().toText());
+
+    // Make sure that two different hosts were returned.
+    EXPECT_NE(hosts[0]->getIPv4SubnetID(), hosts[1]->getIPv4SubnetID());
+}
+
+void
+HostMgrTest::testGet4(BaseHostDataSource& data_source) {
+    // Initially, no host should be present.
+    ConstHostPtr host =
+        HostMgr::instance().get4(SubnetID(1), Host::IDENT_HWADDR,
+                                 &hwaddrs_[0]->hwaddr_[0],
+                                 hwaddrs_[0]->hwaddr_.size());
+    ASSERT_FALSE(host);
+
+    // Add new host to the database.
+    addHost4(data_source, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
+
+    CfgMgr::instance().commit();
+
+    // Retrieve the host from the database and expect that the parameters match.
+    host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_HWADDR,
+                                    &hwaddrs_[0]->hwaddr_[0],
+                                    hwaddrs_[0]->hwaddr_.size());
+    ASSERT_TRUE(host);
+    EXPECT_EQ(1, host->getIPv4SubnetID());
+    EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
+}
+
+void
+HostMgrTest::testGet4Any() {
+    // Initially, no host should be present.
+    ConstHostPtr host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
+                                                 &duids_[0]->getDuid()[0],
+                                                 duids_[0]->getDuid().size());
+    ASSERT_FALSE(host);
+    HostMgr::instance().get4Any(SubnetID(1), Host::IDENT_DUID,
+                                &duids_[0]->getDuid()[0],
+                                duids_[0]->getDuid().size());
+    ASSERT_FALSE(host);
+
+    // Add new host to the database.
+    HostPtr new_host(new Host(duids_[0]->toText(), "duid", SubnetID(1),
+                              SUBNET_ID_UNUSED, IOAddress("192.0.2.5")));
+    // Abuse of the server's configuration.
+    getCfgHosts()->add(new_host);
+
+    CfgMgr::instance().commit();
+
+    // Retrieve the host from the database and expect that the parameters match.
+    host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
+                                    &duids_[0]->getDuid()[0],
+                                    duids_[0]->getDuid().size());
+    ASSERT_TRUE(host);
+    EXPECT_EQ(1, host->getIPv4SubnetID());
+    EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
+
+    // Set the negative cache flag on the host.
+    new_host->setNegative(true);
+
+    // get4 is not supposed to get it.
+    host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
+                                    &duids_[0]->getDuid()[0],
+                                    duids_[0]->getDuid().size());
+    EXPECT_FALSE(host);
+
+    // But get4Any should.
+    host = HostMgr::instance().get4Any(SubnetID(1), Host::IDENT_DUID,
+                                       &duids_[0]->getDuid()[0],
+                                       duids_[0]->getDuid().size());
+    ASSERT_TRUE(host);
+    EXPECT_EQ(1, host->getIPv4SubnetID());
+    EXPECT_EQ("192.0.2.5", host->getIPv4Reservation().toText());
+    EXPECT_TRUE(host->getNegative());
+
+    // To be sure. Note we use the CfgHosts source so only this
+    // get4 overload works.
+    host = HostMgr::instance().get4(SubnetID(1), Host::IDENT_DUID,
+                                    &duids_[0]->getDuid()[0],
+                                    duids_[0]->getDuid().size());
+    EXPECT_FALSE(host);
+}
+
+void
+HostMgrTest::testGet6(BaseHostDataSource& data_source) {
+    // Initially, no host should be present.
+    ConstHostPtr host =
+        HostMgr::instance().get6(SubnetID(2), Host::IDENT_DUID,
+                                 &duids_[0]->getDuid()[0],
+                                 duids_[0]->getDuid().size());
+    ASSERT_FALSE(host);
+
+    // Add new host to the database.
+    addHost6(data_source, duids_[0], SubnetID(2), IOAddress("2001:db8:1::1"));
+
+    CfgMgr::instance().commit();
+
+    // Retrieve the host from the database and expect that the parameters match.
+    host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_DUID,
+                                    &duids_[0]->getDuid()[0],
+                                    duids_[0]->getDuid().size());
+    ASSERT_TRUE(host);
+    EXPECT_EQ(2, host->getIPv6SubnetID());
+    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
+                                               IOAddress("2001:db8:1::1"))));
+}
+
+void
+HostMgrTest::testGet6Any() {
+    // Initially, no host should be present.
+    ConstHostPtr host = HostMgr::instance().get6(SubnetID(2),
+                                                 Host::IDENT_HWADDR,
+                                                 &hwaddrs_[0]->hwaddr_[0],
+                                                 hwaddrs_[0]->hwaddr_.size());
+    ASSERT_FALSE(host);
+    host = HostMgr::instance().get6Any(SubnetID(2), Host::IDENT_HWADDR,
+                                       &hwaddrs_[0]->hwaddr_[0],
+                                       hwaddrs_[0]->hwaddr_.size());
+    ASSERT_FALSE(host);
+
+    // Add new host to the database.
+    HostPtr new_host(new Host(hwaddrs_[0]->toText(false), "hw-address",
+                              SubnetID(1), SubnetID(2),
+                              IOAddress::IPV4_ZERO_ADDRESS()));
+    new_host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
+                                       IOAddress("2001:db8:1::1"), 128));
+    // Abuse of the server's configuration.
+    getCfgHosts()->add(new_host);
+
+    CfgMgr::instance().commit();
+
+    // Retrieve the host from the database and expect that the parameters match.
+    host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_HWADDR,
+                                    &hwaddrs_[0]->hwaddr_[0],
+                                    hwaddrs_[0]->hwaddr_.size());
+    ASSERT_TRUE(host);
+    EXPECT_EQ(2, host->getIPv6SubnetID());
+    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
+                                               IOAddress("2001:db8:1::1"))));
+
+    // Set the negative cache flag on the host.
+    new_host->setNegative(true);
+
+    // get6 is not supposed to get it.
+    host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_HWADDR,
+                                    &hwaddrs_[0]->hwaddr_[0],
+                                    hwaddrs_[0]->hwaddr_.size());
+    EXPECT_FALSE(host);
+
+    // But get6Any should.
+    host = HostMgr::instance().get6Any(SubnetID(2), Host::IDENT_HWADDR,
+                                       &hwaddrs_[0]->hwaddr_[0],
+                                       hwaddrs_[0]->hwaddr_.size());
+    ASSERT_TRUE(host);
+    EXPECT_EQ(2, host->getIPv6SubnetID());
+    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
+                                               IOAddress("2001:db8:1::1"))));
+    EXPECT_TRUE(host->getNegative());
+
+    // To be sure. Note we use the CfgHosts source so only this
+    // get6 overload works.
+    host = HostMgr::instance().get6(SubnetID(2), Host::IDENT_HWADDR,
+                                    &hwaddrs_[0]->hwaddr_[0],
+                                    hwaddrs_[0]->hwaddr_.size());
+    EXPECT_FALSE(host);
+}
+
+void
+HostMgrTest::testGet6ByPrefix(BaseHostDataSource& data_source1,
+                              BaseHostDataSource& data_source2) {
+    ConstHostPtr host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 64);
+    ASSERT_FALSE(host);
+
+    // Add a host with a reservation for a prefix 2001:db8:1::/64.
+    addHost6(data_source1, duids_[0], SubnetID(2), IOAddress("2001:db8:1::"), 64);
+
+    // Add another host having a reservation for prefix 2001:db8:1:0:6::/72.
+    addHost6(data_source2, duids_[1], SubnetID(3), IOAddress("2001:db8:1:0:6::"), 72);
+
+    CfgMgr::instance().commit();
+
+    // Retrieve first reservation.
+    host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 64);
+    ASSERT_TRUE(host);
+    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
+                                               IOAddress("2001:db8:1::"), 64)));
+
+    // Make sure the first reservation is not retrieved when the prefix
+    // length is incorrect.
+    host = HostMgr::instance().get6(IOAddress("2001:db8:1::"), 72);
+    EXPECT_FALSE(host);
+
+    // Retrieve second reservation.
+    host = HostMgr::instance().get6(IOAddress("2001:db8:1:0:6::"), 72);
+    ASSERT_TRUE(host);
+    EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
+                                               IOAddress("2001:db8:1:0:6::"), 72)));
+
+    // Make sure the second reservation is not retrieved when the prefix
+    // length is incorrect.
+    host = HostMgr::instance().get6(IOAddress("2001:db8:1:0:6::"), 64);
+    EXPECT_FALSE(host);
+}
+
+void
+HostMgrTest::testGetAll4BySubnetIP(BaseHostDataSource& data_source1,
+                                   BaseHostDataSource& data_source2) {
+    // Set the mode of operation with multiple reservations for the same
+    // IP address.
+    ASSERT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
+    CfgMgr::instance().getStagingCfg()->getCfgHosts()->setIPReservationsUnique(false);
+
+    // Initially, no reservations should be present.
+    ConstHostCollection hosts = HostMgr::instance().getAll4(SubnetID(1),
+                                                            IOAddress("192.0.2.5"));
+    ASSERT_TRUE(hosts.empty());
+
+    // Add two reservations for the same subnet and IP address.
+    addHost4(data_source1, hwaddrs_[0], SubnetID(1), IOAddress("192.0.2.5"));
+    addHost4(data_source2, hwaddrs_[1], SubnetID(1), IOAddress("192.0.2.5"));
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching subnet is specified, nothing should be returned.
+    hosts = HostMgr::instance().getAll4(SubnetID(100), IOAddress("192.0.2.5"));
+    ASSERT_TRUE(hosts.empty());
+
+    // For the correct subnet, there should be two reservations.
+    hosts = HostMgr::instance().getAll4(SubnetID(1), IOAddress("192.0.2.5"));
+    ASSERT_EQ(2, hosts.size());
+
+    // Make sure that subnet is correct.
+    EXPECT_EQ(1, hosts[0]->getIPv4SubnetID());
+    EXPECT_EQ(1, hosts[1]->getIPv4SubnetID());
+
+    // Make sure that two hosts were returned with different identifiers
+    // but the same address.
+    EXPECT_NE(hosts[0]->getIdentifierAsText(), hosts[1]->getIdentifierAsText());
+    EXPECT_EQ("192.0.2.5", hosts[0]->getIPv4Reservation().toText());
+    EXPECT_EQ("192.0.2.5", hosts[1]->getIPv4Reservation().toText());
+}
+
+void
+HostMgrTest::testGetAll6BySubnetIP(BaseHostDataSource& data_source1,
+                                   BaseHostDataSource& data_source2) {
+    // Set the mode of operation with multiple reservations for the same
+    // IP address.
+    ASSERT_TRUE(HostMgr::instance().setIPReservationsUnique(false));
+    CfgMgr::instance().getStagingCfg()->getCfgHosts()->setIPReservationsUnique(false);
+
+    // Initially, no reservations should be present.
+    ConstHostCollection hosts = HostMgr::instance().getAll6(SubnetID(1),
+                                                            IOAddress("2001:db8:1::5"));
+    ASSERT_TRUE(hosts.empty());
+
+    // Add two reservations for the same subnet.
+    addHost6(data_source1, duids_[0], SubnetID(1), IOAddress("2001:db8:1::5"));
+    addHost6(data_source2, duids_[1], SubnetID(1), IOAddress("2001:db8:1::5"));
+
+    CfgMgr::instance().commit();
+
+    // If there non-matching subnet is specified, nothing should be returned.
+    hosts = HostMgr::instance().getAll6(SubnetID(100), IOAddress("2001:db8:1::5"));
+    ASSERT_TRUE(hosts.empty());
+
+    // For the correct subnet, there should be two reservations.
+    hosts = HostMgr::instance().getAll6(SubnetID(1), IOAddress("2001:db8:1::5"));
+    ASSERT_EQ(2, hosts.size());
+
+    // Make sure that subnet is correct.
+    EXPECT_EQ(1, hosts[0]->getIPv6SubnetID());
+    EXPECT_EQ(1, hosts[1]->getIPv6SubnetID());
+
+    // Make sure that two hosts were returned with different identifiers
+    // but the same address.
+    EXPECT_NE(hosts[0]->getIdentifierAsText(), hosts[1]->getIdentifierAsText());
+    EXPECT_TRUE(hosts[0]->hasReservation(
+                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
+    EXPECT_TRUE(hosts[1]->hasReservation(
+                IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::5"))));
+}
+
 }  // namespace test
 }  // namespace dhcp
 }  // namespace isc
index f0ede642e3f0dd066a5559765fd6ee5f0b67bff6..700d2f736ea25ee4db5d2090918bd905b36919f8 100644 (file)
@@ -8,8 +8,11 @@
 #define GENERIC_HOST_DATA_SOURCE_UNITTEST_H
 
 #include <asiolink/io_address.h>
+#include <database/database_connection.h>
 #include <dhcpsrv/base_host_data_source.h>
+#include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/host.h>
+#include <dhcpsrv/host_mgr.h>
 #include <dhcpsrv/testutils/generic_backend_unittest.h>
 #include <dhcp/classify.h>
 #include <dhcp/option.h>
@@ -532,6 +535,405 @@ public:
 
 };
 
+class HostMgrDbLostCallbackTest : public ::testing::Test {
+public:
+    HostMgrDbLostCallbackTest()
+        : 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::HostMgr::setIOService(io_service_);
+        isc::dhcp::TimerMgr::instance()->setIOService(io_service_);
+        isc::dhcp::CfgMgr::instance().clear();
+    }
+
+    ~HostMgrDbLostCallbackTest() {
+        isc::db::DatabaseConnection::db_lost_callback_ = 0;
+        isc::db::DatabaseConnection::db_recovered_callback_ = 0;
+        isc::db::DatabaseConnection::db_failed_callback_ = 0;
+        isc::dhcp::HostMgr::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 host manager to
+    /// wipe out any prior instance
+    virtual void SetUp() {
+        isc::dhcp::HostMgr::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.
+        createSchema();
+        // Wipe out any pre-existing mgr
+        isc::dhcp::HostMgr::create();
+        isc::dhcp::CfgMgr::instance().clear();
+    }
+
+    /// @brief Pre-text exit clean up
+    ///
+    /// Invoked by gtest upon test exit, we destroy the schema
+    /// we created.
+    virtual void TearDown() {
+        isc::dhcp::HostMgr::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
+        destroySchema();
+        isc::dhcp::CfgMgr::instance().clear();
+    }
+
+    /// @brief Abstract method for destroying the back end specific shcema
+    virtual void destroySchema() = 0;
+
+    /// @brief Abstract method for creating the back end specific shcema
+    virtual void createSchema() = 0;
+
+    /// @brief Abstract method which returns the back end specific connection
+    /// string
+    virtual std::string validConnectString() = 0;
+
+    /// @brief Abstract method which returns invalid back end specific connection
+    /// string
+    virtual std::string invalidConnectString() = 0;
+
+    /// @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 host manager's behavior if DB connection is lost
+    ///
+    /// This function creates a host 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 host 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 host manager's behavior if DB connection is lost
+    ///
+    /// This function creates a host 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 host 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 host manager's behavior if DB connection is lost
+    ///
+    /// This function creates a host 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 host 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 host manager's behavior if DB connection is lost
+    ///
+    /// This function creates a host 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 host 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 host 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 host 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 host 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_;
+};
+
+/// @brief Test fixture class for @c HostMgr class.
+class HostMgrTest : public ::testing::Test {
+protected:
+
+    /// @brief Prepares the class for a test.
+    ///
+    /// This method crates a handful of unique HW address and DUID objects
+    /// for use in unit tests. These objects are held in the @c hwaddrs_ and
+    /// @c duids_ members respectively.
+    ///
+    /// This method also resets the @c CfgMgr configuration and re-creates
+    /// the @c HostMgr object.
+    virtual void SetUp();
+
+    /// @brief Convenience method returning a pointer to the @c CfgHosts object
+    /// in the @c CfgMgr.
+    CfgHostsPtr getCfgHosts() const;
+
+    /// @brief Inserts IPv4 reservation into the host data source.
+    ///
+    /// @param data_source Reference to the data source to which the reservation
+    /// should be inserted.
+    /// @param hwaddr Pointer to the hardware address to be associated with the
+    /// reservation.
+    /// @param subnet_id IPv4 subnet id.
+    /// @param address IPv4 address to be reserved.
+    void addHost4(BaseHostDataSource& data_source,
+                  const HWAddrPtr& hwaddr,
+                  const SubnetID& subnet_id,
+                  const isc::asiolink::IOAddress& address);
+
+    /// @brief Inserts IPv6 reservation into the host data source.
+    ///
+    /// @param data_source Reference to the data source to which the reservation
+    /// should be inserted.
+    /// @param duid Pointer to the DUID to be associated with the reservation.
+    /// @param subnet_id IPv6 subnet id.
+    /// @param address IPv6 address/prefix to be reserved.
+    /// @param prefix_len Prefix length. The default value is 128 which
+    /// indicates that the reservation is for an IPv6 address rather than a
+    /// prefix.
+    void addHost6(BaseHostDataSource& data_source,
+                  const DuidPtr& duid,
+                  const SubnetID& subnet_id,
+                  const isc::asiolink::IOAddress& address,
+                  const uint8_t prefix_len = 128);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified HW address.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGetAll(BaseHostDataSource& data_source1,
+                    BaseHostDataSource& data_source2);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified DHCPv4 subnet.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGetAll4BySubnet(BaseHostDataSource& data_source1,
+                             BaseHostDataSource& data_source2);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified DHCPv6 subnet.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGetAll6BySubnet(BaseHostDataSource& data_source1,
+                             BaseHostDataSource& data_source2);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified hostname.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGetAllbyHostname(BaseHostDataSource& data_source1,
+                              BaseHostDataSource& data_source2);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified hostname and DHCPv4 subnet.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGetAllbyHostnameSubnet4(BaseHostDataSource& data_source1,
+                                     BaseHostDataSource& data_source2);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified hostname and DHCPv6 subnet.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGetAllbyHostnameSubnet6(BaseHostDataSource& data_source1,
+                                     BaseHostDataSource& data_source2);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified DHCPv4 subnet by pages.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param use_database True when the second reservation is inserted
+    /// in a database.
+    void testGetPage4(bool use_database);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified DHCPv6 subnet by pages.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param use_database True when the second reservation is inserted
+    /// in a database.
+    void testGetPage6(bool use_database);
+
+    /// @brief This test verifies that HostMgr returns all reservations
+    /// by pages.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param use_database True when the second reservation is inserted
+    /// in a database.
+    void testGetPage4All(bool use_database);
+
+    /// @brief This test verifies that HostMgr returns all reservations
+    /// by pages.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param use_database True when the second reservation is inserted
+    /// in a database.
+    void testGetPage6All(bool use_database);
+
+    /// @brief This test verifies that it is possible to retrieve IPv4
+    /// reservation for the particular host using HostMgr.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGetAll4(BaseHostDataSource& data_source1,
+                     BaseHostDataSource& data_source2);
+
+    /// @brief This test verifies that it is possible to retrieve an IPv4
+    /// reservation for the particular host using HostMgr.
+    ///
+    /// @param data_source Host data source to which reservation is inserted and
+    /// from which it will be retrieved.
+    void testGet4(BaseHostDataSource& data_source);
+
+    /// @brief This test verifies that it is possible to retrieve negative
+    /// cached reservation with and only with get4Any.
+    void testGet4Any();
+
+    /// @brief This test verifies that it is possible to retrieve an IPv6
+    /// reservation for the particular host using HostMgr.
+    ///
+    /// @param data_source Host data source to which reservation is inserted and
+    /// from which it will be retrieved.
+    void testGet6(BaseHostDataSource& data_source);
+
+    /// @brief This test verifies that it is possible to retrieve negative
+    /// cached reservation with and only with get6Any.
+    void testGet6Any();
+
+    /// @brief This test verifies that it is possible to retrieve an IPv6
+    /// prefix reservation for the particular host using HostMgr.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGet6ByPrefix(BaseHostDataSource& data_source1,
+                          BaseHostDataSource& data_source2);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified DHCPv4 subnet and IPv4 address.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGetAll4BySubnetIP(BaseHostDataSource& data_source1,
+                               BaseHostDataSource& data_source2);
+
+    /// @brief This test verifies that HostMgr returns all reservations for the
+    /// specified DHCPv6 subnet and IPv6 address.
+    ///
+    /// If reservations are added to different host data sources, it is expected
+    /// that the @c HostMgr will retrieve reservations from both of them.
+    ///
+    /// @param data_source1 Host data source to which first reservation is
+    /// inserted.
+    /// @param data_source2 Host data source to which second reservation is
+    /// inserted.
+    void testGetAll6BySubnetIP(BaseHostDataSource& data_source1,
+                               BaseHostDataSource& data_source2);
+
+    /// @brief HW addresses to be used by the tests.
+    std::vector<HWAddrPtr> hwaddrs_;
+    /// @brief DUIDs to be used by the tests.
+    std::vector<DuidPtr> duids_;
+};
+
 }  // namespace test
 }  // namespace dhcp
 }  // namespace isc