BIND 10 trac2404, updated. b6c480a59485c8a53d9beea2dba85a667aef7556 [2404] Extending test cases as the result of review
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Dec 3 21:24:27 UTC 2012
The branch, trac2404 has been updated
via b6c480a59485c8a53d9beea2dba85a667aef7556 (commit)
via 495d4e2f6970ef05f5f764f1fcd6661b5403cefb (commit)
via ef364ccb84c6b8eea4952c0a59c6bb560ff43ca4 (commit)
from 46cfa0779257292e55c048a3854f0df4fe1cbd08 (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 b6c480a59485c8a53d9beea2dba85a667aef7556
Author: Stephen Morris <stephen at isc.org>
Date: Mon Dec 3 21:23:48 2012 +0000
[2404] Extending test cases as the result of review
commit 495d4e2f6970ef05f5f764f1fcd6661b5403cefb
Author: Stephen Morris <stephen at isc.org>
Date: Mon Dec 3 15:35:36 2012 +0000
[2404] More changes as a result of review
Including:
* Updates to comments etc.
* Addition of Lease4::operator==() (and associated unit tests)
commit ef364ccb84c6b8eea4952c0a59c6bb560ff43ca4
Author: Stephen Morris <stephen at isc.org>
Date: Fri Nov 30 15:49:42 2012 +0000
[2404] First set of changes as a result of review
* Corrections of miscellaneous typos in comments
* Update database version to 1.0
* Handling of truncation while fetching data from the database
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcp/duid.h | 3 +-
src/lib/dhcpsrv/database_backends.dox | 11 +
src/lib/dhcpsrv/dhcpdb_create.mysql | 9 +-
src/lib/dhcpsrv/lease_mgr.cc | 39 +-
src/lib/dhcpsrv/lease_mgr.h | 33 +-
src/lib/dhcpsrv/mysql_lease_mgr.cc | 251 ++++++++++---
src/lib/dhcpsrv/mysql_lease_mgr.h | 87 ++++-
.../dhcpsrv/tests/lease_mgr_factory_unittest.cc | 2 +-
src/lib/dhcpsrv/tests/lease_mgr_unittest.cc | 384 +++++++++++++++++---
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc | 326 ++++++++++++-----
src/lib/dhcpsrv/tests/schema_copy.h | 8 +-
11 files changed, 936 insertions(+), 217 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/duid.h b/src/lib/dhcp/duid.h
index e226216..84ada81 100644
--- a/src/lib/dhcp/duid.h
+++ b/src/lib/dhcp/duid.h
@@ -84,7 +84,8 @@ typedef boost::shared_ptr<DUID> DuidPtr;
/// This class is intended to be a generic IPv4 client identifier. It can hold
/// a client-id
class ClientId : DUID {
- public:
+public:
+ static const size_t MAX_CLIENT_ID_LEN = DUID::MAX_DUID_LEN;
/// constructor based on vector<uint8_t>
ClientId(const std::vector<uint8_t>& clientid);
diff --git a/src/lib/dhcpsrv/database_backends.dox b/src/lib/dhcpsrv/database_backends.dox
index 057f7c0..f954bed 100644
--- a/src/lib/dhcpsrv/database_backends.dox
+++ b/src/lib/dhcpsrv/database_backends.dox
@@ -8,6 +8,17 @@
the abstract isc::dhcp::LeaseMgr class. This provides methods to
create, retrieve, modify and delete leases in the database.
+ There are currently two available Lease Managers, MySQL and Memfile:
+
+ - The MySQL lease manager uses the freely available MySQL as its backend
+ database. This is not included in BIND 10 DHCP by default:
+ the --with-dhcp-mysql switch must be supplied to "configure" for support
+ to be compiled into the software.
+ - Memfile is an in-memory lease database, with (currently) nothing being
+ written to persistent storage. The long-term plans for the backend do
+ include the ability to store this on disk, but it is currently a
+ low-priority item.
+
@section dhcpdb-instantiation Instantiation of Lease Managers
A lease manager is instantiated through the LeaseMgrFactory class. This
diff --git a/src/lib/dhcpsrv/dhcpdb_create.mysql b/src/lib/dhcpsrv/dhcpdb_create.mysql
index 777a12f..695091d 100644
--- a/src/lib/dhcpsrv/dhcpdb_create.mysql
+++ b/src/lib/dhcpsrv/dhcpdb_create.mysql
@@ -43,7 +43,7 @@ CREATE TABLE lease4 (
# N.B. The use of a VARCHAR for the address is temporary for development:
# it will eventually be replaced by BINARY(16).
CREATE TABLE lease6 (
- address VARCHAR(40) PRIMARY KEY NOT NULL, # IPv6 address
+ address VARCHAR(39) PRIMARY KEY NOT NULL, # IPv6 address
duid VARBINARY(128), # DUID
valid_lifetime INT UNSIGNED, # Length of the lease (seconds)
expire TIMESTAMP, # Expiration time of the lease
@@ -72,12 +72,17 @@ COMMIT;
# This table is only modified during schema upgrades. For historical reasons
# (related to the names of the columns in the BIND 10 DNS database file), the
# first column is called "version" and not "major".
+#
+# NOTE: this MUST be kept in step with src/lib/dhcpsrv/tests/schema_copy.h,
+# which defines the schema for the unit tests. If you are updating
+# the version number, the schema has changed: please ensure that
+# schema_copy.h has been updated as well.
CREATE TABLE schema_version (
version INT PRIMARY KEY NOT NULL, # Major version number
minor INT # Minor version number
);
START TRANSACTION;
-INSERT INTO schema_version VALUES (0, 2);
+INSERT INTO schema_version VALUES (1, 0);
COMMIT;
# Notes:
diff --git a/src/lib/dhcpsrv/lease_mgr.cc b/src/lib/dhcpsrv/lease_mgr.cc
index 5a3dc59..f7b6373 100644
--- a/src/lib/dhcpsrv/lease_mgr.cc
+++ b/src/lib/dhcpsrv/lease_mgr.cc
@@ -29,7 +29,8 @@
using namespace std;
-using namespace isc::dhcp;
+namespace isc {
+namespace dhcp {
Lease6::Lease6(LeaseType type, const isc::asiolink::IOAddress& addr,
DuidPtr duid, uint32_t iaid, uint32_t preferred, uint32_t valid,
@@ -83,16 +84,46 @@ Lease6::toText() {
}
bool
+Lease4::operator==(const Lease4& other) const {
+ return (
+ addr_ == other.addr_ &&
+ ext_ == other.ext_ &&
+ hwaddr_ == other.hwaddr_ &&
+ *client_id_ == *other.client_id_ &&
+ t1_ == other.t1_ &&
+ t2_ == other.t2_ &&
+ valid_lft_ == other.valid_lft_ &&
+ cltt_ == other.cltt_ &&
+ subnet_id_ == other.subnet_id_ &&
+ fixed_ == other.fixed_ &&
+ hostname_ == other.hostname_ &&
+ fqdn_fwd_ == other.fqdn_fwd_ &&
+ fqdn_rev_ == other.fqdn_rev_ &&
+ comments_ == other.comments_
+ );
+}
+
+bool
Lease6::operator==(const Lease6& other) const {
return (
- type_ == other.type_ &&
addr_ == other.addr_ &&
+ type_ == other.type_ &&
prefixlen_ == other.prefixlen_ &&
iaid_ == other.iaid_ &&
*duid_ == *other.duid_ &&
preferred_lft_ == other.preferred_lft_ &&
valid_lft_ == other.valid_lft_ &&
+ t1_ == other.t1_ &&
+ t2_ == other.t2_ &&
cltt_ == other.cltt_ &&
- subnet_id_ == other.subnet_id_
- );
+ subnet_id_ == other.subnet_id_ &&
+ fixed_ == other.fixed_ &&
+ hostname_ == other.hostname_ &&
+ fqdn_fwd_ == other.fqdn_fwd_ &&
+ fqdn_rev_ == other.fqdn_rev_ &&
+ comments_ == other.comments_
+ );
}
+
+} // namespace isc::dhcp
+} // namespace isc
diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h
index 8b24151..f81f4c3 100644
--- a/src/lib/dhcpsrv/lease_mgr.h
+++ b/src/lib/dhcpsrv/lease_mgr.h
@@ -101,6 +101,13 @@ public:
isc::Exception(file, line, what) {}
};
+/// @brief Data is truncated
+class DataTruncated : public Exception {
+public:
+ DataTruncated(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) {}
+};
+
/// @brief Structure that holds a lease for IPv4 address
///
/// For performance reasons it is a simple structure, not a class. If we chose
@@ -108,6 +115,8 @@ public:
/// would be required. As this is a critical part of the code that will be used
/// extensively, direct access is warranted.
struct Lease4 {
+ // The following constants definine the size of fields in the database
+ static const size_t HWADDR_MAX = 20; // Maximum size of hardware address
/// @brief Constructor
///
@@ -173,10 +182,10 @@ struct Lease4 {
/// IA container and not the address itself, since our data model does not
/// define a separate IA entity, we are keeping it in the lease. In the
/// case of multiple addresses/prefixes for the same IA, each must have
- /// consistent T1 and T2 values. This is pecified in seconds since cltt.
+ /// consistent T1 and T2 values. This is specified in seconds since cltt.
uint32_t t2_;
- /// @brief Ralid lifetime
+ /// @brief Valid lifetime
///
/// Expressed as number of seconds since cltt.
uint32_t valid_lft_;
@@ -218,6 +227,18 @@ struct Lease4 {
/// system administrator.
std::string comments_;
+ /// @brief Compare two leases for equality
+ ///
+ /// @param other lease6 object with which to compare
+ bool operator==(const Lease4& other) const;
+
+ /// @brief Compare two leases for inequality
+ ///
+ /// @param other lease6 object with which to compare
+ bool operator!=(const Lease4& other) const {
+ return (!operator==(other));
+ }
+
/// @todo: Add DHCPv4 failover related fields here
};
@@ -234,6 +255,7 @@ typedef std::vector<Lease4Ptr> Lease4Collection;
/// For performance reasons it is a simple structure, not a class. If we chose
/// make it a class, all fields would have to made private and getters/setters
/// would be required. As this is a critical part of the code that will be used
+/// extensively, direct access is warranted.
struct Lease6 {
/// @brief Type of lease contents
@@ -249,6 +271,8 @@ struct Lease6 {
uint32_t t2, SubnetID subnet_id, uint8_t prefixlen_ = 0);
/// @brief IPv6 address
+ ///
+ /// IPv6 address or, in the case of a prefix delegation, the prefix.
isc::asiolink::IOAddress addr_;
/// @brief Lease type
@@ -264,12 +288,12 @@ struct Lease6 {
/// @brief Identity Association Identifier (IAID)
///
/// DHCPv6 stores all addresses and prefixes in IA containers (IA_NA,
- /// IA_TA, IA_PD). Most containers may appear more than once in a message.
+ /// IA_TA, IA_PD). All containers may appear more than once in a message.
/// To differentiate between them, the IAID field is present
uint32_t iaid_;
/// @brief Client identifier
- boost::shared_ptr<DUID> duid_;
+ DuidPtr duid_;
/// @brief preferred lifetime
///
@@ -363,7 +387,6 @@ struct Lease6 {
bool operator!=(const Lease6& other) const {
return (!operator==(other));
}
-
};
/// @brief Pointer to a Lease6 structure.
diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc
index 12c6946..79fefad 100644
--- a/src/lib/dhcpsrv/mysql_lease_mgr.cc
+++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc
@@ -17,8 +17,10 @@
#include <asiolink/io_address.h>
#include <dhcpsrv/mysql_lease_mgr.h>
+#include <boost/static_assert.hpp>
#include <mysql/mysqld_error.h>
+#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
@@ -79,21 +81,39 @@ namespace {
/// fields. The values should be greater than or equal to the length set in
/// the schema definition.
///
-/// The exception is the length of any VARCHAR fields: these should be set
-/// greater than or equal to the length of the field plus 2: this allows for
-/// the insertion of a trailing null regardless of whether the data returned
-/// contains a trailing null (the documentation is not clear on this point).
+/// The exception is the length of any VARCHAR fields: buffers for these should
+/// be set greater than or equal to the length of the field plus 1: this allows
+/// for the insertion of a trailing null whatever data is returned.
-const size_t ADDRESS6_TEXT_MAX_LEN = 42; ///< Max size of a IPv6 text buffer
-const size_t DUID_MAX_LEN = 128; ///< Max size of a DUID
-const size_t HWADDR_MAX_LEN = 128; ///< Max size of a hardware address
-const size_t CLIENT_ID_MAX_LEN = 128; ///< Max size of a client ID
+/// @brief Maximum size of an IPv6 address represented as a text string.
+///
+/// This is 32 hexadecimal characters written in 8 groups of four, plus seven
+/// colon separators.
+const size_t ADDRESS6_TEXT_MAX_LEN = 39;
+
+/// @brief Maximum size of a DUID.
+const size_t DUID_MAX_LEN = 128;
+
+/// @brief Maximum size of a hardware address.
+const size_t HWADDR_MAX_LEN = 20;
+
+/// @brief Maximum size of a client identification.
+///
+/// Note that the value is arbitrarily chosen: RFC 2131 does not specify an
+/// upper limit, but this seems long enough.
+const size_t CLIENT_ID_MAX_LEN = 128;
+
+/// @brief Number of columns in Lease4 table
+const size_t LEASE4_COLUMNS = 6;
+
+/// @brief Number of columns in Lease6 table
+const size_t LEASE6_COLUMNS = 9;
/// @brief MySQL True/False constants
///
/// Declare typed values so as to avoid problems of data conversion. These
/// are local to the file but are given the prefix MLM (MySql Lease Manager) to
-/// avoid any likely conflicts with variables n header files named TRUE or
+/// avoid any likely conflicts with variables in header files named TRUE or
/// FALSE.
const my_bool MLM_FALSE = 0; ///< False value
@@ -136,6 +156,7 @@ TaggedStatement tagged_statements[] = {
"valid_lifetime, expire, subnet_id "
"FROM lease4 "
"WHERE hwaddr = ?"},
+
{MySqlLeaseMgr::GET_LEASE4_HWADDR_SUBID,
"SELECT address, hwaddr, client_id, "
"valid_lifetime, expire, subnet_id "
@@ -190,6 +211,69 @@ TaggedStatement tagged_statements[] = {
namespace isc {
namespace dhcp {
+/// @brief Common MySQL and Lease Data Methods
+///
+/// The MySqlLease4Exchange and MySqlLease6Exchange classes provide the
+/// functionaility to set up binding information between variables in the
+/// program and data extracted from the database. This class is the common
+/// base to both of them, containing some common methods.
+
+class MySqlLeaseExchange {
+public:
+ /// @brief Set error indicators
+ ///
+ /// Sets the error indicator for each of the MYSQL_BIND elements. It points
+ /// the "error" field within an element of the input array to the
+ /// corresponding element of the passed error array.
+ ///
+ /// @param bind Array of BIND elements
+ /// @param error Array of error elements. If there is an error in getting
+ /// data associated with one of the "bind" elements, the
+ /// corresponding element in the error array is set to MLM_TRUE.
+ /// @param count Size of each of the arrays.
+ void setErrorIndicators(MYSQL_BIND* bind, my_bool* error, size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ error[i] = MLM_FALSE;
+ bind[i].error = reinterpret_cast<char*>(&error[i]);
+ }
+ }
+
+ /// @brief Return columns in error
+ ///
+ /// If an error is returned from a fetch (in particular, a truncated
+ /// status), this method can be called to get the names of the fields in
+ /// error. It returns a string comprising the names of the fields
+ /// separated by commas. In the case of there being no error indicators
+ /// set, it returns the string "(None)".
+ ///
+ /// @param error Array of error elements. An element is set to MLM_TRUE
+ /// if the corresponding column in the database is the source of
+ /// the error.
+ /// @param names Array of column names, the same size as the error array.
+ /// @param count Size of each of the arrays.
+ std::string getColumnsInError(my_bool* error, std::string* names,
+ size_t count) {
+ std::string result = "";
+
+ // Accumulate list of column names
+ for (size_t i = 0; i < count; ++i) {
+ if (error[i] == MLM_TRUE) {
+ if (!result.empty()) {
+ result += ", ";
+ }
+ result += names[i];
+ }
+ }
+
+ if (result.empty()) {
+ result = "(None)";
+ }
+
+ return (result);
+ }
+};
+
+
/// @brief Exchange MySQL and Lease4 Data
///
/// On any MySQL operation, arrays of MYSQL_BIND structures must be built to
@@ -203,15 +287,28 @@ namespace dhcp {
/// @note There are no unit tests for this class. It is tested indirectly
/// in all MySqlLeaseMgr::xxx4() calls where it is used.
-class MySqlLease4Exchange {
+class MySqlLease4Exchange : public MySqlLeaseExchange {
public:
+ /// @brief Set number of columns in this lease structure
+ static const size_t LEASE_COLUMNS = LEASE4_COLUMNS;
+
/// @brief Constructor
///
- /// The initialization of the variables here is nonly to satisfy cppcheck -
+ /// The initialization of the variables here is only to satisfy cppcheck -
/// all variables are initialized/set in the methods before they are used.
MySqlLease4Exchange() : addr4_(0), hwaddr_length_(0), client_id_length_(0) {
memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
memset(client_id_buffer_, 0, sizeof(client_id_buffer_));
+ std::fill(&error_[0], &error_[LEASE_COLUMNS], MLM_FALSE);
+
+ // Set the column names (for error messages)
+ columns_[0] = "address";
+ columns_[1] = "hwaddr";
+ columns_[2] = "client_id";
+ columns_[3] = "valid_lifetime";
+ columns_[4] = "expire";
+ columns_[5] = "subnet_id";
+ BOOST_STATIC_ASSERT(5 < LEASE_COLUMNS);
}
/// @brief Create MYSQL_BIND objects for Lease4 Pointer
@@ -235,14 +332,14 @@ public:
// structure.
// Address: uint32_t
- // The address in the Lease structre is an IOAddress object. Convert
+ // The address in the Lease structure is an IOAddress object. Convert
// this to an integer for storage.
addr4_ = static_cast<uint32_t>(lease_->addr_);
bind_[0].buffer_type = MYSQL_TYPE_LONG;
bind_[0].buffer = reinterpret_cast<char*>(&addr4_);
bind_[0].is_unsigned = MLM_TRUE;
- // hwaddr: varbinary
+ // hwaddr: varbinary(128)
// For speed, we avoid copying the data into temporary storage and
// instead extract it from the lease structure directly.
hwaddr_length_ = lease_->hwaddr_.size();
@@ -251,7 +348,7 @@ public:
bind_[1].buffer_length = hwaddr_length_;
bind_[1].length = &hwaddr_length_;
- // client_id: varbinary
+ // client_id: varbinary(128)
client_id_ = lease_->client_id_->getClientId();
client_id_length_ = client_id_.size();
bind_[2].buffer_type = MYSQL_TYPE_BLOB;
@@ -285,9 +382,15 @@ public:
bind_[5].buffer = reinterpret_cast<char*>(&lease_->subnet_id_);
bind_[5].is_unsigned = MLM_TRUE;
+ // Add the error flags
+ setErrorIndicators(bind_, error_, LEASE_COLUMNS);
+
+ // .. and check that we have the numbers correct at compile time.
+ BOOST_STATIC_ASSERT(5 < LEASE_COLUMNS);
+
// Add the data to the vector. Note the end element is one after the
// end of the array.
- return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[6]));
+ return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
}
/// @brief Create BIND array to receive data
@@ -335,9 +438,15 @@ public:
bind_[5].buffer = reinterpret_cast<char*>(&subnet_id_);
bind_[5].is_unsigned = MLM_TRUE;
+ // Add the error flags
+ setErrorIndicators(bind_, error_, LEASE_COLUMNS);
+
+ // .. and check that we have the numbers correct at compile time.
+ BOOST_STATIC_ASSERT(5 < LEASE_COLUMNS);
+
// Add the data to the vector. Note the end element is one after the
// end of the array.
- return(std::vector<MYSQL_BIND>(&bind_[0], &bind_[6]));
+ return(std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
}
/// @brief Copy Received Data into Lease6 Object
@@ -359,12 +468,29 @@ public:
valid_lifetime_, cltt, subnet_id_)));
}
+ /// @brief Return columns in error
+ ///
+ /// If an error is returned from a fetch (in particular, a truncated
+ /// status), this method can be called to get the names of the fields in
+ /// error. It returns a string comprising the names of the fields
+ /// separated by commas. In the case of there being no error indicators
+ /// set, it returns the string "(None)".
+ ///
+ /// @return Comma-separated list of columns in error, or the string
+ /// "(None)".
+ std::string getErrorColumns() {
+ return (getColumnsInError(error_, columns_, LEASE_COLUMNS));
+ }
+
private:
+
// Note: All array lengths are equal to the corresponding variable in the
// schema.
// Note: Arrays are declared fixed length for speed of creation
uint32_t addr4_; ///< IPv4 address
- MYSQL_BIND bind_[6]; ///< Bind array
+ MYSQL_BIND bind_[LEASE_COLUMNS]; ///< Bind array
+ std::string columns_[LEASE_COLUMNS];///< Column names
+ my_bool error_[LEASE_COLUMNS]; ///< Error array
std::vector<uint8_t> hwaddr_; ///< Hardware address
uint8_t hwaddr_buffer_[HWADDR_MAX_LEN];
///< Hardware address buffer
@@ -394,7 +520,10 @@ private:
/// @note There are no unit tests for this class. It is tested indirectly
/// in all MySqlLeaseMgr::xxx6() calls where it is used.
-class MySqlLease6Exchange {
+class MySqlLease6Exchange : public MySqlLeaseExchange {
+ /// @brief Set number of columns in this lease structure
+ static const size_t LEASE_COLUMNS = LEASE6_COLUMNS;
+
public:
/// @brief Constructor
///
@@ -403,6 +532,19 @@ public:
MySqlLease6Exchange() : addr6_length_(0), duid_length_(0) {
memset(addr6_buffer_, 0, sizeof(addr6_buffer_));
memset(duid_buffer_, 0, sizeof(duid_buffer_));
+ std::fill(&error_[0], &error_[LEASE_COLUMNS], MLM_FALSE);
+
+ // Set the column names (for error messages)
+ columns_[0] = "address";
+ columns_[1] = "duid";
+ columns_[2] = "valid_lifetime";
+ columns_[3] = "expire";
+ columns_[4] = "subnet_id";
+ columns_[5] = "pref_lifetime";
+ columns_[6] = "lease_type";
+ columns_[7] = "iaid";
+ columns_[8] = "prefix_len";
+ BOOST_STATIC_ASSERT(5 < LEASE_COLUMNS);
}
/// @brief Create MYSQL_BIND objects for Lease6 Pointer
@@ -421,7 +563,7 @@ public:
// for this lease.
memset(bind_, 0, sizeof(bind_));
- // address: varchar(40)
+ // address: varchar(39)
addr6_ = lease_->addr_.toText();
addr6_length_ = addr6_.size();
@@ -435,7 +577,7 @@ public:
// The const_cast could be avoided by copying the string to a writeable
// buffer and storing the address of that in the "buffer" element.
// However, this introduces a copy operation (with additional overhead)
- // purely to get round the strictures introduced by design of the
+ // purely to get round the structures introduced by design of the
// MySQL interface (which uses the area pointed to by "buffer" as input
// when specifying query parameters and as output when retrieving data).
// For that reason, "const_cast" has been used.
@@ -465,7 +607,7 @@ public:
//
// expire = cltt_ + valid_lft_
//
- // @TODO Handle overflows
+ // @todo Handle overflows
MySqlLeaseMgr::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_,
expire_);
bind_[3].buffer_type = MYSQL_TYPE_TIMESTAMP;
@@ -503,9 +645,15 @@ public:
bind_[8].buffer = reinterpret_cast<char*>(&lease_->prefixlen_);
bind_[8].is_unsigned = MLM_TRUE;
+ // Add the error flags
+ setErrorIndicators(bind_, error_, LEASE_COLUMNS);
+
+ // .. and check that we have the numbers correct at compile time.
+ BOOST_STATIC_ASSERT(8 < LEASE_COLUMNS);
+
// Add the data to the vector. Note the end element is one after the
// end of the array.
- return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[9]));
+ return (std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
}
/// @brief Create BIND array to receive data
@@ -521,10 +669,10 @@ public:
// Initialize MYSQL_BIND array.
memset(bind_, 0, sizeof(bind_));
- // address: varchar
+ // address: varchar(39)
// A Lease6_ address has a maximum of 39 characters. The array is
- // a few bytes longer than this to guarantee that we can always null
- // terminate it.
+ // one byte longer than this to guarantee that we can always null
+ // terminate it whatever is returned.
addr6_length_ = sizeof(addr6_buffer_) - 1;
bind_[0].buffer_type = MYSQL_TYPE_STRING;
bind_[0].buffer = addr6_buffer_;
@@ -573,9 +721,15 @@ public:
bind_[8].buffer = reinterpret_cast<char*>(&prefixlen_);
bind_[8].is_unsigned = MLM_TRUE;
+ // Add the error flags
+ setErrorIndicators(bind_, error_, LEASE_COLUMNS);
+
+ // .. and check that we have the numbers correct at compile time.
+ BOOST_STATIC_ASSERT(8 < LEASE_COLUMNS);
+
// Add the data to the vector. Note the end element is one after the
// end of the array.
- return(std::vector<MYSQL_BIND>(&bind_[0], &bind_[9]));
+ return(std::vector<MYSQL_BIND>(&bind_[0], &bind_[LEASE_COLUMNS]));
}
/// @brief Copy Received Data into Lease6 Object
@@ -633,18 +787,34 @@ public:
return (result);
}
+ /// @brief Return columns in error
+ ///
+ /// If an error is returned from a fetch (in particular, a truncated
+ /// status), this method can be called to get the names of the fields in
+ /// error. It returns a string comprising the names of the fields
+ /// separated by commas. In the case of there being no error indicators
+ /// set, it returns the string "(None)".
+ ///
+ /// @return Comma-separated list of columns in error, or the string
+ /// "(None)".
+ std::string getErrorColumns() {
+ return (getColumnsInError(error_, columns_, LEASE_COLUMNS));
+ }
+
private:
// Note: All array lengths are equal to the corresponding variable in the
// schema.
// Note: arrays are declared fixed length for speed of creation
std::string addr6_; ///< String form of address
- char addr6_buffer_[ADDRESS6_TEXT_MAX_LEN]; ///< Character
+ char addr6_buffer_[ADDRESS6_TEXT_MAX_LEN + 1]; ///< Character
///< array form of V6 address
unsigned long addr6_length_; ///< Length of the address
- MYSQL_BIND bind_[9]; ///< Bind array
+ MYSQL_BIND bind_[LEASE_COLUMNS]; ///< Bind array
+ std::string columns_[LEASE_COLUMNS];///< Column names
std::vector<uint8_t> duid_; ///< Client identification
uint8_t duid_buffer_[DUID_MAX_LEN]; ///< Buffer form of DUID
unsigned long duid_length_; ///< Length of the DUID
+ my_bool error_[LEASE_COLUMNS]; ///< Error indicators
MYSQL_TIME expire_; ///< Lease expiry time
uint32_t iaid_; ///< Identity association ID
Lease6Ptr lease_; ///< Pointer to lease object
@@ -715,9 +885,8 @@ MySqlLeaseMgr::MySqlLeaseMgr(const LeaseMgr::ParameterMap& parameters)
// Enable autocommit. To avoid a flush to disk on every commit, the global
// parameter innodb_flush_log_at_trx_commit should be set to 2. This will
// cause the changes to be written to the log, but flushed to disk in the
- // background every second or so. Setting the parameter to that value will
- // speed up the system, but at the risk of losing data if the system
- // crashes.
+ // background every second. Setting the parameter to that value will speed
+ // up the system, but at the risk of losing data if the system crashes.
my_bool result = mysql_autocommit(mysql_, 1);
if (result != 0) {
isc_throw(DbOperationError, mysql_error(mysql_));
@@ -818,7 +987,7 @@ MySqlLeaseMgr::openDatabase() {
shost = getParameter("host");
host = shost.c_str();
} catch (...) {
- ; // No host. Fine, we'll use "localhost"
+ // No host. Fine, we'll use "localhost"
}
const char* user = NULL;
@@ -827,7 +996,7 @@ MySqlLeaseMgr::openDatabase() {
suser = getParameter("user");
user = suser.c_str();
} catch (...) {
- ; // No user. Fine, we'll use NULL
+ // No user. Fine, we'll use NULL
}
const char* password = NULL;
@@ -836,7 +1005,7 @@ MySqlLeaseMgr::openDatabase() {
spassword = getParameter("password");
password = spassword.c_str();
} catch (...) {
- ; // No password. Fine, we'll use NULL
+ // No password. Fine, we'll use NULL
}
const char* name = NULL;
@@ -928,7 +1097,7 @@ MySqlLeaseMgr::prepareStatements() {
}
// Add leases to the database. The two public methods accept a lease object
-// (of different types), bind the contents to the appropriate prepared
+// (either V4 of V6), bind the contents to the appropriate prepared
// statement, then call common code to execute the statement.
bool
@@ -1025,9 +1194,6 @@ void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
status = mysql_stmt_store_result(statements_[stindex]);
checkError(status, stindex, "unable to set up for storing all results");
- // Initialize for returning the data
- result.clear();
-
// Set up the fetch "release" object to release resources associated
// with the call to mysql_stmt_fetch when this method exits, then
// retrieve the data.
@@ -1055,8 +1221,9 @@ void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
// Error - unable to fetch results
checkError(status, stindex, "unable to fetch results");
} else if (status == MYSQL_DATA_TRUNCATED) {
- // @TODO Handle truncation
- ;
+ // Data truncated - throw an exception indicating what was at fault
+ isc_throw(DataTruncated, "returned data truncated column affected: "
+ << exchange->getErrorColumns());
}
}
@@ -1281,7 +1448,7 @@ MySqlLeaseMgr::getLease6(const DUID& duid, uint32_t iaid) const {
// Note that the const_cast could be avoided by copying the DUID to
// a writeable buffer and storing the address of that in the "buffer"
// element. However, this introduces a copy operation (with additional
- // overhead) purely to get round the strictures introduced by design of
+ // overhead) purely to get round the structures introduced by design of
// the MySQL interface (which uses the area pointed to by "buffer" as
// input when specifying query parameters and as output when retrieving
// data). For that reason, "const_cast" has been used.
@@ -1488,7 +1655,7 @@ MySqlLeaseMgr::getName() const {
try {
name = getParameter("name");
} catch (...) {
- ;
+ // Return an empty name
}
return (name);
}
diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.h b/src/lib/dhcpsrv/mysql_lease_mgr.h
index 6a39d4b..be86c3a 100644
--- a/src/lib/dhcpsrv/mysql_lease_mgr.h
+++ b/src/lib/dhcpsrv/mysql_lease_mgr.h
@@ -27,11 +27,11 @@ namespace dhcp {
// Define the current database schema values
-const uint32_t CURRENT_VERSION_VERSION = 0;
-const uint32_t CURRENT_VERSION_MINOR = 2;
+const uint32_t CURRENT_VERSION_VERSION = 1;
+const uint32_t CURRENT_VERSION_MINOR = 0;
-// Forward declaration of the Lease exchange objects. This class is defined
+// Forward declaration of the Lease exchange objects. These classes are defined
// in the .cc file.
class MySqlLease4Exchange;
class MySqlLease6Exchange;
@@ -119,6 +119,12 @@ public:
/// @param addr address of the searched lease
///
/// @return smart pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress& addr) const;
@@ -132,6 +138,12 @@ public:
/// @param hwaddr hardware address of the client
///
/// @return lease collection
+ ///
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Collection getLease4(const HWAddr& hwaddr) const;
/// @brief Returns existing IPv4 leases for specified hardware address
@@ -144,6 +156,12 @@ public:
/// @param subnet_id identifier of the subnet that lease must belong to
///
/// @return a pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Ptr getLease4(const HWAddr& hwaddr,
SubnetID subnet_id) const;
@@ -157,6 +175,12 @@ public:
/// @param clientid client identifier
///
/// @return lease collection
+ ///
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Collection getLease4(const ClientId& clientid) const;
/// @brief Returns existing IPv4 lease for specified client-id
@@ -168,6 +192,12 @@ public:
/// @param subnet_id identifier of the subnet that lease must belong to
///
/// @return a pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease4Ptr getLease4(const ClientId& clientid,
SubnetID subnet_id) const;
@@ -183,6 +213,9 @@ public:
///
/// @throw isc::BadValue record retrieved from database had an invalid
/// lease type field.
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
virtual Lease6Ptr getLease6(const isc::asiolink::IOAddress& addr) const;
@@ -198,6 +231,14 @@ public:
/// @param iaid IA identifier
///
/// @return smart pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::BadValue record retrieved from database had an invalid
+ /// lease type field.
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease6Collection getLease6(const DUID& duid,
uint32_t iaid) const;
@@ -208,6 +249,14 @@ public:
/// @param subnet_id subnet id of the subnet the lease belongs to
///
/// @return smart pointer to the lease (or NULL if a lease is not found)
+ ///
+ /// @throw isc::BadValue record retrieved from database had an invalid
+ /// lease type field.
+ /// @throw isc::dhcp::DataTruncation Data was truncated on retrieval to
+ /// fit into the space allocated for the result. This indicates a
+ /// programming error.
+ /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// failed.
virtual Lease6Ptr getLease6(const DUID& duid, uint32_t iaid,
SubnetID subnet_id) const;
@@ -370,13 +419,13 @@ public:
DELETE_LEASE4, // Delete from lease4 by address
DELETE_LEASE6, // Delete from lease6 by address
GET_LEASE4_ADDR, // Get lease4 by address
- GET_LEASE4_CLIENTID, // Get lease4 by Client ID
- GET_LEASE4_CLIENTID_SUBID, // Get lease4 by Client ID
+ GET_LEASE4_CLIENTID, // Get lease4 by client ID
+ GET_LEASE4_CLIENTID_SUBID, // Get lease4 by client ID & subnet ID
GET_LEASE4_HWADDR, // Get lease4 by HW address
GET_LEASE4_HWADDR_SUBID, // Get lease4 by HW address & subnet ID
GET_LEASE6_ADDR, // Get lease6 by address
GET_LEASE6_DUID_IAID, // Get lease6 by DUID and IAID
- GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and Subnet ID
+ GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and subnet ID
GET_VERSION, // Obtain version number
INSERT_LEASE4, // Add entry to lease4 table
INSERT_LEASE6, // Add entry to lease6 table
@@ -423,9 +472,9 @@ private:
/// @brief Add Lease Common Code
///
- /// This method performs the common actions for both flavours of the
- /// addLease method. It binds the contents of the lease object to
- /// the prepated statement and adds it to the database.
+ /// This method performs the common actions for both flavours (V4 and V6)
+ /// of the addLease method. It binds the contents of the lease object to
+ /// the prepared statement and adds it to the database.
///
/// @param stindex Index of statemnent being executed
/// @param bind MYSQL_BIND array that has been created for the type
@@ -446,8 +495,9 @@ private:
/// @param stindex Index of statement being executed
/// @param bind MYSQL_BIND array for input parameters
/// @param exchange Exchange object to use
- /// @param lease LeaseCollection object returned. Note that any data in
- /// the collection is cleared before new data is added.
+ /// @param lease LeaseCollection object returned. Note that any leases in
+ /// the collection when this method is called are not erased: the
+ /// new data is appended to the end.
/// @param single If true, only a single data item is to be retrieved.
/// If more than one is present, a MultipleRecords exception will
/// be thrown.
@@ -469,8 +519,9 @@ private:
///
/// @param stindex Index of statement being executed
/// @param bind MYSQL_BIND array for input parameters
- /// @param lease LeaseCollection object returned. Note that any data in
- /// the collection is cleared before new data is added.
+ /// @param lease LeaseCollection object returned. Note that any leases in
+ /// the collection when this method is called are not erased: the
+ /// new data is appended to the end.
///
/// @throw isc::dhcp::BadValue Data retrieved from the database was invalid.
/// @throw isc::dhcp::DbOperationError An operation on the open database has
@@ -489,8 +540,8 @@ private:
///
/// @param stindex Index of statement being executed
/// @param bind MYSQL_BIND array for input parameters
- /// @param lease LeaseCollection object returned. Note that any data in
- /// the collection is cleared before new data is added.
+ /// @param lease LeaseCollection object returned. Note that any existing
+ /// data in the collection is erased first.
///
/// @throw isc::dhcp::BadValue Data retrieved from the database was invalid.
/// @throw isc::dhcp::DbOperationError An operation on the open database has
@@ -502,7 +553,7 @@ private:
getLeaseCollection(stindex, bind, exchange6_, result);
}
- /// @brief Get Lease6 Common Code
+ /// @brief Get Lease4 Common Code
///
/// This method performs the common actions for the various getLease4()
/// methods. It acts as an interface to the getLeaseCollection() method,
@@ -514,9 +565,9 @@ private:
void getLease(StatementIndex stindex, MYSQL_BIND* bind,
Lease4Ptr& result) const;
- /// @brief Get Lease4 Common Code
+ /// @brief Get Lease6 Common Code
///
- /// This method performs the common actions for the various getLease4()
+ /// This method performs the common actions for the various getLease46)
/// methods. It acts as an interface to the getLeaseCollection() method,
/// but retrieveing only a single lease.
///
diff --git a/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc
index 40ecba3..e343c44 100644
--- a/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc
+++ b/src/lib/dhcpsrv/tests/lease_mgr_factory_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
+// 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
diff --git a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
index 82600c6..d973999 100644
--- a/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
+// 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
@@ -238,16 +238,12 @@ public:
};
namespace {
-// empty class for now, but may be extended once Addr6 becomes bigger
-class LeaseMgrTest : public ::testing::Test {
-public:
- LeaseMgrTest() {
- }
-};
-// This test checks if the LeaseMgr can be instantiated and that it
-// parses parameters string properly.
-TEST_F(LeaseMgrTest, getParameter) {
+/// @brief getParameter test
+///
+/// This test checks if the LeaseMgr can be instantiated and that it
+/// parses parameters string properly.
+TEST(LeaseMgr, getParameter) {
LeaseMgr::ParameterMap pmap;
pmap[std::string("param1")] = std::string("value1");
@@ -263,7 +259,9 @@ TEST_F(LeaseMgrTest, getParameter) {
// are purely virtual, so we would only call ConcreteLeaseMgr methods.
// Those methods are just stubs that do not return anything.
-// Lease4 is also defined in lease_mgr.h, so is tested in this file as well.
+/// @brief Lease4 Constructor Test
+///
+/// Lease4 is also defined in lease_mgr.h, so is tested in this file as well.
// This test checks if the Lease4 structure can be instantiated correctly
TEST(Lease4, Lease4Constructor) {
@@ -278,61 +276,351 @@ TEST(Lease4, Lease4Constructor) {
// ...and a time
const time_t current_time = time(NULL);
- // Other random constants
- const uint32_t ADDRESS = 103478;
- const uint32_t VALID_LIFETIME = 10986;
+ // Other random constants.
const uint32_t SUBNET_ID = 42;
+ const uint32_t VALID_LIFETIME = 500;
+
+ // We want to check that various addresses work, so let's iterate over
+ // these.
+ const uint32_t ADDRESS[] = {
+ 0x00000000, 0x01020304, 0x7fffffff, 0x80000000, 0x80000001, 0xffffffff
+ };
+
+ for (int i = 0; i < sizeof(ADDRESS) / sizeof(ADDRESS[0]); ++i) {
+
+ // Create the lease
+ Lease4 lease(ADDRESS[i], HWADDR, sizeof(HWADDR),
+ CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, current_time,
+ SUBNET_ID);
+
+ EXPECT_EQ(ADDRESS[i], static_cast<uint32_t>(lease.addr_));
+ EXPECT_EQ(0, lease.ext_);
+ EXPECT_TRUE(hwaddr == lease.hwaddr_);
+ EXPECT_TRUE(clientid == *lease.client_id_);
+ EXPECT_EQ(0, lease.t1_);
+ EXPECT_EQ(0, lease.t2_);
+ EXPECT_EQ(VALID_LIFETIME, lease.valid_lft_);
+ EXPECT_EQ(current_time, lease.cltt_);
+ EXPECT_EQ(SUBNET_ID, lease.subnet_id_);
+ EXPECT_FALSE(lease.fixed_);
+ EXPECT_TRUE(lease.hostname_.empty());
+ EXPECT_FALSE(lease.fqdn_fwd_);
+ EXPECT_FALSE(lease.fqdn_rev_);
+ EXPECT_TRUE(lease.comments_.empty());
+ }
+}
+
+/// @brief Lease4 Equality Test
+///
+/// Checks that the operator==() correctly compares two leases for equality.
+/// As operator!=() is also defined for this class, every check on operator==()
+/// is followed by the reverse check on operator!=().
+TEST(Lease4, OperatorEquals) {
- // Create the lease
- Lease4 lease(ADDRESS, HWADDR, sizeof(HWADDR), CLIENTID, sizeof(CLIENTID),
- VALID_LIFETIME, current_time, SUBNET_ID);
-
- EXPECT_EQ(ADDRESS, static_cast<uint32_t>(lease.addr_));
- EXPECT_EQ(0, lease.ext_);
- EXPECT_TRUE(hwaddr == lease.hwaddr_);
- EXPECT_TRUE(clientid == *lease.client_id_);
- EXPECT_EQ(0, lease.t1_);
- EXPECT_EQ(0, lease.t2_);
- EXPECT_EQ(VALID_LIFETIME, lease.valid_lft_);
- EXPECT_EQ(current_time, lease.cltt_);
- EXPECT_EQ(SUBNET_ID, lease.subnet_id_);
- EXPECT_FALSE(lease.fixed_);
- EXPECT_TRUE(lease.hostname_.empty());
- EXPECT_FALSE(lease.fqdn_fwd_);
- EXPECT_FALSE(lease.fqdn_rev_);
- EXPECT_TRUE(lease.comments_.empty());
+ // Random values for the tests
+ const uint32_t ADDRESS = 0x01020304;
+ const uint8_t HWADDR[] = {0x08, 0x00, 0x2b, 0x02, 0x3f, 0x4e};
+ std::vector<uint8_t> hwaddr(HWADDR, HWADDR + sizeof(HWADDR));
+ const uint8_t CLIENTID[] = {0x17, 0x34, 0xe2, 0xff, 0x09, 0x92, 0x54};
+ std::vector<uint8_t> clientid_vec(CLIENTID, CLIENTID + sizeof(CLIENTID));
+ ClientId clientid(clientid_vec);
+ const time_t current_time = time(NULL);
+ const uint32_t SUBNET_ID = 42;
+ const uint32_t VALID_LIFETIME = 500;
+
+ // Check when the leases are equal.
+ Lease4 lease1(ADDRESS, HWADDR, sizeof(HWADDR),
+ CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, current_time,
+ SUBNET_ID);
+ Lease4 lease2(ADDRESS, HWADDR, sizeof(HWADDR),
+ CLIENTID, sizeof(CLIENTID), VALID_LIFETIME, current_time,
+ SUBNET_ID);
+ EXPECT_TRUE(lease1 == lease2);
+ EXPECT_FALSE(lease1 != lease2);
+
+ // Now vary individual fields in a lease and check that the leases compare
+ // not equal in every case.
+ lease1.addr_ = IOAddress(ADDRESS + 1);
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.addr_ = lease2.addr_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.ext_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.ext_ = lease2.ext_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.hwaddr_[0];
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.hwaddr_ = lease2.hwaddr_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++clientid_vec[0];
+ lease1.client_id_.reset(new ClientId(clientid_vec));
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ --clientid_vec[0];
+ lease1.client_id_.reset(new ClientId(clientid_vec));
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.t1_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.t1_ = lease2.t1_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.t2_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.t2_ = lease2.t2_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.valid_lft_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.valid_lft_ = lease2.valid_lft_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.cltt_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.cltt_ = lease2.cltt_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.subnet_id_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.subnet_id_ = lease2.subnet_id_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.fixed_ = !lease1.fixed_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.fixed_ = lease2.fixed_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.hostname_ += string("Something random");
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.hostname_ = lease2.hostname_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.fqdn_fwd_ = !lease1.fqdn_fwd_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.fqdn_fwd_ = lease2.fqdn_fwd_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.fqdn_rev_ = !lease1.fqdn_rev_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.fqdn_rev_ = lease2.fqdn_rev_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.comments_ += string("Something random");
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.comments_ = lease2.comments_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
}
+
+
// Lease6 is also defined in lease_mgr.h, so is tested in this file as well.
// This test checks if the Lease6 structure can be instantiated correctly
TEST(Lease6, Lease6Constructor) {
- IOAddress addr("2001:db8:1::456");
+ // check a variety of addresses with different bits set.
+ const char* ADDRESS[] = {
+ "::", "::1", "2001:db8:1::456",
+ "7fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+ "8000::", "8000::1",
+ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
+ };
+ // Other values
uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
DuidPtr duid(new DUID(llt, sizeof(llt)));
-
uint32_t iaid = 7; // just a number
-
SubnetID subnet_id = 8; // just another number
- Lease6Ptr x(new Lease6(Lease6::LEASE_IA_NA, addr,
- duid, iaid, 100, 200, 50, 80,
- subnet_id));
-
- EXPECT_TRUE(x->addr_ == addr);
- EXPECT_TRUE(*x->duid_ == *duid);
- EXPECT_TRUE(x->iaid_ == iaid);
- EXPECT_TRUE(x->subnet_id_ == subnet_id);
- EXPECT_TRUE(x->type_ == Lease6::LEASE_IA_NA);
- EXPECT_TRUE(x->preferred_lft_ == 100);
- EXPECT_TRUE(x->valid_lft_ == 200);
- EXPECT_TRUE(x->t1_ == 50);
- EXPECT_TRUE(x->t2_ == 80);
+ for (int i = 0; i < sizeof(ADDRESS) / sizeof(ADDRESS[0]); ++i) {
+ IOAddress addr(ADDRESS[i]);
+ Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr,
+ duid, iaid, 100, 200, 50, 80,
+ subnet_id));
+
+ EXPECT_TRUE(lease->addr_ == addr);
+ EXPECT_TRUE(*lease->duid_ == *duid);
+ EXPECT_TRUE(lease->iaid_ == iaid);
+ EXPECT_TRUE(lease->subnet_id_ == subnet_id);
+ EXPECT_TRUE(lease->type_ == Lease6::LEASE_IA_NA);
+ EXPECT_TRUE(lease->preferred_lft_ == 100);
+ EXPECT_TRUE(lease->valid_lft_ == 200);
+ EXPECT_TRUE(lease->t1_ == 50);
+ EXPECT_TRUE(lease->t2_ == 80);
+ }
// Lease6 must be instantiated with a DUID, not with NULL pointer
+ IOAddress addr(ADDRESS[0]);
EXPECT_THROW(new Lease6(Lease6::LEASE_IA_NA, addr,
DuidPtr(), iaid, 100, 200, 50, 80,
subnet_id), InvalidOperation);
}
+
+/// @brief Lease6 Equality Test
+///
+/// Checks that the operator==() correctly compares two leases for equality.
+/// As operator!=() is also defined for this class, every check on operator==()
+/// is followed by the reverse check on operator!=().
+TEST(Lease6, OperatorEquals) {
+
+ // check a variety of addressemas with different bits set.
+ const IOAddress addr("2001:db8:1::456");
+ uint8_t duid_array[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+ DuidPtr duid(new DUID(duid_array, sizeof(duid_array)));
+ uint32_t iaid = 7; // just a number
+ SubnetID subnet_id = 8; // just another number
+
+ // Check for equality.
+ Lease6 lease1(Lease6::LEASE_IA_NA, addr, duid, iaid, 100, 200, 50, 80,
+ subnet_id);
+ Lease6 lease2(Lease6::LEASE_IA_NA, addr, duid, iaid, 100, 200, 50, 80,
+ subnet_id);
+ EXPECT_TRUE(lease1 == lease2);
+ EXPECT_FALSE(lease1 != lease2);
+
+ // Go through and alter all the fields one by one
+
+ lease1.addr_ = IOAddress("::1");
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.addr_ = lease2.addr_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.type_ = Lease6::LEASE_IA_PD;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.type_ = lease2.type_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.prefixlen_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.prefixlen_ = lease2.prefixlen_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.iaid_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.iaid_ = lease2.iaid_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++duid_array[0];
+ lease1.duid_.reset(new DUID(duid_array, sizeof(duid_array)));
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ --duid_array[0];
+ lease1.duid_.reset(new DUID(duid_array, sizeof(duid_array)));
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.preferred_lft_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.preferred_lft_ = lease2.preferred_lft_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.valid_lft_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.valid_lft_ = lease2.valid_lft_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.t1_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.t1_ = lease2.t1_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.t2_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.t2_ = lease2.t2_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.cltt_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.cltt_ = lease2.cltt_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ ++lease1.subnet_id_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.subnet_id_ = lease2.subnet_id_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.fixed_ = !lease1.fixed_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.fixed_ = lease2.fixed_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.hostname_ += string("Something random");
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.hostname_ = lease2.hostname_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.fqdn_fwd_ = !lease1.fqdn_fwd_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.fqdn_fwd_ = lease2.fqdn_fwd_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.fqdn_rev_ = !lease1.fqdn_rev_;
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.fqdn_rev_ = lease2.fqdn_rev_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+
+ lease1.comments_ += string("Something random");
+ EXPECT_FALSE(lease1 == lease2);
+ EXPECT_TRUE(lease1 != lease2);
+ lease1.comments_ = lease2.comments_;
+ EXPECT_TRUE(lease1 == lease2); // Check that the reversion has made the
+ EXPECT_FALSE(lease1 != lease2); // ... lease equal
+}
}; // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
index e7b64ab..7f6bcc9 100644
--- a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
+++ b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
@@ -20,6 +20,7 @@
#include <gtest/gtest.h>
+#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
@@ -72,7 +73,7 @@ string connectionString(const char* type, const char* name, const char* host,
if (type != NULL) {
result += string(type);
}
-if (name != NULL) {
+ if (name != NULL) {
if (! result.empty()) {
result += space;
}
@@ -182,9 +183,11 @@ public:
ioaddress6_.push_back(ioaddr);
}
+ // Ensure schema is the correct one.
destroySchema();
createSchema();
+ // Connect to the database
try {
LeaseMgrFactory::create(validConnectionString());
} catch (...) {
@@ -200,9 +203,8 @@ public:
/// @brief Destructor
///
- /// Rolls back all pending transactions. The deletion of the
- /// lmptr_ member variable will close the database. Then
- /// reopen it and delete everything created by the test.
+ /// Rolls back all pending transactions. The deletion of lmptr_ will close
+ /// the database. Then reopen it and delete everything created by the test.
virtual ~MySqlLeaseMgrTest() {
lmptr_->rollback();
LeaseMgrFactory::destroy();
@@ -221,8 +223,8 @@ public:
/// @brief Initialize Lease4 Fields
///
- /// Returns a pointer to a Lease4 structure. Different values are put
- /// in the lease according to the address passed.
+ /// Returns a pointer to a Lease4 structure. Different values are put into
+ /// the lease according to the address passed.
///
/// This is just a convenience function for the test methods.
///
@@ -330,8 +332,8 @@ public:
/// @brief Initialize Lease6 Fields
///
- /// Returns a pointer to a Lease6 structure. Different values are put
- /// in the lease according to the address passed.
+ /// Returns a pointer to a Lease6 structure. Different values are put into
+ /// the lease according to the address passed.
///
/// This is just a convenience function for the test methods.
///
@@ -359,8 +361,7 @@ public:
lease->type_ = Lease6::LEASE_IA_TA;
lease->prefixlen_ = 4;
lease->iaid_ = 142;
- lease->duid_ = boost::shared_ptr<DUID>(
- new DUID(vector<uint8_t>(8, 0x77)));
+ lease->duid_ = DuidPtr(new DUID(vector<uint8_t>(8, 0x77)));
lease->preferred_lft_ = 900;
lease->valid_lft_ = 8677;
lease->cltt_ = 168256;
@@ -370,8 +371,7 @@ public:
lease->type_ = Lease6::LEASE_IA_TA;
lease->prefixlen_ = 0;
lease->iaid_ = 42;
- lease->duid_ = boost::shared_ptr<DUID>(
- new DUID(vector<uint8_t>(8, 0x42)));
+ lease->duid_ = DuidPtr(new DUID(vector<uint8_t>(8, 0x42)));
lease->preferred_lft_ = 3600;
lease->valid_lft_ = 3677;
lease->cltt_ = 123456;
@@ -381,8 +381,7 @@ public:
lease->type_ = Lease6::LEASE_IA_PD;
lease->prefixlen_ = 7;
lease->iaid_ = 89;
- lease->duid_ = boost::shared_ptr<DUID>(
- new DUID(vector<uint8_t>(8, 0x3a)));
+ lease->duid_ = DuidPtr(new DUID(vector<uint8_t>(8, 0x3a)));
lease->preferred_lft_ = 1800;
lease->valid_lft_ = 5412;
lease->cltt_ = 234567;
@@ -396,7 +395,7 @@ public:
for (uint8_t i = 31; i < 126; ++i) {
duid.push_back(i);
}
- lease->duid_ = boost::shared_ptr<DUID>(new DUID(duid));
+ lease->duid_ = DuidPtr(new DUID(duid));
// The times used in the next tests are deliberately restricted - we
// should be able to cope with valid lifetimes up to 0xffffffff.
@@ -412,8 +411,7 @@ public:
lease->type_ = Lease6::LEASE_IA_PD;
lease->prefixlen_ = 15;
lease->iaid_ = 42;
- lease->duid_ = boost::shared_ptr<DUID>(
- new DUID(vector<uint8_t>(8, 0x42)));
+ lease->duid_ = DuidPtr(new DUID(vector<uint8_t>(8, 0x42)));
lease->preferred_lft_ = 4800;
lease->valid_lft_ = 7736;
lease->cltt_ = 222456;
@@ -424,8 +422,8 @@ public:
lease->type_ = Lease6::LEASE_IA_PD;
lease->prefixlen_ = 24;
lease->iaid_ = 42; // Same as lease 4
- lease->duid_ = boost::shared_ptr<DUID>(
- new DUID(vector<uint8_t>(8, 0x42))); // Same as lease 4
+ lease->duid_ = DuidPtr(new DUID(vector<uint8_t>(8, 0x42)));
+ // Same as lease 4
lease->preferred_lft_ = 5400;
lease->valid_lft_ = 7832;
lease->cltt_ = 227476;
@@ -436,8 +434,8 @@ public:
lease->type_ = Lease6::LEASE_IA_PD;
lease->prefixlen_ = 24;
lease->iaid_ = 93;
- lease->duid_ = boost::shared_ptr<DUID>(
- new DUID(vector<uint8_t>(8, 0x42))); // Same as lease 4
+ lease->duid_ = DuidPtr(new DUID(vector<uint8_t>(8, 0x42)));
+ // Same as lease 4
lease->preferred_lft_ = 5400;
lease->valid_lft_ = 1832;
lease->cltt_ = 627476;
@@ -448,8 +446,7 @@ public:
lease->type_ = Lease6::LEASE_IA_PD;
lease->prefixlen_ = 24;
lease->iaid_ = 42;
- lease->duid_ = boost::shared_ptr<DUID>(
- new DUID(vector<uint8_t>(8, 0xe5)));
+ lease->duid_ = DuidPtr(new DUID(vector<uint8_t>(8, 0xe5)));
lease->preferred_lft_ = 5600;
lease->valid_lft_ = 7975;
lease->cltt_ = 213876;
@@ -482,7 +479,10 @@ public:
// Check they are different
for (int i = 0; i < (leases.size() - 1); ++i) {
for (int j = (i + 1); j < leases.size(); ++j) {
- ASSERT_TRUE(leases[i] != leases[j]);
+ stringstream s;
+ s << "Comparing leases " << i << " & " << j << " for equality";
+ SCOPED_TRACE(s.str());
+ EXPECT_TRUE(*leases[i] != *leases[j]);
}
}
}
@@ -537,6 +537,47 @@ public:
vector<IOAddress> ioaddress6_; ///< IOAddress forms of IPv6 addresses
};
+///@{
+/// @brief Test Utilities
+///
+/// The follow are a set of functions used during the tests.
+
+/// @brief Compare two Lease4 structures for equality
+void
+detailCompareLease(const Lease4Ptr& first, const Lease4Ptr& second) {
+ // Compare address strings. Comparison of address objects is not used, as
+ // odd things happen when they are different: the EXPECT_EQ macro appears to
+ // call the operator uint32_t() function, which causes an exception to be
+ // thrown for IPv6 addresses.
+ EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
+ EXPECT_TRUE(first->hwaddr_ == second->hwaddr_);
+ EXPECT_TRUE(*first->client_id_ == *second->client_id_);
+ EXPECT_EQ(first->valid_lft_, second->valid_lft_);
+ EXPECT_EQ(first->cltt_, second->cltt_);
+ EXPECT_EQ(first->subnet_id_, second->subnet_id_);
+}
+
+/// @brief Compare two Lease6 structures for equality
+void
+detailCompareLease(const Lease6Ptr& first, const Lease6Ptr& second) {
+ EXPECT_EQ(first->type_, second->type_);
+
+ // Compare address strings. Comparison of address objects is not used, as
+ // odd things happen when they are different: the EXPECT_EQ macro appears to
+ // call the operator uint32_t() function, which causes an exception to be
+ // thrown for IPv6 addresses.
+ EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
+ EXPECT_EQ(first->prefixlen_, second->prefixlen_);
+ EXPECT_EQ(first->iaid_, second->iaid_);
+ EXPECT_TRUE(*first->duid_ == *second->duid_);
+ EXPECT_EQ(first->preferred_lft_, second->preferred_lft_);
+ EXPECT_EQ(first->valid_lft_, second->valid_lft_);
+ EXPECT_EQ(first->cltt_, second->cltt_);
+ EXPECT_EQ(first->subnet_id_, second->subnet_id_);
+}
+
+///@}
+
/// @brief Check that database can be opened
///
@@ -654,8 +695,6 @@ TEST_F(MySqlLeaseMgrTest, checkTimeConversion) {
/// @brief Check getName() returns correct database name
TEST_F(MySqlLeaseMgrTest, getName) {
EXPECT_EQ(std::string("keatest"), lmptr_->getName());
-
- // @TODO: check for the negative
}
/// @brief Check that getVersion() returns the expected version
@@ -667,53 +706,9 @@ TEST_F(MySqlLeaseMgrTest, checkVersion) {
EXPECT_EQ(CURRENT_VERSION_MINOR, version.second);
}
-/// @brief Compare two Lease4 structures for equality
-void
-detailCompareLease(const Lease4Ptr& first, const Lease4Ptr& second) {
- // Compare address strings. Comparison of address objects is not used, as
- // odd things happen when they are different: the EXPECT_EQ macro appears to
- // call the operator uint32_t() function, which causes an exception to be
- // thrown for IPv6 addresses.
- EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
- EXPECT_TRUE(first->hwaddr_ == second->hwaddr_);
- EXPECT_TRUE(*first->client_id_ == *second->client_id_);
- EXPECT_EQ(first->valid_lft_, second->valid_lft_);
- EXPECT_EQ(first->cltt_, second->cltt_);
- EXPECT_EQ(first->subnet_id_, second->subnet_id_);
-}
-
-/// @brief Compare two Lease6 structures for equality
-void
-detailCompareLease(const Lease6Ptr& first, const Lease6Ptr& second) {
- EXPECT_EQ(first->type_, second->type_);
-
- // Compare address strings. Comparison of address objects is not used, as
- // odd things happen when they are different: the EXPECT_EQ macro appears to
- // call the operator uint32_t() function, which causes an exception to be
- // thrown for IPv6 addresses.
- EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
- EXPECT_EQ(first->prefixlen_, second->prefixlen_);
- EXPECT_EQ(first->iaid_, second->iaid_);
- EXPECT_TRUE(*first->duid_ == *second->duid_);
- EXPECT_EQ(first->preferred_lft_, second->preferred_lft_);
- EXPECT_EQ(first->valid_lft_, second->valid_lft_);
- EXPECT_EQ(first->cltt_, second->cltt_);
- EXPECT_EQ(first->subnet_id_, second->subnet_id_);
-}
-
-
-/// @brief Basic Lease Checks
-///
-/// Checks that the add/get/delete works. All are done within one
-/// test so that "rollback" can be used to remove trace of the tests
-/// from the database.
+/// @brief Basic Lease4 Checks
///
-/// Tests where a collection of leases can be returned are in the test
-/// Lease4Collection.
-///
-/// @param leases Vector of leases used in the tests
-/// @param ioaddress Vector of IOAddresses used in the tests
-
+/// Checks that the addLease, getLease4 (by address) and deleteLease4 works.
TEST_F(MySqlLeaseMgrTest, basicLease4) {
// Get the leases to be used for the test.
vector<Lease4Ptr> leases = createLeases4();
@@ -756,15 +751,9 @@ TEST_F(MySqlLeaseMgrTest, basicLease4) {
detailCompareLease(leases[2], l_returned);
}
-
-/// @brief Check individual Lease6 methods
-///
-/// Checks that the add/get/delete works. All are done within one
-/// test so that "rollback" can be used to remove trace of the tests
-/// from the database.
+/// @brief Basic Lease6 Checks
///
-/// Tests where a collection of leases can be returned are in the test
-/// Lease6Collection.
+/// Checks that the addLease, getLease6 (by address) and deleteLease6 works.
TEST_F(MySqlLeaseMgrTest, basicLease6) {
// Get the leases to be used for the test.
vector<Lease6Ptr> leases = createLeases6();
@@ -814,29 +803,38 @@ TEST_F(MySqlLeaseMgrTest, basicLease6) {
TEST_F(MySqlLeaseMgrTest, getLease4AddressSubnetId) {
// Get the leases to be used for the test.
vector<Lease4Ptr> leases = createLeases4();
+ const SubnetID lease1_subnetid = leases[1]->subnet_id_;
+
+ // Generate a Subnet ID known to be invalid - one more than the maximum
+ // Subnet ID in all the leases.
+ SubnetID invalid_subnetid = 0;
+ for (int i = 0; i < leases.size(); ++i) {
+ invalid_subnetid = max(invalid_subnetid, leases[i]->subnet_id_);
+ }
+ ++invalid_subnetid;
+
// Add just one to the database.
EXPECT_TRUE(lmptr_->addLease(leases[1]));
// Look for a known lease with a valid Subnet ID
- Lease4Ptr l_returned = lmptr_->getLease4(ioaddress4_[1], 73);
+ Lease4Ptr l_returned = lmptr_->getLease4(ioaddress4_[1], lease1_subnetid);
ASSERT_TRUE(l_returned);
detailCompareLease(leases[1], l_returned);
// Look for a lease known to be in the database with an invalid Subnet ID
- l_returned = lmptr_->getLease4(ioaddress4_[1], 74);
+ l_returned = lmptr_->getLease4(ioaddress4_[1], invalid_subnetid);
EXPECT_FALSE(l_returned);
// Look for a lease known not to be in the database with a valid Subnet ID
- l_returned = lmptr_->getLease4(ioaddress4_[2], 73);
+ l_returned = lmptr_->getLease4(ioaddress4_[2], lease1_subnetid);
EXPECT_FALSE(l_returned);
// Look for a lease known not to be in the database with and invalid
- l_returned = lmptr_->getLease4(ioaddress4_[2], 74);
+ l_returned = lmptr_->getLease4(ioaddress4_[2], invalid_subnetid);
EXPECT_FALSE(l_returned);
}
-
/// @brief Check GetLease4 methods - access by Hardware Address
///
/// Adds leases to the database and checks that they can be accessed via
@@ -880,15 +878,39 @@ TEST_F(MySqlLeaseMgrTest, getLease4Hwaddr) {
vector<uint8_t> invalid(6, 0);
returned = lmptr_->getLease4(invalid);
EXPECT_EQ(0, returned.size());
-
- // And check that size of the vector matters
- invalid = leases[4]->hwaddr_;
- invalid.push_back(0);
- returned = lmptr_->getLease4(invalid);
- EXPECT_EQ(0, returned.size());
}
+// @brief Get lease4 by hardware address (2)
+//
+// Check that the system can cope with getting a hardware address of
+// any size.
+TEST_F(MySqlLeaseMgrTest, getLease4HwaddrSize) {
+
+ // Create leases, although we need only one.
+ vector<Lease4Ptr> leases = createLeases4();
+
+ // Now add leases with increasing hardware address size.
+ for (uint8_t i = 0; i <= Lease4::HWADDR_MAX; ++i) {
+ leases[1]->hwaddr_.resize(i, i);
+ EXPECT_TRUE(lmptr_->addLease(leases[1]));
+ Lease4Collection returned = lmptr_->getLease4(leases[1]->hwaddr_);
+ ASSERT_EQ(1, returned.size());
+ detailCompareLease(leases[1], *returned.begin());
+ (void) lmptr_->deleteLease4(leases[1]->addr_);
+ }
+ // Expect some problem when accessing a lease that had too long a hardware
+ // address. (The 42 is a random value put in each byte of the address.)
+ // In fact the address is stored in a truncated form, so we won't find it
+ // when we look.
+ // @todo Check if there is some way of detecting that data added
+ // to the database is truncated. There does not appear to
+ // be any indication in the C API.
+ leases[1]->hwaddr_.resize(Lease4::HWADDR_MAX + 100, 42);
+ EXPECT_TRUE(lmptr_->addLease(leases[1]));
+ Lease4Collection returned = lmptr_->getLease4(leases[1]->hwaddr_);
+ EXPECT_EQ(0, returned.size());
+}
/// @brief Check GetLease4 methods - access by Hardware Address & Subnet ID
///
@@ -938,8 +960,46 @@ TEST_F(MySqlLeaseMgrTest, getLease4HwaddrSubnetId) {
EXPECT_THROW(returned = lmptr_->getLease4(leases[1]->hwaddr_,
leases[1]->subnet_id_),
isc::dhcp::MultipleRecords);
+
+ // Delete all leases in the database
+ for (int i = 0; ADDRESS4[i] != NULL; ++i) {
+ IOAddress addr(ADDRESS4[i]);
+ (void) lmptr_->deleteLease4(addr);
+ }
}
+// @brief Get lease4 by hardware address and subnet ID (2)
+//
+// Check that the system can cope with getting a hardware address of
+// any size.
+TEST_F(MySqlLeaseMgrTest, getLease4HwaddrSubnetIdSize) {
+
+ // Create leases, although we need only one.
+ vector<Lease4Ptr> leases = createLeases4();
+
+ // Now add leases with increasing hardware address size and check
+ // that they can be retrieved.
+ for (uint8_t i = 0; i <= Lease4::HWADDR_MAX; ++i) {
+ leases[1]->hwaddr_.resize(i, i);
+ EXPECT_TRUE(lmptr_->addLease(leases[1]));
+ Lease4Ptr returned = lmptr_->getLease4(leases[1]->hwaddr_,
+ leases[1]->subnet_id_);
+ ASSERT_TRUE(returned);
+ detailCompareLease(leases[1], returned);
+ (void) lmptr_->deleteLease4(leases[1]->addr_);
+ }
+
+ // Expect some error when getting a lease with too long a hardware
+ // address. Set the contents of each byte to 42, a random value.
+ // @todo Check if there is some way of detecting that data added
+ // to the database is truncated. There does not appear to
+ // be any indication in the C API.
+ leases[1]->hwaddr_.resize(Lease4::HWADDR_MAX + 100, 42);
+ EXPECT_TRUE(lmptr_->addLease(leases[1]));
+ Lease4Ptr returned = lmptr_->getLease4(leases[1]->hwaddr_,
+ leases[1]->subnet_id_);
+ EXPECT_FALSE(returned);
+}
/// @brief Check GetLease4 methods - access by Client ID
///
@@ -988,6 +1048,34 @@ TEST_F(MySqlLeaseMgrTest, getLease4ClientId) {
EXPECT_EQ(0, returned.size());
}
+// @brief Get Lease4 by client ID (2)
+//
+// Check that the system can cope with a client ID of any size.
+TEST_F(MySqlLeaseMgrTest, getLease4ClientIdSize) {
+
+ // Create leases, although we need only one.
+ vector<Lease4Ptr> leases = createLeases4();
+
+ // Now add leases with increasing Client ID size can be retrieved.
+ // For speed, go from 0 to 128 is steps of 16.
+ // Intermediate client_id_max is to overcome problem if
+ // ClientId::MAX_CLIENT_ID_LEN is used in an EXPECT_EQ.
+ int client_id_max = ClientId::MAX_CLIENT_ID_LEN;
+ EXPECT_EQ(128, client_id_max);
+ for (uint8_t i = 0; i <= client_id_max; i += 16) {
+ vector<uint8_t> clientid_vec(i, i);
+ leases[1]->client_id_.reset(new ClientId(clientid_vec));
+ EXPECT_TRUE(lmptr_->addLease(leases[1]));
+ Lease4Collection returned = lmptr_->getLease4(*leases[1]->client_id_);
+ ASSERT_TRUE(returned.size() == 1);
+ detailCompareLease(leases[1], *returned.begin());
+ (void) lmptr_->deleteLease4(leases[1]->addr_);
+ }
+
+ // Don't bother to check client IDs longer than the maximum -
+ // these cannot be constructed, and that limitation is tested
+ // in the DUID/Client ID unit tests.
+}
/// @brief Check GetLease4 methods - access by Client ID & Subnet ID
///
@@ -1026,7 +1114,6 @@ TEST_F(MySqlLeaseMgrTest, getLease4ClientIdSubnetId) {
EXPECT_FALSE(returned);
}
-
/// @brief Check GetLease6 methods - access by DUID/IAID
///
/// Adds leases to the database and checks that they can be accessed via
@@ -1072,7 +1159,33 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) {
EXPECT_EQ(0, returned.size());
}
+// @brief Get Lease4 by DUID and IAID (2)
+//
+// Check that the system can cope with a DUID of any size.
+TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSize) {
+
+ // Create leases, although we need only one.
+ vector<Lease6Ptr> leases = createLeases6();
+
+ // Now add leases with increasing DUID size can be retrieved.
+ // For speed, go from 0 to 128 is steps of 16.
+ int duid_max = DUID::MAX_DUID_LEN;
+ EXPECT_EQ(128, duid_max);
+ for (uint8_t i = 0; i <= duid_max; i += 16) {
+ vector<uint8_t> duid_vec(i, i);
+ leases[1]->duid_.reset(new DUID(duid_vec));
+ EXPECT_TRUE(lmptr_->addLease(leases[1]));
+ Lease6Collection returned = lmptr_->getLease6(*leases[1]->duid_,
+ leases[1]->iaid_);
+ EXPECT_EQ(1, returned.size());
+ detailCompareLease(leases[1], *returned.begin());
+ (void) lmptr_->deleteLease6(leases[1]->addr_);
+ }
+ // Don't bother to check DUIDs longer than the maximum - these cannot be
+ // constructed, and that limitation is tested in the DUID/Client ID unit
+ // tests.
+}
/// @brief Check GetLease6 methods - access by DUID/IAID/SubnetID
///
@@ -1111,6 +1224,34 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetId) {
EXPECT_FALSE(returned);
}
+// @brief Get Lease4 by DUID, IAID & subnet ID (2)
+//
+// Check that the system can cope with a DUID of any size.
+TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetIdSize) {
+
+ // Create leases, although we need only one.
+ vector<Lease6Ptr> leases = createLeases6();
+
+ // Now add leases with increasing DUID size can be retrieved.
+ // For speed, go from 0 to 128 is steps of 16.
+ int duid_max = DUID::MAX_DUID_LEN;
+ EXPECT_EQ(128, duid_max);
+ for (uint8_t i = 0; i <= duid_max; i += 16) {
+ vector<uint8_t> duid_vec(i, i);
+ leases[1]->duid_.reset(new DUID(duid_vec));
+ EXPECT_TRUE(lmptr_->addLease(leases[1]));
+ Lease6Ptr returned = lmptr_->getLease6(*leases[1]->duid_,
+ leases[1]->iaid_,
+ leases[1]->subnet_id_);
+ ASSERT_TRUE(returned);
+ detailCompareLease(leases[1], returned);
+ (void) lmptr_->deleteLease6(leases[1]->addr_);
+ }
+
+ // Don't bother to check DUIDs longer than the maximum - these cannot be
+ // constructed, and that limitation is tested in the DUID/Client ID unit
+ // tests.
+}
/// @brief Lease4 update tests
///
@@ -1156,7 +1297,6 @@ TEST_F(MySqlLeaseMgrTest, updateLease4) {
EXPECT_THROW(lmptr_->updateLease4(leases[2]), isc::dhcp::NoSuchLease);
}
-
/// @brief Lease6 update tests
///
/// Checks that we are able to update a lease in the database.
diff --git a/src/lib/dhcpsrv/tests/schema_copy.h b/src/lib/dhcpsrv/tests/schema_copy.h
index 72f6f88..48a11ca 100644
--- a/src/lib/dhcpsrv/tests/schema_copy.h
+++ b/src/lib/dhcpsrv/tests/schema_copy.h
@@ -25,7 +25,9 @@ namespace {
// by semicolons, and the strings must end with a comma. The final line
// statement must be NULL (not in quotes)
-// THIS MUST BE KEPT UP TO DATE AND UPDATED IF THE SCHEMA CHANGES
+// NOTE: This file mirrors the schema in src/lib/dhcpsrv/dhcpdb_create.mysql.
+// If this file is altered, please ensure that any change is compatible
+// with the schema in dhcpdb_create.mysql.
// Deletion of existing tables.
@@ -50,7 +52,7 @@ const char* create_statement[] = {
") ENGINE = INNODB",
"CREATE TABLE lease6 ("
- "address VARCHAR(40) PRIMARY KEY NOT NULL,"
+ "address VARCHAR(39) PRIMARY KEY NOT NULL,"
"duid VARBINARY(128),"
"valid_lifetime INT UNSIGNED,"
"expire TIMESTAMP,"
@@ -75,7 +77,7 @@ const char* create_statement[] = {
"minor INT"
")",
- "INSERT INTO schema_version VALUES (0, 2)",
+ "INSERT INTO schema_version VALUES (1, 0)",
NULL
};
More information about the bind10-changes
mailing list