BIND 10 trac3360, updated. fbae37a0d687905cc456031131ec020f8182c16d [3360] Implemented CSV parser for DHCPv6 leases.
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Mar 24 06:45:37 UTC 2014
The branch, trac3360 has been updated
via fbae37a0d687905cc456031131ec020f8182c16d (commit)
via 3150e9c0e6ccf84d2bce9f14b4d8916c45cb8767 (commit)
from 6199f3a5ea37a65a2405e571a5b189dc127af138 (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 fbae37a0d687905cc456031131ec020f8182c16d
Author: Marcin Siodelski <marcin at isc.org>
Date: Mon Mar 24 07:44:55 2014 +0100
[3360] Implemented CSV parser for DHCPv6 leases.
commit 3150e9c0e6ccf84d2bce9f14b4d8916c45cb8767
Author: Marcin Siodelski <marcin at isc.org>
Date: Sat Mar 15 22:00:19 2014 +0100
[3360] Implemented class for writing/reading DHCPv6 leases from CSV.
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 1 +
src/lib/dhcp/duid.cc | 38 ++++-
src/lib/dhcp/duid.h | 19 ++-
src/lib/dhcp/tests/duid_unittest.cc | 33 +++-
src/lib/dhcpsrv/Makefile.am | 1 +
src/lib/dhcpsrv/csv_lease_file6.cc | 172 +++++++++++++++++++
src/lib/dhcpsrv/csv_lease_file6.h | 150 +++++++++++++++++
src/lib/dhcpsrv/tests/Makefile.am | 8 +-
src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc | 173 ++++++++++++++++++++
src/lib/dhcpsrv/tests/lease_file_io.cc | 69 ++++++++
.../tests/lease_file_io.h} | 50 +++---
src/lib/dhcpsrv/tests/testdata/Makefile.am | 8 +
src/lib/dhcpsrv/tests/testdata/leases6_0.csv | 6 +
src/lib/util/csv_file.h | 26 +++
14 files changed, 725 insertions(+), 29 deletions(-)
create mode 100644 src/lib/dhcpsrv/csv_lease_file6.cc
create mode 100644 src/lib/dhcpsrv/csv_lease_file6.h
create mode 100644 src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc
create mode 100644 src/lib/dhcpsrv/tests/lease_file_io.cc
copy src/lib/{dhcp/tests/pkt_filter6_test_stub.cc => dhcpsrv/tests/lease_file_io.h} (54%)
create mode 100644 src/lib/dhcpsrv/tests/testdata/Makefile.am
create mode 100644 src/lib/dhcpsrv/tests/testdata/leases6_0.csv
-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 83707ee..0a00696 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1535,6 +1535,7 @@ AC_CONFIG_FILES([compatcheck/Makefile
src/lib/dhcpsrv/Makefile
src/lib/dhcpsrv/tests/Makefile
src/lib/dhcpsrv/tests/test_libraries.h
+ src/lib/dhcpsrv/tests/testdata/Makefile
src/lib/dhcp/tests/Makefile
src/lib/dns/benchmarks/Makefile
src/lib/dns/gen-rdatacode.py
diff --git a/src/lib/dhcp/duid.cc b/src/lib/dhcp/duid.cc
index 80fa724..64f9c63 100644
--- a/src/lib/dhcp/duid.cc
+++ b/src/lib/dhcp/duid.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2014 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
@@ -14,8 +14,11 @@
#include <dhcp/duid.h>
#include <exceptions/exceptions.h>
+#include <util/encode/hex.h>
#include <util/io_utilities.h>
-
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/constants.hpp>
+#include <boost/algorithm/string/split.hpp>
#include <iomanip>
#include <sstream>
#include <vector>
@@ -62,6 +65,37 @@ DUID::DUIDType DUID::getType() const {
}
}
+DUID
+DUID::fromText(const std::string& text) {
+ /// @todo optimize stream operations here.
+ std::vector<std::string> split_text;
+ boost::split(split_text, text, boost::is_any_of(":"),
+ boost::algorithm::token_compress_on);
+
+ std::ostringstream s;
+ for (size_t i = 0; i < split_text.size(); ++i) {
+ if (split_text[i].size() == 1) {
+ s << "0";
+
+ } else if (split_text[i].size() > 2) {
+ isc_throw(isc::BadValue, "invalid DUID '" << text << "'");
+ }
+ s << split_text[i];
+ }
+ if (s.str().empty()) {
+ isc_throw(isc::BadValue, "empty DUID is not allowed");
+ }
+
+ std::vector<uint8_t> binary;
+ try {
+ util::encode::decodeHex(s.str(), binary);
+ } catch (const Exception& ex) {
+ isc_throw(isc::BadValue, "failed to create DUID from text '"
+ << text << "': " << ex.what());
+ }
+ return DUID(&binary[0], binary.size());
+}
+
std::string DUID::toText() const {
std::stringstream tmp;
tmp << std::hex;
diff --git a/src/lib/dhcp/duid.h b/src/lib/dhcp/duid.h
index 1cd8388..19d164d 100644
--- a/src/lib/dhcp/duid.h
+++ b/src/lib/dhcp/duid.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2014 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
@@ -69,6 +69,23 @@ class DUID {
/// @brief Returns the DUID type
DUIDType getType() const;
+ /// @brief Create DUID from the textual format.
+ ///
+ /// This static function parses a DUID specified in the textual format.
+ /// The format being parsed should match the DUID representation returned
+ /// by the @c DUID::toText method, i.e. the pairs of hexadecimal digits
+ /// representing bytes of DUID must be separated by colons. Usually the
+ /// single byte is represented by two hexadecimal digits. However, this
+ /// function allows one digit per byte. In this case, a zero is prepended
+ /// before the conversion. For example, a DUID 0:1:2::4:5 equals to
+ /// 00:01:02:00:04:05.
+ ///
+ /// @param text DUID in the hexadecimal format with digits representing
+ /// individual bytes separated by colons.
+ ///
+ /// @throw isc::BadValue if parsing the DUID failed.
+ static DUID fromText(const std::string& text);
+
/// @brief Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
std::string toText() const;
diff --git a/src/lib/dhcp/tests/duid_unittest.cc b/src/lib/dhcp/tests/duid_unittest.cc
index 36499c2..9d3ec75 100644
--- a/src/lib/dhcp/tests/duid_unittest.cc
+++ b/src/lib/dhcp/tests/duid_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2014 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
@@ -126,6 +126,37 @@ TEST(DuidTest, getType) {
EXPECT_EQ(DUID::DUID_UNKNOWN, duid_invalid->getType());
}
+// This test checks that the DUID instance can be created from the textual
+// format and that error is reported if the textual format is invalid.
+TEST(DuidTest, fromText) {
+ scoped_ptr<DUID> duid;
+ // DUID with only decimal digits.
+ ASSERT_NO_THROW(
+ duid.reset(new DUID(DUID::fromText("00:01:02:03:04:05:06")))
+ );
+ EXPECT_EQ("00:01:02:03:04:05:06", duid->toText());
+ // DUID with some hexadecimal digits (upper case and lower case).
+ ASSERT_NO_THROW(
+ duid.reset(new DUID(DUID::fromText("00:aa:bb:CD:ee:EF:ab")))
+ );
+ EXPECT_EQ("00:aa:bb:cd:ee:ef:ab", duid->toText());
+ // DUID with one digit for a particular byte.
+ ASSERT_NO_THROW(
+ duid.reset(new DUID(DUID::fromText("00:a:bb:D:ee:EF:ab")))
+ );
+ EXPECT_EQ("00:0a:bb:0d:ee:ef:ab", duid->toText());
+ // Repeated colon sign in the DUID should be ignored.
+ ASSERT_NO_THROW(
+ duid.reset(new DUID(DUID::fromText("00::bb:D:ee:EF:ab")))
+ );
+ EXPECT_EQ("00:bb:0d:ee:ef:ab", duid->toText());
+ // DUID with excessive number of digits for one of the bytes.
+ EXPECT_THROW(
+ duid.reset(new DUID(DUID::fromText("00:01:021:03:04:05:06"))),
+ isc::BadValue
+ );
+}
+
// Test checks if the toText() returns valid texual representation
TEST(DuidTest, toText) {
uint8_t data1[] = {0, 1, 2, 3, 4, 0xff, 0xfe};
diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am
index 1c8a18a..3d0ff91 100644
--- a/src/lib/dhcpsrv/Makefile.am
+++ b/src/lib/dhcpsrv/Makefile.am
@@ -39,6 +39,7 @@ libb10_dhcpsrv_la_SOURCES =
libb10_dhcpsrv_la_SOURCES += addr_utilities.cc addr_utilities.h
libb10_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h
libb10_dhcpsrv_la_SOURCES += callout_handle_store.h
+libb10_dhcpsrv_la_SOURCES += csv_lease_file6.cc csv_lease_file6.h
libb10_dhcpsrv_la_SOURCES += d2_client_cfg.cc d2_client_cfg.h
libb10_dhcpsrv_la_SOURCES += d2_client_mgr.cc d2_client_mgr.h
libb10_dhcpsrv_la_SOURCES += dbaccess_parser.cc dbaccess_parser.h
diff --git a/src/lib/dhcpsrv/csv_lease_file6.cc b/src/lib/dhcpsrv/csv_lease_file6.cc
new file mode 100644
index 0000000..886ea08
--- /dev/null
+++ b/src/lib/dhcpsrv/csv_lease_file6.cc
@@ -0,0 +1,172 @@
+// Copyright (C) 2014 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 <dhcpsrv/csv_lease_file6.h>
+#include <algorithm>
+
+using namespace isc::asiolink;
+using namespace isc::util;
+
+namespace isc {
+namespace dhcp {
+
+CSVLeaseFile6::CSVLeaseFile6(const std::string& filename)
+ : CSVFile(filename) {
+ initColumns();
+}
+
+void
+CSVLeaseFile6::initColumns() {
+ addColumn("address");
+ addColumn("duid");
+ addColumn("valid_lifetime");
+ addColumn("expire");
+ addColumn("subnet_id");
+ addColumn("pref_lifetime");
+ addColumn("lease_type");
+ addColumn("iaid");
+ addColumn("prefix_len");
+ addColumn("fqdn_fwd");
+ addColumn("fqdn_rev");
+ addColumn("hostname");
+}
+
+void
+CSVLeaseFile6::append(const Lease6& lease) const {
+ CSVRow row(getColumnCount());
+ row.writeAt(getColumnIndex("address"), lease.addr_.toText());
+ row.writeAt(getColumnIndex("duid"), lease.duid_->toText());
+ row.writeAt(getColumnIndex("valid_lifetime"), lease.valid_lft_);
+ row.writeAt(getColumnIndex("expire"), lease.cltt_ + lease.valid_lft_);
+ row.writeAt(getColumnIndex("subnet_id"), lease.subnet_id_);
+ row.writeAt(getColumnIndex("pref_lifetime"), lease.preferred_lft_);
+ row.writeAt(getColumnIndex("lease_type"), lease.type_);
+ row.writeAt(getColumnIndex("iaid"), lease.iaid_);
+ row.writeAt(getColumnIndex("prefix_len"),
+ static_cast<int>(lease.prefixlen_));
+ row.writeAt(getColumnIndex("fqdn_fwd"), lease.fqdn_fwd_);
+ row.writeAt(getColumnIndex("fqdn_rev"), lease.fqdn_rev_);
+ row.writeAt(getColumnIndex("hostname"), lease.hostname_);
+ CSVFile::append(row);
+}
+
+bool
+CSVLeaseFile6::next(Lease6Ptr& lease) {
+ lease.reset();
+
+ CSVRow row;
+ CSVFile::next(row);
+
+ if (row == CSVFile::EMPTY_ROW()) {
+ return (true);
+ }
+
+ try {
+ lease.reset(new Lease6(readType(row), readAddress(row), readDUID(row),
+ readIAID(row), readPreferred(row),
+ readValid(row), 0, 0, readSubnetID(row),
+ readPrefixLen(row)));
+ lease->cltt_ = readCltt(row);
+ lease->fqdn_fwd_ = readFqdnFwd(row);
+ lease->fqdn_rev_ = readFqdnRev(row);
+ lease->hostname_ = readhostname(row);
+
+ } catch (std::exception& ex) {
+ lease.reset();
+ setReadMsg(ex.what());
+ return (false);
+ }
+ return (true);
+}
+
+Lease::Type
+CSVLeaseFile6::readType(const CSVRow& row) {
+ return (static_cast<Lease::Type>
+ (row.readAndConvertAt<int>(getColumnIndex("lease_type"))));
+}
+
+IOAddress
+CSVLeaseFile6::readAddress(const CSVRow& row) {
+ IOAddress address(row.readAt(getColumnIndex("address")));
+ return (address);
+}
+
+DuidPtr
+CSVLeaseFile6::readDUID(const util::CSVRow& row) {
+ DuidPtr duid(new DUID(DUID::fromText(row.readAt(getColumnIndex("duid")))));
+ return (duid);
+}
+
+uint32_t
+CSVLeaseFile6::readIAID(const CSVRow& row) {
+ uint32_t iaid = row.readAndConvertAt<uint32_t>(getColumnIndex("iaid"));
+ return (iaid);
+}
+
+uint32_t
+CSVLeaseFile6::readPreferred(const CSVRow& row) {
+ uint32_t pref =
+ row.readAndConvertAt<uint32_t>(getColumnIndex("pref_lifetime"));
+ return (pref);
+}
+
+uint32_t
+CSVLeaseFile6::readValid(const CSVRow& row) {
+ uint32_t valid =
+ row.readAndConvertAt<uint32_t>(getColumnIndex("valid_lifetime"));
+ return (valid);
+}
+
+uint32_t
+CSVLeaseFile6::readCltt(const CSVRow& row) {
+ uint32_t cltt = row.readAndConvertAt<uint32_t>(getColumnIndex("expire"))
+ - readValid();
+ return (cltt);
+}
+
+SubnetID
+CSVLeaseFile6::readSubnetID(const CSVRow& row) {
+ SubnetID subnet_id =
+ row.readAndConvertAt<SubnetID>(getColumnIndex("subnet_id"));
+ return (subnet_id);
+}
+
+uint8_t
+CSVLeaseFile6::readPrefixLen(const CSVRow& row) {
+ int prefixlen = row.readAndConvertAt<int>(getColumnIndex("prefix_len"));
+ return (static_cast<uint8_t>(prefixlen));
+}
+
+bool
+CSVLeaseFile6::readFqdnFwd(const CSVRow& row) {
+ bool fqdn_fwd = row.readAndConvertAt<bool>(getColumnIndex("fqdn_fwd"));
+ return (fqdn_fwd);
+}
+
+bool
+CSVLeaseFile6::readFqdnRev(const CSVRow& row) {
+ bool fqdn_rev = row.readAndConvertAt<bool>(getColumnIndex("fqdn_rev"));
+ return (fqdn_rev);
+}
+
+std::string
+CSVLeaseFile6::readHostname(const CSVRow& row) {
+ std::string hostname = row.readAt(getColumnIndex("hostname"));
+ return (hostname);
+}
+
+
+
+} // end of namespace isc::dhcp
+} // end of namespace isc
diff --git a/src/lib/dhcpsrv/csv_lease_file6.h b/src/lib/dhcpsrv/csv_lease_file6.h
new file mode 100644
index 0000000..7e58470
--- /dev/null
+++ b/src/lib/dhcpsrv/csv_lease_file6.h
@@ -0,0 +1,150 @@
+// Copyright (C) 2014 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.
+
+#ifndef CSV_LEASE_FILE6_H
+#define CSV_LEASE_FILE6_H
+
+#include <asiolink/io_address.h>
+#include <dhcp/duid.h>
+#include <dhcpsrv/lease.h>
+#include <dhcpsrv/subnet.h>
+#include <util/csv_file.h>
+#include <boost/shared_ptr.hpp>
+#include <stdint.h>
+#include <string>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Provides methods to access CSV file with DHCPv6 leases.
+class CSVLeaseFile6 : public isc::util::CSVFile {
+public:
+
+ /// @brief Constructor.
+ ///
+ /// Initializes columns of the lease file.
+ ///
+ /// @param filename Name of the lease file.
+ CSVLeaseFile6(const std::string& filename);
+
+ /// @brief Appends the lease record to the CSV file.
+ ///
+ /// @param lease Structure representing a DHCPv6 lease.
+ void append(const Lease6& lease) const;
+
+ /// @brief Reads next lease from the CSV file.
+ ///
+ /// If this function hits an error during lease read, it sets the error
+ /// message using @c CSVFile::setReadMsg and returns false. The error
+ /// string may be read using @c CSVFile::getReadMsg.
+ ///
+ /// @param [out] lease Pointer to the lease read from CSV file or
+ /// NULL pointer if lease hasn't been read.
+ ///
+ /// @return Boolean value indicating that the new lease has been
+ /// read from the CSV file (if true), or that the error has occurred
+ /// (false).
+ bool next(Lease6Ptr& lease);
+
+private:
+
+ /// @brief Initializes columns of the CSV file holding leases.
+ ///
+ /// This function initializes the following columns:
+ /// - address
+ /// - duid
+ /// - valid_lifetime
+ /// - expire
+ /// - subnet_id
+ /// - pref_lifetime
+ /// - lease_type
+ /// - iaid
+ /// - prefix_len
+ /// - fqdn_fwd
+ /// - fqdn_rev
+ /// - hostname
+ void initColumns();
+
+ ///
+ /// @name Methods which read specific lease fields from the CSV row.
+ ///
+ //@{
+ ///
+ /// @brief Reads lease type from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ Lease::Type readType(const util::CSVRow& row);
+
+ /// @brief Reads lease address from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ asiolink::IOAddress readAddress(const util::CSVRow& row);
+
+ /// @brief Reads DUID from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ DuidPtr readDUID(const util::CSVRow& row);
+
+ /// @brief Reads IAID from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ uint32_t readIAID(const util::CSVRow& row);
+
+ /// @brief Reads preferred lifetime from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ uint32_t readPreferred(const util::CSVRow& row);
+
+ /// @brief Reads valid lifetime from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ uint32_t readValid(const util::CSVRow& row);
+
+ /// @brief Reads cltt value from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ uint32_t readCltt(const util::CSVRow& row);
+
+ /// @brief Reads subnet id from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ SubnetID readSubnetID(const util::CSVRow& row);
+
+ /// @brief Reads prefix length from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ uint8_t readPrefixLen(const util::CSVRow& row);
+
+ /// @brief Reads the FQDN forward flag from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ bool readFqdnFwd(const util::CSVRow& row);
+
+ /// @brief Reads the FQDN reverse flag from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ bool readFqdnRev(const util::CSVRow& row);
+
+ /// @brief Reads hostname from the CSV file row.
+ ///
+ /// @param row CSV file holding lease values.
+ std::string readHostname(const util::CSVRow& row);
+ //@}
+
+};
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif // CSV_LEASE_FILE6_H
diff --git a/src/lib/dhcpsrv/tests/Makefile.am b/src/lib/dhcpsrv/tests/Makefile.am
index f3e0b11..ba7f719 100644
--- a/src/lib/dhcpsrv/tests/Makefile.am
+++ b/src/lib/dhcpsrv/tests/Makefile.am
@@ -1,9 +1,9 @@
-SUBDIRS = .
+SUBDIRS = . testdata
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
-AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/lib/dhcp/tests\"
-AM_CPPFLAGS += -DDHCP_DATA_DIR=\"$(abs_top_builddir)/src/lib/dhcp/tests\"
+AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/lib/dhcpsrv/tests/testdata\"
+AM_CPPFLAGS += -DDHCP_DATA_DIR=\"$(abs_top_builddir)/src/lib/dhcpsrv/tests/testdata\"
AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
AM_CXXFLAGS = $(B10_CXXFLAGS)
@@ -56,9 +56,11 @@ libdhcpsrv_unittests_SOURCES += addr_utilities_unittest.cc
libdhcpsrv_unittests_SOURCES += alloc_engine_unittest.cc
libdhcpsrv_unittests_SOURCES += callout_handle_store_unittest.cc
libdhcpsrv_unittests_SOURCES += cfgmgr_unittest.cc
+libdhcpsrv_unittests_SOURCES += csv_lease_file6_unittest.cc
libdhcpsrv_unittests_SOURCES += d2_client_unittest.cc
libdhcpsrv_unittests_SOURCES += d2_udp_unittest.cc
libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc
+libdhcpsrv_unittests_SOURCES += lease_file_io.cc lease_file_io.h
libdhcpsrv_unittests_SOURCES += lease_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_mgr_factory_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc
diff --git a/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc b/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc
new file mode 100644
index 0000000..e156969
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright (C) 2014 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 <asiolink/io_address.h>
+#include <dhcp/duid.h>
+#include <dhcpsrv/csv_lease_file6.h>
+#include <dhcpsrv/lease.h>
+#include <dhcpsrv/tests/lease_file_io.h>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <gtest/gtest.h>
+#include <sstream>
+
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+using namespace isc::dhcp::test;
+using namespace isc::util;
+
+namespace {
+
+const uint8_t DUID0[] = { 0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf };
+const uint8_t DUID1[] = { 1, 1, 1, 1, 0xa, 1, 2, 3, 4, 5 };
+
+class CSVLeaseFile6Test : public ::testing::Test {
+public:
+
+ CSVLeaseFile6Test();
+
+ /// @brief Prepends the absolute path to the file specified
+ /// as an argument.
+ ///
+ /// @param filename Name of the file.
+ /// @return Absolute path to the test file.
+ static std::string absolutePath(const std::string& filename);
+
+ DuidPtr makeDUID(const uint8_t* duid, const unsigned int size) const {
+ return (DuidPtr(new DUID(duid, size)));
+ }
+
+ std::string filename_;
+ LeaseFileIO io_;
+
+};
+
+CSVLeaseFile6Test::CSVLeaseFile6Test()
+ : filename_(absolutePath("leases6.csv")), io_(filename_) {
+}
+
+std::string
+CSVLeaseFile6Test::absolutePath(const std::string& filename) {
+ std::ostringstream s;
+ s << TEST_DATA_BUILDDIR << "/" << filename;
+ return (s.str());
+}
+
+TEST_F(CSVLeaseFile6Test, parse) {
+ boost::scoped_ptr<CSVLeaseFile6>
+ lf(new CSVLeaseFile6(absolutePath("leases6_0.csv")));
+ ASSERT_NO_THROW(lf->open());
+
+ Lease6Ptr lease;
+ bool lease_read = false;
+ ASSERT_NO_THROW(lease_read = lf->next(lease));
+ ASSERT_TRUE(lease);
+ EXPECT_TRUE(lease_read);
+ EXPECT_EQ("2001:db8:1::1", lease->addr_.toText());
+ ASSERT_TRUE(lease->duid_);
+ EXPECT_EQ("00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f", lease->duid_->toText());
+ EXPECT_EQ(200, lease->valid_lft_);
+ EXPECT_EQ(0, lease->cltt_);
+ EXPECT_EQ(8, lease->subnet_id_);
+ EXPECT_EQ(100, lease->preferred_lft_);
+ EXPECT_EQ(Lease::TYPE_NA, lease->type_);
+ EXPECT_EQ(7, lease->iaid_);
+ EXPECT_EQ(0, lease->prefixlen_);
+ EXPECT_TRUE(lease->fqdn_fwd_);
+ EXPECT_TRUE(lease->fqdn_rev_);
+ EXPECT_EQ("host.example.com", lease->hostname_);
+
+ EXPECT_FALSE(lease_read = lf->next(lease));
+
+ ASSERT_NO_THROW(lease_read = lf->next(lease));
+ ASSERT_TRUE(lease);
+ EXPECT_TRUE(lease_read);
+ EXPECT_EQ("2001:db8:2::10", lease->addr_.toText());
+ ASSERT_TRUE(lease->duid_);
+ EXPECT_EQ("01:01:01:01:0a:01:02:03:04:05", lease->duid_->toText());
+ EXPECT_EQ(300, lease->valid_lft_);
+ EXPECT_EQ(0, lease->cltt_);
+ EXPECT_EQ(6, lease->subnet_id_);
+ EXPECT_EQ(150, lease->preferred_lft_);
+ EXPECT_EQ(Lease::TYPE_NA, lease->type_);
+ EXPECT_EQ(8, lease->iaid_);
+ EXPECT_EQ(0, lease->prefixlen_);
+ EXPECT_FALSE(lease->fqdn_fwd_);
+ EXPECT_FALSE(lease->fqdn_rev_);
+ EXPECT_TRUE(lease->hostname_.empty());
+
+ EXPECT_FALSE(lease_read = lf->next(lease));
+
+ ASSERT_NO_THROW(lease_read = lf->next(lease));
+ ASSERT_TRUE(lease);
+ EXPECT_TRUE(lease_read);
+ EXPECT_EQ("3000:1::", lease->addr_.toText());
+ ASSERT_TRUE(lease->duid_);
+ EXPECT_EQ("00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f", lease->duid_->toText());
+ EXPECT_EQ(0, lease->valid_lft_);
+ EXPECT_EQ(200, lease->cltt_);
+ EXPECT_EQ(8, lease->subnet_id_);
+ EXPECT_EQ(0, lease->preferred_lft_);
+ EXPECT_EQ(Lease::TYPE_PD, lease->type_);
+ EXPECT_EQ(16, lease->iaid_);
+ EXPECT_EQ(64, lease->prefixlen_);
+ EXPECT_FALSE(lease->fqdn_fwd_);
+ EXPECT_FALSE(lease->fqdn_rev_);
+ EXPECT_TRUE(lease->hostname_.empty());
+
+ ASSERT_NO_THROW(lease_read = lf->next(lease));
+ EXPECT_TRUE(lease_read);
+ EXPECT_FALSE(lease);
+}
+
+TEST_F(CSVLeaseFile6Test, recreate) {
+ boost::scoped_ptr<CSVLeaseFile6> lf(new CSVLeaseFile6(filename_));
+ ASSERT_NO_THROW(lf->recreate());
+ ASSERT_TRUE(io_.exists());
+
+ Lease6Ptr lease(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"),
+ makeDUID(DUID0, sizeof(DUID0)),
+ 7, 100, 200, 50, 80, 8, true, true,
+ "host.example.com"));
+ lease->cltt_ = 0;
+ ASSERT_NO_THROW(lf->append(*lease));
+
+ lease.reset(new Lease6(Lease::TYPE_NA, IOAddress("2001:db8:2::10"),
+ makeDUID(DUID1, sizeof(DUID1)),
+ 8, 150, 300, 40, 70, 6, false, false,
+ "", 128));
+ lease->cltt_ = 0;
+ ASSERT_NO_THROW(lf->append(*lease));
+
+ lease.reset(new Lease6(Lease::TYPE_PD, IOAddress("3000:1:1::"),
+ makeDUID(DUID0, sizeof(DUID0)),
+ 7, 150, 300, 40, 70, 10, false, false,
+ "", 64));
+ lease->cltt_ = 0;
+ ASSERT_NO_THROW(lf->append(*lease));
+
+ EXPECT_EQ("address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,"
+ "lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname\n"
+ "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,"
+ "200,200,8,100,0,7,0,1,1,host.example.com\n"
+ "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05"
+ ",300,300,6,150,0,8,128,0,0,\n"
+ "3000:1:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,"
+ "300,300,10,150,2,7,64,0,0,\n",
+ io_.readFile());
+}
+
+} // end of anonymous namespace
diff --git a/src/lib/dhcpsrv/tests/lease_file_io.cc b/src/lib/dhcpsrv/tests/lease_file_io.cc
new file mode 100644
index 0000000..7f7b459
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/lease_file_io.cc
@@ -0,0 +1,69 @@
+// Copyright (C) 2014 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 <dhcpsrv/tests/lease_file_io.h>
+#include <fstream>
+#include <sstream>
+
+namespace isc {
+namespace dhcp {
+namespace test {
+
+LeaseFileIO::LeaseFileIO(const std::string& filename)
+ : testfile_(filename) {
+ removeFile();
+}
+
+LeaseFileIO::~LeaseFileIO() {
+ // removeFile();
+}
+
+bool
+LeaseFileIO::exists() const {
+ std::ifstream fs(testfile_.c_str());
+ bool ok = fs.good();
+ fs.close();
+ return (ok);
+}
+
+std::string
+LeaseFileIO::readFile() const {
+ std::ifstream fs(testfile_.c_str());
+ if (!fs.is_open()) {
+ return ("");
+ }
+ std::string contents((std::istreambuf_iterator<char>(fs)),
+ std::istreambuf_iterator<char>());
+ fs.close();
+ return (contents);
+}
+
+void
+LeaseFileIO::removeFile() const {
+ remove(testfile_.c_str());
+}
+
+void
+LeaseFileIO::writeFile(const std::string& contents) const {
+ std::ofstream fs(testfile_.c_str(), std::ofstream::out);
+ if (fs.is_open()) {
+ fs << contents;
+ fs.close();
+ }
+}
+
+} // end of namespace isc::dhcp::test
+} // end of namespace isc::dhcp
+} // end of namespace isc
+
diff --git a/src/lib/dhcpsrv/tests/lease_file_io.h b/src/lib/dhcpsrv/tests/lease_file_io.h
new file mode 100644
index 0000000..b2e4da2
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/lease_file_io.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2014 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.
+
+#ifndef LEASE_FILE_IO_H
+#define LEASE_FILE_IO_H
+
+#include <string>
+
+namespace isc {
+namespace dhcp {
+namespace test {
+
+class LeaseFileIO {
+public:
+ LeaseFileIO(const std::string& filename);
+
+ ~LeaseFileIO();
+
+ /// @brief Check if test file exists on disk.
+ bool exists() const;
+
+ /// @brief Reads whole lease file.
+ ///
+ /// @return Contents of the file.
+ std::string readFile() const;
+
+ /// @brief Removes existing file (if any).
+ void removeFile() const;
+
+ /// @brief Creates file with contents.
+ ///
+ /// @param contents Contents of the file.
+ void writeFile(const std::string& contents) const;
+
+ /// @brief Absolute path to the file used in the tests.
+ std::string testfile_;
+
+};
+
+}
+}
+}
+
+#endif // LEASE_FILE_IO_H
diff --git a/src/lib/dhcpsrv/tests/testdata/Makefile.am b/src/lib/dhcpsrv/tests/testdata/Makefile.am
new file mode 100644
index 0000000..ce2dace
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/testdata/Makefile.am
@@ -0,0 +1,8 @@
+SUBDIRS = .
+
+# CSV files are created by unit tests which check the CSVLeaseFile6
+# and CSVLeaseFile4 classes.
+CLEANFILES = *.csv
+
+EXTRA_DIST = leases6_0.csv
+
diff --git a/src/lib/dhcpsrv/tests/testdata/leases6_0.csv b/src/lib/dhcpsrv/tests/testdata/leases6_0.csv
new file mode 100644
index 0000000..3e3eaab
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/testdata/leases6_0.csv
@@ -0,0 +1,6 @@
+address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname
+2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,200,8,100,0,7,0,1,1,host.example.com
+2001:db8:1::1,,200,200,8,100,0,7,0,1,1,host.example.com
+2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05,300,300,6,150,0,8,0,0,0,
+2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,200,200,8,100,0,7,10,1,1,host.example.com
+3000:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,0,200,8,0,2,16,64,0,0,
diff --git a/src/lib/util/csv_file.h b/src/lib/util/csv_file.h
index bf2bdb2..e974641 100644
--- a/src/lib/util/csv_file.h
+++ b/src/lib/util/csv_file.h
@@ -118,6 +118,32 @@ public:
/// @c CSVRow::getValuesCount.
std::string readAt(const size_t at) const;
+ /// @brief Retrieves a value from the internal container.
+ ///
+ /// This method is reads a value from the internal container and converts
+ /// this value to the type specified as a template parameter. Internally
+ /// it uses @c boost::lexical_cast.
+ ///
+ /// @param at Index of the value in the container. The values are indexed
+ /// from 0, where 0 corresponds to the left-most value in the CSV file row.
+ /// @tparam T type of the value to convert to.
+ ///
+ /// @return Converted value.
+ ///
+ /// @throw CSVFileError if the index is out of range or if the
+ /// @c boost::bad_lexical_cast is thrown by the @c boost::lexical_cast.
+ template<typename T>
+ T readAndConvertAt(const size_t at) const {
+ T cast_value;
+ try {
+ cast_value = boost::lexical_cast<T>(readAt(at).c_str());
+
+ } catch (const boost::bad_lexical_cast& ex) {
+ isc_throw(CSVFileError, ex.what());
+ }
+ return (cast_value);
+ }
+
/// @brief Creates a text representation of the CSV file row.
///
/// This function iterates over all values currently held in the internal
More information about the bind10-changes
mailing list