]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[313-return-a-list-of-all-reservations-by-subnet-id] Added host manager tests
authorFrancis Dupont <fdupont@isc.org>
Mon, 14 Jan 2019 14:58:23 +0000 (15:58 +0100)
committerFrancis Dupont <fdupont@isc.org>
Tue, 29 Jan 2019 09:49:05 +0000 (04:49 -0500)
src/lib/dhcpsrv/cql_host_data_source.cc
src/lib/dhcpsrv/host_mgr.cc
src/lib/dhcpsrv/pgsql_host_data_source.cc
src/lib/dhcpsrv/tests/host_mgr_unittest.cc

index af9ab3e7660cf87f2a2f4cab256f3185e15d114c..308fd1cc85c8034358508af2f04f4a1ab61a955a 100644 (file)
@@ -2170,11 +2170,7 @@ CqlHostDataSourceImpl::getPage4(const SubnetID& subnet_id,
                           CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_PAGE,
                           where_values);
 
-    // Sort result.
-    std::sort(result.begin(), result.end(),
-              [] (const ConstHostPtr& host1,
-                  const ConstHostPtr& host2) {
-                  return (host1->getHostId() < host2->getHostId()); });
+    // Note the result is not ordered (or ordered following TOKEN).
 
     return (result);
 }
@@ -2206,11 +2202,7 @@ CqlHostDataSourceImpl::getPage6(const SubnetID& subnet_id,
                           CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_PAGE,
                           where_values);
 
-    // Sort result.
-    std::sort(result.begin(), result.end(),
-              [] (const ConstHostPtr& host1,
-                  const ConstHostPtr& host2) {
-                  return (host1->getHostId() < host2->getHostId()); });
+    // Note the result is not ordered (or ordered following TOKEN).
 
     return (result);
 }
index cbc28146f7e3e3d327a6d83d87ddea61d2841c11..bfb146900f1294a616f2005c83ed85f94ff12344 100644 (file)
@@ -152,6 +152,7 @@ HostMgr::getPage4(const SubnetID& subnet_id,
             return (hosts);
         } else {
             ++source_index;
+            lower_host_id = 0;
             continue;
         }
     }
@@ -178,6 +179,7 @@ HostMgr::getPage6(const SubnetID& subnet_id,
             return (hosts);
         } else {
             ++source_index;
+            lower_host_id = 0;
             continue;
         }
     }
index 9145ba4cbca848801c1c952c19501e2797d71b9f..fa1f2e20341a4457aeb2c9a14f1c4eec7e427e58 100644 (file)
@@ -2273,7 +2273,7 @@ PgSqlHostDataSource::getPage6(const SubnetID& subnet_id,
 
     ConstHostCollection result;
     impl_->getHostCollection(PgSqlHostDataSourceImpl::GET_HOST_SUBID6_PAGE,
-                             bind_array, impl_->host_exchange_,
+                             bind_array, impl_->host_ipv6_exchange_,
                              result, false);
 
     return (result);
index bac9a6711cee479adfb3c4d9dd9c750a31a1764c..6211e172cdd6d524a9c37320118f30ec07c4eff7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -96,6 +96,52 @@ protected:
     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 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 it is possible to retrieve IPv4
     /// reservation for the particular host using HostMgr.
     ///
@@ -268,6 +314,236 @@ HostMgrTest::testGetAll(BaseHostDataSource& data_source1,
     }
 }
 
+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::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::testGetAll4(BaseHostDataSource& data_source1,
                          BaseHostDataSource& data_source2) {
@@ -493,13 +769,41 @@ HostMgrTest::testGet6ByPrefix(BaseHostDataSource& data_source1,
     EXPECT_FALSE(host);
 }
 
-/// This test verifies that HostMgr returns all reservations for the
-/// specified HW address. The reservations are defined in the server's
-/// configuration.
+// This test verifies that HostMgr returns all reservations for the
+// specified HW address. The reservations are defined in the server's
+// configuration.
 TEST_F(HostMgrTest, getAll) {
     testGetAll(*getCfgHosts(), *getCfgHosts());
 }
 
+// This test verifies that HostMgr returns all reservations for the
+// specified DHCPv4 subnet. The reservations are defined in the server's
+// configuration.
+TEST_F(HostMgrTest, getAll4BySubnet) {
+    testGetAll4BySubnet(*getCfgHosts(), *getCfgHosts());
+}
+
+// This test verifies that HostMgr returns all reservations for the
+// specified DHCPv6 subnet. The reservations are defined in the server's
+// configuration.
+TEST_F(HostMgrTest, getAll6BySubnet) {
+    testGetAll6BySubnet(*getCfgHosts(), *getCfgHosts());
+}
+
+// This test verifies that HostMgr returns all reservations for the
+// specified DHCPv4 subnet by pages. The reservations are defined in
+// the server's configuration.
+TEST_F(HostMgrTest, getPage4) {
+    testGetPage4(false);
+}
+
+// This test verifies that HostMgr returns all reservations for the
+// specified DHCPv6 subnet by pages. The reservations are defined in
+// the server's configuration.
+TEST_F(HostMgrTest, getPage6) {
+    testGetPage6(false);
+}
+
 // This test verifies that it is possible to gather all reservations for the
 // specified IPv4 address from the HostMgr. The reservations are specified in
 // the server's configuration.
@@ -714,6 +1018,32 @@ 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 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 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 IPv4 reservations for a particular client can
 // be retrieved from the configuration file and a database simultaneously.
 TEST_F(MySQLHostMgrTest, getAll4) {
@@ -805,11 +1135,38 @@ public:
     }
 };
 
+// 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 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 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 IPv4 reservations for a particular client can
 // be retrieved from the configuration file and a database simultaneously.
 TEST_F(PostgreSQLHostMgrTest, getAll4) {
@@ -889,6 +1246,32 @@ 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 subnet can
+// be retrieved by pages from the configuration file and a database
+// simultaneously.
+TEST_F(CQLHostMgrTest, getPage4) {
+    testGetPage4(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 IPv4 reservations for a particular client can
 // be retrieved from the configuration file and a database simultaneously.
 TEST_F(CQLHostMgrTest, getAll4) {