From 351dbdab0925b72ddaad6f95b9008426ceb834ee Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Mon, 10 Dec 2012 17:06:50 +0100 Subject: [PATCH] [2526] OptionInt can be now used for V4 and V6. --- src/lib/dhcp/option.cc | 55 +++-- src/lib/dhcp/option.h | 16 ++ src/lib/dhcp/option_definition.h | 5 +- src/lib/dhcp/option_int.h | 21 +- src/lib/dhcp/tests/option_int_unittest.cc | 275 ++++++++++++++++------ 5 files changed, 275 insertions(+), 97 deletions(-) diff --git a/src/lib/dhcp/option.cc b/src/lib/dhcp/option.cc index 4638025f03..738f023c12 100644 --- a/src/lib/dhcp/option.cc +++ b/src/lib/dhcp/option.cc @@ -99,6 +99,40 @@ void Option::pack(isc::util::OutputBuffer& buf) { void Option::pack4(isc::util::OutputBuffer& buf) { + if (universe_ == V4) { + // Write a header. + packHeader(buf); + // Write data. + if (!data_.empty()) { + buf.writeData(&data_[0], data_.size()); + } + // Write sub-options. + packOptions(buf); + } else { + isc_throw(BadValue, "Invalid universe type " << universe_); + } + + return; +} + +void Option::pack6(isc::util::OutputBuffer& buf) { + if (universe_ == V6) { + // Write a header. + packHeader(buf); + // Write data. + if (!data_.empty()) { + buf.writeData(&data_[0], data_.size()); + } + // Write sub-options. + packOptions(buf); + } else { + isc_throw(BadValue, "Invalid universe type " << universe_); + } + return; +} + +void +Option::packHeader(isc::util::OutputBuffer& buf) { if (universe_ == V4) { if (len() > 255) { isc_throw(OutOfRange, "DHCPv4 Option " << type_ << " is too big. " @@ -110,32 +144,11 @@ Option::pack4(isc::util::OutputBuffer& buf) { buf.writeUint8(type_); buf.writeUint8(len() - getHeaderLen()); - if (!data_.empty()) { - buf.writeData(&data_[0], data_.size()); - } - - packOptions(buf); } else { - isc_throw(BadValue, "Invalid universe type " << universe_); - } - - return; -} - -void Option::pack6(isc::util::OutputBuffer& buf) { - if (universe_ == V6) { buf.writeUint16(type_); buf.writeUint16(len() - getHeaderLen()); - if (!data_.empty()) { - buf.writeData(&data_[0], data_.size()); - } - - packOptions(buf); - } else { - isc_throw(BadValue, "Invalid universe type " << universe_); } - return; } void diff --git a/src/lib/dhcp/option.h b/src/lib/dhcp/option.h index a6b062286e..6dfba8fc1b 100644 --- a/src/lib/dhcp/option.h +++ b/src/lib/dhcp/option.h @@ -312,6 +312,22 @@ protected: /// @throw BadValue Universe is not V6. virtual void pack6(isc::util::OutputBuffer& buf); + /// @brief Store option's header in a buffer. + /// + /// This method writes option's header into a buffer in the + /// on-wire format. The universe set for the particular option + /// is used to determine whether option code and length are + /// stored as 2-byte (for DHCPv6) or single-byte (for DHCPv4) + /// values. For DHCPv4 options, this method checks if the + /// length does not exceed 255 bytes and throws exception if + /// it does. + /// This method is used by derived classes to pack option's + /// header into a buffer. This method should not be called + /// directly by other classes. + /// + /// @param [out] buf output buffer. + void packHeader(isc::util::OutputBuffer& buf); + /// @brief Store sub options in a buffer. /// /// This method stores all sub-options defined for a particular diff --git a/src/lib/dhcp/option_definition.h b/src/lib/dhcp/option_definition.h index 1456f2e25b..698c2fda7d 100644 --- a/src/lib/dhcp/option_definition.h +++ b/src/lib/dhcp/option_definition.h @@ -344,6 +344,7 @@ public: /// @brief Factory function to create option with integer value. /// + /// @param u universe (V4 or V6). /// @param type option type. /// @param begin iterator pointing to the beginning of the buffer. /// @param end iterator pointing to the end of the buffer. @@ -351,10 +352,10 @@ public: /// /// @throw isc::OutOfRange if provided option buffer length is invalid. template - static OptionPtr factoryInteger(Option::Universe, uint16_t type, + static OptionPtr factoryInteger(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end) { - OptionPtr option(new OptionInt(type, begin, end)); + OptionPtr option(new OptionInt(u, type, begin, end)); return (option); } diff --git a/src/lib/dhcp/option_int.h b/src/lib/dhcp/option_int.h index 12ca8f3e50..21e2997322 100644 --- a/src/lib/dhcp/option_int.h +++ b/src/lib/dhcp/option_int.h @@ -41,13 +41,14 @@ class OptionInt: public Option { public: /// @brief Constructor. /// + /// @param u universe (V4 or V6) /// @param type option type. /// @param value option value. /// /// @throw isc::dhcp::InvalidDataType if data field type provided /// as template parameter is not a supported integer type. - OptionInt(uint16_t type, T value) - : Option(Option::V6, type), value_(value) { + OptionInt(Option::Universe u, uint16_t type, T value) + : Option(u, type), value_(value) { if (!OptionDataTypeTraits::integer_type) { isc_throw(dhcp::InvalidDataType, "non-integer type"); } @@ -59,6 +60,7 @@ public: /// may throw exception if \ref unpack function throws during buffer /// parsing. /// + /// @param u universe (V4 or V6) /// @param type option type. /// @param begin iterator to first byte of option data. /// @param end iterator to end of option data (first byte after option end). @@ -66,9 +68,9 @@ public: /// @throw isc::OutOfRange if provided buffer is shorter than data size. /// @throw isc::dhcp::InvalidDataType if data field type provided /// as template parameter is not a supported integer type. - OptionInt(uint16_t type, OptionBufferConstIter begin, + OptionInt(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end) - : Option(Option::V6, type) { + : Option(u, type) { if (!OptionDataTypeTraits::integer_type) { isc_throw(dhcp::InvalidDataType, "non-integer type"); } @@ -84,8 +86,8 @@ public: /// equal to 1, 2 or 4 bytes. The data type is not checked in this function /// because it is checked in a constructor. void pack(isc::util::OutputBuffer& buf) { - buf.writeUint16(type_); - buf.writeUint16(len() - OPTION6_HDR_LEN); + // Pack option header. + packHeader(buf); // Depending on the data type length we use different utility functions // writeUint16 or writeUint32 which write the data in the network byte // order to the provided buffer. The same functions can be safely used @@ -168,7 +170,10 @@ public: /// /// @return length of this option virtual uint16_t len() { - uint16_t length = OPTION6_HDR_LEN + sizeof(T); + // Calculate the length of the header. + uint16_t length = (universe_ == Option::V4) ? OPTION4_HDR_LEN : OPTION6_HDR_LEN; + // The data length is equal to size of T. + length += sizeof(T);; // length of all suboptions for (Option::OptionCollection::iterator it = options_.begin(); it != options_.end(); @@ -186,4 +191,4 @@ private: } // isc::dhcp namespace } // isc namespace -#endif // OPTION6_INT_H +#endif // OPTION_INT_H diff --git a/src/lib/dhcp/tests/option_int_unittest.cc b/src/lib/dhcp/tests/option_int_unittest.cc index 06e1f6176e..73659d9098 100644 --- a/src/lib/dhcp/tests/option_int_unittest.cc +++ b/src/lib/dhcp/tests/option_int_unittest.cc @@ -31,6 +31,9 @@ using namespace isc::util; namespace { +/// Option code being used in many test cases. +const uint16_t TEST_OPT_CODE = 232; + /// @brief OptionInt test class. class OptionIntTest : public ::testing::Test { public: @@ -48,22 +51,24 @@ public: /// @note this function does not perform type check. Make /// sure that only int8_t or uint8_t type is used. /// + /// @param u universe (V4 or V6). /// @tparam T int8_t or uint8_t. template - void basicTest8() { + void basicTest8(const Option::Universe u) { // Create option that conveys single 8 bit integer value. boost::shared_ptr > opt; // Initialize buffer with this value. buf_[0] = 0xa1; // Constructor may throw in case provided buffer is too short. ASSERT_NO_THROW( - opt = boost::shared_ptr >(new OptionInt(D6O_PREFERENCE, - buf_.begin(), - buf_.end())) + opt = boost::shared_ptr >(new OptionInt(u, + TEST_OPT_CODE, + buf_.begin(), + buf_.begin() + 1)) ); - EXPECT_EQ(Option::V6, opt->getUniverse()); - EXPECT_EQ(D6O_PREFERENCE, opt->getType()); + EXPECT_EQ(u, opt->getUniverse()); + EXPECT_EQ(TEST_OPT_CODE, opt->getType()); // Option should return the same value that we initialized the first // byte of the buffer with. EXPECT_EQ(static_cast(0xa1), opt->getValue()); @@ -73,16 +78,28 @@ public: // Data length is 1 byte. EXPECT_EQ(1, opt->len() - opt->getHeaderLen()); - EXPECT_EQ(D6O_PREFERENCE, opt->getType()); - // The total length is 1 byte for data and 4 bytes for header. - EXPECT_EQ(5, out_buf_.getLength()); + EXPECT_EQ(TEST_OPT_CODE, opt->getType()); + // The total length is 1 byte for data and 2 bytes or 4 bytes + // for option code and option length. + if (u == Option::V4) { + EXPECT_EQ(3, out_buf_.getLength()); + } else { + EXPECT_EQ(5, out_buf_.getLength()); + } // Check if pack worked properly: InputBuffer out(out_buf_.getData(), out_buf_.getLength()); - // if option type is correct - EXPECT_EQ(D6O_PREFERENCE, out.readUint16()); - // if option length is correct - EXPECT_EQ(1, out.readUint16()); + if (u == Option::V4) { + // if option type is correct + EXPECT_EQ(TEST_OPT_CODE, out.readUint8()); + // if option length is correct + EXPECT_EQ(1, out.readUint8()); + } else { + // if option type is correct + EXPECT_EQ(TEST_OPT_CODE, out.readUint16()); + // if option length is correct + EXPECT_EQ(1, out.readUint16()); + } // if data is correct EXPECT_EQ(0xa1, out.readUint8() ); } @@ -92,9 +109,10 @@ public: /// @note this function does not perform type check. Make /// sure that only int16_t or uint16_t type is used. /// + /// @param u universe (V4 or V6) /// @tparam T int16_t or uint16_t. template - void basicTest16() { + void basicTest16(const Option::Universe u) { // Create option that conveys single 16-bit integer value. boost::shared_ptr > opt; // Initialize buffer with uint16_t value. @@ -102,13 +120,14 @@ public: buf_[1] = 0xa2; // Constructor may throw in case provided buffer is too short. ASSERT_NO_THROW( - opt = boost::shared_ptr >(new OptionInt(D6O_ELAPSED_TIME, - buf_.begin(), - buf_.end())) + opt = boost::shared_ptr >(new OptionInt(u, + TEST_OPT_CODE, + buf_.begin(), + buf_.begin() + 2)) ); - EXPECT_EQ(Option::V6, opt->getUniverse()); - EXPECT_EQ(D6O_ELAPSED_TIME, opt->getType()); + EXPECT_EQ(u, opt->getUniverse()); + EXPECT_EQ(TEST_OPT_CODE, opt->getType()); // Option should return the value equal to the contents of first // and second byte of the buffer. EXPECT_EQ(static_cast(0xa1a2), opt->getValue()); @@ -118,16 +137,27 @@ public: // Data length is 2 bytes. EXPECT_EQ(2, opt->len() - opt->getHeaderLen()); - EXPECT_EQ(D6O_ELAPSED_TIME, opt->getType()); - // The total length is 2 byte for data and 4 bytes for header. - EXPECT_EQ(6, out_buf_.getLength()); + EXPECT_EQ(TEST_OPT_CODE, opt->getType()); + // The total length is 2 bytes for data and 2 or 4 bytes for aheader. + if (u == Option::V4) { + EXPECT_EQ(4, out_buf_.getLength()); + } else { + EXPECT_EQ(6, out_buf_.getLength()); + } // Check if pack worked properly: InputBuffer out(out_buf_.getData(), out_buf_.getLength()); - // if option type is correct - EXPECT_EQ(D6O_ELAPSED_TIME, out.readUint16()); - // if option length is correct - EXPECT_EQ(2, out.readUint16()); + if (u == Option::V4) { + // if option type is correct + EXPECT_EQ(TEST_OPT_CODE, out.readUint8()); + // if option length is correct + EXPECT_EQ(2, out.readUint8()); + } else { + // if option type is correct + EXPECT_EQ(TEST_OPT_CODE, out.readUint16()); + // if option length is correct + EXPECT_EQ(2, out.readUint16()); + } // if data is correct EXPECT_EQ(0xa1a2, out.readUint16() ); } @@ -137,9 +167,10 @@ public: /// @note this function does not perform type check. Make /// sure that only int32_t or uint32_t type is used. /// + /// @param u universe (V4 or V6). /// @tparam T int32_t or uint32_t. template - void basicTest32() { + void basicTest32(const Option::Universe u) { // Create option that conveys single 32-bit integer value. boost::shared_ptr > opt; // Initialize buffer with 32-bit integer value. @@ -149,13 +180,14 @@ public: buf_[3] = 0xa4; // Constructor may throw in case provided buffer is too short. ASSERT_NO_THROW( - opt = boost::shared_ptr >(new OptionInt(D6O_CLT_TIME, - buf_.begin(), - buf_.end())) - ); + opt = boost::shared_ptr >(new OptionInt(u, + TEST_OPT_CODE, + buf_.begin(), + buf_.begin() + 4)) + ); - EXPECT_EQ(Option::V6, opt->getUniverse()); - EXPECT_EQ(D6O_CLT_TIME, opt->getType()); + EXPECT_EQ(u, opt->getUniverse()); + EXPECT_EQ(TEST_OPT_CODE, opt->getType()); // Option should return the value equal to the value made of // first 4 bytes of the buffer. EXPECT_EQ(static_cast(0xa1a2a3a4), opt->getValue()); @@ -165,16 +197,27 @@ public: // Data length is 4 bytes. EXPECT_EQ(4, opt->len() - opt->getHeaderLen()); - EXPECT_EQ(D6O_CLT_TIME, opt->getType()); - // The total length is 4 bytes for data and 4 bytes for header. - EXPECT_EQ(8, out_buf_.getLength()); + EXPECT_EQ(TEST_OPT_CODE, opt->getType()); + // The total length is 4 bytes for data and 2 or 4 bytes for a header. + if (u == Option::V4) { + EXPECT_EQ(6, out_buf_.getLength()); + } else { + EXPECT_EQ(8, out_buf_.getLength()); + } // Check if pack worked properly: InputBuffer out(out_buf_.getData(), out_buf_.getLength()); - // if option type is correct - EXPECT_EQ(D6O_CLT_TIME, out.readUint16()); - // if option length is correct - EXPECT_EQ(4, out.readUint16()); + if (u == Option::V4) { + // if option type is correct + EXPECT_EQ(TEST_OPT_CODE, out.readUint8()); + // if option length is correct + EXPECT_EQ(4, out.readUint8()); + } else { + // if option type is correct + EXPECT_EQ(TEST_OPT_CODE, out.readUint16()); + // if option length is correct + EXPECT_EQ(4, out.readUint16()); + } // if data is correct EXPECT_EQ(0xa1a2a3a4, out.readUint32()); } @@ -189,43 +232,70 @@ public: TEST_F(OptionIntTest, useInvalidType) { EXPECT_THROW( - boost::scoped_ptr >(new OptionInt(D6O_ELAPSED_TIME, 10)), + boost::scoped_ptr >(new OptionInt(Option::V6, + D6O_ELAPSED_TIME, 10)), InvalidDataType ); EXPECT_THROW( - boost::scoped_ptr >(new OptionInt(D6O_ELAPSED_TIME, 10)), + boost::scoped_ptr >(new OptionInt(Option::V6, + D6O_ELAPSED_TIME, 10)), InvalidDataType ); } -TEST_F(OptionIntTest, basicUint8) { - basicTest8(); +TEST_F(OptionIntTest, basicUint8V4) { + basicTest8(Option::V4); } -TEST_F(OptionIntTest, basicUint16) { - basicTest16(); +TEST_F(OptionIntTest, basicUint8V6) { + basicTest8(Option::V6); } -TEST_F(OptionIntTest, basicUint32) { - basicTest32(); +TEST_F(OptionIntTest, basicUint16V4) { + basicTest16(Option::V4); } -TEST_F(OptionIntTest, basicInt8) { - basicTest8(); +TEST_F(OptionIntTest, basicUint16V6) { + basicTest16(Option::V6); } -TEST_F(OptionIntTest, basicInt16) { - basicTest16(); +TEST_F(OptionIntTest, basicUint32V4) { + basicTest32(Option::V4); } -TEST_F(OptionIntTest, basicInt32) { - basicTest32(); +TEST_F(OptionIntTest, basicUint32V6) { + basicTest32(Option::V6); +} + +TEST_F(OptionIntTest, basicInt8V4) { + basicTest8(Option::V4); +} + +TEST_F(OptionIntTest, basicInt8V6) { + basicTest8(Option::V6); +} + +TEST_F(OptionIntTest, basicInt16V4) { + basicTest16(Option::V4); +} + +TEST_F(OptionIntTest, basicInt16V6) { + basicTest16(Option::V6); +} + +TEST_F(OptionIntTest, basicInt32V4) { + basicTest32(Option::V4); +} + +TEST_F(OptionIntTest, basicInt32V6) { + basicTest32(Option::V6); } TEST_F(OptionIntTest, setValueUint8) { - boost::shared_ptr > opt(new OptionInt(D6O_PREFERENCE, 123)); + boost::shared_ptr > opt(new OptionInt(Option::V6, + D6O_PREFERENCE, 123)); // Check if constructor intitialized the option value correctly. EXPECT_EQ(123, opt->getValue()); // Override the value. @@ -238,7 +308,8 @@ TEST_F(OptionIntTest, setValueUint8) { } TEST_F(OptionIntTest, setValueInt8) { - boost::shared_ptr > opt(new OptionInt(D6O_PREFERENCE, -123)); + boost::shared_ptr > opt(new OptionInt(Option::V6, + D6O_PREFERENCE, -123)); // Check if constructor intitialized the option value correctly. EXPECT_EQ(-123, opt->getValue()); // Override the value. @@ -252,7 +323,8 @@ TEST_F(OptionIntTest, setValueInt8) { TEST_F(OptionIntTest, setValueUint16) { - boost::shared_ptr > opt(new OptionInt(D6O_ELAPSED_TIME, 123)); + boost::shared_ptr > opt(new OptionInt(Option::V6, + D6O_ELAPSED_TIME, 123)); // Check if constructor intitialized the option value correctly. EXPECT_EQ(123, opt->getValue()); // Override the value. @@ -265,7 +337,8 @@ TEST_F(OptionIntTest, setValueUint16) { } TEST_F(OptionIntTest, setValueInt16) { - boost::shared_ptr > opt(new OptionInt(D6O_ELAPSED_TIME, -16500)); + boost::shared_ptr > opt(new OptionInt(Option::V6, + D6O_ELAPSED_TIME, -16500)); // Check if constructor intitialized the option value correctly. EXPECT_EQ(-16500, opt->getValue()); // Override the value. @@ -278,7 +351,8 @@ TEST_F(OptionIntTest, setValueInt16) { } TEST_F(OptionIntTest, setValueUint32) { - boost::shared_ptr > opt(new OptionInt(D6O_CLT_TIME, 123)); + boost::shared_ptr > opt(new OptionInt(Option::V6, + D6O_CLT_TIME, 123)); // Check if constructor intitialized the option value correctly. EXPECT_EQ(123, opt->getValue()); // Override the value. @@ -290,8 +364,9 @@ TEST_F(OptionIntTest, setValueUint32) { EXPECT_EQ(0x01020304, opt->getValue()); } -TEST_F(OptionIntTest, setValueint32) { - boost::shared_ptr > opt(new OptionInt(D6O_CLT_TIME, -120100)); +TEST_F(OptionIntTest, setValueInt32) { + boost::shared_ptr > opt(new OptionInt(Option::V6, + D6O_CLT_TIME, -120100)); // Check if constructor intitialized the option value correctly. EXPECT_EQ(-120100, opt->getValue()); // Override the value. @@ -303,12 +378,41 @@ TEST_F(OptionIntTest, setValueint32) { EXPECT_EQ(-125000, opt->getValue()); } -TEST_F(OptionIntTest, packSuboptions) { +TEST_F(OptionIntTest, packSuboptions4) { + boost::shared_ptr > opt(new OptionInt(Option::V4, + TEST_OPT_CODE, + 0x0102)); + // Add sub option with some 4 bytes of data (each byte set to 1) + OptionPtr sub1(new Option(Option::V4, TEST_OPT_CODE + 1, OptionBuffer(4, 1))); + // Add sub option with some 5 bytes of data (each byte set to 2) + OptionPtr sub2(new Option(Option::V4, TEST_OPT_CODE + 2, OptionBuffer(5, 2))); + + // Add suboptions. + opt->addOption(sub1); + opt->addOption(sub2); + + // Prepare reference data: option + suoptions in wire format. + uint8_t expected[] = { + TEST_OPT_CODE, 15, // option header + 0x01, 0x02, // data, uint16_t value = 0x0102 + TEST_OPT_CODE + 1, 0x04, 0x01, 0x01, 0x01, 0x01, // sub1 + TEST_OPT_CODE + 2, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02 // sub2 + }; + + // Create on-wire format of option and suboptions. + opt->pack(out_buf_); + // Compare the on-wire data with the reference buffer. + ASSERT_EQ(sizeof(expected), out_buf_.getLength()); + EXPECT_EQ(0, memcmp(out_buf_.getData(), expected, sizeof(expected))); +} + +TEST_F(OptionIntTest, packSuboptions6) { // option code is really uint16_t, but using uint8_t // for easier conversion to uint8_t array. uint8_t opt_code = 80; - boost::shared_ptr > opt(new OptionInt(opt_code, 0x01020304)); + boost::shared_ptr > opt(new OptionInt(Option::V6, + opt_code, 0x01020304)); OptionPtr sub1(new Option(Option::V6, 0xcafe)); boost::shared_ptr addr1( @@ -346,8 +450,46 @@ TEST_F(OptionIntTest, packSuboptions) { EXPECT_EQ(0, memcmp(out_buf_.getData(), expected, 40)); } +TEST_F(OptionIntTest, unpackSuboptions4) { + // Prepare reference data. + const uint8_t expected[] = { + TEST_OPT_CODE, 0x0A, // option code and length + 0x01, 0x02, 0x03, 0x04, // data, uint32_t value = 0x01020304 + TEST_OPT_CODE + 1, 0x4, 0x01, 0x01, 0x01, 0x01 // suboption + }; + // Copy the data to a vector so as we can pas it to the + // OptionInt's constructor. + memcpy(&buf_[0], expected, sizeof(expected)); -TEST_F(OptionIntTest, unpackSuboptions) { + // Create an option. + boost::shared_ptr > opt; + EXPECT_NO_THROW( + opt = boost::shared_ptr< + OptionInt >(new OptionInt(Option::V4, TEST_OPT_CODE, + buf_.begin() + 2, + buf_.begin() + sizeof(expected))); + ); + ASSERT_TRUE(opt); + + // Verify that it has expected type and data. + EXPECT_EQ(TEST_OPT_CODE, opt->getType()); + EXPECT_EQ(0x01020304, opt->getValue()); + + // Expect that there is the sub option with the particular + // option code added. + OptionPtr subopt = opt->getOption(TEST_OPT_CODE + 1); + ASSERT_TRUE(subopt); + // Check that this option has correct universe and code. + EXPECT_EQ(Option::V4, subopt->getUniverse()); + EXPECT_EQ(TEST_OPT_CODE + 1, subopt->getType()); + // Check the sub option's data. + OptionBuffer subopt_buf = subopt->getData(); + ASSERT_EQ(4, subopt_buf.size()); + // The data in the input buffer starts at offset 8. + EXPECT_TRUE(std::equal(subopt_buf.begin(), subopt_buf.end(), buf_.begin() + 8)); +} + +TEST_F(OptionIntTest, unpackSuboptions6) { // option code is really uint16_t, but using uint8_t // for easier conversion to uint8_t array. const uint8_t opt_code = 80; @@ -376,8 +518,9 @@ TEST_F(OptionIntTest, unpackSuboptions) { boost::shared_ptr > opt; EXPECT_NO_THROW( opt = boost::shared_ptr< - OptionInt >(new OptionInt(opt_code, buf_.begin() + 4, - buf_.begin() + sizeof(expected))); + OptionInt >(new OptionInt(Option::V6, opt_code, + buf_.begin() + 4, + buf_.begin() + sizeof(expected))); ); ASSERT_TRUE(opt);