Browse Source

[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
Thomas Markwalder 10 years ago
parent
commit
57b308ffd5

+ 1 - 0
src/bin/dhcp6/tests/Makefile.am

@@ -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

+ 6 - 0
src/bin/dhcp6/tests/dhcp6_client.cc

@@ -426,6 +426,12 @@ Dhcp6Client::getLeasesByIAID(const uint32_t iaid) const {
 }
 
 void
+Dhcp6Client::setDUID(const std::string& str) {
+    DUID d = DUID::fromText(str);
+    duid_.reset(new DUID(d));
+}
+
+void
 Dhcp6Client::modifyDUID() {
     if (!duid_) {
         duid_ = generateDUID(DUID::DUID_LLT);

+ 10 - 0
src/bin/dhcp6/tests/dhcp6_client.h

@@ -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

+ 0 - 115
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -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.
 

+ 0 - 34
src/bin/dhcp6/tests/dhcp6_test_utils.cc

@@ -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) {

+ 0 - 11
src/bin/dhcp6/tests/dhcp6_test_utils.h

@@ -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
     ///

+ 146 - 0
src/bin/dhcp6/tests/host_unittest.cc

@@ -0,0 +1,146 @@
+// 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