From: Francis Dupont Date: Mon, 14 Jan 2019 14:58:23 +0000 (+0100) Subject: [313-return-a-list-of-all-reservations-by-subnet-id] Added host manager tests X-Git-Tag: 429-Updated-StampedValue-to-support-reals_base~83 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=642bf42782569a18ea8744763092dcd7adbef5f4;p=thirdparty%2Fkea.git [313-return-a-list-of-all-reservations-by-subnet-id] Added host manager tests --- diff --git a/src/lib/dhcpsrv/cql_host_data_source.cc b/src/lib/dhcpsrv/cql_host_data_source.cc index af9ab3e766..308fd1cc85 100644 --- a/src/lib/dhcpsrv/cql_host_data_source.cc +++ b/src/lib/dhcpsrv/cql_host_data_source.cc @@ -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); } diff --git a/src/lib/dhcpsrv/host_mgr.cc b/src/lib/dhcpsrv/host_mgr.cc index cbc28146f7..bfb146900f 100644 --- a/src/lib/dhcpsrv/host_mgr.cc +++ b/src/lib/dhcpsrv/host_mgr.cc @@ -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; } } diff --git a/src/lib/dhcpsrv/pgsql_host_data_source.cc b/src/lib/dhcpsrv/pgsql_host_data_source.cc index 9145ba4cbc..fa1f2e2034 100644 --- a/src/lib/dhcpsrv/pgsql_host_data_source.cc +++ b/src/lib/dhcpsrv/pgsql_host_data_source.cc @@ -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); diff --git a/src/lib/dhcpsrv/tests/host_mgr_unittest.cc b/src/lib/dhcpsrv/tests/host_mgr_unittest.cc index bac9a6711c..6211e172cd 100644 --- a/src/lib/dhcpsrv/tests/host_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/host_mgr_unittest.cc @@ -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) {