Browse Source

[3806] Added and/or fixed toText implementations for various options.

Marcin Siodelski 10 years ago
parent
commit
cebd8442c1

+ 36 - 15
src/lib/dhcp/option.cc

@@ -195,29 +195,50 @@ bool Option::delOption(uint16_t opt_type) {
 }
 
 
-std::string Option::toText(int indent /* =0 */ ) {
-    std::stringstream tmp;
-
-    for (int i = 0; i < indent; i++)
-        tmp << " ";
-
-    tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ": ";
+std::string Option::toText(int indent) {
+    std::stringstream output;
+    output << headerToText(indent) << ": ";
 
     for (unsigned int i = 0; i < data_.size(); i++) {
         if (i) {
-            tmp << ":";
+            output << ":";
         }
-        tmp << setfill('0') << setw(2) << hex
+        output << setfill('0') << setw(2) << hex
             << static_cast<unsigned short>(data_[i]);
     }
 
-    // print suboptions
-    for (OptionCollection::const_iterator opt = options_.begin();
-         opt != options_.end();
-         ++opt) {
-        tmp << (*opt).second->toText(indent+2);
+    // Append suboptions.
+    output << suboptionsToText(indent + 2);
+
+    return (output.str());
+}
+
+std::string
+Option::headerToText(const int indent) {
+    std::stringstream output;
+    for (int i = 0; i < indent; i++)
+        output << " ";
+
+    int field_len = (getUniverse() == V4 ? 3 : 5);
+    output << "type=" << std::setw(field_len) << std::setfill('0')
+           << type_ << ", len=" << std::setw(field_len) << std::setfill('0')
+           << len()-getHeaderLen();
+    return (output.str());
+}
+
+std::string
+Option::suboptionsToText(const int indent) const {
+    std::stringstream output;
+
+    if (!options_.empty()) {
+        output << "," << std::endl << "options:";
+        for (OptionCollection::const_iterator opt = options_.begin();
+             opt != options_.end(); ++opt) {
+            output << std::endl << (*opt).second->toText(indent);
+        }
     }
-    return tmp.str();
+
+    return (output.str());
 }
 
 uint16_t

+ 26 - 2
src/lib/dhcp/option.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-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
@@ -423,7 +423,31 @@ protected:
     /// those into one exception which can be documented here.
     void unpackOptions(const OptionBuffer& buf);
 
-    /// @brief A private method used for option correctness.
+    /// @brief Returns option header in the textual format.
+    ///
+    /// This protected method should be called by the derived classes in
+    /// their respective @c toText implementations.
+    ///
+    /// @param indent Number of spaces to insert before the text.
+    ///
+    /// @return Option header in the textual format.
+    std::string headerToText(const int indent = 0);
+
+    /// @brief Returns collection of suboptions in the textual format.
+    ///
+    /// This protected method should be called by the derived classes
+    /// in their respective @c toText implementations to append the
+    /// suboptions held by this option. Note that there are some
+    /// option types which don't have suboptions because they contain
+    /// variable length fields. For such options this method is not
+    /// called.
+    ///
+    /// @param indent Number of spaces to insert before the text.
+    ///
+    //// @return Suboptions in the textual format.
+    std::string suboptionsToText(const int indent = 0) const;
+
+    /// @brief A protected method used for option correctness.
     ///
     /// It is used in constructors. In there are any problems detected
     /// (like specifying type > 255 for DHCPv4 option), it will throw

+ 6 - 11
src/lib/dhcp/option4_addrlst.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012,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
@@ -120,21 +120,16 @@ uint16_t Option4AddrLst::len() {
     return (getHeaderLen() + addrs_.size() * V4ADDRESS_LEN);
 }
 
-std::string Option4AddrLst::toText(int indent /* =0 */ ) {
-    std::stringstream tmp;
-
-    for (int i = 0; i < indent; i++) {
-        tmp << " ";
-    }
-
-    tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ":";
+std::string Option4AddrLst::toText(int indent) {
+    std::stringstream output;
+    output << headerToText(indent) << ":";
 
     for (AddressContainer::const_iterator addr = addrs_.begin();
          addr != addrs_.end(); ++addr) {
-        tmp << " " << (*addr);
+        output << " " << (*addr);
     }
 
-    return tmp.str();
+    return (output.str());
 }
 
 } // end of isc::dhcp namespace

+ 6 - 9
src/lib/dhcp/option6_addrlst.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2012, 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012,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
@@ -97,18 +97,15 @@ void Option6AddrLst::unpack(OptionBufferConstIter begin,
     }
 }
 
-std::string Option6AddrLst::toText(int indent /* =0 */) {
-    stringstream tmp;
-    for (int i = 0; i < indent; i++)
-        tmp << " ";
-
-    tmp << "type=" << type_ << " " << addrs_.size() << "addr(s): ";
+std::string Option6AddrLst::toText(int indent) {
+    stringstream output;
+    output << headerToText(indent) << ":";
 
     for (AddressContainer::const_iterator addr = addrs_.begin();
          addr != addrs_.end(); ++addr) {
-        tmp << *addr << " ";
+        output << " " << *addr;
     }
-    return tmp.str();
+    return (output.str());
 }
 
 uint16_t Option6AddrLst::len() {

+ 13 - 30
src/lib/dhcp/option_custom.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2013, 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013,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
@@ -349,17 +349,17 @@ OptionCustom::dataFieldToText(const OptionDataType data_type,
         text << readAddress(index);
         break;
     case OPT_FQDN_TYPE:
-        text << readFqdn(index);
+        text << "\"" << readFqdn(index) << "\"";
         break;
     case OPT_STRING_TYPE:
-        text << readString(index);
+        text << "\"" << readString(index) << "\"";
         break;
     default:
         ;
     }
 
     // Append data field type in brackets.
-    text << " ( " << OptionDataTypeUtil::getDataTypeName(data_type) << " ) ";
+    text << " (" << OptionDataTypeUtil::getDataTypeName(data_type) << ")";
 
     return (text.str());
 }
@@ -532,13 +532,9 @@ void OptionCustom::initialize(const OptionBufferConstIter first,
 }
 
 std::string OptionCustom::toText(int indent) {
-    std::stringstream tmp;
+    std::stringstream output;
 
-    for (int i = 0; i < indent; ++i)
-        tmp << " ";
-
-    tmp << "type=" << type_ << ", len=" << len()-getHeaderLen()
-        << ", data fields:" << std::endl;
+    output << headerToText(indent) << ":";
 
     OptionDataType data_type = definition_.getType();
     if (data_type == OPT_RECORD_TYPE) {
@@ -550,13 +546,8 @@ std::string OptionCustom::toText(int indent) {
         // with them.
         for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
              field != fields.end(); ++field) {
-            for (int j = 0; j < indent + 2; ++j) {
-                tmp << " ";
-            }
-            tmp << "#" << std::distance(fields.begin(), field) << " "
-                << dataFieldToText(*field, std::distance(fields.begin(),
-                                                         field))
-                << std::endl;
+            output << " " << dataFieldToText(*field, std::distance(fields.begin(),
+                                                                   field));
         }
     } else {
         // For non-record types we iterate over all buffers
@@ -565,22 +556,14 @@ std::string OptionCustom::toText(int indent) {
         // and non-arrays as they only differ in such a way that
         // non-arrays have just single data field.
         for (unsigned int i = 0; i < getDataFieldsNum(); ++i) {
-            for (int j = 0; j < indent + 2; ++j) {
-                tmp << " ";
-            }
-            tmp << "#" << i << " "
-                << dataFieldToText(definition_.getType(), i)
-                << std::endl;
+            output << " " << dataFieldToText(definition_.getType(), i);
         }
     }
 
-    // print suboptions
-    for (OptionCollection::const_iterator opt = options_.begin();
-         opt != options_.end();
-         ++opt) {
-        tmp << (*opt).second->toText(indent+2);
-    }
-    return tmp.str();
+    // Append suboptions.
+    output << suboptionsToText(indent + 2);
+
+    return (output.str());
 }
 
 } // end of isc::dhcp namespace

+ 31 - 0
src/lib/dhcp/option_int.h

@@ -21,6 +21,7 @@
 #include <util/io_utilities.h>
 
 #include <stdint.h>
+#include <sstream>
 
 namespace isc {
 namespace dhcp {
@@ -205,6 +206,36 @@ public:
         return (length);
     }
 
+    /// @brief Returns option carrying an integer value in the textual
+    /// format.
+    ///
+    /// The returned value also includes the suboptions if present.
+    ///
+    /// @param indent Number of spaces to be inserted before the text.
+    virtual std::string toText(int indent = 0) {
+        std::stringstream output;
+        output << headerToText(indent) << ": ";
+
+        // For 1 byte long data types we need to cast to the integer
+        // because they are usually implemented as "char" types, in
+        // which case the character rather than number would be printed.
+        if (OptionDataTypeTraits<T>::len == 1) {
+            output << static_cast<int>(getValue());
+        } else {
+            output << getValue();
+        }
+
+        // Append data type name.
+        output << " ("
+               << OptionDataTypeUtil::getDataTypeName(OptionDataTypeTraits<T>::type)
+               << ")";
+
+        // Append suboptions.
+        output << suboptionsToText(indent + 2);
+
+        return (output.str());
+    }
+
 private:
 
     T value_;  ///< Value conveyed by the option.

+ 21 - 2
src/lib/dhcp/option_int_array.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013,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
@@ -19,7 +19,7 @@
 #include <dhcp/option.h>
 #include <dhcp/option_data_types.h>
 #include <util/io_utilities.h>
-
+#include <sstream>
 #include <stdint.h>
 
 namespace isc {
@@ -249,6 +249,25 @@ public:
         return (length);
     }
 
+    /// @brief Returns textual representation of the option.
+    ///
+    /// @param indent Number of space characters to be inserted before
+    /// the text.
+    ///
+    /// @return textual representation of the option.
+    virtual std::string toText(int indent = 0) {
+        std::stringstream output;
+        output << headerToText(indent) << ":";
+
+        std::string data_type = OptionDataTypeUtil::getDataTypeName(OptionDataTypeTraits<T>::type);
+        for (typename std::vector<T>::const_iterator value = values_.begin();
+             value != values_.end(); ++value) {
+            output << " " << *value << " (" << data_type << ")";
+        }
+
+        return (output.str());
+    }
+
 private:
 
     std::vector<T> values_;

+ 11 - 1
src/lib/dhcp/option_string.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,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
@@ -13,6 +13,7 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <dhcp/option_string.h>
+#include <sstream>
 
 namespace isc {
 namespace dhcp {
@@ -82,5 +83,14 @@ OptionString::unpack(OptionBufferConstIter begin,
     setData(begin, end);
 }
 
+std::string
+OptionString::toText(int indent) {
+    std::ostringstream output;
+    output << headerToText(indent) << ": "
+           << "\"" << getValue() << "\" (string)";
+
+    return (output.str());
+}
+
 } // end of isc::dhcp namespace
 } // end of isc namespace

+ 8 - 1
src/lib/dhcp/option_string.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,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
@@ -103,6 +103,13 @@ public:
     /// @throw isc::OutOfRange if provided buffer is truncated.
     virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
 
+    /// @brief Returns option information in the textual format.
+    ///
+    /// @param indent Number of space characters to be inserted before
+    /// the text.
+    ///
+    /// @return Option information in the textual format.
+    virtual std::string toText(int indent = 0);
 };
 
 /// Pointer to the OptionString object.

+ 28 - 3
src/lib/dhcp/option_vendor.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013, 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,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
@@ -17,6 +17,7 @@
 #include <dhcp/dhcp4.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/option_vendor.h>
+#include <sstream>
 
 using namespace isc::dhcp;
 
@@ -42,8 +43,7 @@ void OptionVendor::pack(isc::util::OutputBuffer& buf) {
         // Calculate and store data-len as follows:
         // data-len = total option length - header length
         //            - enterprise id field length - data-len field size
-        buf.writeUint8(len() - getHeaderLen() -
-                       sizeof(uint32_t) - sizeof(uint8_t));
+        buf.writeUint8(dataLen());
     }
 
     packOptions(buf);
@@ -85,3 +85,28 @@ uint16_t OptionVendor::len() {
     }
     return (length);
 }
+
+uint8_t
+OptionVendor::dataLen() {
+    // Calculate and store data-len as follows:
+    // data-len = total option length - header length
+    //            - enterprise id field length - data-len field size
+    return (len() - getHeaderLen() - sizeof(uint32_t) - sizeof(uint8_t));
+}
+
+std::string
+OptionVendor::toText(int indent) {
+    std::stringstream output;
+    output << headerToText(indent) << ": "
+           << getVendorId() << " (uint32)";
+
+    // For the DHCPv4 there is one more field.
+    if (getUniverse() == Option::V4) {
+        output << " " << static_cast<int>(dataLen()) << " (uint8)";
+    }
+
+    // Append suboptions.
+    output << suboptionsToText(indent + 2);
+
+    return (output.str());
+}

+ 18 - 1
src/lib/dhcp/option_vendor.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,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
@@ -92,8 +92,25 @@ public:
     /// @return length of this option
     virtual uint16_t len();
 
+    /// @brief Returns the option in the textual format.
+    ///
+    /// @param indent Number of spaces to be inserted before the text.
+    ///
+    /// @return Vendor option in the textual format.
+    virtual std::string toText(int indent = 0);
+
 private:
 
+    /// @brief Calculates the data-len value for DHCPv4.
+    ///
+    /// The data-len field is only present in DHCPv4 space. It follows
+    /// the vendor-id field. This method is called from the
+    /// @c OptionVendor::pack and @c OptionVendor::toText to calculate
+    /// this value.
+    ///
+    /// @return Returns calculated data-len value.
+    uint8_t dataLen();
+
     uint32_t vendor_id_;  ///< Enterprise-id
 };
 

+ 1 - 1
src/lib/dhcp/pkt.h

@@ -161,7 +161,7 @@ public:
     /// implementations of this method.
     ///
     /// @return string with text representation
-    virtual std::string toText() = 0;
+    virtual std::string toText() const = 0;
 
     /// @brief Returns packet size in binary format.
     ///

+ 14 - 13
src/lib/dhcp/pkt4.cc

@@ -358,21 +358,22 @@ Pkt4::makeLabel(const HWAddrPtr& hwaddr, const ClientIdPtr& client_id,
 
 
 std::string
-Pkt4::toText() {
-    stringstream tmp;
-    tmp << "localAddr=" << local_addr_ << ":" << local_port_
-        << " remoteAddr=" << remote_addr_
-        << ":" << remote_port_ << ", msgtype=" << static_cast<int>(getType())
-        << ", transid=0x" << hex << transid_ << dec << endl;
-
-    for (isc::dhcp::OptionCollection::iterator opt=options_.begin();
-         opt != options_.end();
-         ++opt) {
-        tmp << "  " << opt->second->toText();
+Pkt4::toText() const {
+    stringstream output;
+    output << "local_address=" << local_addr_ << ":" << local_port_
+        << ", remote_adress=" << remote_addr_
+        << ":" << remote_port_ << ", msg_type=" << static_cast<int>(getType())
+        << ", transid=0x" << hex << transid_ << dec;
+
+    if (!options_.empty()) {
+        output << "," << std::endl << "options:";
+        for (isc::dhcp::OptionCollection::const_iterator opt = options_.begin();
+             opt != options_.end(); ++opt) {
+            output << std::endl << opt->second->toText(2);
+        }
     }
 
-
-    return tmp.str();
+    return (output.str());
 }
 
 void

+ 1 - 1
src/lib/dhcp/pkt4.h

@@ -137,7 +137,7 @@ public:
     /// This function is useful mainly for debugging.
     ///
     /// @return string with text representation
-    std::string toText();
+    std::string toText() const;
 
     /// @brief Returns the size of the required buffer to build the packet.
     ///

+ 2 - 2
src/lib/dhcp/pkt6.cc

@@ -496,14 +496,14 @@ Pkt6::getMACFromDUID() {
 }
 
 std::string
-Pkt6::toText() {
+Pkt6::toText() const {
     stringstream tmp;
     tmp << "localAddr=[" << local_addr_ << "]:" << local_port_
         << " remoteAddr=[" << remote_addr_
         << "]:" << remote_port_ << endl;
     tmp << "msgtype=" << static_cast<int>(msg_type_) << ", transid=0x" <<
         hex << transid_ << dec << endl;
-    for (isc::dhcp::OptionCollection::iterator opt=options_.begin();
+    for (isc::dhcp::OptionCollection::const_iterator opt=options_.begin();
          opt != options_.end();
          ++opt) {
         tmp << opt->second->toText() << std::endl;

+ 1 - 1
src/lib/dhcp/pkt6.h

@@ -162,7 +162,7 @@ public:
     /// This function is useful mainly for debugging.
     ///
     /// @return string with text representation
-    virtual std::string toText();
+    virtual std::string toText() const;
 
     /// @brief Returns length of the packet.
     ///

+ 35 - 1
src/lib/dhcp/tests/option_custom_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2013,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
@@ -1570,4 +1570,38 @@ TEST_F(OptionCustomTest, invalidIndex) {
     EXPECT_THROW(option->readInteger<uint32_t>(11), isc::OutOfRange);
 }
 
+// This test checks that the custom option holding a record of data
+// fields can be presented in the textual format.
+TEST_F(OptionCustomTest, toTextRecord) {
+    OptionDefinition opt_def("foo", 123, "record");
+    opt_def.addRecordField("uint32");
+    opt_def.addRecordField("string");
+
+    OptionCustom option(opt_def, Option::V4);
+    option.writeInteger<uint32_t>(10);
+    option.writeString("lorem ipsum", 1);
+
+    EXPECT_EQ("type=123, len=015: 10 (uint32) \"lorem ipsum\" (string)",
+              option.toText());
+}
+
+// This test checks that the custom option holding other data type
+// than "record" be presented in the textual format.
+TEST_F(OptionCustomTest, toTextNoRecord) {
+    OptionDefinition opt_def("foo", 234, "uint32");
+
+    OptionCustom option(opt_def, Option::V6);
+    option.writeInteger<uint32_t>(123456);
+
+    OptionDefinition sub_opt_def("bar", 333, "fqdn");
+    OptionCustomPtr sub_opt(new OptionCustom(sub_opt_def, Option::V6));
+    sub_opt->writeFqdn("myhost.example.org.");
+    option.addOption(sub_opt);
+
+    EXPECT_EQ("type=00234, len=00028: 123456 (uint32),\n"
+              "options:\n"
+              "  type=00333, len=00020: \"myhost.example.org.\" (fqdn)",
+              option.toText());
+}
+
 } // anonymous namespace

+ 11 - 1
src/lib/dhcp/tests/option_int_array_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012,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
@@ -464,4 +464,14 @@ TEST_F(OptionIntArrayTest, addValuesInt32) {
     addValuesTest<int16_t>();
 }
 
+TEST_F(OptionIntArrayTest, toText) {
+    OptionUint32Array option(Option::V4, 128);
+    option.addValue(1);
+    option.addValue(32);
+    option.addValue(324);
+
+    EXPECT_EQ("type=128, len=012: 1 (uint32) 32 (uint32) 324 (uint32)",
+              option.toText());
+}
+
 } // anonymous namespace

+ 16 - 1
src/lib/dhcp/tests/option_int_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012,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
@@ -560,4 +560,19 @@ TEST_F(OptionIntTest, unpackSuboptions6) {
     ASSERT_FALSE(subopt);
 }
 
+// This test checks that the toText function returns the option in the
+// textual format correctly.
+TEST_F(OptionIntTest, toText) {
+    OptionUint32 option(Option::V4, 128, 345678);
+    EXPECT_EQ("type=128, len=004: 345678 (uint32)", option.toText());
+
+    option.addOption(OptionPtr(new OptionUint16(Option::V4, 1, 234)));
+    option.addOption(OptionPtr(new OptionUint8(Option::V4, 3, 22)));
+    EXPECT_EQ("type=128, len=011: 345678 (uint32),\n"
+              "options:\n"
+              "  type=001, len=002: 234 (uint16)\n"
+              "  type=003, len=001: 22 (uint8)",
+              option.toText());
+}
+
 } // anonymous namespace

+ 15 - 1
src/lib/dhcp/tests/option_string_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,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
@@ -157,4 +157,18 @@ TEST_F(OptionStringTest, pack) {
     EXPECT_TRUE(option_value == test_string);
 }
 
+// This test checks that the DHCP option holding a single string is
+// correctly returned in the textual format.
+TEST_F(OptionStringTest, toText) {
+    // V4 option
+    std::string option_value("lorem ipsum");
+    OptionString optv4(Option::V4, 122, option_value);
+    EXPECT_EQ("type=122, len=011: \"lorem ipsum\" (string)", optv4.toText());
+
+    // V6 option
+    option_value = "is a filler text";
+    OptionString optv6(Option::V6, 512, option_value);
+    EXPECT_EQ("type=00512, len=00016: \"is a filler text\" (string)", optv6.toText());
+}
+
 } // anonymous namespace

+ 3 - 3
src/lib/dhcp/tests/option_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-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
@@ -233,7 +233,7 @@ TEST_F(OptionTest, v4_toText) {
 
     Option opt(Option::V4, 253, buf);
 
-    EXPECT_EQ("type=253, len=3: 00:0f:ff", opt.toText());
+    EXPECT_EQ("type=253, len=003: 00:0f:ff", opt.toText());
 }
 
 // Tests simple constructor
@@ -443,7 +443,7 @@ TEST_F(OptionTest, v6_toText) {
     buf_[2] = 0xff;
 
     OptionPtr opt(new Option(Option::V6, 258, buf_.begin(), buf_.begin() + 3 ));
-    EXPECT_EQ("type=258, len=3: 00:0f:ff", opt->toText());
+    EXPECT_EQ("type=00258, len=00003: 00:0f:ff", opt->toText());
 }
 
 

+ 26 - 1
src/lib/dhcp/tests/option_vendor_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013,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
@@ -19,6 +19,7 @@
 #include <dhcp/docsis3_option_defs.h>
 #include <dhcp/libdhcp++.h>
 #include <dhcp/option_vendor.h>
+#include <dhcp/option_int.h>
 #include <dhcp/option_int_array.h>
 #include <exceptions/exceptions.h>
 #include <util/buffer.h>
@@ -237,4 +238,28 @@ TEST_F(OptionVendorTest, packUnpack6) {
     EXPECT_FALSE(memcmp(&binary[0], output.getData(), output.getLength()));
 }
 
+// Tests that the vendor option is correctly returned in the textual
+// format for DHCPv4 case.
+TEST_F(OptionVendorTest, toText4) {
+    OptionVendor option(Option::V4, 1024);
+    option.addOption(OptionPtr(new OptionUint32(Option::V4, 1, 100)));
+
+    EXPECT_EQ("type=125, len=011: 1024 (uint32) 6 (uint8),\n"
+              "options:\n"
+              "  type=001, len=004: 100 (uint32)",
+              option.toText());
+}
+
+// Tests that the vendor option is correctly returned in the textual
+// format for DHCPv6 case.
+TEST_F(OptionVendorTest, toText6) {
+    OptionVendor option(Option::V6, 2048);
+    option.addOption(OptionPtr(new OptionUint16(Option::V6, 1, 100)));
+
+    EXPECT_EQ("type=00017, len=00010: 2048 (uint32),\n"
+              "options:\n"
+              "  type=00001, len=00002: 100 (uint16)",
+              option.toText());
+}
+
 }

+ 23 - 0
src/lib/dhcp/tests/pkt4_unittest.cc

@@ -18,7 +18,9 @@
 #include <dhcp/dhcp4.h>
 #include <dhcp/libdhcp++.h>
 #include <dhcp/docsis3_option_defs.h>
+#include <dhcp/option_int.h>
 #include <dhcp/option_string.h>
+#include <dhcp/option4_addrlst.h>
 #include <dhcp/pkt4.h>
 #include <exceptions/exceptions.h>
 #include <util/buffer.h>
@@ -962,4 +964,25 @@ TEST_F(Pkt4Test, getName) {
     }
 }
 
+// This test checks that the packet data are correctly converted to the
+// textual format.
+TEST_F(Pkt4Test, toText) {
+    Pkt4 pkt(DHCPDISCOVER, 2543);
+    pkt.setLocalAddr(IOAddress("192.0.2.34"));
+    pkt.setRemoteAddr(IOAddress("192.10.33.4"));
+
+    pkt.addOption(OptionPtr(new Option4AddrLst(123, IOAddress("192.0.2.3"))));
+    pkt.addOption(OptionPtr(new OptionUint32(Option::V4, 156, 123456)));
+    pkt.addOption(OptionPtr(new OptionString(Option::V4, 87, "lorem ipsum")));
+
+    EXPECT_EQ("local_address=192.0.2.34:67, remote_adress=192.10.33.4:68, "
+              "msg_type=1, transid=0x9ef,\n"
+              "options:\n"
+              "  type=053, len=001: 01\n"
+              "  type=087, len=011: \"lorem ipsum\" (string)\n"
+              "  type=123, len=004: 192.0.2.3\n"
+              "  type=156, len=004: 123456 (uint32)",
+              pkt.toText());
+}
+
 } // end of anonymous namespace