From f5ce317a12cee51158e5d22c9b10ab053a197bf4 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Mon, 30 Sep 2019 15:33:57 +0200 Subject: [PATCH] [392-search-of-reservations-by-hostname] Checkpoint: did tests, todo doc and hook --- src/lib/dhcpsrv/cfg_hosts.cc | 6 +- src/lib/dhcpsrv/mysql_host_data_source.cc | 2 +- .../tests/cql_host_data_source_unittest.cc | 17 ++ src/lib/dhcpsrv/tests/host_mgr_unittest.cc | 263 ++++++++++++++++++ .../tests/mysql_host_data_source_unittest.cc | 17 ++ .../tests/pgsql_host_data_source_unittest.cc | 17 ++ .../generic_host_data_source_unittest.cc | 223 +++++++++++++++ .../generic_host_data_source_unittest.h | 18 ++ 8 files changed, 560 insertions(+), 3 deletions(-) diff --git a/src/lib/dhcpsrv/cfg_hosts.cc b/src/lib/dhcpsrv/cfg_hosts.cc index f93467665c..5ec8407f67 100644 --- a/src/lib/dhcpsrv/cfg_hosts.cc +++ b/src/lib/dhcpsrv/cfg_hosts.cc @@ -367,7 +367,8 @@ CfgHosts::getAllbyHostnameInternal4(const std::string& hostname, LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID4) - .arg(hostname); + .arg(hostname) + .arg(subnet_id); // Use try hostname. const HostContainerIndex5& idx = hosts_.get<5>(); @@ -403,7 +404,8 @@ CfgHosts::getAllbyHostnameInternal6(const std::string& hostname, LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_HOSTNAME_SUBNET_ID6) - .arg(hostname); + .arg(hostname) + .arg(subnet_id); // Use try hostname. const HostContainerIndex5& idx = hosts_.get<5>(); diff --git a/src/lib/dhcpsrv/mysql_host_data_source.cc b/src/lib/dhcpsrv/mysql_host_data_source.cc index 3c0c2d7c38..5340070881 100644 --- a/src/lib/dhcpsrv/mysql_host_data_source.cc +++ b/src/lib/dhcpsrv/mysql_host_data_source.cc @@ -3116,7 +3116,7 @@ MySqlHostDataSource::getAllbyHostname6(const std::string& hostname, inbind[1].is_unsigned = MLM_TRUE; ConstHostCollection result; - impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID4, + impl_->getHostCollection(MySqlHostDataSourceImpl::GET_HOST_HOSTNAME_SUBID6, inbind, impl_->host_ipv6_exchange_, result, false); return (result); diff --git a/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc index bf8fe28bf1..bf4602b928 100644 --- a/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/tests/cql_host_data_source_unittest.cc @@ -332,6 +332,23 @@ TEST_F(CqlHostDataSourceTest, getAll6BySubnet) { testGetAll6(); } +// Verifies that host reservations with the same hostname can be retrieved +TEST_F(CqlHostDataSourceTest, getAllbyHostname) { + testGetAllbyHostname(); +} + +// Verifies that IPv4 host reservations with the same hostname and in +// the same subnet can be retrieved +TEST_F(CqlHostDataSourceTest, getAllbyHostname4) { + testGetAllbyHostname4(); +} + +// Verifies that IPv6 host reservations with the same hostname and in +// the same subnet can be retrieved +TEST_F(CqlHostDataSourceTest, getAllbyHostname6) { + testGetAllbyHostname6(); +} + // Verifies that IPv4 host reservations in the same subnet can be retrieved // by pages. TEST_F(CqlHostDataSourceTest, getPage4) { diff --git a/src/lib/dhcpsrv/tests/host_mgr_unittest.cc b/src/lib/dhcpsrv/tests/host_mgr_unittest.cc index 6a540388ba..573cd24297 100644 --- a/src/lib/dhcpsrv/tests/host_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/host_mgr_unittest.cc @@ -122,6 +122,45 @@ protected: 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 testGetAllbyHostname4(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 testGetAllbyHostname6(BaseHostDataSource& data_source1, + BaseHostDataSource& data_source2); + /// @brief This test verifies that HostMgr returns all reservations for the /// specified DHCPv4 subnet by pages. /// @@ -376,6 +415,150 @@ HostMgrTest::testGetAll6BySubnet(BaseHostDataSource& data_source1, 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::testGetAllbyHostname4(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::testGetAllbyHostname6(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(); @@ -790,6 +973,26 @@ TEST_F(HostMgrTest, getAll6BySubnet) { testGetAll6BySubnet(*getCfgHosts(), *getCfgHosts()); } +// This test verifies that HostMgr returns all reservations for the specified +// hostname. The reservations are defined in the server's configuration. +TEST_F(HostMgrTest, getAllbyHostname) { + testGetAllbyHostname(*getCfgHosts(), *getCfgHosts()); +} + +// This test verifies that HostMgr returns all reservations for the specified +// hostname and DHCPv4 subnet. The reservations are defined in the server's +// configuration. +TEST_F(HostMgrTest, getAllbyHostname4) { + testGetAllbyHostname4(*getCfgHosts(), *getCfgHosts()); +} + +// This test verifies that HostMgr returns all reservations for the specified +// hostname and DHCPv6 subnet. The reservations are defined in the server's +// configuration. +TEST_F(HostMgrTest, getAllbyHostname6) { + testGetAllbyHostname4(*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. @@ -1034,6 +1237,26 @@ TEST_F(MySQLHostMgrTest, 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(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, getAllbyHostname4) { + testGetAllbyHostname4(*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, getAllbyHostname6) { + testGetAllbyHostname6(*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. @@ -1159,6 +1382,26 @@ TEST_F(PostgreSQLHostMgrTest, 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(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, getAllbyHostname4) { + testGetAllbyHostname4(*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, getAllbyHostname6) { + testGetAllbyHostname6(*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. @@ -1265,6 +1508,26 @@ 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, getAllbyHostname4) { + testGetAllbyHostname4(*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, getAllbyHostname6) { + testGetAllbyHostname6(*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. diff --git a/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc index c1fd8bc980..e6e8b4506c 100644 --- a/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc @@ -321,6 +321,23 @@ TEST_F(MySqlHostDataSourceTest, getAll6BySubnet) { testGetAll6(); } +// Verifies that host reservations with the same hostname can be retrieved +TEST_F(MySqlHostDataSourceTest, getAllbyHostname) { + testGetAllbyHostname(); +} + +// Verifies that IPv4 host reservations with the same hostname and in +// the same subnet can be retrieved +TEST_F(MySqlHostDataSourceTest, getAllbyHostname4) { + testGetAllbyHostname4(); +} + +// Verifies that IPv6 host reservations with the same hostname and in +// the same subnet can be retrieved +TEST_F(MySqlHostDataSourceTest, getAllbyHostname6) { + testGetAllbyHostname6(); +} + // Verifies that IPv4 host reservations in the same subnet can be retrieved // by pages. TEST_F(MySqlHostDataSourceTest, getPage4) { diff --git a/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc index 1925d7eedc..c456940cf0 100644 --- a/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc @@ -307,6 +307,23 @@ TEST_F(PgSqlHostDataSourceTest, getAll6BySubnet) { testGetAll6(); } +// Verifies that host reservations with the same hostname can be retrieved +TEST_F(PgSqlHostDataSourceTest, getAllbyHostname) { + testGetAllbyHostname(); +} + +// Verifies that IPv4 host reservations with the same hostname and in +// the same subnet can be retrieved +TEST_F(PgSqlHostDataSourceTest, getAllbyHostname4) { + testGetAllbyHostname4(); +} + +// Verifies that IPv6 host reservations with the same hostname and in +// the same subnet can be retrieved +TEST_F(PgSqlHostDataSourceTest, getAllbyHostname6) { + testGetAllbyHostname6(); +} + // Verifies that IPv4 host reservations in the same subnet can be retrieved // by pages. TEST_F(PgSqlHostDataSourceTest, getPage4) { diff --git a/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.cc b/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.cc index e75c207567..b3e1c14429 100644 --- a/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.cc @@ -463,6 +463,229 @@ GenericHostDataSourceTest::testGetAll6() { } } +void +GenericHostDataSourceTest::testGetAllbyHostname() { + // Make sure we have a pointer to the host data source. + ASSERT_TRUE(hdsptr_); + + // Let's create some hosts... + Host::IdentifierType id = Host::IDENT_HWADDR; + HostPtr host1 = HostDataSourceUtils::initializeHost4("192.0.2.1", id); + host1->setHostname("host"); + + id = Host::IDENT_DUID; + HostPtr host2 = HostDataSourceUtils::initializeHost4("192.0.2.2", id); + host2->setHostname("Host"); + + HostPtr host3 = HostDataSourceUtils::initializeHost6("2001:db8::1", id, false); + host3->setHostname("hOSt"); + + HostPtr host4 = HostDataSourceUtils::initializeHost6("2001:db8::2", id, false); + host4->setHostname("host.example.com"); + + // Now add them all to the host data source. + ASSERT_NO_THROW(hdsptr_->add(host1)); + ASSERT_NO_THROW(hdsptr_->add(host2)); + ASSERT_NO_THROW(hdsptr_->add(host3)); + ASSERT_NO_THROW(hdsptr_->add(host4)); + + // Retrieve unknown name. + ConstHostCollection from_hds = hdsptr_->getAllbyHostname("foo"); + EXPECT_TRUE(from_hds.empty()); + + // Retrieve one reservation. + from_hds = hdsptr_->getAllbyHostname("host.example.com"); + ASSERT_EQ(1, from_hds.size()); + HostDataSourceUtils::compareHosts(host4, from_hds[0]); + + // Retrieve all reservations with host hostname. + from_hds = hdsptr_->getAllbyHostname("host"); + EXPECT_EQ(3, from_hds.size()); + bool got1 = false; + bool got2 = false; + bool got3 = false; + for (auto host : from_hds) { + if (host->getIdentifierType() == Host::IDENT_HWADDR) { + EXPECT_FALSE(got1); + got1 = true; + HostDataSourceUtils::compareHosts(host1, host); + } else if (host->getIPv4Reservation().isV4Zero()) { + EXPECT_FALSE(got3); + got3 = true; + HostDataSourceUtils::compareHosts(host3, host); + } else { + EXPECT_FALSE(got2); + got2 = true; + HostDataSourceUtils::compareHosts(host2, host); + } + } + EXPECT_TRUE(got1); + EXPECT_TRUE(got2); + EXPECT_TRUE(got3); +} + +void +GenericHostDataSourceTest::testGetAllbyHostname4() { + // Make sure we have a pointer to the host data source. + ASSERT_TRUE(hdsptr_); + + // Let's create some hosts... + Host::IdentifierType id = Host::IDENT_HWADDR; + HostPtr host1 = HostDataSourceUtils::initializeHost4("192.0.2.1", id); + host1->setHostname("host"); + + id = Host::IDENT_DUID; + HostPtr host2 = HostDataSourceUtils::initializeHost4("192.0.2.2", id); + host2->setHostname("Host"); + CfgOptionPtr opts = host2->getCfgOption4(); + OptionDescriptor desc = + createOption(Option::V4, DHO_BOOT_FILE_NAME, + true, false, "my-boot-file"); + opts->add(desc, DHCP4_OPTION_SPACE); + + HostPtr host3 = HostDataSourceUtils::initializeHost4("192.0.2.3", id); + host3->setHostname("hOSt"); + + HostPtr host4 = HostDataSourceUtils::initializeHost4("192.0.2.4", id); + host4->setHostname("host.example.com"); + + // Set them in the same subnets. + SubnetID subnet4 = host1->getIPv4SubnetID(); + host2->setIPv4SubnetID(subnet4); + host3->setIPv4SubnetID(subnet4); + host4->setIPv4SubnetID(subnet4); + SubnetID subnet6 = host1->getIPv6SubnetID(); + host2->setIPv6SubnetID(subnet6); + host3->setIPv6SubnetID(subnet6); + host4->setIPv6SubnetID(subnet6); + + // Now add them all to the host data source. + ASSERT_NO_THROW(hdsptr_->add(host1)); + ASSERT_NO_THROW(hdsptr_->add(host2)); + ASSERT_NO_THROW(hdsptr_->add(host3)); + ASSERT_NO_THROW(hdsptr_->add(host4)); + + // Retrieve unknown name. + ConstHostCollection from_hds = hdsptr_->getAllbyHostname4("foo", subnet4); + EXPECT_TRUE(from_hds.empty()); + + // Retrieve one reservation. + from_hds = hdsptr_->getAllbyHostname4("host.example.com", subnet4); + ASSERT_EQ(1, from_hds.size()); + HostDataSourceUtils::compareHosts(host4, from_hds[0]); + + // Check that the subnet is checked. + from_hds = hdsptr_->getAllbyHostname4("host.example.com", subnet4 + 1); + EXPECT_TRUE(from_hds.empty()); + + // Retrieve all reservations with host hostname. + from_hds = hdsptr_->getAllbyHostname4("host", subnet4); + EXPECT_EQ(3, from_hds.size()); + bool got1 = false; + bool got2 = false; + bool got3 = false; + bool got4 = false; + for (auto host : from_hds) { + if (host->getIdentifierType() == Host::IDENT_HWADDR) { + EXPECT_FALSE(got1); + got1 = true; + HostDataSourceUtils::compareHosts(host1, host); + } else if (!host->getCfgOption4()->empty()) { + EXPECT_FALSE(got2); + got2 = true; + HostDataSourceUtils::compareHosts(host2, host); + } else { + EXPECT_FALSE(got3); + got3 = true; + HostDataSourceUtils::compareHosts(host3, host); + } + } + EXPECT_TRUE(got1); + EXPECT_TRUE(got2); + EXPECT_TRUE(got3); +} + +void +GenericHostDataSourceTest::testGetAllbyHostname6() { + // Make sure we have a pointer to the host data source. + ASSERT_TRUE(hdsptr_); + + // Let's create some hosts... + Host::IdentifierType id = Host::IDENT_HWADDR; + HostPtr host1 = HostDataSourceUtils::initializeHost6("2001:db8::1", id, false); + host1->setHostname("host"); + + id = Host::IDENT_DUID; + HostPtr host2 = HostDataSourceUtils::initializeHost6("2001:db8::2", id, false); + host2->setHostname("Host"); + CfgOptionPtr opts = host2->getCfgOption6(); + OptionDescriptor desc = + createOption(Option::V6, D6O_BOOTFILE_URL, + true, true, "my-boot-file"); + opts->add(desc, DHCP6_OPTION_SPACE); + + HostPtr host3 = HostDataSourceUtils::initializeHost6("2001:db8::3", id, false); + host3->setHostname("hOSt"); + + HostPtr host4 = HostDataSourceUtils::initializeHost6("2001:db8::4", id, false); + host4->setHostname("host.example.com"); + + // Set them in the same subnets. + SubnetID subnet4 = host1->getIPv4SubnetID(); + host2->setIPv4SubnetID(subnet4); + host3->setIPv4SubnetID(subnet4); + host4->setIPv4SubnetID(subnet4); + SubnetID subnet6 = host1->getIPv6SubnetID(); + host2->setIPv6SubnetID(subnet6); + host3->setIPv6SubnetID(subnet6); + host4->setIPv6SubnetID(subnet6); + + // Now add them all to the host data source. + ASSERT_NO_THROW(hdsptr_->add(host1)); + ASSERT_NO_THROW(hdsptr_->add(host2)); + ASSERT_NO_THROW(hdsptr_->add(host3)); + ASSERT_NO_THROW(hdsptr_->add(host4)); + + // Retrieve unknown name. + ConstHostCollection from_hds = hdsptr_->getAllbyHostname6("foo", subnet6); + EXPECT_TRUE(from_hds.empty()); + + // Retrieve one reservation. + from_hds = hdsptr_->getAllbyHostname6("host.example.com", subnet6); + ASSERT_EQ(1, from_hds.size()); + HostDataSourceUtils::compareHosts(host4, from_hds[0]); + + // Check that the subnet is checked. + from_hds = hdsptr_->getAllbyHostname6("host.example.com", subnet6 + 1); + EXPECT_TRUE(from_hds.empty()); + + // Retrieve all reservations with host hostname. + from_hds = hdsptr_->getAllbyHostname6("host", subnet6); + EXPECT_EQ(3, from_hds.size()); + bool got1 = false; + bool got2 = false; + bool got3 = false; + bool got4 = false; + for (auto host : from_hds) { + if (host->getIdentifierType() == Host::IDENT_HWADDR) { + EXPECT_FALSE(got1); + got1 = true; + HostDataSourceUtils::compareHosts(host1, host); + } else if (!host->getCfgOption6()->empty()) { + EXPECT_FALSE(got2); + got2 = true; + HostDataSourceUtils::compareHosts(host2, host); + } else { + EXPECT_FALSE(got3); + got3 = true; + HostDataSourceUtils::compareHosts(host3, host); + } + } + EXPECT_TRUE(got1); + EXPECT_TRUE(got2); + EXPECT_TRUE(got3); +} + void GenericHostDataSourceTest::testGetPage4() { // Make sure we have a pointer to the host data source. diff --git a/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.h b/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.h index d398bb77e5..7c4103f872 100644 --- a/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.h +++ b/src/lib/dhcpsrv/testutils/generic_host_data_source_unittest.h @@ -202,6 +202,24 @@ public: /// Uses gtest macros to report failures. void testGetAll6(); + /// @brief Test that Verifies that host reservations with the same + /// hostname can be retrieved properly. + /// + /// Uses gtest macros to report failures. + void testGetAllbyHostname(); + + /// @brief Test that Verifies that IPv4 host reservations with the same + /// hostname and in the same subnet can be retrieved properly. + /// + /// Uses gtest macros to report failures. + void testGetAllbyHostname4(); + + /// @brief Test that Verifies that IPv6 host reservations with the same + /// hostname and in the same subnet can be retrieved properly. + /// + /// Uses gtest macros to report failures. + void testGetAllbyHostname6(); + /// @brief Test that Verifies that pages of host reservations in the /// same subnet can be retrieved properly. /// -- 2.47.2