From: Marcin Siodelski Date: Wed, 10 Oct 2012 11:18:57 +0000 (+0200) Subject: [2304] Unit tests for Option6IntArray. X-Git-Tag: trac2402_base~5^2~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cd86c2c845e03de172d832256ea3542203f40a5f;p=thirdparty%2Fkea.git [2304] Unit tests for Option6IntArray. --- diff --git a/src/lib/dhcp/option6_int_array.h b/src/lib/dhcp/option6_int_array.h index 6783bf3808..b87f538ca5 100644 --- a/src/lib/dhcp/option6_int_array.h +++ b/src/lib/dhcp/option6_int_array.h @@ -41,17 +41,29 @@ class Option6IntArray: public Option { public: - typedef std::vector ValuesCollection; + /// @brief Constructor. + /// + /// Creates option with empty values vector. + /// + /// @param type option type. + Option6IntArray(uint16_t type) + : Option(Option::V6, type), + values_(0) { + if (!OptionDataTypes::valid) { + isc_throw(dhcp::InvalidDataType, "non-numeric type"); + } + } /// @brief Constructor. /// /// @param type option type. - /// @param value option value. - Option6IntArray(uint16_t type, const ValuesCollection& values) - : Option(Option::V6, type), values_(values) { + /// @param buf buffer with option data. + Option6IntArray(uint16_t type, const OptionBuffer& buf) + : Option(Option::V6, type) { if (!OptionDataTypes::valid) { isc_throw(dhcp::InvalidDataType, "non-numeric type"); } + unpack(buf.begin(), buf.end()); } /// @brief Constructor. @@ -128,14 +140,17 @@ public: } begin += sizeof(T); } - - LibDHCP::unpackOptions6(OptionBuffer(begin, end), options_); } - /// @brief Returns collection of values. + /// @brief Return collection of option values. /// /// @return collection of values. - const ValuesCollection& getValues() const { return values_; } + const std::vector& getValues() const { return (values_); } + + /// @brief Set option values. + /// + /// @param collection of values to be set. + void setValues(const std::vector& values) { values_ = values; } /// @brief returns complete length of option /// @@ -155,7 +170,7 @@ public: private: - ValuesCollection values_; + std::vector values_; }; } // isc::dhcp namespace diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am index e676834c1e..92eb4ddece 100644 --- a/src/lib/dhcp/tests/Makefile.am +++ b/src/lib/dhcp/tests/Makefile.am @@ -33,6 +33,7 @@ libdhcp___unittests_SOURCES += option6_ia_unittest.cc libdhcp___unittests_SOURCES += option6_addrlst_unittest.cc libdhcp___unittests_SOURCES += option4_addrlst_unittest.cc libdhcp___unittests_SOURCES += option6_int_unittest.cc +libdhcp___unittests_SOURCES += option6_int_array_unittest.cc libdhcp___unittests_SOURCES += option_unittest.cc libdhcp___unittests_SOURCES += option_definition_unittest.cc libdhcp___unittests_SOURCES += pkt6_unittest.cc diff --git a/src/lib/dhcp/tests/option6_int_array_unittest.cc b/src/lib/dhcp/tests/option6_int_array_unittest.cc new file mode 100644 index 0000000000..26af72608e --- /dev/null +++ b/src/lib/dhcp/tests/option6_int_array_unittest.cc @@ -0,0 +1,279 @@ +// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// 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 +#include + +#include +#include +#include +#include +#include + +using namespace std; +using namespace isc; +using namespace isc::dhcp; +using namespace isc::asiolink; +using namespace isc::util; + +namespace { + +/// @brief Option6IntArray test class. +class Option6IntArrayTest : public ::testing::Test { +public: + /// @brief Constructor. + /// + /// Initializes the option buffer with some data. + Option6IntArrayTest(): buf_(255), out_buf_(255) { + for (int i = 0; i < 255; i++) { + buf_[i] = 255 - i; + } + } + + OptionBuffer buf_; ///< Option buffer + OutputBuffer out_buf_; ///< Output buffer +}; + +/// @todo: below, there is a bunch of tests for options that +/// convey unsigned values. We should maybe extend these tests for +/// signed types too. + +TEST_F(Option6IntArrayTest, useInvalidType) { + const uint16_t opt_code = 80; + EXPECT_THROW( + boost::scoped_ptr< + Option6IntArray >(new Option6IntArray(opt_code, OptionBuffer(5))), + InvalidDataType + ); + + EXPECT_THROW( + boost::scoped_ptr< + Option6IntArray >(new Option6IntArray(opt_code, + OptionBuffer(10))), + InvalidDataType + ); + +} + +TEST_F(Option6IntArrayTest, bufferToUint8) { + // Create option that conveys array of multiple uint8_t values. + // In fact there is no need to use this template class for array + // of uint8_t values because Option class is sufficient - it + // returns the buffer which is actually the array of uint8_t. + // However, since we allow using uint8_t types with this template + // class we have to test it here. + boost::shared_ptr > opt; + const int opt_len = 10; + const uint16_t opt_code = 80; + // Constructor may throw in case provided buffer is too short. + ASSERT_NO_THROW( + opt = boost::shared_ptr< + Option6IntArray >(new Option6IntArray(opt_code, buf_.begin(), + buf_.begin() + opt_len)) + ); + + EXPECT_EQ(Option::V6, opt->getUniverse()); + EXPECT_EQ(opt_code, opt->getType()); + // Option should return the same value that we initialized the first + // byte of the buffer with. + std::vector values = opt->getValues(); + ASSERT_EQ(opt_len, values.size()); + EXPECT_TRUE(std::equal(buf_.begin(), buf_.begin() + opt_len, values.begin())); + + // test for pack() + opt->pack(out_buf_); + + // Data length is 10 bytes. + EXPECT_EQ(10, opt->len() - opt->getHeaderLen()); + EXPECT_EQ(opt_code, opt->getType()); + // The total length is 10 bytes for data and 4 bytes for header. + ASSERT_EQ(14, out_buf_.getLength()); + + // Check if pack worked properly: + InputBuffer out(out_buf_.getData(), out_buf_.getLength()); + // if option type is correct + EXPECT_EQ(opt_code, out.readUint16()); + // if option length is correct + EXPECT_EQ(10, out.readUint16()); + // if data is correct + std::vector out_data; + ASSERT_NO_THROW(out.readVector(out_data, opt_len)); + ASSERT_EQ(opt_len, out_data.size()); + EXPECT_TRUE(std::equal(buf_.begin(), buf_.begin() + opt_len, out_data.begin()));; +} + +TEST_F(Option6IntArrayTest, bufferToUint16) { + // Create option that conveys array of multiple uint16_t values. + boost::shared_ptr > opt; + const int opt_len = 20; + const uint16_t opt_code = 81; + // Constructor may throw in case provided buffer is too short. + ASSERT_NO_THROW( + opt = boost::shared_ptr< + Option6IntArray >(new Option6IntArray(opt_code, buf_.begin(), + buf_.begin() + opt_len)) + ); + + EXPECT_EQ(Option::V6, opt->getUniverse()); + EXPECT_EQ(opt_code, opt->getType()); + // Option should return vector of uint16_t values which should be + // constructed from the buffer we provided. + std::vector values = opt->getValues(); + // Let's pack the values back into some uint8_t buffer to compare + // it later with the reference data. + std::vector values_buf; + for (int i = 0; i < values.size(); ++i) { + // Values have been read from the buffer in network + // byte order. We put them back in the same order here. + values_buf.push_back(values[i] >> 8); + values_buf.push_back(values[i] & 0xFF); + } + ASSERT_EQ(opt_len, values_buf.size()); + EXPECT_TRUE(std::equal(buf_.begin(), buf_.begin() + opt_len, values_buf.begin())); + + // Test for pack() + opt->pack(out_buf_); + + // Data length is 20 bytes. + EXPECT_EQ(20, opt->len() - opt->getHeaderLen()); + EXPECT_EQ(opt_code, opt->getType()); + // The total length is 20 bytes for data and 4 bytes for header. + ASSERT_EQ(24, out_buf_.getLength()); + + // Check if pack worked properly: + InputBuffer out(out_buf_.getData(), out_buf_.getLength()); + // if option type is correct + EXPECT_EQ(opt_code, out.readUint16()); + // if option length is correct + EXPECT_EQ(20, out.readUint16()); + // if data is correct + std::vector out_data; + ASSERT_NO_THROW(out.readVector(out_data, opt_len)); + ASSERT_EQ(opt_len, out_data.size()); + EXPECT_TRUE(std::equal(buf_.begin(), buf_.begin() + opt_len, out_data.begin()));; +} + +TEST_F(Option6IntArrayTest, bufferToUint32) { + // Create option that conveys array of multiple uint16_t values. + boost::shared_ptr > opt; + const int opt_len = 40; + const uint16_t opt_code = 82; + // Constructor may throw in case provided buffer is too short. + ASSERT_NO_THROW( + opt = boost::shared_ptr< + Option6IntArray >(new Option6IntArray(opt_code, buf_.begin(), + buf_.begin() + opt_len)) + ); + + EXPECT_EQ(Option::V6, opt->getUniverse()); + EXPECT_EQ(opt_code, opt->getType()); + // Option should return vector of uint32_t values which should be + // constructed from the buffer we provided. + std::vector values = opt->getValues(); + // Let's pack the values back into some uint8_t buffer to compare + // it later with the reference data. + std::vector values_buf; + for (int i = 0; i < values.size(); ++i) { + // Values have been read from the buffer in network + // byte order. We put them back in the same order here. + values_buf.push_back(values[i] >> 24); + values_buf.push_back(values[i] >> 16 & 0xFF); + values_buf.push_back(values[i] >> 8 & 0xFF); + values_buf.push_back(values[i] & 0xFF); + } + ASSERT_EQ(opt_len, values_buf.size()); + EXPECT_TRUE(std::equal(buf_.begin(), buf_.begin() + opt_len, values_buf.begin())); + + // Test for pack() + opt->pack(out_buf_); + + // Data length is 40 bytes. + EXPECT_EQ(40, opt->len() - opt->getHeaderLen()); + EXPECT_EQ(opt_code, opt->getType()); + // The total length is 40 bytes for data and 4 bytes for header. + ASSERT_EQ(44, out_buf_.getLength()); + + // Check if pack worked properly: + InputBuffer out(out_buf_.getData(), out_buf_.getLength()); + // if option type is correct + EXPECT_EQ(opt_code, out.readUint16()); + // if option length is correct + EXPECT_EQ(40, out.readUint16()); + // if data is correct + std::vector out_data; + ASSERT_NO_THROW(out.readVector(out_data, opt_len)); + ASSERT_EQ(opt_len, out_data.size()); + EXPECT_TRUE(std::equal(buf_.begin(), buf_.begin() + opt_len, out_data.begin()));; +} + + +TEST_F(Option6IntArrayTest, setValuesUint8) { + const uint16_t opt_code = 100; + // Create option with empty vector of values. + boost::shared_ptr > opt(new Option6IntArray(opt_code)); + // Initialize vector with some data and pass to the option. + std::vector values; + for (int i = 0; i < 10; ++i) { + values.push_back(255 - i); + } + opt->setValues(values); + + // Check if universe, option type and data was set correctly. + EXPECT_EQ(Option::V6, opt->getUniverse()); + EXPECT_EQ(opt_code, opt->getType()); + std::vector returned_values = opt->getValues(); + EXPECT_TRUE(std::equal(values.begin(), values.end(), returned_values.begin())); +} + +TEST_F(Option6IntArrayTest, setValuesUint16) { + const uint16_t opt_code = 101; + // Create option with empty vector of values. + boost::shared_ptr > opt(new Option6IntArray(opt_code)); + // Initialize vector with some data and pass to the option. + std::vector values; + for (int i = 0; i < 10; ++i) { + values.push_back(0xFFFF - i); + } + opt->setValues(values); + + // Check if universe, option type and data was set correctly. + EXPECT_EQ(Option::V6, opt->getUniverse()); + EXPECT_EQ(opt_code, opt->getType()); + std::vector returned_values = opt->getValues(); + EXPECT_TRUE(std::equal(values.begin(), values.end(), returned_values.begin())); +} + +TEST_F(Option6IntArrayTest, setValuesUint32) { + const uint32_t opt_code = 101; + // Create option with empty vector of values. + boost::shared_ptr > opt(new Option6IntArray(opt_code)); + // Initialize vector with some data and pass to the option. + std::vector values; + for (int i = 0; i < 10; ++i) { + values.push_back(0xFFFFFFFF - i); + } + opt->setValues(values); + + // Check if universe, option type and data was set correctly. + EXPECT_EQ(Option::V6, opt->getUniverse()); + EXPECT_EQ(opt_code, opt->getType()); + std::vector returned_values = opt->getValues(); + EXPECT_TRUE(std::equal(values.begin(), values.end(), returned_values.begin())); +} + +} // anonymous namespace diff --git a/src/lib/dhcp/tests/option6_int_unittest.cc b/src/lib/dhcp/tests/option6_int_unittest.cc index fad615d3fe..906b954077 100644 --- a/src/lib/dhcp/tests/option6_int_unittest.cc +++ b/src/lib/dhcp/tests/option6_int_unittest.cc @@ -182,7 +182,7 @@ TEST_F(Option6IntTest, basicUint32) { } -TEST_F(Option6IntTest, simpleUint8) { +TEST_F(Option6IntTest, setValueUint8) { boost::shared_ptr > opt(new Option6Int(D6O_PREFERENCE, 123)); // Check if constructor intitialized the option value correctly. EXPECT_EQ(123, opt->getValue()); @@ -195,7 +195,7 @@ TEST_F(Option6IntTest, simpleUint8) { EXPECT_EQ(111, opt->getValue()); } -TEST_F(Option6IntTest, simpleUint16) { +TEST_F(Option6IntTest, setValueUint16) { boost::shared_ptr > opt(new Option6Int(D6O_ELAPSED_TIME, 123)); // Check if constructor intitialized the option value correctly. EXPECT_EQ(123, opt->getValue()); @@ -208,7 +208,7 @@ TEST_F(Option6IntTest, simpleUint16) { EXPECT_EQ(0x0102, opt->getValue()); } -TEST_F(Option6IntTest, simpleUint32) { +TEST_F(Option6IntTest, setValueUint32) { boost::shared_ptr > opt(new Option6Int(D6O_CLT_TIME, 123)); // Check if constructor intitialized the option value correctly. EXPECT_EQ(123, opt->getValue()); diff --git a/src/lib/dhcp/tests/option_definition_unittest.cc b/src/lib/dhcp/tests/option_definition_unittest.cc index 7e1e5d5763..229771b68f 100644 --- a/src/lib/dhcp/tests/option_definition_unittest.cc +++ b/src/lib/dhcp/tests/option_definition_unittest.cc @@ -486,8 +486,7 @@ TEST_F(OptionDefinitionTest, factoryUint16Array) { boost::shared_ptr > option_cast_v6 = boost::static_pointer_cast >(option_v6); // Get the values from the initiated options and validate. - Option6IntArray::ValuesCollection values = - option_cast_v6->getValues(); + std::vector values = option_cast_v6->getValues(); for (int i = 0; i < values.size(); ++i) { // Expected value is calculated using on the same pattern // as the one we used to initiate buffer: @@ -534,8 +533,7 @@ TEST_F(OptionDefinitionTest, factoryUint32Array) { boost::shared_ptr > option_cast_v6 = boost::static_pointer_cast >(option_v6); // Get the values from the initiated options and validate. - Option6IntArray::ValuesCollection values = - option_cast_v6->getValues(); + std::vector values = option_cast_v6->getValues(); for (int i = 0; i < values.size(); ++i) { // Expected value is calculated using on the same pattern // as the one we used to initiate buffer: