123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 |
- // 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 <config.h>
- #include <exceptions/exceptions.h>
- #include <asiolink/io_address.h>
- #include <dhcp/dhcp4.h>
- #include <dhcp/dhcp6.h>
- #include <dhcp/option4_addrlst.h>
- #include <dhcp/option6_addrlst.h>
- #include <dhcp/option6_ia.h>
- #include <dhcp/option6_iaaddr.h>
- #include <dhcp/option6_int.h>
- #include <dhcp/option6_int_array.h>
- #include <dhcp/option_definition.h>
- #include <gtest/gtest.h>
- #include <boost/shared_ptr.hpp>
- #include <boost/pointer_cast.hpp>
- using namespace std;
- using namespace isc;
- using namespace isc::dhcp;
- using namespace isc::util;
- namespace {
- /// @brief OptionDefinition test class.
- ///
- /// This class does not do anything useful but we keep
- /// it around for the future.
- class OptionDefinitionTest : public ::testing::Test {
- public:
- // @brief Constructor.
- OptionDefinitionTest() { }
- };
- TEST_F(OptionDefinitionTest, constructor) {
- // Specify the option data type as string. This should get converted
- // to enum value returned by getType().
- OptionDefinition opt_def1("OPTION_CLIENTID", 1, "string");
- EXPECT_EQ("OPTION_CLIENTID", opt_def1.getName());
- EXPECT_EQ(1, opt_def1.getCode());
- EXPECT_EQ(OptionDefinition::STRING_TYPE, opt_def1.getType());
- EXPECT_FALSE(opt_def1.getArrayType());
- EXPECT_NO_THROW(opt_def1.validate());
- // Specify the option data type as an enum value.
- OptionDefinition opt_def2("OPTION_RAPID_COMMIT", 14,
- OptionDefinition::EMPTY_TYPE);
- EXPECT_EQ("OPTION_RAPID_COMMIT", opt_def2.getName());
- EXPECT_EQ(14, opt_def2.getCode());
- EXPECT_EQ(OptionDefinition::EMPTY_TYPE, opt_def2.getType());
- EXPECT_FALSE(opt_def2.getArrayType());
- EXPECT_NO_THROW(opt_def1.validate());
- // Check if it is possible to set that option is an array.
- OptionDefinition opt_def3("OPTION_NIS_SERVERS", 27,
- OptionDefinition::IPV6_ADDRESS_TYPE,
- true);
- EXPECT_EQ("OPTION_NIS_SERVERS", opt_def3.getName());
- EXPECT_EQ(27, opt_def3.getCode());
- EXPECT_EQ(OptionDefinition::IPV6_ADDRESS_TYPE, opt_def3.getType());
- EXPECT_TRUE(opt_def3.getArrayType());
- EXPECT_NO_THROW(opt_def3.validate());
- // The created object is invalid if invalid data type is specified but
- // constructor shouldn't throw exception. The object is validated after
- // it has been created.
- EXPECT_NO_THROW(
- OptionDefinition opt_def4("OPTION_SERVERID",
- OptionDefinition::UNKNOWN_TYPE + 10,
- OptionDefinition::STRING_TYPE);
- );
- }
- TEST_F(OptionDefinitionTest, addRecordField) {
- // We can only add fields to record if the option type has been
- // specified as 'record'. We try all other types but 'record'
- // here and expect exception to be thrown.
- for (int i = 0; i < OptionDefinition::UNKNOWN_TYPE; ++i) {
- // Do not try for 'record' type because this is the only
- // type for which adding record will succeed.
- if (i == OptionDefinition::RECORD_TYPE) {
- continue;
- }
- OptionDefinition opt_def("OPTION_IAADDR", 5,
- static_cast<OptionDefinition::DataType>(i));
- EXPECT_THROW(opt_def.addRecordField("uint8"), isc::InvalidOperation);
- }
- // Positive scenario starts here.
- OptionDefinition opt_def("OPTION_IAADDR", 5, "record");
- EXPECT_NO_THROW(opt_def.addRecordField("ipv6-address"));
- EXPECT_NO_THROW(opt_def.addRecordField("uint32"));
- // It should not matter if we specify field type by its name or using enum.
- EXPECT_NO_THROW(opt_def.addRecordField(OptionDefinition::UINT32_TYPE));
- // Check what we have actually added.
- OptionDefinition::RecordFieldsCollection fields = opt_def.getRecordFields();
- ASSERT_EQ(3, fields.size());
- EXPECT_EQ(OptionDefinition::IPV6_ADDRESS_TYPE, fields[0]);
- EXPECT_EQ(OptionDefinition::UINT32_TYPE, fields[1]);
- EXPECT_EQ(OptionDefinition::UINT32_TYPE, fields[2]);
- // Let's try some more negative scenarios: use invalid data types.
- EXPECT_THROW(opt_def.addRecordField("unknown_type_xyz"), isc::BadValue);
- OptionDefinition::DataType invalid_type =
- static_cast<OptionDefinition::DataType>(OptionDefinition::UNKNOWN_TYPE + 10);
- EXPECT_THROW(opt_def.addRecordField(invalid_type), isc::BadValue);
- }
- TEST_F(OptionDefinitionTest, validate) {
- // Not supported option type string is not allowed.
- OptionDefinition opt_def1("OPTION_CLIENTID", D6O_CLIENTID, "non-existent-type");
- EXPECT_THROW(opt_def1.validate(), isc::OutOfRange);
- // Not supported option type enum value is not allowed.
- OptionDefinition opt_def2("OPTION_CLIENTID", D6O_CLIENTID, OptionDefinition::UNKNOWN_TYPE);
- EXPECT_THROW(opt_def2.validate(), isc::OutOfRange);
- OptionDefinition opt_def3("OPTION_CLIENTID", D6O_CLIENTID,
- static_cast<OptionDefinition::DataType>(OptionDefinition::UNKNOWN_TYPE
- + 2));
- EXPECT_THROW(opt_def3.validate(), isc::OutOfRange);
-
- // Empty option name is not allowed.
- OptionDefinition opt_def4("", D6O_CLIENTID, "string");
- EXPECT_THROW(opt_def4.validate(), isc::BadValue);
- // Option name must not contain spaces.
- OptionDefinition opt_def5(" OPTION_CLIENTID", D6O_CLIENTID, "string");
- EXPECT_THROW(opt_def5.validate(), isc::BadValue);
- OptionDefinition opt_def6("OPTION CLIENTID", D6O_CLIENTID, "string");
- EXPECT_THROW(opt_def6.validate(), isc::BadValue);
- }
- TEST_F(OptionDefinitionTest, factoryAddrList6) {
- OptionDefinition opt_def("OPTION_NIS_SERVERS", D6O_NIS_SERVERS,
- "ipv6-address", true);
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- // Create a list of some V6 addresses.
- std::vector<asiolink::IOAddress> addrs;
- addrs.push_back(asiolink::IOAddress("2001:0db8::ff00:0042:8329"));
- addrs.push_back(asiolink::IOAddress("2001:0db8::ff00:0042:2319"));
- addrs.push_back(asiolink::IOAddress("::1"));
- addrs.push_back(asiolink::IOAddress("::2"));
- // Write addresses to the buffer.
- OptionBuffer buf(addrs.size() * asiolink::V6ADDRESS_LEN);
- for (int i = 0; i < addrs.size(); ++i) {
- asio::ip::address_v6::bytes_type addr_bytes =
- addrs[i].getAddress().to_v6().to_bytes();
- ASSERT_EQ(asiolink::V6ADDRESS_LEN, addr_bytes.size());
- std::copy(addr_bytes.begin(), addr_bytes.end(),
- buf.begin() + i * asiolink::V6ADDRESS_LEN);
- }
- // Create DHCPv6 option from this buffer. Once option is created it is
- // supposed to have internal list of addresses that it parses out from
- // the provided buffer.
- OptionPtr option_v6;
- ASSERT_NO_THROW(
- option_v6 = factory(Option::V6, D6O_NIS_SERVERS, buf);
- );
- ASSERT_TRUE(typeid(*option_v6) == typeid(Option6AddrLst));
- boost::shared_ptr<Option6AddrLst> option_cast_v6 =
- boost::static_pointer_cast<Option6AddrLst>(option_v6);
- ASSERT_TRUE(option_cast_v6);
- // Get the list of parsed addresses from the option object.
- std::vector<asiolink::IOAddress> addrs_returned =
- option_cast_v6->getAddresses();
- // The list of addresses must exactly match addresses that we
- // stored in the buffer to create the option from it.
- EXPECT_TRUE(std::equal(addrs.begin(), addrs.end(), addrs_returned.begin()));
- // The provided buffer's length must be a multiple of V6 address length.
- // Let's extend the buffer by one byte so as this condition is not
- // fulfilled anymore.
- buf.insert(buf.end(), 1, 1);
- // It should throw exception then.
- EXPECT_THROW(
- factory(Option::V6, D6O_NIS_SERVERS, buf),
- isc::OutOfRange
- );
- }
- TEST_F(OptionDefinitionTest, factoryAddrList4) {
- OptionDefinition opt_def("OPTION_NAME_SERVERS", D6O_NIS_SERVERS,
- "ipv4-address", true);
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- // Create a list of some V6 addresses.
- std::vector<asiolink::IOAddress> addrs;
- addrs.push_back(asiolink::IOAddress("192.168.0.1"));
- addrs.push_back(asiolink::IOAddress("172.16.1.1"));
- addrs.push_back(asiolink::IOAddress("127.0.0.1"));
- addrs.push_back(asiolink::IOAddress("213.41.23.12"));
- // Write addresses to the buffer.
- OptionBuffer buf(addrs.size() * asiolink::V4ADDRESS_LEN);
- for (int i = 0; i < addrs.size(); ++i) {
- asio::ip::address_v4::bytes_type addr_bytes =
- addrs[i].getAddress().to_v4().to_bytes();
- ASSERT_EQ(asiolink::V4ADDRESS_LEN, addr_bytes.size());
- std::copy(addr_bytes.begin(), addr_bytes.end(),
- buf.begin() + i * asiolink::V4ADDRESS_LEN);
- }
- // Create DHCPv6 option from this buffer. Once option is created it is
- // supposed to have internal list of addresses that it parses out from
- // the provided buffer.
- OptionPtr option_v4;
- ASSERT_NO_THROW(
- option_v4 = factory(Option::V4, DHO_NAME_SERVERS, buf)
- );
- ASSERT_TRUE(typeid(*option_v4) == typeid(Option4AddrLst));
- // Get the list of parsed addresses from the option object.
- boost::shared_ptr<Option4AddrLst> option_cast_v4 =
- boost::static_pointer_cast<Option4AddrLst>(option_v4);
- std::vector<asiolink::IOAddress> addrs_returned =
- option_cast_v4->getAddresses();
- // The list of addresses must exactly match addresses that we
- // stored in the buffer to create the option from it.
- EXPECT_TRUE(std::equal(addrs.begin(), addrs.end(), addrs_returned.begin()));
- // The provided buffer's length must be a multiple of V4 address length.
- // Let's extend the buffer by one byte so as this condition is not
- // fulfilled anymore.
- buf.insert(buf.end(), 1, 1);
- // It should throw exception then.
- EXPECT_THROW(factory(Option::V4, DHO_NIS_SERVERS, buf), isc::OutOfRange);
- }
- TEST_F(OptionDefinitionTest, factoryEmpty) {
- OptionDefinition opt_def("OPTION_RAPID_COMMIT", D6O_RAPID_COMMIT, "empty");
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- // Create option instance and provide empty buffer as expected.
- OptionPtr option_v6;
- ASSERT_NO_THROW(
- option_v6 = factory(Option::V6, D6O_RAPID_COMMIT, OptionBuffer())
- );
- ASSERT_TRUE(typeid(*option_v6) == typeid(Option));
- // Expect 'empty' DHCPv6 option.
- EXPECT_EQ(Option::V6, option_v6->getUniverse());
- EXPECT_EQ(4, option_v6->getHeaderLen());
- EXPECT_EQ(0, option_v6->getData().size());
- // Repeat the same test scenario for DHCPv4 option.
- EXPECT_THROW(factory(Option::V4, 214, OptionBuffer(2)),isc::BadValue);
- OptionPtr option_v4;
- ASSERT_NO_THROW(option_v4 = factory(Option::V4, 214, OptionBuffer()));
- // Expect 'empty' DHCPv4 option.
- EXPECT_EQ(Option::V4, option_v4->getUniverse());
- EXPECT_EQ(2, option_v4->getHeaderLen());
- EXPECT_EQ(0, option_v4->getData().size());
- // This factory produces empty option (consisting of option type
- // and length). Attempt to provide some data in the buffer should
- // result in exception.
- EXPECT_THROW(factory(Option::V6, D6O_RAPID_COMMIT,OptionBuffer(2)),isc::BadValue);
- }
- TEST_F(OptionDefinitionTest, factoryIA6) {
- // This option consists of IAID, T1 and T2 fields (each 4 bytes long).
- const int option6_ia_len = 12;
- // Get the factory function pointer.
- OptionDefinition opt_def("OPTION_IA_NA", D6O_IA_NA, "record", true);
- // Each data field is uint32.
- for (int i = 0; i < 3; ++i) {
- EXPECT_NO_THROW(opt_def.addRecordField("uint32"));
- }
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- // Check the positive scenario.
- OptionBuffer buf(12);
- for (int i = 0; i < buf.size(); ++i) {
- buf[i] = i;
- }
- OptionPtr option_v6;
- ASSERT_NO_THROW(option_v6 = factory(Option::V6, D6O_IA_NA, buf));
- ASSERT_TRUE(typeid(*option_v6) == typeid(Option6IA));
- boost::shared_ptr<Option6IA> option_cast_v6 =
- boost::static_pointer_cast<Option6IA>(option_v6);
- EXPECT_EQ(0x00010203, option_cast_v6->getIAID());
- EXPECT_EQ(0x04050607, option_cast_v6->getT1());
- EXPECT_EQ(0x08090A0B, option_cast_v6->getT2());
- // This should work for DHCPv6 only, try passing invalid universe value.
- EXPECT_THROW(
- factory(Option::V4, D6O_IA_NA, OptionBuffer(option6_ia_len)),
- isc::BadValue
- );
- // The length of the buffer must be 12 bytes.
- // Check too short buffer.
- EXPECT_THROW(
- factory(Option::V6, D6O_IA_NA, OptionBuffer(option6_ia_len - 1)),
- isc::OutOfRange
- );
- // Check too long buffer.
- EXPECT_THROW(
- factory(Option::V6, D6O_IA_NA, OptionBuffer(option6_ia_len + 1)),
- isc::OutOfRange
- );
- }
- TEST_F(OptionDefinitionTest, factoryIAAddr6) {
- // This option consists of IPV6 Address (16 bytes) and preferred-lifetime and
- // valid-lifetime fields (each 4 bytes long).
- const int option6_iaaddr_len = 24;
- OptionDefinition opt_def("OPTION_IAADDR", D6O_IAADDR, "record");
- ASSERT_NO_THROW(opt_def.addRecordField("ipv6-address"));
- ASSERT_NO_THROW(opt_def.addRecordField("uint32"));
- ASSERT_NO_THROW(opt_def.addRecordField("uint32"));
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- // Check the positive scenario.
- OptionPtr option_v6;
- asiolink::IOAddress addr_v6("2001:0db8::ff00:0042:8329");
- OptionBuffer buf(asiolink::V6ADDRESS_LEN);
- ASSERT_TRUE(addr_v6.getAddress().is_v6());
- asio::ip::address_v6::bytes_type addr_bytes =
- addr_v6.getAddress().to_v6().to_bytes();
- ASSERT_EQ(asiolink::V6ADDRESS_LEN, addr_bytes.size());
- std::copy(addr_bytes.begin(), addr_bytes.end(), buf.begin());
- for (int i = 0; i < option6_iaaddr_len - asiolink::V6ADDRESS_LEN; ++i) {
- buf.push_back(i);
- }
- ASSERT_NO_THROW(option_v6 = factory(Option::V6, D6O_IAADDR, buf));
- ASSERT_TRUE(typeid(*option_v6) == typeid(Option6IAAddr));
- boost::shared_ptr<Option6IAAddr> option_cast_v6 =
- boost::static_pointer_cast<Option6IAAddr>(option_v6);
- EXPECT_EQ(addr_v6, option_cast_v6->getAddress());
- EXPECT_EQ(0x00010203, option_cast_v6->getPreferred());
- EXPECT_EQ(0x04050607, option_cast_v6->getValid());
- // This should work for DHCPv6 only, try passing invalid universe value.
- EXPECT_THROW(
- factory(Option::V4, D6O_IAADDR, OptionBuffer(option6_iaaddr_len)),
- isc::BadValue
- );
- // The length of the buffer must be 12 bytes.
- // Check too short buffer.
- EXPECT_THROW(
- factory(Option::V6, D6O_IAADDR, OptionBuffer(option6_iaaddr_len - 1)),
- isc::OutOfRange
- );
- // Check too long buffer.
- EXPECT_THROW(
- factory(Option::V6, D6O_IAADDR, OptionBuffer(option6_iaaddr_len + 1)),
- isc::OutOfRange
- );
- }
- TEST_F(OptionDefinitionTest, factoryIntegerInvalidType) {
- // The template function factoryInteger<> accepts integer values only
- // as template typename. Here we try passing different type and
- // see if it rejects it.
- EXPECT_THROW(
- OptionDefinition::factoryInteger<bool>(Option::V6, D6O_PREFERENCE, OptionBuffer(1)),
- isc::dhcp::InvalidDataType
- );
- }
- TEST_F(OptionDefinitionTest, factoryUint8) {
- OptionDefinition opt_def("OPTION_PREFERENCE", D6O_PREFERENCE, "uint8");
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- OptionPtr option_v6;
- // Try to use correct buffer length = 1 byte.
- ASSERT_NO_THROW(
- option_v6 = factory(Option::V6, D6O_PREFERENCE, OptionBuffer(1, 1));
- );
- ASSERT_TRUE(typeid(*option_v6) == typeid(Option6Int<uint8_t>));
- // Validate the value.
- boost::shared_ptr<Option6Int<uint8_t> > option_cast_v6 =
- boost::static_pointer_cast<Option6Int<uint8_t> >(option_v6);
- EXPECT_EQ(1, option_cast_v6->getValue());
- // Try to provide too large buffer. Expect exception.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, D6O_PREFERENCE, OptionBuffer(3)),
- isc::OutOfRange
- );
- // Try to provide zero-length buffer. Expect exception.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, D6O_PREFERENCE, OptionBuffer()),
- isc::OutOfRange
- );
- // @todo Add more cases for DHCPv4
- }
- TEST_F(OptionDefinitionTest, factoryUint16) {
- OptionDefinition opt_def("OPTION_ELAPSED_TIME", D6O_ELAPSED_TIME, "uint16");
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- OptionPtr option_v6;
- // Try to use correct buffer length = 2 bytes.
- OptionBuffer buf;
- buf.push_back(1);
- buf.push_back(2);
- ASSERT_NO_THROW(
- option_v6 = factory(Option::V6, D6O_ELAPSED_TIME, buf);
- );
- ASSERT_TRUE(typeid(*option_v6) == typeid(Option6Int<uint16_t>));
- // Validate the value.
- boost::shared_ptr<Option6Int<uint16_t> > option_cast_v6 =
- boost::static_pointer_cast<Option6Int<uint16_t> >(option_v6);
- EXPECT_EQ(0x0102, option_cast_v6->getValue());
- // Try to provide too large buffer. Expect exception.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, D6O_ELAPSED_TIME, OptionBuffer(3)),
- isc::OutOfRange
- );
- // Try to provide zero-length buffer. Expect exception.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, D6O_ELAPSED_TIME, OptionBuffer(1)),
- isc::OutOfRange
- );
- // @todo Add more cases for DHCPv4
- }
- TEST_F(OptionDefinitionTest, factoryUint32) {
- OptionDefinition opt_def("OPTION_CLT_TIME", D6O_CLT_TIME, "uint32");
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- OptionPtr option_v6;
- OptionBuffer buf;
- buf.push_back(1);
- buf.push_back(2);
- buf.push_back(3);
- buf.push_back(4);
- ASSERT_NO_THROW(
- option_v6 = factory(Option::V6, D6O_CLT_TIME, buf);
- );
- ASSERT_TRUE(typeid(*option_v6) == typeid(Option6Int<uint32_t>));
- // Validate the value.
- boost::shared_ptr<Option6Int<uint32_t> > option_cast_v6 =
- boost::static_pointer_cast<Option6Int<uint32_t> >(option_v6);
- EXPECT_EQ(0x01020304, option_cast_v6->getValue());
- // Try to provide too large buffer. Expect exception.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, D6O_CLT_TIME, OptionBuffer(5)),
- isc::OutOfRange
- );
- // Try to provide zero-length buffer. Expect exception.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, D6O_CLT_TIME, OptionBuffer(2)),
- isc::OutOfRange
- );
- // @todo Add more cases for DHCPv4
- }
- TEST_F(OptionDefinitionTest, factoryUint16Array) {
- // Let's define some dummy option.
- const uint16_t opt_code = 79;
- OptionDefinition opt_def("OPTION_UINT16_ARRAY", opt_code, "uint16", true);
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- OptionPtr option_v6;
- // Positive scenario, initiate the buffer with length being
- // multiple of uint16_t size.
- // buffer elements will be: 0x112233.
- OptionBuffer buf(6);
- for (int i = 0; i < 6; ++i) {
- buf[i] = i / 2;
- }
- // Constructor should succeed because buffer has correct size.
- EXPECT_NO_THROW(
- option_v6 = factory(Option::V6, opt_code, buf);
- );
- ASSERT_TRUE(typeid(*option_v6) == typeid(Option6IntArray<uint16_t>));
- boost::shared_ptr<Option6IntArray<uint16_t> > option_cast_v6 =
- boost::static_pointer_cast<Option6IntArray<uint16_t> >(option_v6);
- // Get the values from the initiated options and validate.
- std::vector<uint16_t> 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:
- // for i=0, expected = 0x00, for i = 1, expected == 0x11 etc.
- uint16_t expected = (i << 8) | i;
- EXPECT_EQ(expected, values[i]);
- }
- // Provided buffer size must be greater than zero. Check if we
- // get exception if we provide zero-length buffer.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, opt_code, OptionBuffer()),
- isc::OutOfRange
- );
- // Buffer length must be multiple of data type size.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, opt_code, OptionBuffer(5)),
- isc::OutOfRange
- );
- }
- TEST_F(OptionDefinitionTest, factoryUint32Array) {
- // Let's define some dummy option.
- const uint16_t opt_code = 80;
- OptionDefinition opt_def("OPTION_UINT32_ARRAY", opt_code, "uint32", true);
- Option::Factory* factory(NULL);
- EXPECT_NO_THROW(factory = opt_def.getFactory());
- ASSERT_TRUE(factory != NULL);
- OptionPtr option_v6;
- // Positive scenario, initiate the buffer with length being
- // multiple of uint16_t size.
- // buffer elements will be: 0x111122223333.
- OptionBuffer buf(12);
- for (int i = 0; i < buf.size(); ++i) {
- buf[i] = i / 4;
- }
- // Constructor should succeed because buffer has correct size.
- EXPECT_NO_THROW(
- option_v6 = factory(Option::V6, opt_code, buf);
- );
- ASSERT_TRUE(typeid(*option_v6) == typeid(Option6IntArray<uint32_t>));
- boost::shared_ptr<Option6IntArray<uint32_t> > option_cast_v6 =
- boost::static_pointer_cast<Option6IntArray<uint32_t> >(option_v6);
- // Get the values from the initiated options and validate.
- std::vector<uint32_t> 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:
- // for i=0, expected = 0x0000, for i = 1, expected == 0x1111 etc.
- uint32_t expected = 0x01010101 * i;
- EXPECT_EQ(expected, values[i]);
- }
- // Provided buffer size must be greater than zero. Check if we
- // get exception if we provide zero-length buffer.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, opt_code, OptionBuffer()),
- isc::OutOfRange
- );
- // Buffer length must be multiple of data type size.
- EXPECT_THROW(
- option_v6 = factory(Option::V6, opt_code, OptionBuffer(5)),
- isc::OutOfRange
- );
- }
- TEST_F(OptionDefinitionTest, recognizeFormat) {
- // IA_NA option format.
- OptionDefinition opt_def1("OPTION_IA_NA", D6O_IA_NA, "record");
- for (int i = 0; i < 3; ++i) {
- opt_def1.addRecordField("uint32");
- }
- EXPECT_TRUE(opt_def1.haveIA6Format());
- // Create non-matching format to check that this function does not
- // return 'true' all the time.
- OptionDefinition opt_def2("OPTION_IA_NA", D6O_IA_NA, "uint16");
- EXPECT_FALSE(opt_def2.haveIA6Format());
- // IAADDR option format.
- OptionDefinition opt_def3("OPTION_IAADDR", D6O_IAADDR, "record");
- opt_def3.addRecordField("ipv6-address");
- opt_def3.addRecordField("uint32");
- opt_def3.addRecordField("uint32");
- EXPECT_TRUE(opt_def3.haveIAAddr6Format());
- // Create non-matching format to check that this function does not
- // return 'true' all the time.
- OptionDefinition opt_def4("OPTION_IAADDR", D6O_IAADDR, "uint32", true);
- EXPECT_FALSE(opt_def4.haveIAAddr6Format());
- }
- } // anonymous namespace
|