Commit 57b308ff authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[3689] Added new host test file

Addressing more review comments...

new file - host_unittest.cc
    contains Dhcp6Client based host reservation tests

dhcp6_client.cc
dhcp6_client.h
    added setDuid(str) method to allow duid to be set to
    specific value

dhcp6_srv_unittest.cc -
    deleted host reservation tests, now in host_unittest.cc

dhcp6_test_utils.cc
dhcp6_test_utils.h
    deleted createHost6() method
parent 973bb3ae
......@@ -75,6 +75,7 @@ dhcp6_unittests_SOURCES = dhcp6_unittests.cc
dhcp6_unittests_SOURCES += dhcp6_srv_unittest.cc
dhcp6_unittests_SOURCES += fqdn_unittest.cc
dhcp6_unittests_SOURCES += hooks_unittest.cc
dhcp6_unittests_SOURCES += host_unittest.cc
dhcp6_unittests_SOURCES += dhcp6_test_utils.cc dhcp6_test_utils.h
dhcp6_unittests_SOURCES += d2_unittest.cc d2_unittest.h
dhcp6_unittests_SOURCES += marker_file.cc
......
......@@ -425,6 +425,12 @@ Dhcp6Client::getLeasesByIAID(const uint32_t iaid) const {
return (leases);
}
void
Dhcp6Client::setDUID(const std::string& str) {
DUID d = DUID::fromText(str);
duid_.reset(new DUID(d));
}
void
Dhcp6Client::modifyDUID() {
if (!duid_) {
......
......@@ -302,6 +302,16 @@ public:
return (srv_);
}
/// @brief Sets the client's DUID from a string value
///
/// Replaces the client's DUID with one constructed from the given
/// string. The string is expected to hexadecimal digits with or
/// without ":" separators.
///
/// The DUID modification affects the value returned by the
/// @c Dhcp6Client::getClientId
void setDUID(const std::string& duid_str);
/// @brief Modifies the client's DUID (adds one to it).
///
/// The DUID should be modified to test negative scenarios when the client
......
......@@ -2094,121 +2094,6 @@ TEST_F(Dhcpv6SrvTest, relayOverrideAndClientClass) {
EXPECT_TRUE(subnet1 == srv_.selectSubnet(sol));
}
// Verify that a host reservation is used and that the lease name is set to
// the reservation hostname.
TEST_F(Dhcpv6SrvTest, hostReservationWithHostName) {
// set duid_ for createHost6
generateClientId();
// create host reservation
IOAddress res_address("2001:db8:1:1::babe");
createHost6(true, IPv6Resrv::TYPE_NA, res_address, "alice");
// Let's create a REQUEST
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
// with a valid hint
IOAddress hint("2001:db8:1:1::dead:beef");
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, hint));
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
ia->addOption(hint_opt);
req->addOption(ia);
// Set client id to match duid_
OptionPtr clientid = generateClientId();
req->addOption(clientid);
// server-id is mandatory in REQUEST
req->addOption(srv_.getServerID());
// Pass it to the server and hope for a REPLY
Pkt6Ptr reply = srv_.processRequest(req);
// check if we get response at all
checkResponse(reply, DHCPV6_REPLY, 1234);
OptionPtr tmp = reply->getOption(D6O_IA_NA);
ASSERT_TRUE(tmp);
// check that IA_NA was returned and that there's an address included
boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234,
subnet_->getT1(),
subnet_->getT2());
ASSERT_TRUE(addr);
// check that we've got the address we requested
checkIAAddr(addr, res_address, Lease::TYPE_NA);
// check that the lease is really in the database
Lease6Ptr l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr);
ASSERT_TRUE(l);
// Verify that lease hostname matches the reservation name
EXPECT_EQ("alice", l->hostname_);
}
// Verify that a host reservation is used and that the lease name is blank
// when the reservation hostname is blank.
TEST_F(Dhcpv6SrvTest, hostReservationWithoutHostName) {
// set duid_ for createHost6
generateClientId();
// create host reservation
IOAddress res_address("2001:db8:1:1::babe");
createHost6(true, IPv6Resrv::TYPE_NA, res_address, "");
// Let's create a REQUEST
Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
req->setRemoteAddr(IOAddress("fe80::abcd"));
req->setIface("eth0");
boost::shared_ptr<Option6IA> ia = generateIA(D6O_IA_NA, 234, 1500, 3000);
// with a valid hint
IOAddress hint("2001:db8:1:1::dead:beef");
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_NA, hint));
OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
ia->addOption(hint_opt);
req->addOption(ia);
// Set client id to match duid_
OptionPtr clientid = generateClientId();
req->addOption(clientid);
// server-id is mandatory in REQUEST
req->addOption(srv_.getServerID());
// Pass it to the server and hope for a REPLY
Pkt6Ptr reply = srv_.processRequest(req);
// check if we get response at all
checkResponse(reply, DHCPV6_REPLY, 1234);
OptionPtr tmp = reply->getOption(D6O_IA_NA);
ASSERT_TRUE(tmp);
// check that IA_NA was returned and that there's an address included
boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234,
subnet_->getT1(),
subnet_->getT2());
ASSERT_TRUE(addr);
// check that we've got the address we requested
checkIAAddr(addr, res_address, Lease::TYPE_NA);
// check that the lease is really in the database
Lease6Ptr l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr);
ASSERT_TRUE(l);
// Verify that lease hostname matches the reservation name
EXPECT_EQ("", l->hostname_);
}
/// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
/// to call processX() methods.
......
......@@ -77,40 +77,6 @@ Dhcpv6SrvTest::checkIA_NA(const Pkt6Ptr& rsp, uint32_t expected_iaid,
return (addr);
}
/// @brief Utility function that creates a host reservation (duid)
///
/// @param add_to_host_mgr true if the reservation should be added
/// @param type specifies reservation type (NA or PD)
/// @param addr specifies reserved address
/// @param hostname specifies hostname to be used in reservation
/// @return created Host object.
HostPtr
Dhcpv6SrvTest::createHost6(bool add_to_host_mgr, IPv6Resrv::Type type,
const asiolink::IOAddress& addr, const std::string& hostname) {
HostPtr host(new Host(&duid_->getDuid()[0], duid_->getDuid().size(),
Host::IDENT_DUID, SubnetID(0), subnet_->getID(),
asiolink::IOAddress("0.0.0.0"), hostname));
// Prefix length doesn't matter here, let's assume address is /128 and
// prefix is /64
IPv6Resrv resv(type, addr, type == IPv6Resrv::TYPE_NA? 128 : 64);
host->addReservation(resv);
if (add_to_host_mgr) {
// Let's add the host.
CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
// We also need to add existing subnet
CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet_);
// Commit this configuration.
CfgMgr::instance().commit();
}
return (host);
}
boost::shared_ptr<Option6IAPrefix>
Dhcpv6SrvTest::checkIA_PD(const Pkt6Ptr& rsp, uint32_t expected_iaid,
uint32_t expected_t1, uint32_t expected_t2) {
......
......@@ -345,17 +345,6 @@ public:
/// @param srv Server to be configured.
void configure(const std::string& config, NakedDhcpv6Srv& srv);
/// @brief Utility function that creates a host reservation (duid)
///
/// @param add_to_host_mgr true if the reservation should be added
/// @param type specifies reservation type (NA or PD)
/// @param addr specifies reserved address
/// @param hostname specifies hostname to be used in reservation
/// @return created Host object.
isc::dhcp::HostPtr
createHost6(bool add_to_host_mgr, isc::dhcp::IPv6Resrv::Type type,
const asiolink::IOAddress& addr, const std::string& hostname);
/// @brief Checks that server response (ADVERTISE or REPLY) contains proper
/// IA_NA option
///
......
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp6/tests/dhcp6_test_utils.h>
#include <dhcp6/tests/dhcp6_client.h>
using namespace isc;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using namespace isc::test;
namespace {
/// @brief Set of JSON configurations used by the Host reservation unit tests.
///
/// - Configuration 0:
/// Single subnet with two reservations, one with a hostname, one without
const char* CONFIGS[] = {
// Configuration 0:
"{ "
"\"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"valid-lifetime\": 4000, "
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ "
" { "
" \"subnet\": \"2001:db8:1::/48\", "
" \"pools\": [ { \"pool\": \"2001:db8:1:1::/64\" } ],"
" \"interface\" : \"eth0\" , "
" \"reservations\": ["
" {"
" \"duid\": \"01:02:03:04\","
" \"ip-addresses\": [ \"2001:db8:1:1::babe\" ],"
" \"hostname\": \"alice\""
" },"
" {"
" \"duid\": \"01:02:03:05\","
" \"ip-addresses\": [ \"2001:db8:1:1::babf\" ]"
" } ]"
" } ]"
"}"
};
/// @brief Test fixture class for testing host reservations
class HostTest : public Dhcpv6SrvTest {
public:
/// @brief Constructor.
///
/// Sets up fake interfaces.
HostTest()
: Dhcpv6SrvTest(),
iface_mgr_test_config_(true) {
}
/// @brief Interface Manager's fake configuration control.
IfaceMgrTestConfig iface_mgr_test_config_;
};
TEST_F(HostTest, basicSARRs) {
Dhcp6Client client;
configure(CONFIGS[0], *client.getServer());
// Make sure we ended-up having expected number of subnets configured.
const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
getCfgSubnets6()->getAll();
ASSERT_EQ(1, subnets->size());
// Configure client to request IA_NA and aAppend IA_NA option
// to the client's message.
client.setDUID("01:02:03:04");
client.useNA();
ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
// Verify that the client we got the reserved address
ASSERT_EQ(1, client.getLeaseNum());
Lease6 lease_client = client.getLease(0);
EXPECT_EQ("2001:db8:1:1::babe", lease_client.addr_.toText());
// Check that the server recorded the lease.
// and lease has reserved hostname
Lease6Ptr lease_server = checkLease(lease_client);
ASSERT_TRUE(lease_server);
EXPECT_EQ("alice", lease_server->hostname_);
// Now redo the client, adding one to the DUID
client.clearConfig();
client.modifyDUID();
client.useNA();
ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
// Verify that the client we got the reserved address
ASSERT_EQ(1, client.getLeaseNum());
lease_client = client.getLease(0);
EXPECT_EQ("2001:db8:1:1::babf", lease_client.addr_.toText());
// Check that the server recorded the lease.
// and that the server lease has NO hostname
lease_server = checkLease(lease_client);
ASSERT_TRUE(lease_server);
EXPECT_EQ("", lease_server->hostname_);
// Now redo the client with yet another DUID and verify that
// we get a dynamic address.
client.clearConfig();
client.modifyDUID();
client.useNA();
ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef"));
// Perform 4-way exchange.
ASSERT_NO_THROW(client.doSARR());
// Verify that the client got a dynamic address
ASSERT_EQ(1, client.getLeaseNum());
lease_client = client.getLease(0);
EXPECT_EQ("2001:db8:1:1::", lease_client.addr_.toText());
// Check that the server recorded the lease.
// and that the server lease has NO hostname
lease_server = checkLease(lease_client);
ASSERT_TRUE(lease_server);
EXPECT_EQ("", lease_server->hostname_);
}
} // end of anonymous namespace
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment