BIND 10 trac2140, updated. 0b7e9646307a6e58d3e1df60c68cbac5dbcbfecb [2140] LeaseMgr tweaks.

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Sep 12 19:28:04 UTC 2012


The branch, trac2140 has been updated
       via  0b7e9646307a6e58d3e1df60c68cbac5dbcbfecb (commit)
       via  01eb4277b933cb0537204d98b9200550ee3eb641 (commit)
       via  5ff43d80fb8eaae5ac2621a5a754cf94204149de (commit)
      from  2c7936f05e6e2055016cdf7f4c915a80f465cde5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 0b7e9646307a6e58d3e1df60c68cbac5dbcbfecb
Author: Tomek Mrugalski <tomasz at isc.org>
Date:   Wed Sep 12 21:27:30 2012 +0200

    [2140] LeaseMgr tweaks.

commit 01eb4277b933cb0537204d98b9200550ee3eb641
Author: Tomek Mrugalski <tomasz at isc.org>
Date:   Wed Sep 12 20:39:07 2012 +0200

    [2140] ClientId class implemented and tested.

commit 5ff43d80fb8eaae5ac2621a5a754cf94204149de
Author: Tomek Mrugalski <tomasz at isc.org>
Date:   Wed Sep 12 17:09:40 2012 +0200

    [2140] DUID is now a separate class in separate files

-----------------------------------------------------------------------

Summary of changes:
 src/lib/dhcp/Makefile.am                 |    1 +
 src/lib/dhcp/duid.cc                     |  111 +++++++++++++++++++
 src/lib/dhcp/duid.h                      |  110 +++++++++++++++++++
 src/lib/dhcp/lease_mgr.cc                |   12 ++-
 src/lib/dhcp/lease_mgr.h                 |  140 +++++++++++-------------
 src/lib/dhcp/tests/Makefile.am           |    1 +
 src/lib/dhcp/tests/duid_unittest.cc      |  173 ++++++++++++++++++++++++++++++
 src/lib/dhcp/tests/lease_mgr_unittest.cc |   66 ++++--------
 8 files changed, 492 insertions(+), 122 deletions(-)
 create mode 100644 src/lib/dhcp/duid.cc
 create mode 100644 src/lib/dhcp/duid.h
 create mode 100644 src/lib/dhcp/tests/duid_unittest.cc

-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index 9f52690..b656e83 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -29,6 +29,7 @@ libb10_dhcp___la_SOURCES += option4_addrlst.cc option4_addrlst.h
 libb10_dhcp___la_SOURCES += dhcp6.h dhcp4.h
 libb10_dhcp___la_SOURCES += pkt6.cc pkt6.h
 libb10_dhcp___la_SOURCES += pkt4.cc pkt4.h
+libb10_dhcp___la_SOURCES += duid.cc duid.h
 
 EXTRA_DIST  = README
 #EXTRA_DIST += log_messages.mes
diff --git a/src/lib/dhcp/duid.cc b/src/lib/dhcp/duid.cc
new file mode 100644
index 0000000..912fc48
--- /dev/null
+++ b/src/lib/dhcp/duid.cc
@@ -0,0 +1,111 @@
+// Copyright (C) 2012 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 <vector>
+#include <exceptions/exceptions.h>
+#include <stdint.h>
+#include <util/io_utilities.h>
+#include <dhcp/duid.h>
+
+namespace isc {
+namespace dhcp {
+
+DUID::DUID(const std::vector<uint8_t>& duid) {
+    if (duid.size() > MAX_DUID_LEN) {
+        isc_throw(OutOfRange, "DUID too large");
+    } else {
+        duid_ = duid;
+    }
+}
+
+DUID::DUID(const uint8_t * data, size_t len) {
+    if (len > MAX_DUID_LEN) {
+        isc_throw(OutOfRange, "DUID too large");
+    }
+
+    duid_ = std::vector<uint8_t>(data, data + len);
+}
+
+const std::vector<uint8_t>& DUID::getDuid() const {
+    return duid_;
+}
+
+DUID::DUIDType DUID::getType() const {
+    if (duid_.size() < 2) {
+        return (DUID_UNKNOWN);
+    }
+    uint16_t type = (duid_[0] << 8) + duid_[1];
+    if (type < DUID_MAX) {
+        return (static_cast<DUID::DUIDType>(type));
+    } else {
+        return (DUID_UNKNOWN);
+    }
+}
+
+bool DUID::operator == (const DUID& other) const {
+    return (this->duid_ == other.duid_);
+}
+
+bool DUID::operator != (const DUID& other) const {
+    return (this->duid_ != other.duid_);
+}
+
+/// constructor based on vector<uint8_t>
+ClientId::ClientId(const std::vector<uint8_t>& clientid)
+    :DUID(clientid) {
+}
+
+/// constructor based on C-style data
+ClientId::ClientId(const uint8_t *clientid, size_t len)
+    :DUID(clientid, len) {
+}
+
+/// constructor based on IOAddress
+ClientId::ClientId(const isc::asiolink::IOAddress& addr)
+    :DUID(std::vector<uint8_t>(4, 0)) {
+    if (addr.getFamily() != AF_INET) {
+        isc_throw(BadValue, "Client-id supports only IPv4 addresses");
+    }
+    isc::util::writeUint32(addr, &duid_[0]);
+}
+
+/// @brief returns reference to the client-id data
+const std::vector<uint8_t> ClientId::getClientId() const {
+    return duid_;
+}
+
+isc::asiolink::IOAddress ClientId::getAddress() const {
+    if (duid_.size() != sizeof(uint32_t)) {
+        isc_throw(BadValue, "This client-id is not an IPv4 address");
+    }
+
+    return isc::asiolink::IOAddress( isc::util::readUint32(&duid_[0]) );
+}
+
+bool ClientId::isAddress() const {
+    return (duid_.size() == sizeof(uint32_t));
+}
+
+// compares two client-ids
+bool ClientId::operator == (const ClientId& other) const {
+    return (this->duid_ == other.duid_);
+}
+
+// compares two client-ids
+bool ClientId::operator != (const ClientId& other) const {
+    return (this->duid_ != other.duid_);
+}
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
diff --git a/src/lib/dhcp/duid.h b/src/lib/dhcp/duid.h
new file mode 100644
index 0000000..132d1d7
--- /dev/null
+++ b/src/lib/dhcp/duid.h
@@ -0,0 +1,110 @@
+// Copyright (C) 2012 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 <stdint.h>
+#include <unistd.h>
+#include <vector>
+#include <asiolink/io_address.h>
+
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Holds DUID (DHCPv6 Unique Identifier)
+///
+/// This class holds DUID, that is used in client-id, server-id and
+/// several other options. It is used to identify DHCPv6 entity.
+class DUID {
+ public:
+    /// @brief maximum duid size
+    /// As defined in RFC3315, section 9.1
+    static const size_t MAX_DUID_LEN = 128;
+
+    /// @brief specifies DUID type
+    typedef enum {
+        DUID_UNKNOWN = 0, ///< invalid/unknown type
+        DUID_LLT = 1,     ///< link-layer + time, see RFC3315, section 9.2
+        DUID_EN = 2,      ///< enterprise-id, see RFC3315, section 9.3
+        DUID_LL = 3,      ///< link-layer, see RFC3315, section 9.4
+        DUID_UUID = 4,    ///< UUID, see RFC6355
+        DUID_MAX          ///< not a real type, just maximum defined value + 1
+    } DUIDType;
+
+    /// @brief creates a DUID
+    DUID(const std::vector<uint8_t>& duid);
+
+    /// @brief creates a DUID
+    DUID(const uint8_t *duid, size_t len);
+
+    /// @brief returns a const reference to the actual DUID value
+    ///
+    /// Note: This reference is only valid as long as the DUID
+    /// that returned it.
+    const std::vector<uint8_t>& getDuid() const;
+
+    /// @brief returns DUID type
+    DUIDType getType() const;
+
+    // compares two DUIDs
+    bool operator == (const DUID& other) const;
+
+    // compares two DUIDs
+    bool operator != (const DUID& other) const;
+
+ protected:
+    /// the actual content of the DUID
+    std::vector<uint8_t> duid_;
+};
+
+/// @brief Holds Client identifier or client IPv4 address
+///
+/// This class is intended to be a generic IPv4 client identifier. It can hold
+/// a client-id
+class ClientId : DUID {
+ public:
+
+    /// constructor based on vector<uint8_t>
+    ClientId(const std::vector<uint8_t>& clientid);
+
+    /// constructor based on C-style data
+    ClientId(const uint8_t *clientid, size_t len);
+
+    /// constructor based on IOAddress
+    ///
+    /// @throw BadValue if specified address is not IPv4
+    ClientId(const isc::asiolink::IOAddress& addr);
+
+    /// @brief returns reference to the client-id data
+    ///
+    /// This reference is only valid as long as the object
+    /// that returned it.
+    const std::vector<uint8_t> getClientId() const;
+
+    /// @brief return an IPv4 address represented by this client-id
+    ///
+    /// @throw BadValue if this client-id is not an IPv4 address
+    isc::asiolink::IOAddress getAddress() const;
+
+    /// @brief returns if client-id is an address
+    bool isAddress() const;
+
+    // compares two client-ids
+    bool operator == (const ClientId& other) const;
+
+    // compares two client-ids
+    bool operator != (const ClientId& other) const;
+};
+
+}; // end of isc::dhcp namespace
+}; // end of isc namespace
diff --git a/src/lib/dhcp/lease_mgr.cc b/src/lib/dhcp/lease_mgr.cc
index 6e349bd..927c328 100644
--- a/src/lib/dhcp/lease_mgr.cc
+++ b/src/lib/dhcp/lease_mgr.cc
@@ -31,6 +31,10 @@ using namespace isc::dhcp;
 
 LeaseMgr::LeaseMgr(const std::string& dbconfig) {
 
+    if (dbconfig.length() == 0) {
+        return;
+    }
+
     vector<string> tokens;
 
     boost::split(tokens, dbconfig, boost::is_any_of("\t "));
@@ -47,8 +51,14 @@ LeaseMgr::LeaseMgr(const std::string& dbconfig) {
         }
 
     }
+}
 
-    /// @todo: Parse dbconfig string
+std::string LeaseMgr::getParameter(const std::string& name) const {
+    map<string, string>::const_iterator param = parameters_.find(name);
+    if (param == parameters_.end()) {
+        isc_throw(BadValue, "Parameter not found");
+    }
+    return (param->second);
 }
 
 LeaseMgr::~LeaseMgr() {
diff --git a/src/lib/dhcp/lease_mgr.h b/src/lib/dhcp/lease_mgr.h
index 63c166c..3f90ee0 100644
--- a/src/lib/dhcp/lease_mgr.h
+++ b/src/lib/dhcp/lease_mgr.h
@@ -18,48 +18,12 @@
 #include <map>
 #include <asiolink/io_address.h>
 #include <boost/shared_ptr.hpp>
+#include <dhcp/option.h>
+#include <dhcp/duid.h>
 
 namespace isc {
 namespace dhcp {
 
-/// @brief Holds Client identifier
-class ClientId {
- public:
-    ClientId(const std::vector<uint8_t>& duid);
-    ClientId(const char *duid, size_t len);
-    ClientId(uint32_t id);
-    ClientId(const isc::asiolink::IOAddress& addr);
-    const std::vector<uint8_t> getClientId() const;
-    bool operator == (const ClientId& other);
- protected:
-    std::vector<uint8_t> clientid_;
-};
-
-/// @brief Holds DUID (DHCPv6 Unique Identifier)
-///
-/// This class holds DUID, that is used in client-id, server-id and
-/// several other options. It is used to identify DHCPv6 entity.
-class DUID {
-
-    /// @brief specifies DUID type
-    typedef enum {
-        DUID_UNKNOWN = 0, // invalid/unknown type
-        DUID_LLT = 1, // link-layer + time, see RFC3315, section 9.2
-        DUID_EN = 2,  // enterprise-id, see RFC3315, section 9.3
-        DUID_LL = 3,  // link-layer, see RFC3315, section 9.4
-        DUID_UUID = 4, // UUID, see RFC6355
-    } DUIDType;
-
- public:
-    DUID(const std::vector<uint8_t>& duid);
-    DUID(const char *duid, size_t len);
-    const std::vector<uint8_t> getDuid() const;
-    DUIDType getType();
-    bool operator == (const DUID& other);
- protected:
-    std::vector<uint8_t> duid_;
-};
-
 /// @brief Structure that holds a lease for IPv4 address
 ///
 /// For performance reasons it is a simple structure, not a class. If we chose
@@ -67,7 +31,8 @@ class DUID {
 /// would be required. As this is a critical part of the code that will be used
 /// extensively, direct access is warranted.
 struct Lease4 {
-    uint32_t addr_; /// IPv4 address
+    /// IPv4 address
+    isc::asiolink::IOAddress addr_;
 
     /// @brief Address extension
     ///
@@ -76,16 +41,18 @@ struct Lease4 {
     /// Port-restricted Addresses), where several clients may get the same address, but
     /// different port ranges. This feature is not expected to be widely used.
     /// Under normal circumstances, the value should be 0.
-    uint32_t ext_; /// address extension
+    uint32_t ext_;
 
     /// @brief hardware address
-    std::vector<uint8_t> hwaddr;
+    std::vector<uint8_t> hwaddr_;
 
     /// @brief client identifier
-    std::vector<uint8_t> client_id; 
+    boost::shared_ptr<ClientId> client_id_;
 
-    /// valid lifetime timestamp
-    uint32_t valid_lft;
+    /// @brief valid lifetime
+    ///
+    /// Expressed as number of seconds since cltt
+    uint32_t valid_lft_;
 
     /// @brief Recycle timer
     ///
@@ -93,44 +60,45 @@ struct Lease4 {
     /// or expired. This timer specifies number of seconds that it should be kept
     /// after release or expiration, in case the client returns. This feature is not
     /// currently used and this value is set to 0.
-    uint32_t recycle_time; 
+    uint32_t recycle_time_;
 
     /// @brief client last transmission time
     ///
     /// Specifies a timestamp, when last transmission from a client was received.
-    time_t cltt;
+    time_t cltt_;
 
     /// @brief Pool identifier
     ///
     /// Specifies pool-id of the pool that the lease belongs to
-    uint32_t pool_id;
+    uint32_t pool_id_;
 
     /// @brief Is this a fixed lease?
     ///
     /// Fixed leases are kept after they are released/expired.
-    bool fixed;
+    bool fixed_;
 
     /// @brief client hostname
     ///
     /// This field may be empty
-    std::string hostname;
+    std::string hostname_;
 
     /// @brief did we update AAAA record for this lease?
-    bool fqdn_fwd;
+    bool fqdn_fwd_;
 
-    /// @brief did we update PTR record for this lease? 
-    bool fqdn_rev;
+    /// @brief did we update PTR record for this lease?
+    bool fqdn_rev_;
 
     /// @brief additional options stored with this lease
     ///
-    /// Currently not used.
-    std::string options; 
+    /// This field is currently not used.
+    /// @todo We need a way to store options in the databased.
+    Option::OptionCollection options_;
 
     /// @brief Lease comments.
     ///
     /// Currently not used. It may be used for keeping comments made by the
     /// system administrator.
-    std::string comments; 
+    std::string comments_;
 };
 
 /// @brief Pointer to a Lease4 structure.
@@ -173,7 +141,7 @@ struct Lease6 {
     /// client has its own unique DUID (DHCP Unique IDentifier). Furthermore, client's
     /// HW address is not always available, because client may be behind a relay (relay
     /// stores only link-local address).
-    std::vector<uint8_t> hwaddr;
+    std::vector<uint8_t> hwaddr_;
 
     /// @brief client identifier
     boost::shared_ptr<DUID> duid_;
@@ -182,17 +150,21 @@ struct Lease6 {
     ///
     /// This parameter specifies preferred lifetime since the lease was assigned/renewed
     /// (cltt), expressed in seconds.
-    uint32_t preferred_lft;
+    uint32_t preferred_lft_;
 
     /// @brief valid lifetime
-    uint32_t valid_lft;
+    ///
+    /// This parameter specified valid lifetime since the lease was assigned/renewed
+    /// (cltt), expressed in seconds.
+    uint32_t valid_lft_;
 
     /// @brief T1 timer
     ///
     /// Specifies renewal time. Although technically it is a property of IA container,
     /// not the address itself, since our data model does not define separate IA
     /// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
-    /// for the same IA, each must have consistent T1 and T2 values.
+    /// for the same IA, each must have consistent T1 and T2 values. Specified in
+    /// seconds since cltt.
     uint32_t t1_;
 
     /// @brief T2 timer
@@ -200,7 +172,8 @@ struct Lease6 {
     /// Specifies rebinding time. Although technically it is a property of IA container,
     /// not the address itself, since our data model does not define separate IA
     /// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
-    /// for the same IA, each must have consistent T1 and T2 values.
+    /// for the same IA, each must have consistent T1 and T2 values. Specified in
+    /// seconds since cltt.
     uint32_t t2_;
 
     /// @brief Recycle timer
@@ -209,45 +182,45 @@ struct Lease6 {
     /// or expired. This timer specifies number of seconds that it should be kept
     /// after release or expiration, in case the client returns. This feature is not
     /// currently used and this value is set to 0.
-    uint32_t recycle_time; 
+    uint32_t recycle_time_;
 
     /// @brief client last transmission time
     ///
     /// Specifies a timestamp, when last transmission from a client was received.
-    time_t cltt;
+    time_t cltt_;
 
     /// @brief Pool identifier
     ///
     /// Specifies pool-id of the pool that the lease belongs to
-    uint32_t pool_id;
+    uint32_t pool_id_;
 
     /// @brief Is this a fixed lease?
     ///
     /// Fixed leases are kept after they are released/expired.
-    bool fixed;
+    bool fixed_;
 
     /// @brief client hostname
     ///
     /// This field may be empty
-    std::string hostname;
+    std::string hostname_;
 
     /// @brief did we update AAAA record for this lease?
-    bool fqdn_fwd;
+    bool fqdn_fwd_;
 
-    /// @brief did we update PTR record for this lease? 
-    bool fqdn_rev;
+    /// @brief did we update PTR record for this lease?
+    bool fqdn_rev_;
 
     /// @brief additional options stored with this lease
     ///
     /// That field is currently not used. We may keep extra options assigned
     /// for leasequery and possibly other purposes.
-    /// @todo: Define this as a container of options
-    std::string options; 
+    /// @todo We need a way to store options in the databased.
+    Option::OptionCollection options_;
 
-    /// @brief /// comments on that lease
+    /// @brief Lease comments
     ///
-    /// (currently not used)
-    std::string comments; 
+    /// This field is currently not used.
+    std::string comments_;
 };
 
 /// @brief Pointer to a Lease6 structure.
@@ -364,14 +337,31 @@ public:
     virtual std::string getDescription() const = 0;
 
     /// @brief Returns backend version.
+    ///
+    /// @todo: We will need to implement 3 version functions eventually:
+    /// A. abstract API version
+    /// B. backend version
+    /// C. database version (stored in the database scheme)
+    ///
+    /// and then check that:
+    /// B>=A and B=C (it is ok to have newer backend, as it should be backward
+    /// compatible)
+    /// Also if B>C, some database upgrade procedure may happen
     virtual std::string getVersion() const = 0;
 
-    /// @todo: Add pool management here
-
     /// @todo: Add host management here
+    /// As host reservation is outside of scope for 2012, support for hosts
+    /// is currently postponed.
+
 protected:
+    /// @brief returns value of the parameter
+    std::string getParameter(const std::string& name) const;
 
     /// @brief list of parameters passed in dbconfig
+    ///
+    /// That will be mostly used for storing database name, username,
+    /// password and other parameters required for DB access. It is not
+    /// intended to keep any DHCP-related parameters.
     std::map<std::string, std::string> parameters_;
 };
 
diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am
index 05faee8..68e2e00 100644
--- a/src/lib/dhcp/tests/Makefile.am
+++ b/src/lib/dhcp/tests/Makefile.am
@@ -39,6 +39,7 @@ libdhcp___unittests_SOURCES += ../option4_addrlst.cc ../option4_addrlst.h option
 libdhcp___unittests_SOURCES += ../option.h ../option.cc option_unittest.cc
 libdhcp___unittests_SOURCES += ../pkt6.h ../pkt6.cc pkt6_unittest.cc
 libdhcp___unittests_SOURCES += ../pkt4.h ../pkt4.cc pkt4_unittest.cc
+libdhcp___unittests_SOURCES += ../duid.h ../duid.cc duid_unittest.cc
 
 libdhcp___unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
 libdhcp___unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
diff --git a/src/lib/dhcp/tests/duid_unittest.cc b/src/lib/dhcp/tests/duid_unittest.cc
new file mode 100644
index 0000000..d3da6e8
--- /dev/null
+++ b/src/lib/dhcp/tests/duid_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright (C) 2011  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 <iostream>
+#include <sstream>
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+#include <exceptions/exceptions.h>
+#include <boost/scoped_ptr.hpp>
+#include <asiolink/io_address.h>
+#include <dhcp/duid.h>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+// don't import the entire boost namespace.  It will unexpectedly hide uint8_t
+// for some systems.
+using boost::scoped_ptr;
+
+namespace {
+
+TEST(DuidTest, constructor) {
+
+    uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+
+    vector<uint8_t> data2(data1, data1 + sizeof(data1));
+
+    scoped_ptr<DUID> duid1(new DUID(data1, sizeof(data1)));
+    scoped_ptr<DUID> duid2(new DUID(data2));
+
+    vector<uint8_t> vecdata = duid1->getDuid();
+    EXPECT_EQ(data2, vecdata);
+    EXPECT_EQ(DUID::DUID_LLT, duid1->getType());
+
+    vecdata = duid2->getDuid();
+    EXPECT_EQ(data2, vecdata);
+
+    EXPECT_EQ(DUID::DUID_LLT, duid2->getType());
+}
+
+TEST(DuidTest, size) {
+    const int MAX_DUID_SIZE = 128;
+    uint8_t data[MAX_DUID_SIZE + 1];
+    vector<uint8_t> data2;
+    for (uint8_t i = 0; i < MAX_DUID_SIZE + 1; ++i) {
+        data[i] = i;
+        if (i < MAX_DUID_SIZE)
+            data2.push_back(i);
+    }
+    ASSERT_EQ(data2.size(), MAX_DUID_SIZE);
+
+    scoped_ptr<DUID> duidmaxsize1(new DUID(data, MAX_DUID_SIZE));
+    scoped_ptr<DUID> duidmaxsize2(new DUID(data2));
+
+    EXPECT_THROW(
+        scoped_ptr<DUID> toolarge1(new DUID(data, MAX_DUID_SIZE + 1)),
+        OutOfRange);
+
+    // that's one too much
+    data2.push_back(128);
+
+    EXPECT_THROW(
+        scoped_ptr<DUID> toolarge2(new DUID(data2)),
+        OutOfRange);
+}
+
+TEST(DuidTest, getType) {
+    uint8_t llt[] =     {0, 1, 2, 3, 4, 5, 6};
+    uint8_t en[] =      {0, 2, 2, 3, 4, 5, 6};
+    uint8_t ll[] =      {0, 3, 2, 3, 4, 5, 6};
+    uint8_t uuid[] =    {0, 4, 2, 3, 4, 5, 6};
+    uint8_t invalid[] = {0,55, 2, 3, 4, 5, 6};
+
+    scoped_ptr<DUID> duid_llt(new DUID(llt, sizeof(llt)));
+    scoped_ptr<DUID> duid_en(new DUID(en, sizeof(en)));
+    scoped_ptr<DUID> duid_ll(new DUID(ll, sizeof(ll)));
+    scoped_ptr<DUID> duid_uuid(new DUID(uuid, sizeof(uuid)));
+    scoped_ptr<DUID> duid_invalid(new DUID(invalid, sizeof(invalid)));
+
+    EXPECT_EQ(DUID::DUID_LLT,     duid_llt->getType());
+    EXPECT_EQ(DUID::DUID_EN,      duid_en->getType());
+    EXPECT_EQ(DUID::DUID_LL,      duid_ll->getType());
+    EXPECT_EQ(DUID::DUID_UUID,    duid_uuid->getType());
+    EXPECT_EQ(DUID::DUID_UNKNOWN, duid_invalid->getType());
+}
+
+TEST(DuidTest, operators) {
+    uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+    uint8_t data2[] = {0, 1, 2, 3, 4};
+    uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
+    uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
+
+    scoped_ptr<DUID> duid1(new DUID(data1, sizeof(data1)));
+    scoped_ptr<DUID> duid2(new DUID(data2, sizeof(data2)));
+    scoped_ptr<DUID> duid3(new DUID(data3, sizeof(data3)));
+    scoped_ptr<DUID> duid4(new DUID(data4, sizeof(data4)));
+
+    EXPECT_TRUE(*duid1 == *duid4);
+    EXPECT_FALSE(*duid1 == *duid2);
+    EXPECT_FALSE(*duid1 == *duid3);
+
+    EXPECT_FALSE(*duid1 != *duid4);
+    EXPECT_TRUE(*duid1 != *duid2);
+    EXPECT_TRUE(*duid1 != *duid3);
+}
+
+TEST(ClientIdTest, constructor) {
+    IOAddress addr2("192.0.2.1");
+    IOAddress addr3("2001:db8:1::1");
+
+    uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+    vector<uint8_t> data2(data1, data1 + sizeof(data1));
+    uint8_t data3[] = {192, 0 , 2, 1 };
+
+    // checks for C-style construtor (uint8_t * + len)
+    scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
+    vector<uint8_t> vecdata = id1->getClientId();
+    EXPECT_EQ(data2, vecdata);
+    EXPECT_FALSE(id1->isAddress());
+    EXPECT_THROW(id1->getAddress(), BadValue);
+
+    // checks for vector-based constructor
+    scoped_ptr<ClientId> id2(new ClientId(data2));
+    vecdata = id2->getClientId();
+    EXPECT_EQ(data2, vecdata);
+    EXPECT_FALSE(id1->isAddress());
+    EXPECT_THROW(id1->getAddress(), BadValue);
+
+    // checks for IOAddress based constructor
+    scoped_ptr<ClientId> id3(new ClientId(addr2));
+    vecdata = id3->getClientId();
+    EXPECT_TRUE(vecdata == vector<uint8_t>(data3, data3 + 4));
+    EXPECT_EQ("192.0.2.1", id3->getAddress().toText());
+
+    // should support v4 address only, v6 is a wrong address here
+    EXPECT_THROW(new ClientId(addr3), BadValue);
+}
+
+TEST(ClientIdTest, operators) {
+    uint8_t data1[] = {0, 1, 2, 3, 4, 5, 6};
+    uint8_t data2[] = {0, 1, 2, 3, 4};
+    uint8_t data3[] = {0, 1, 2, 3, 4, 5, 7}; // last digit different
+    uint8_t data4[] = {0, 1, 2, 3, 4, 5, 6}; // the same as 1
+
+    scoped_ptr<ClientId> id1(new ClientId(data1, sizeof(data1)));
+    scoped_ptr<ClientId> id2(new ClientId(data2, sizeof(data2)));
+    scoped_ptr<ClientId> id3(new ClientId(data3, sizeof(data3)));
+    scoped_ptr<ClientId> id4(new ClientId(data4, sizeof(data4)));
+
+    EXPECT_TRUE(*id1 == *id4);
+    EXPECT_FALSE(*id1 == *id2);
+    EXPECT_FALSE(*id1 == *id3);
+
+    EXPECT_FALSE(*id1 != *id4);
+    EXPECT_TRUE(*id1 != *id2);
+    EXPECT_TRUE(*id1 != *id3);
+}
+
+} // end of anonymous namespace
diff --git a/src/lib/dhcp/tests/lease_mgr_unittest.cc b/src/lib/dhcp/tests/lease_mgr_unittest.cc
index 601c38e..39102bb 100644
--- a/src/lib/dhcp/tests/lease_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/lease_mgr_unittest.cc
@@ -25,6 +25,11 @@ using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::dhcp;
 
+// This is a concrete implementation of a Lease database.
+// It does not do anything useful now, and is used for abstract LeaseMgr
+// class testing. It may later evolve into more useful backend if the
+// need arises. We can reuse code from memfile benchmark. See code in
+// tests/tools/dhcp-ubench/memfile_bench.{cc|h}
 class Memfile_LeaseMgr : public LeaseMgr {
 public:
 
@@ -124,6 +129,9 @@ public:
 
     /// @brief Returns backend version.
     std::string getVersion() const { return "test-version"; }
+
+    using LeaseMgr::getParameter;
+
 protected:
 
 
@@ -185,51 +193,6 @@ std::string Memfile_LeaseMgr::getDescription() const {
                    "purpose is to test abstract lease manager API."));
 }
 
-#if 0
-bool Memfile_LeaseMgr::addLease(Lease4Ptr lease) {
-    if (ip4Hash_.find(lease->addr) != ip4Hash_.end()) {
-        // there is such an address already in the hash
-        return false;
-    }
-    ip4Hash_.insert(pair<uint32_t, Lease4Ptr>(lease->addr, lease));
-    lease->hostname = "add";
-    writeLease(lease);
-    return (true);
-}
-
-Lease4Ptr Memfile_LeaseMgr::getLease(uint32_t addr) {
-    leaseIt x = ip4Hash_.find(addr);
-    if (x != ip4Hash_.end()) {
-        return x->second; // found
-    }
-
-    // not found
-    return Lease4Ptr();
-}
-
-Lease4Ptr Memfile_LeaseMgr::updateLease(uint32_t addr, uint32_t new_cltt) {
-    leaseIt x = ip4Hash_.find(addr);
-    if (x != ip4Hash_.end()) {
-        x->second->cltt = new_cltt;
-        x->second->hostname = "update";
-        writeLease(x->second);
-        return x->second;
-    }
-    return Lease4Ptr();
-}
-
-bool Memfile_LeaseMgr::deleteLease(uint32_t addr) {
-    leaseIt x = ip4Hash_.find(addr);
-    if (x != ip4Hash_.end()) {
-        x->second->hostname = "delete";
-        writeLease(x->second);
-        ip4Hash_.erase(x);
-        return true;
-    }
-    return false;
-}
-#endif
-
 namespace {
 // empty class for now, but may be extended once Addr6 becomes bigger
 class LeaseMgrTest : public ::testing::Test {
@@ -240,9 +203,20 @@ public:
 
 TEST_F(LeaseMgrTest, constructor) {
 
-    LeaseMgr * leaseMgr = new Memfile_LeaseMgr("param1=value1");
+    // should not throw any exceptions here
+    Memfile_LeaseMgr * leaseMgr = new Memfile_LeaseMgr("");
+    delete leaseMgr;
+
+    leaseMgr = new Memfile_LeaseMgr("param1=value1 param2=value2");
+
+    EXPECT_EQ("value1", leaseMgr->getParameter("param1"));
+    EXPECT_EQ("value2", leaseMgr->getParameter("param2"));
+    EXPECT_THROW(leaseMgr->getParameter("param3"), BadValue);
 
     delete leaseMgr;
 }
 
+// There's no point in calling any other methods in LeaseMgr, as they
+// are purely virtual, so we would only call Memfile_LeaseMgr methods.
+
 }; // end of anonymous namespace



More information about the bind10-changes mailing list