From: Shawn Routhier Date: Thu, 1 Oct 2015 00:49:22 +0000 (-0700) Subject: [trac3576] Clean up white space and add new files X-Git-Tag: trac3874_base~40^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d17f7e918d1bab4abb87750d671de78dfc8f7963;p=thirdparty%2Fkea.git [trac3576] Clean up white space and add new files --- diff --git a/src/lib/dhcp/option_opaque_data_tuples.cc b/src/lib/dhcp/option_opaque_data_tuples.cc new file mode 100644 index 0000000000..4a37e2e228 --- /dev/null +++ b/src/lib/dhcp/option_opaque_data_tuples.cc @@ -0,0 +1,154 @@ +// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include +#include +#include +#include + +namespace isc { +namespace dhcp { + +OptionOpaqueDataTuples::OptionOpaqueDataTuples(Option::Universe u, + const uint16_t type) + : Option(u, type) { +} + +OptionOpaqueDataTuples::OptionOpaqueDataTuples(Option::Universe u, + const uint16_t type, + OptionBufferConstIter begin, + OptionBufferConstIter end) + : Option(u, type) { + unpack(begin, end); +} + +void +OptionOpaqueDataTuples::pack(isc::util::OutputBuffer& buf) { + packHeader(buf); + + for (TuplesCollection::const_iterator it = tuples_.begin(); + it != tuples_.end(); ++it) { + it->pack(buf); + } + +} + +void +OptionOpaqueDataTuples::unpack(OptionBufferConstIter begin, + OptionBufferConstIter end) { + if (std::distance(begin, end) < getMinimalLength() - getHeaderLen()) { + isc_throw(OutOfRange, "parsed data tuples option data truncated to" + " size " << std::distance(begin, end)); + } + + // Start reading opaque data. + size_t offset = 0; + while (offset < std::distance(begin, end)) { + // Parse a tuple. + OpaqueDataTuple tuple(getLengthFieldType(), begin + offset, end); + addTuple(tuple); + // The tuple has been parsed correctly which implies that it is safe to + // advance the offset by its total length. + offset += tuple.getTotalLength(); + } +} + +void +OptionOpaqueDataTuples::addTuple(const OpaqueDataTuple& tuple) { + if (tuple.getLengthFieldType() != getLengthFieldType()) { + isc_throw(isc::BadValue, "attempted to add opaque data tuple having" + " invalid size of the length field " + << tuple.getDataFieldSize() << " to Vendor Class option"); + } + + tuples_.push_back(tuple); +} + + +void +OptionOpaqueDataTuples::setTuple(const size_t at, const OpaqueDataTuple& tuple) { + if (at >= getTuplesNum()) { + isc_throw(isc::OutOfRange, "attempted to set an opaque data for the" + " vendor option at position " << at << " which is out of" + " range"); + + } else if (tuple.getLengthFieldType() != getLengthFieldType()) { + isc_throw(isc::BadValue, "attempted to set opaque data tuple having" + " invalid size of the length field " + << tuple.getDataFieldSize() << " to Vendor Class option"); + } + + tuples_[at] = tuple; +} + +OpaqueDataTuple +OptionOpaqueDataTuples::getTuple(const size_t at) const { + if (at >= getTuplesNum()) { + isc_throw(isc::OutOfRange, "attempted to get an opaque data for the" + " vendor option at position " << at << " which is out of" + " range. There are only " << getTuplesNum() << " tuples"); + } + return (tuples_[at]); +} + +bool +OptionOpaqueDataTuples::hasTuple(const std::string& tuple_str) const { + // Iterate over existing tuples (there shouldn't be many of them), + // and try to match the searched one. + for (TuplesCollection::const_iterator it = tuples_.begin(); + it != tuples_.end(); ++it) { + if (*it == tuple_str) { + return (true); + } + } + return (false); +} + + +uint16_t +OptionOpaqueDataTuples::len() { + // The option starts with the header. + uint16_t length = getHeaderLen(); + // Now iterate over existing tuples and add their size. + for (TuplesCollection::const_iterator it = tuples_.begin(); + it != tuples_.end(); ++it) { + length += it->getTotalLength(); + } + + return (length); +} + +std::string +OptionOpaqueDataTuples::toText(int indent) { + std::ostringstream s; + + // Apply indentation + s << std::string(indent, ' '); + + + + // Print type and length + s << "type=" << getType() << ", len=" << len() - getHeaderLen() << std::dec; + // Iterate over all tuples and print their size and contents. + for (unsigned i = 0; i < getTuplesNum(); ++i) { + // Print the tuple. + s << ", data-len" << i << "=" << getTuple(i).getLength(); + s << ", data" << i << "='" << getTuple(i) << "'"; + } + + return (s.str()); +} + +} // namespace isc::dhcp +} // namespace isc diff --git a/src/lib/dhcp/option_opaque_data_tuples.h b/src/lib/dhcp/option_opaque_data_tuples.h new file mode 100644 index 0000000000..ee7adaf26b --- /dev/null +++ b/src/lib/dhcp/option_opaque_data_tuples.h @@ -0,0 +1,174 @@ +// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#ifndef OPTION_OPAQUE_DATA_TUPLES_H +#define OPTION_OPAQUE_DATA_TUPLES_H + +#include +#include +#include +#include +#include +#include +#include + +namespace isc { +namespace dhcp { + +/// @brief This class encapsulates a collection of data tuples and could be +/// used by multiple options. It is tailored for use with the DHCPv6 +/// Bootfile-param option (option 60). +/// +/// The format of the option is described in section 3.2 of RFC5970. +/// This option may carry an arbitrary number of tuples carrying opaque data. +/// Each tuple consists of a field holding the length of the opaque data +/// followed by a string containing the data itself. For option 60 each +/// length field is 2 bytes long and the data is a UTF-8 string that is not +/// null terminated. +/// +/// @todo The class is similar to the class used by the DHCPv6 Vendor Class +/// (16) and DHCPv4 V-I Vendor Class (124) options, though they include an +/// enterprise (or vendor) ID in the option. In the future it may +/// make sense to rewrite the OptionVendorClass to derive from this class. +class OptionOpaqueDataTuples : public Option { +public: + + /// @brief Collection of opaque data tuples carried by the option. + typedef std::vector TuplesCollection; + + /// @brief Constructor. + /// + /// This constructor creates an instance of an OpaqueDataTuple that can + /// be used for an option such as DHCPv6 Bootfile Parameters (60). + /// + /// @param u universe (v4 or v6). + /// @param type option type + OptionOpaqueDataTuples(Option::Universe u, const uint16_t type); + + /// @brief Constructor. + /// + /// This constructor creates an instance of the option using a buffer with + /// on-wire data. It may throw an exception if the @c unpack method throws. + /// + /// @param u universe (v4 or v6) + /// @param type option type + /// @param begin Iterator pointing to the beginning of the buffer holding an + /// option. + /// @param end Iterator pointing to the end of the buffer holding an option. + OptionOpaqueDataTuples(Option::Universe u, const uint16_t type, + OptionBufferConstIter begin, + OptionBufferConstIter end); + + /// @brief Renders option into the buffer in the wire format. + /// + /// @param [out] buf Buffer to which the option is rendered. + virtual void pack(isc::util::OutputBuffer& buf); + + /// @brief Parses buffer holding an option. + /// + /// This function parses the buffer holding an option and initializes option + /// properties: the collection of tuples. + /// + /// @param begin Iterator pointing to the beginning of the buffer holding an + /// option. + /// @param end Iterator pointing to the end of the buffer holding an option. + virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end); + + /// @brief Adds a new opaque data tuple to the option. + /// + /// @param tuple Tuple to be added. + /// @throw isc::BadValue if the type of the tuple doesn't match the + /// universe this option belongs to. + void addTuple(const OpaqueDataTuple& tuple); + + /// @brief Replaces tuple at the specified index with a new tuple. + /// + /// This function replaces an opaque data tuple at the specified position + /// with the new tuple. If the specified index is out of range an exception + /// is thrown. + /// + /// @param at Index at which the tuple should be replaced. + /// @param tuple Tuple to be set. + /// @throw isc::OutOfRange if the tuple position is out of range. + /// @throw isc::BadValue if the type of the tuple doesn't match the + /// universe this option belongs to. + void setTuple(const size_t at, const OpaqueDataTuple& tuple); + + /// @brief Returns opaque data tuple at the specified position. + /// + /// If the specified position is out of range an exception is thrown. + /// + /// @param at Index at which the tuple should be replaced. + /// @throw isc::OutOfRange if the tuple position is out of range. + OpaqueDataTuple getTuple(const size_t at) const; + + /// @brief Returns the number of opaque data tuples added to the option. + size_t getTuplesNum() const { + return (tuples_.size()); + } + + /// @brief Returns collection of opaque data tuples carried in the option. + const TuplesCollection& getTuples() const { + return (tuples_); + } + + /// @brief Checks if the object holds the opaque data tuple with the + /// specified string. + /// + /// @param tuple_str String representation of the tuple being searched. + /// @return true if the specified tuple exists for this option. + bool hasTuple(const std::string& tuple_str) const; + + /// @brief Returns the full length of the option, including option header. + virtual uint16_t len(); + + /// @brief Returns text representation of the option. + /// + /// @param indent Number of space characters before text. + /// @return Text representation of the option. + virtual std::string toText(int indent = 0); + +private: + + /// @brief Returns the tuple length field type for the given universe. + /// + /// This function returns the length field type which should be used + /// for the opaque data tuples being added to this option. + /// Currently this class is only used for a DHCPv6 option it may be expanded + /// for DHCPv4 in the future + /// + /// @return Tuple length field type for the universe this option belongs to. + OpaqueDataTuple::LengthFieldType getLengthFieldType() const { + return (OpaqueDataTuple::LENGTH_2_BYTES); + } + + /// @brief Returns minimal length of the option for the given universe. + /// Currently this class is only used for a DHCPv6 option it may be expanded + /// for DHCPv4 in the future + uint16_t getMinimalLength() const { + return (4); + } + + /// @brief Collection of opaque data tuples carried by the option. + TuplesCollection tuples_; + +}; + +/// @brief Defines a pointer to the @c OptionOpaqueDataTuples. +typedef boost::shared_ptr OptionOpaqueDataTuplesPtr; + +} +} + +#endif // OPTION_OPAQUE_DATA_TUPLES_H diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am index 56014da2a4..2e21b53f41 100644 --- a/src/lib/dhcp/tests/Makefile.am +++ b/src/lib/dhcp/tests/Makefile.am @@ -51,6 +51,7 @@ libdhcp___unittests_SOURCES += hwaddr_unittest.cc libdhcp___unittests_SOURCES += iface_mgr_unittest.cc libdhcp___unittests_SOURCES += iface_mgr_test_config.cc iface_mgr_test_config.h libdhcp___unittests_SOURCES += libdhcp++_unittest.cc +libdhcp___unittests_SOURCES += opaque_data_tuple_unittest.cc libdhcp___unittests_SOURCES += option4_addrlst_unittest.cc libdhcp___unittests_SOURCES += option4_client_fqdn_unittest.cc libdhcp___unittests_SOURCES += option6_addrlst_unittest.cc diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc index 802a54607c..1e5d6a8549 100644 --- a/src/lib/dhcp/tests/libdhcp++_unittest.cc +++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc @@ -1031,7 +1031,7 @@ TEST_F(LibDhcpTest, stdOptionDefs6) { 0x00, 0x01, 0x02 }; std::vector bparam_buf(bparam_data, - bparam_data + sizeof(bparam_data));; + bparam_data + sizeof(bparam_data));; // The actual test starts here for all supported option codes. LibDhcpTest::testStdOptionDefs6(D6O_CLIENTID, begin, end, @@ -1183,13 +1183,13 @@ TEST_F(LibDhcpTest, stdOptionDefs6) { LibDhcpTest::testStdOptionDefs6(D6O_BOOTFILE_PARAM, bparam_buf.begin(), bparam_buf.end(), - typeid(OptionOpaqueDataTuples)); + typeid(OptionOpaqueDataTuples)); LibDhcpTest::testStdOptionDefs6(D6O_CLIENT_ARCH_TYPE, begin, end, - typeid(OptionIntArray)); + typeid(OptionIntArray)); LibDhcpTest::testStdOptionDefs6(D6O_NII, begin, begin + 3, - typeid(OptionCustom)); + typeid(OptionCustom)); LibDhcpTest::testStdOptionDefs6(D6O_RSOO, begin, end, typeid(OptionCustom), diff --git a/src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc b/src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc new file mode 100644 index 0000000000..be8a3be04a --- /dev/null +++ b/src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc @@ -0,0 +1,258 @@ +// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include + +#include +#include +#include +#include + +using namespace isc; +using namespace isc::dhcp; +using namespace isc::util; + +namespace { + +// This test checks that the DHCPv6 option constructor sets the default +// properties to the expected values. +TEST(OptionOpaqueDataTuples, constructor6) { + OptionOpaqueDataTuples data_tuple(Option::V6, 60); + // Option length is 2 bytes for option code + 2 bytes for option size + EXPECT_EQ(4, data_tuple.len()); + // There should be no tuples. + EXPECT_EQ(0, data_tuple.getTuplesNum()); +} + +// This test verifies that it is possible to append the opaque data tuple +// to the option and then retrieve it. +TEST(OptionOpaqueDataTuples, addTuple) { + OptionOpaqueDataTuples data_tuple(Option::V6, 60); + // Initially there should be no tuples (for DHCPv6). + ASSERT_EQ(0, data_tuple.getTuplesNum()); + // Create a new tuple and add it to the option. + OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES); + tuple = "xyz"; + data_tuple.addTuple(tuple); + // The option should now hold one tuple. + ASSERT_EQ(1, data_tuple.getTuplesNum()); + EXPECT_EQ("xyz", data_tuple.getTuple(0).getText()); + // Add another tuple. + tuple = "abc"; + data_tuple.addTuple(tuple); + // The option should now hold exactly two tuples in the order in which + // they were added. + ASSERT_EQ(2, data_tuple.getTuplesNum()); + EXPECT_EQ("xyz", data_tuple.getTuple(0).getText()); + EXPECT_EQ("abc", data_tuple.getTuple(1).getText()); + + // Check that hasTuple correctly identifies existing tuples. + EXPECT_TRUE(data_tuple.hasTuple("xyz")); + EXPECT_TRUE(data_tuple.hasTuple("abc")); + EXPECT_FALSE(data_tuple.hasTuple("other")); + + // Attempt to add the tuple with 1 byte long length field should fail + // for DHCPv6 option. + OpaqueDataTuple tuple2(OpaqueDataTuple::LENGTH_1_BYTE); + EXPECT_THROW(data_tuple.addTuple(tuple2), isc::BadValue); +} + +// This test checks that it is possible to replace existing tuple. +TEST(OptionOpaqueDataTuples, setTuple) { + OptionOpaqueDataTuples data_tuple(Option::V6, 60); + // Initially there should be no tuples (for DHCPv6). + ASSERT_EQ(0, data_tuple.getTuplesNum()); + // Add a tuple + OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES); + tuple = "xyz"; + data_tuple.addTuple(tuple); + + // Add another one. + tuple = "abc"; + data_tuple.addTuple(tuple); + ASSERT_EQ(2, data_tuple.getTuplesNum()); + ASSERT_EQ("abc", data_tuple.getTuple(1).getText()); + + // Try to replace them with new tuples. + tuple = "new_xyz"; + ASSERT_NO_THROW(data_tuple.setTuple(0, tuple)); + ASSERT_EQ(2, data_tuple.getTuplesNum()); + EXPECT_EQ("new_xyz", data_tuple.getTuple(0).getText()); + + tuple = "new_abc"; + ASSERT_NO_THROW(data_tuple.setTuple(1, tuple)); + ASSERT_EQ(2, data_tuple.getTuplesNum()); + EXPECT_EQ("new_abc", data_tuple.getTuple(1).getText()); + + // For out of range position, exception should be thrown. + tuple = "foo"; + EXPECT_THROW(data_tuple.setTuple(2, tuple), isc::OutOfRange); +} + +// Check that the returned length of the DHCPv6 option is correct. +TEST(OptionOpaqueDataTuples, len6) { + OptionOpaqueDataTuples data_tuple(Option::V6, 60); + ASSERT_EQ(4, data_tuple.len()); + // Add first tuple. + OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES); + tuple = "xyz"; + ASSERT_NO_THROW(data_tuple.addTuple(tuple)); + // The total length grows by 2 bytes of the length field and 3 bytes + // consumed by 'xyz'. + EXPECT_EQ(9, data_tuple.len()); + // Add another tuple and check that the total size gets increased. + tuple = "abc"; + data_tuple.addTuple(tuple); + EXPECT_EQ(14, data_tuple.len()); +} + +// Check that the DHCPv6 option is rendered to the buffer in wire format. +TEST(OptionOpaqueDataTuples, pack6) { + OptionOpaqueDataTuples data_tuple(Option::V6, 60); + ASSERT_EQ(0, data_tuple.getTuplesNum()); + // Add tuple. + OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES); + tuple = "Hello world"; + data_tuple.addTuple(tuple); + // And add another tuple so as resulting option is a bit more complex. + tuple = "foo"; + data_tuple.addTuple(tuple); + + // Render the data to the buffer. + OutputBuffer buf(10); + ASSERT_NO_THROW(data_tuple.pack(buf)); + ASSERT_EQ(22, buf.getLength()); + + // Prepare reference data. + const uint8_t ref[] = { + 0x00, 0x3C, 0x00, 0x12, // option 60, length 18 + 0x00, 0x0B, // tuple length is 11 + 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello + 0x77, 0x6F, 0x72, 0x6C, 0x64, // world + 0x00, 0x03, // tuple length is 3 + 0x66, 0x6F, 0x6F // foo + }; + // Compare the buffer with reference data. + EXPECT_EQ(0, memcmp(static_cast(ref), + static_cast(buf.getData()), + buf.getLength())); +} + +// This function checks that the DHCPv6 option with two opaque data tuples +// is parsed correctly. +TEST(OptionOpaqueDataTuples, unpack6) { + // Prepare data to decode. + const uint8_t buf_data[] = { + 0x00, 0x0B, // tuple length is 11 + 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello + 0x77, 0x6F, 0x72, 0x6C, 0x64, // world + 0x00, 0x03, // tuple length is 3 + 0x66, 0x6F, 0x6F // foo + }; + OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); + + OptionOpaqueDataTuplesPtr data_tuple; + ASSERT_NO_THROW( + data_tuple = OptionOpaqueDataTuplesPtr(new OptionOpaqueDataTuples(Option::V6, + 60, + buf.begin(), + buf.end())); + ); + EXPECT_EQ(D6O_BOOTFILE_PARAM, data_tuple->getType()); + ASSERT_EQ(2, data_tuple->getTuplesNum()); + EXPECT_EQ("Hello world", data_tuple->getTuple(0).getText()); + EXPECT_EQ("foo", data_tuple->getTuple(1).getText()); +} + +// This test checks that the DHCPv6 option with opaque data of size 0 +// is correctly parsed. +TEST(OptionOpaqueDataTuples, unpack6EmptyTuple) { + // Prepare data to decode. + const uint8_t buf_data[] = { + 0x00, 0x00 // tuple length is 0 + }; + OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); + + OptionOpaqueDataTuplesPtr data_tuple; + ASSERT_NO_THROW( + data_tuple = OptionOpaqueDataTuplesPtr(new OptionOpaqueDataTuples(Option::V6, + 60, + buf.begin(), + buf.end())); + ); + EXPECT_EQ(D6O_BOOTFILE_PARAM, data_tuple->getType()); + ASSERT_EQ(1, data_tuple->getTuplesNum()); + EXPECT_TRUE(data_tuple->getTuple(0).getText().empty()); +} + +// This test checks that exception is thrown when parsing truncated DHCPv6 +// bootfile-param option +TEST(OptionOpaqueDataTuples, unpack6Truncated) { + // Prepare data to decode. + const uint8_t buf_data[] = { + 0x00, 0x0B, // tuple length is 11 + 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello + 0x77, 0x6F, 0x72, 0x6C // worl (truncated d!) + }; + OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); + + EXPECT_THROW(OptionOpaqueDataTuples (Option::V6, 60, buf.begin(), buf.end()), + isc::dhcp::OpaqueDataTupleError); +} + +// This test checks that the DHCPv6 bootfile-param option containing no opaque +// data is parsed correctly. +TEST(OptionOpaqueDataTuples, unpack6NoTuple) { + // Prepare data to decode. + const uint8_t buf_data[] = { + }; + OptionBuffer buf(buf_data,buf_data + sizeof(buf_data)); + + OptionOpaqueDataTuplesPtr data_tuple; + ASSERT_NO_THROW( + data_tuple = OptionOpaqueDataTuplesPtr(new OptionOpaqueDataTuples(Option::V6, + 60, + buf.begin(), + buf.end())); + ); + EXPECT_EQ(D6O_BOOTFILE_PARAM, data_tuple->getType()); + EXPECT_EQ(0, data_tuple->getTuplesNum()); +} + +// Verifies correctness of the text representation of the DHCPv6 option. +TEST(OptionOpaqueDataTuples, toText6) { + OptionOpaqueDataTuples data_tuple(Option::V6, 60); + ASSERT_EQ(0, data_tuple.getTuplesNum()); + // Lets add a tuple + OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES); + tuple = "Hello world"; + data_tuple.addTuple(tuple); + // And add another tuple so as resulting option is a bit more complex. + tuple = "foo"; + data_tuple.addTuple(tuple); + // Check that the text representation of the option is as expected. + EXPECT_EQ("type=60, len=18," + " data-len0=11, data0='Hello world'," + " data-len1=3, data1='foo'", + data_tuple.toText()); + + // Check that indentation works. + EXPECT_EQ(" type=60, len=18," + " data-len0=11, data0='Hello world'," + " data-len1=3, data1='foo'", + data_tuple.toText(2)); +} + +} // end of anonymous namespace + diff --git a/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc b/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc index 0598efbfb3..93e250d93a 100644 --- a/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_option_def_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above