|
@@ -47,32 +47,35 @@ public:
|
|
|
OptionDefinitionTest() { }
|
|
|
};
|
|
|
|
|
|
+// The purpose of this test is to verify that OptionDefinition
|
|
|
+// constructor initializes its members correctly.
|
|
|
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_EQ(OPT_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);
|
|
|
+ OPT_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_EQ(OPT_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,
|
|
|
+ OPT_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_EQ(OPT_IPV6_ADDRESS_TYPE, opt_def3.getType());
|
|
|
EXPECT_TRUE(opt_def3.getArrayType());
|
|
|
EXPECT_NO_THROW(opt_def3.validate());
|
|
|
|
|
@@ -81,23 +84,27 @@ TEST_F(OptionDefinitionTest, constructor) {
|
|
|
// it has been created.
|
|
|
EXPECT_NO_THROW(
|
|
|
OptionDefinition opt_def4("OPTION_SERVERID",
|
|
|
- OptionDefinition::UNKNOWN_TYPE + 10,
|
|
|
- OptionDefinition::STRING_TYPE);
|
|
|
+ OPT_UNKNOWN_TYPE + 10,
|
|
|
+ OPT_STRING_TYPE);
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+// The purpose of this test is to verify that various data fields
|
|
|
+// can be specified for an option definition when this definition
|
|
|
+// is marked as 'record' and that fields can't be added if option
|
|
|
+// definition is not marked as 'record'.
|
|
|
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) {
|
|
|
+ for (int i = 0; i < OPT_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) {
|
|
|
+ if (i == OPT_RECORD_TYPE) {
|
|
|
continue;
|
|
|
}
|
|
|
OptionDefinition opt_def("OPTION_IAADDR", 5,
|
|
|
- static_cast<OptionDefinition::DataType>(i));
|
|
|
+ static_cast<OptionDataType>(i));
|
|
|
EXPECT_THROW(opt_def.addRecordField("uint8"), isc::InvalidOperation);
|
|
|
}
|
|
|
|
|
@@ -106,54 +113,88 @@ TEST_F(OptionDefinitionTest, addRecordField) {
|
|
|
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));
|
|
|
+ EXPECT_NO_THROW(opt_def.addRecordField(OPT_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]);
|
|
|
+ EXPECT_EQ(OPT_IPV6_ADDRESS_TYPE, fields[0]);
|
|
|
+ EXPECT_EQ(OPT_UINT32_TYPE, fields[1]);
|
|
|
+ EXPECT_EQ(OPT_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);
|
|
|
+ OptionDataType invalid_type =
|
|
|
+ static_cast<OptionDataType>(OPT_UNKNOWN_TYPE + 10);
|
|
|
EXPECT_THROW(opt_def.addRecordField(invalid_type), isc::BadValue);
|
|
|
+
|
|
|
+ // It is bad if we use 'record' option type but don't specify
|
|
|
+ // at least two fields.
|
|
|
+ OptionDefinition opt_def2("OPTION_EMPTY_RECORD", 100, "record");
|
|
|
+ EXPECT_THROW(opt_def2.validate(), MalformedOptionDefinition);
|
|
|
+ opt_def2.addRecordField("uint8");
|
|
|
+ EXPECT_THROW(opt_def2.validate(), MalformedOptionDefinition);
|
|
|
+ opt_def2.addRecordField("uint32");
|
|
|
+ EXPECT_NO_THROW(opt_def2.validate());
|
|
|
}
|
|
|
|
|
|
+// The purpose of this test is to check that validate() function
|
|
|
+// reports errors for invalid option definitions.
|
|
|
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);
|
|
|
+ EXPECT_THROW(opt_def1.validate(), MalformedOptionDefinition);
|
|
|
|
|
|
// 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_def2("OPTION_CLIENTID", D6O_CLIENTID, OPT_UNKNOWN_TYPE);
|
|
|
+ EXPECT_THROW(opt_def2.validate(), MalformedOptionDefinition);
|
|
|
|
|
|
OptionDefinition opt_def3("OPTION_CLIENTID", D6O_CLIENTID,
|
|
|
- static_cast<OptionDefinition::DataType>(OptionDefinition::UNKNOWN_TYPE
|
|
|
+ static_cast<OptionDataType>(OPT_UNKNOWN_TYPE
|
|
|
+ 2));
|
|
|
- EXPECT_THROW(opt_def3.validate(), isc::OutOfRange);
|
|
|
-
|
|
|
+ EXPECT_THROW(opt_def3.validate(), MalformedOptionDefinition);
|
|
|
+
|
|
|
// Empty option name is not allowed.
|
|
|
OptionDefinition opt_def4("", D6O_CLIENTID, "string");
|
|
|
- EXPECT_THROW(opt_def4.validate(), isc::BadValue);
|
|
|
+ EXPECT_THROW(opt_def4.validate(), MalformedOptionDefinition);
|
|
|
|
|
|
// Option name must not contain spaces.
|
|
|
OptionDefinition opt_def5(" OPTION_CLIENTID", D6O_CLIENTID, "string");
|
|
|
- EXPECT_THROW(opt_def5.validate(), isc::BadValue);
|
|
|
+ EXPECT_THROW(opt_def5.validate(), MalformedOptionDefinition);
|
|
|
|
|
|
- OptionDefinition opt_def6("OPTION CLIENTID", D6O_CLIENTID, "string");
|
|
|
- EXPECT_THROW(opt_def6.validate(), isc::BadValue);
|
|
|
+ // Option name must not contain spaces.
|
|
|
+ OptionDefinition opt_def6("OPTION CLIENTID", D6O_CLIENTID, "string", true);
|
|
|
+ EXPECT_THROW(opt_def6.validate(), MalformedOptionDefinition);
|
|
|
+
|
|
|
+ // Having array of strings does not make sense because there is no way
|
|
|
+ // to determine string's length.
|
|
|
+ OptionDefinition opt_def7("OPTION_CLIENTID", D6O_CLIENTID, "string", true);
|
|
|
+ EXPECT_THROW(opt_def7.validate(), MalformedOptionDefinition);
|
|
|
+
|
|
|
+ // It does not make sense to have string field within the record before
|
|
|
+ // other fields because there is no way to determine the length of this
|
|
|
+ // string and thus there is no way to determine where the other field
|
|
|
+ // begins.
|
|
|
+ OptionDefinition opt_def8("OPTION_STATUS_CODE", D6O_STATUS_CODE,
|
|
|
+ "record");
|
|
|
+ opt_def8.addRecordField("string");
|
|
|
+ opt_def8.addRecordField("uint16");
|
|
|
+ EXPECT_THROW(opt_def8.validate(), MalformedOptionDefinition);
|
|
|
+
|
|
|
+ // ... but it is ok if the string value is the last one.
|
|
|
+ OptionDefinition opt_def9("OPTION_STATUS_CODE", D6O_STATUS_CODE,
|
|
|
+ "record");
|
|
|
+ opt_def9.addRecordField("uint8");
|
|
|
+ opt_def9.addRecordField("string");
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryAddrList6) {
|
|
|
+
|
|
|
+// The purpose of this test is to verify that option definition
|
|
|
+// that comprises array of IPv6 addresses will return an instance
|
|
|
+// of option with a list of IPv6 addresses.
|
|
|
+TEST_F(OptionDefinitionTest, ipv6AddressArray) {
|
|
|
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;
|
|
@@ -176,7 +217,7 @@ TEST_F(OptionDefinitionTest, factoryAddrList6) {
|
|
|
// the provided buffer.
|
|
|
OptionPtr option_v6;
|
|
|
ASSERT_NO_THROW(
|
|
|
- option_v6 = factory(Option::V6, D6O_NIS_SERVERS, buf);
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_NIS_SERVERS, buf);
|
|
|
);
|
|
|
ASSERT_TRUE(typeid(*option_v6) == typeid(Option6AddrLst));
|
|
|
boost::shared_ptr<Option6AddrLst> option_cast_v6 =
|
|
@@ -195,17 +236,64 @@ TEST_F(OptionDefinitionTest, factoryAddrList6) {
|
|
|
buf.insert(buf.end(), 1, 1);
|
|
|
// It should throw exception then.
|
|
|
EXPECT_THROW(
|
|
|
- factory(Option::V6, D6O_NIS_SERVERS, buf),
|
|
|
- isc::OutOfRange
|
|
|
+ opt_def.optionFactory(Option::V6, D6O_NIS_SERVERS, buf),
|
|
|
+ InvalidOptionValue
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to verify that option definition
|
|
|
+// that comprises array of IPv6 addresses will return an instance
|
|
|
+// of option with a list of IPv6 addresses. Array of IPv6 addresses
|
|
|
+// is specified as a vector of strings (each string represents single
|
|
|
+// IPv6 address).
|
|
|
+TEST_F(OptionDefinitionTest, ipv6AddressArrayTokenized) {
|
|
|
+ OptionDefinition opt_def("OPTION_NIS_SERVERS", D6O_NIS_SERVERS,
|
|
|
+ "ipv6-address", true);
|
|
|
+
|
|
|
+ // Create a vector 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"));
|
|
|
+
|
|
|
+ // Create a vector of strings representing addresses given above.
|
|
|
+ std::vector<std::string> addrs_str;
|
|
|
+ for (std::vector<asiolink::IOAddress>::const_iterator it = addrs.begin();
|
|
|
+ it != addrs.end(); ++it) {
|
|
|
+ addrs_str.push_back(it->toText());
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create DHCPv6 option using the list of IPv6 addresses given in the
|
|
|
+ // string form.
|
|
|
+ OptionPtr option_v6;
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_NIS_SERVERS,
|
|
|
+ addrs_str);
|
|
|
);
|
|
|
+ // Non-null pointer option is supposed to be returned and it
|
|
|
+ // should have Option6AddrLst type.
|
|
|
+ ASSERT_TRUE(option_v6);
|
|
|
+ ASSERT_TRUE(typeid(*option_v6) == typeid(Option6AddrLst));
|
|
|
+ // Cast to the actual option type to get IPv6 addresses from it.
|
|
|
+ boost::shared_ptr<Option6AddrLst> option_cast_v6 =
|
|
|
+ boost::static_pointer_cast<Option6AddrLst>(option_v6);
|
|
|
+ // Check that cast was successful.
|
|
|
+ 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();
|
|
|
+ // Returned addresses must match the addresses that have been used to create
|
|
|
+ // the option instance.
|
|
|
+ EXPECT_TRUE(std::equal(addrs.begin(), addrs.end(), addrs_returned.begin()));
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryAddrList4) {
|
|
|
+// The purpose of this test is to verify that option definition
|
|
|
+// that comprises array of IPv4 addresses will return an instance
|
|
|
+// of option with a list of IPv4 addresses.
|
|
|
+TEST_F(OptionDefinitionTest, ipv4AddressArray) {
|
|
|
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;
|
|
@@ -228,7 +316,7 @@ TEST_F(OptionDefinitionTest, factoryAddrList4) {
|
|
|
// the provided buffer.
|
|
|
OptionPtr option_v4;
|
|
|
ASSERT_NO_THROW(
|
|
|
- option_v4 = factory(Option::V4, DHO_NAME_SERVERS, buf)
|
|
|
+ option_v4 = opt_def.optionFactory(Option::V4, DHO_NAME_SERVERS, buf)
|
|
|
);
|
|
|
ASSERT_TRUE(typeid(*option_v4) == typeid(Option4AddrLst));
|
|
|
// Get the list of parsed addresses from the option object.
|
|
@@ -245,19 +333,66 @@ TEST_F(OptionDefinitionTest, factoryAddrList4) {
|
|
|
// fulfilled anymore.
|
|
|
buf.insert(buf.end(), 1, 1);
|
|
|
// It should throw exception then.
|
|
|
- EXPECT_THROW(factory(Option::V4, DHO_NIS_SERVERS, buf), isc::OutOfRange);
|
|
|
+ EXPECT_THROW(opt_def.optionFactory(Option::V4, DHO_NIS_SERVERS, buf),
|
|
|
+ InvalidOptionValue);
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to verify that option definition
|
|
|
+// that comprises array of IPv4 addresses will return an instance
|
|
|
+// of option with a list of IPv4 addresses. The array of IPv4 addresses
|
|
|
+// is specified as a vector of strings (each string represents single
|
|
|
+// IPv4 address).
|
|
|
+TEST_F(OptionDefinitionTest, ipv4AddressArrayTokenized) {
|
|
|
+ OptionDefinition opt_def("OPTION_NIS_SERVERS", DHO_NIS_SERVERS,
|
|
|
+ "ipv4-address", true);
|
|
|
+
|
|
|
+ // Create a vector 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"));
|
|
|
+
|
|
|
+ // Create a vector of strings representing addresses given above.
|
|
|
+ std::vector<std::string> addrs_str;
|
|
|
+ for (std::vector<asiolink::IOAddress>::const_iterator it = addrs.begin();
|
|
|
+ it != addrs.end(); ++it) {
|
|
|
+ addrs_str.push_back(it->toText());
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create DHCPv4 option using the list of IPv4 addresses given in the
|
|
|
+ // string form.
|
|
|
+ OptionPtr option_v4;
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ option_v4 = opt_def.optionFactory(Option::V4, DHO_NIS_SERVERS,
|
|
|
+ addrs_str);
|
|
|
+ );
|
|
|
+ // Non-null pointer option is supposed to be returned and it
|
|
|
+ // should have Option6AddrLst type.
|
|
|
+ ASSERT_TRUE(option_v4);
|
|
|
+ ASSERT_TRUE(typeid(*option_v4) == typeid(Option4AddrLst));
|
|
|
+ // Cast to the actual option type to get IPv4 addresses from it.
|
|
|
+ boost::shared_ptr<Option4AddrLst> option_cast_v4 =
|
|
|
+ boost::static_pointer_cast<Option4AddrLst>(option_v4);
|
|
|
+ // Check that cast was successful.
|
|
|
+ ASSERT_TRUE(option_cast_v4);
|
|
|
+ // Get the list of parsed addresses from the option object.
|
|
|
+ std::vector<asiolink::IOAddress> addrs_returned =
|
|
|
+ option_cast_v4->getAddresses();
|
|
|
+ // Returned addresses must match the addresses that have been used to create
|
|
|
+ // the option instance.
|
|
|
+ EXPECT_TRUE(std::equal(addrs.begin(), addrs.end(), addrs_returned.begin()));
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryEmpty) {
|
|
|
+// The purpose of thie test is to verify that option definition for
|
|
|
+// 'empty' option can be created and that it returns 'empty' option.
|
|
|
+TEST_F(OptionDefinitionTest, empty) {
|
|
|
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())
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_RAPID_COMMIT, OptionBuffer())
|
|
|
);
|
|
|
ASSERT_TRUE(typeid(*option_v6) == typeid(Option));
|
|
|
// Expect 'empty' DHCPv6 option.
|
|
@@ -266,31 +401,23 @@ TEST_F(OptionDefinitionTest, factoryEmpty) {
|
|
|
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()));
|
|
|
+ ASSERT_NO_THROW(option_v4 = opt_def.optionFactory(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, factoryBinary) {
|
|
|
+// The purpose of this test is to verify that definition can be
|
|
|
+// creates for the option that holds binary data.
|
|
|
+TEST_F(OptionDefinitionTest, binary) {
|
|
|
// Binary option is the one that is represented by the generic
|
|
|
// Option class. In fact all options can be represented by this
|
|
|
// class but for some of them it is just natural. The SERVERID
|
|
|
// option consists of the option code, length and binary data so
|
|
|
// this one was picked for this test.
|
|
|
OptionDefinition opt_def("OPTION_SERVERID", D6O_SERVERID, "binary");
|
|
|
- Option::Factory* factory(NULL);
|
|
|
- EXPECT_NO_THROW(factory = opt_def.getFactory());
|
|
|
- ASSERT_TRUE(factory != NULL);
|
|
|
|
|
|
// Prepare some dummy data (serverid): 0, 1, 2 etc.
|
|
|
OptionBuffer buf(14);
|
|
@@ -302,7 +429,7 @@ TEST_F(OptionDefinitionTest, factoryBinary) {
|
|
|
// object of the type Option should be returned.
|
|
|
OptionPtr option_v6;
|
|
|
ASSERT_NO_THROW(
|
|
|
- option_v6 = factory(Option::V6, D6O_SERVERID, buf);
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_SERVERID, buf);
|
|
|
);
|
|
|
// Expect base option type returned.
|
|
|
ASSERT_TRUE(typeid(*option_v6) == typeid(Option));
|
|
@@ -320,7 +447,7 @@ TEST_F(OptionDefinitionTest, factoryBinary) {
|
|
|
|
|
|
// Repeat the same test scenario for DHCPv4 option.
|
|
|
OptionPtr option_v4;
|
|
|
- ASSERT_NO_THROW(option_v4 = factory(Option::V4, 214, buf));
|
|
|
+ ASSERT_NO_THROW(option_v4 = opt_def.optionFactory(Option::V4, 214, buf));
|
|
|
// Expect 'empty' DHCPv4 option.
|
|
|
EXPECT_EQ(Option::V4, option_v4->getUniverse());
|
|
|
EXPECT_EQ(2, option_v4->getHeaderLen());
|
|
@@ -331,19 +458,69 @@ TEST_F(OptionDefinitionTest, factoryBinary) {
|
|
|
buf.begin()));
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryIA6) {
|
|
|
+// The purpose of this test is to verify that definition can be
|
|
|
+// creates for the option that holds binary data and that the
|
|
|
+// binary data can be specified in 'comma separated values'
|
|
|
+// format.
|
|
|
+TEST_F(OptionDefinitionTest, binaryTokenized) {
|
|
|
+ OptionDefinition opt_def("OPTION_FOO", 1000, "binary", true);
|
|
|
+
|
|
|
+ // Prepare some dummy data (serverid): 0, 1, 2 etc.
|
|
|
+ OptionBuffer buf(16);
|
|
|
+ for (int i = 0; i < buf.size(); ++i) {
|
|
|
+ buf[i] = i;
|
|
|
+ }
|
|
|
+ std::vector<std::string> hex_data;
|
|
|
+ hex_data.push_back("00010203");
|
|
|
+ hex_data.push_back("04050607");
|
|
|
+ hex_data.push_back("08090A0B0C0D0E0F");
|
|
|
+
|
|
|
+ // Create option instance with the factory function.
|
|
|
+ // If the OptionDefinition code works properly than
|
|
|
+ // object of the type Option should be returned.
|
|
|
+ OptionPtr option_v6;
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, 1000, hex_data);
|
|
|
+ );
|
|
|
+ // Expect base option type returned.
|
|
|
+ ASSERT_TRUE(typeid(*option_v6) == typeid(Option));
|
|
|
+ // Sanity check on universe, length and size. These are
|
|
|
+ // the basic parameters identifying any option.
|
|
|
+ EXPECT_EQ(Option::V6, option_v6->getUniverse());
|
|
|
+ EXPECT_EQ(4, option_v6->getHeaderLen());
|
|
|
+ ASSERT_EQ(buf.size(), option_v6->getData().size());
|
|
|
+
|
|
|
+ // Get data from the option and compare against reference buffer.
|
|
|
+ // They are expected to match.
|
|
|
+ EXPECT_TRUE(std::equal(option_v6->getData().begin(),
|
|
|
+ option_v6->getData().end(),
|
|
|
+ buf.begin()));
|
|
|
+
|
|
|
+ // Repeat the same test scenario for DHCPv4 option.
|
|
|
+ OptionPtr option_v4;
|
|
|
+ ASSERT_NO_THROW(option_v4 = opt_def.optionFactory(Option::V4, 214, hex_data));
|
|
|
+ EXPECT_EQ(Option::V4, option_v4->getUniverse());
|
|
|
+ EXPECT_EQ(2, option_v4->getHeaderLen());
|
|
|
+ ASSERT_EQ(buf.size(), option_v4->getData().size());
|
|
|
+
|
|
|
+ EXPECT_TRUE(std::equal(option_v6->getData().begin(),
|
|
|
+ option_v6->getData().end(),
|
|
|
+ buf.begin()));
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to verify that definition can be created
|
|
|
+// for option that comprises record of data. In this particular test
|
|
|
+// the IA_NA option is used. This option comprises three uint32 fields.
|
|
|
+TEST_F(OptionDefinitionTest, recordIA6) {
|
|
|
// 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);
|
|
|
+ OptionDefinition opt_def("OPTION_IA_NA", D6O_IA_NA, "record", false);
|
|
|
// 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);
|
|
@@ -351,7 +528,7 @@ TEST_F(OptionDefinitionTest, factoryIA6) {
|
|
|
buf[i] = i;
|
|
|
}
|
|
|
OptionPtr option_v6;
|
|
|
- ASSERT_NO_THROW(option_v6 = factory(Option::V6, D6O_IA_NA, buf));
|
|
|
+ ASSERT_NO_THROW(option_v6 = opt_def.optionFactory(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);
|
|
@@ -359,25 +536,18 @@ TEST_F(OptionDefinitionTest, factoryIA6) {
|
|
|
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.
|
|
|
+ // The length of the buffer must be at least 12 bytes.
|
|
|
// Check too short buffer.
|
|
|
EXPECT_THROW(
|
|
|
- factory(Option::V6, D6O_IA_NA, OptionBuffer(option6_ia_len - 1)),
|
|
|
- isc::OutOfRange
|
|
|
+ opt_def.optionFactory(Option::V6, D6O_IA_NA, OptionBuffer(option6_ia_len - 1)),
|
|
|
+ InvalidOptionValue
|
|
|
);
|
|
|
- // Check too long buffer.
|
|
|
- EXPECT_THROW(
|
|
|
- factory(Option::V6, D6O_IA_NA, OptionBuffer(option6_ia_len + 1)),
|
|
|
- isc::OutOfRange
|
|
|
- );
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryIAAddr6) {
|
|
|
+// The purpose of this test is to verify that definition can be created
|
|
|
+// for option that comprises record of data. In this particular test
|
|
|
+// the IAADDR option is used.
|
|
|
+TEST_F(OptionDefinitionTest, recordIAAddr6) {
|
|
|
// 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;
|
|
@@ -386,9 +556,6 @@ TEST_F(OptionDefinitionTest, factoryIAAddr6) {
|
|
|
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;
|
|
@@ -403,7 +570,7 @@ TEST_F(OptionDefinitionTest, factoryIAAddr6) {
|
|
|
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_NO_THROW(option_v6 = opt_def.optionFactory(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);
|
|
@@ -411,44 +578,54 @@ TEST_F(OptionDefinitionTest, factoryIAAddr6) {
|
|
|
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.
|
|
|
+ // The length of the buffer must be at least 12 bytes.
|
|
|
// Check too short buffer.
|
|
|
EXPECT_THROW(
|
|
|
- factory(Option::V6, D6O_IAADDR, OptionBuffer(option6_iaaddr_len - 1)),
|
|
|
- isc::OutOfRange
|
|
|
+ opt_def.optionFactory(Option::V6, D6O_IAADDR, OptionBuffer(option6_iaaddr_len - 1)),
|
|
|
+ InvalidOptionValue
|
|
|
);
|
|
|
- // 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
|
|
|
- );
|
|
|
+// The purpose of this test is to verify that definition can be created
|
|
|
+// for option that comprises record of data. In this particular test
|
|
|
+// the IAADDR option is used. The data for the option is speicifed as
|
|
|
+// a vector of strings. Each string carries the data for the corresponding
|
|
|
+// data field.
|
|
|
+TEST_F(OptionDefinitionTest, recordIAAddr6Tokenized) {
|
|
|
+ // This option consists of IPV6 Address (16 bytes) and preferred-lifetime and
|
|
|
+ // valid-lifetime fields (each 4 bytes long).
|
|
|
+ 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"));
|
|
|
+
|
|
|
+ // Check the positive scenario.
|
|
|
+ std::vector<std::string> data_field_values;
|
|
|
+ data_field_values.push_back("2001:0db8::ff00:0042:8329");
|
|
|
+ data_field_values.push_back("1234");
|
|
|
+ data_field_values.push_back("5678");
|
|
|
+
|
|
|
+ OptionPtr option_v6;
|
|
|
+ ASSERT_NO_THROW(option_v6 = opt_def.optionFactory(Option::V6, D6O_IAADDR,
|
|
|
+ data_field_values));
|
|
|
+ ASSERT_TRUE(typeid(*option_v6) == typeid(Option6IAAddr));
|
|
|
+ boost::shared_ptr<Option6IAAddr> option_cast_v6 =
|
|
|
+ boost::static_pointer_cast<Option6IAAddr>(option_v6);
|
|
|
+ EXPECT_EQ("2001:db8::ff00:42:8329", option_cast_v6->getAddress().toText());
|
|
|
+ EXPECT_EQ(1234, option_cast_v6->getPreferred());
|
|
|
+ EXPECT_EQ(5678, option_cast_v6->getValid());
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryUint8) {
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises single uint8 value can be created and that this definition
|
|
|
+// can be used to create an option with single uint8 value.
|
|
|
+TEST_F(OptionDefinitionTest, uint8) {
|
|
|
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));
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_PREFERENCE, OptionBuffer(1, 1));
|
|
|
);
|
|
|
ASSERT_TRUE(typeid(*option_v6) == typeid(Option6Int<uint8_t>));
|
|
|
// Validate the value.
|
|
@@ -456,26 +633,47 @@ TEST_F(OptionDefinitionTest, factoryUint8) {
|
|
|
boost::static_pointer_cast<Option6Int<uint8_t> >(option_v6);
|
|
|
EXPECT_EQ(1, option_cast_v6->getValue());
|
|
|
|
|
|
- // Try to provide too large buffer. Expect exception.
|
|
|
+ // Try to provide zero-length buffer. Expect exception.
|
|
|
EXPECT_THROW(
|
|
|
- option_v6 = factory(Option::V6, D6O_PREFERENCE, OptionBuffer(3)),
|
|
|
- isc::OutOfRange
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_PREFERENCE, OptionBuffer()),
|
|
|
+ InvalidOptionValue
|
|
|
);
|
|
|
|
|
|
- // 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
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises single uint8 value can be created and that this definition
|
|
|
+// can be used to create an option with single uint8 value.
|
|
|
+TEST_F(OptionDefinitionTest, uint8Tokenized) {
|
|
|
+ OptionDefinition opt_def("OPTION_PREFERENCE", D6O_PREFERENCE, "uint8");
|
|
|
+
|
|
|
+ OptionPtr option_v6;
|
|
|
+ std::vector<std::string> values;
|
|
|
+ values.push_back("123");
|
|
|
+ values.push_back("456");
|
|
|
+ try {
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_PREFERENCE, values);
|
|
|
+ } catch (std::exception& ex) {
|
|
|
+ std::cout << ex.what() << std::endl;
|
|
|
+ }
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_PREFERENCE, values);
|
|
|
);
|
|
|
+ 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(123, option_cast_v6->getValue());
|
|
|
|
|
|
// @todo Add more cases for DHCPv4
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryUint16) {
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises single uint16 value can be created and that this definition
|
|
|
+// can be used to create an option with single uint16 value.
|
|
|
+TEST_F(OptionDefinitionTest, uint16) {
|
|
|
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.
|
|
@@ -483,7 +681,7 @@ TEST_F(OptionDefinitionTest, factoryUint16) {
|
|
|
buf.push_back(1);
|
|
|
buf.push_back(2);
|
|
|
ASSERT_NO_THROW(
|
|
|
- option_v6 = factory(Option::V6, D6O_ELAPSED_TIME, buf);
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_ELAPSED_TIME, buf);
|
|
|
);
|
|
|
ASSERT_TRUE(typeid(*option_v6) == typeid(Option6Int<uint16_t>));
|
|
|
// Validate the value.
|
|
@@ -491,25 +689,44 @@ TEST_F(OptionDefinitionTest, factoryUint16) {
|
|
|
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
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_ELAPSED_TIME, OptionBuffer(1)),
|
|
|
+ InvalidOptionValue
|
|
|
+ );
|
|
|
+
|
|
|
+ // @todo Add more cases for DHCPv4
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises single uint16 value can be created and that this definition
|
|
|
+// can be used to create an option with single uint16 value.
|
|
|
+TEST_F(OptionDefinitionTest, uint16Tokenized) {
|
|
|
+ OptionDefinition opt_def("OPTION_ELAPSED_TIME", D6O_ELAPSED_TIME, "uint16");
|
|
|
+
|
|
|
+ OptionPtr option_v6;
|
|
|
+
|
|
|
+ std::vector<std::string> values;
|
|
|
+ values.push_back("1234");
|
|
|
+ values.push_back("5678");
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_ELAPSED_TIME, values);
|
|
|
);
|
|
|
+ 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(1234, option_cast_v6->getValue());
|
|
|
|
|
|
// @todo Add more cases for DHCPv4
|
|
|
+
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryUint32) {
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises single uint32 value can be created and that this definition
|
|
|
+// can be used to create an option with single uint32 value.
|
|
|
+TEST_F(OptionDefinitionTest, uint32) {
|
|
|
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;
|
|
@@ -518,7 +735,7 @@ TEST_F(OptionDefinitionTest, factoryUint32) {
|
|
|
buf.push_back(3);
|
|
|
buf.push_back(4);
|
|
|
ASSERT_NO_THROW(
|
|
|
- option_v6 = factory(Option::V6, D6O_CLT_TIME, buf);
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_CLT_TIME, buf);
|
|
|
);
|
|
|
ASSERT_TRUE(typeid(*option_v6) == typeid(Option6Int<uint32_t>));
|
|
|
// Validate the value.
|
|
@@ -526,27 +743,44 @@ TEST_F(OptionDefinitionTest, factoryUint32) {
|
|
|
boost::static_pointer_cast<Option6Int<uint32_t> >(option_v6);
|
|
|
EXPECT_EQ(0x01020304, option_cast_v6->getValue());
|
|
|
|
|
|
- // Try to provide too large buffer. Expect exception.
|
|
|
+ // Try to provide too short buffer. Expect exception.
|
|
|
EXPECT_THROW(
|
|
|
- option_v6 = factory(Option::V6, D6O_CLT_TIME, OptionBuffer(5)),
|
|
|
- isc::OutOfRange
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_CLT_TIME, OptionBuffer(2)),
|
|
|
+ InvalidOptionValue
|
|
|
);
|
|
|
- // 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
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises single uint32 value can be created and that this definition
|
|
|
+// can be used to create an option with single uint32 value.
|
|
|
+TEST_F(OptionDefinitionTest, uint32Tokenized) {
|
|
|
+ OptionDefinition opt_def("OPTION_CLT_TIME", D6O_CLT_TIME, "uint32");
|
|
|
+
|
|
|
+ OptionPtr option_v6;
|
|
|
+ std::vector<std::string> values;
|
|
|
+ values.push_back("123456");
|
|
|
+ values.push_back("789");
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, D6O_CLT_TIME, values);
|
|
|
);
|
|
|
+ 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(123456, option_cast_v6->getValue());
|
|
|
|
|
|
// @todo Add more cases for DHCPv4
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryUint16Array) {
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises array of uint16 values can be created and that this definition
|
|
|
+// can be used to create option with an array of uint16 values.
|
|
|
+TEST_F(OptionDefinitionTest, uint16Array) {
|
|
|
// 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
|
|
@@ -558,7 +792,7 @@ TEST_F(OptionDefinitionTest, factoryUint16Array) {
|
|
|
}
|
|
|
// Constructor should succeed because buffer has correct size.
|
|
|
EXPECT_NO_THROW(
|
|
|
- option_v6 = factory(Option::V6, opt_code, buf);
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, opt_code, buf);
|
|
|
);
|
|
|
ASSERT_TRUE(typeid(*option_v6) == typeid(Option6IntArray<uint16_t>));
|
|
|
boost::shared_ptr<Option6IntArray<uint16_t> > option_cast_v6 =
|
|
@@ -576,24 +810,50 @@ TEST_F(OptionDefinitionTest, factoryUint16Array) {
|
|
|
// 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
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, opt_code, OptionBuffer()),
|
|
|
+ InvalidOptionValue
|
|
|
);
|
|
|
// Buffer length must be multiple of data type size.
|
|
|
EXPECT_THROW(
|
|
|
- option_v6 = factory(Option::V6, opt_code, OptionBuffer(5)),
|
|
|
- isc::OutOfRange
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, opt_code, OptionBuffer(5)),
|
|
|
+ InvalidOptionValue
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises array of uint16 values can be created and that this definition
|
|
|
+// can be used to create option with an array of uint16 values.
|
|
|
+TEST_F(OptionDefinitionTest, uint16ArrayTokenized) {
|
|
|
+ // Let's define some dummy option.
|
|
|
+ const uint16_t opt_code = 79;
|
|
|
+ OptionDefinition opt_def("OPTION_UINT16_ARRAY", opt_code, "uint16", true);
|
|
|
+
|
|
|
+ OptionPtr option_v6;
|
|
|
+ std::vector<std::string> str_values;
|
|
|
+ str_values.push_back("12345");
|
|
|
+ str_values.push_back("5679");
|
|
|
+ str_values.push_back("12");
|
|
|
+ EXPECT_NO_THROW(
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, opt_code, str_values);
|
|
|
);
|
|
|
+ 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();
|
|
|
+ EXPECT_EQ(12345, values[0]);
|
|
|
+ EXPECT_EQ(5679, values[1]);
|
|
|
+ EXPECT_EQ(12, values[2]);
|
|
|
}
|
|
|
|
|
|
-TEST_F(OptionDefinitionTest, factoryUint32Array) {
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises array of uint32 values can be created and that this definition
|
|
|
+// can be used to create option with an array of uint32 values.
|
|
|
+TEST_F(OptionDefinitionTest, uint32Array) {
|
|
|
// 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
|
|
@@ -605,7 +865,7 @@ TEST_F(OptionDefinitionTest, factoryUint32Array) {
|
|
|
}
|
|
|
// Constructor should succeed because buffer has correct size.
|
|
|
EXPECT_NO_THROW(
|
|
|
- option_v6 = factory(Option::V6, opt_code, buf);
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, opt_code, buf);
|
|
|
);
|
|
|
ASSERT_TRUE(typeid(*option_v6) == typeid(Option6IntArray<uint32_t>));
|
|
|
boost::shared_ptr<Option6IntArray<uint32_t> > option_cast_v6 =
|
|
@@ -623,16 +883,85 @@ TEST_F(OptionDefinitionTest, factoryUint32Array) {
|
|
|
// 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
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, opt_code, OptionBuffer()),
|
|
|
+ InvalidOptionValue
|
|
|
);
|
|
|
// Buffer length must be multiple of data type size.
|
|
|
EXPECT_THROW(
|
|
|
- option_v6 = factory(Option::V6, opt_code, OptionBuffer(5)),
|
|
|
- isc::OutOfRange
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, opt_code, OptionBuffer(5)),
|
|
|
+ InvalidOptionValue
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to verify that definition for option that
|
|
|
+// comprises array of uint32 values can be created and that this definition
|
|
|
+// can be used to create option with an array of uint32 values.
|
|
|
+TEST_F(OptionDefinitionTest, uint32ArrayTokenized) {
|
|
|
+ // Let's define some dummy option.
|
|
|
+ const uint16_t opt_code = 80;
|
|
|
+
|
|
|
+ OptionDefinition opt_def("OPTION_UINT32_ARRAY", opt_code, "uint32", true);
|
|
|
+
|
|
|
+ OptionPtr option_v6;
|
|
|
+ std::vector<std::string> str_values;
|
|
|
+ str_values.push_back("123456");
|
|
|
+ str_values.push_back("7");
|
|
|
+ str_values.push_back("256");
|
|
|
+ str_values.push_back("1111");
|
|
|
+
|
|
|
+ EXPECT_NO_THROW(
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, opt_code, str_values);
|
|
|
+ );
|
|
|
+ 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();
|
|
|
+ EXPECT_EQ(123456, values[0]);
|
|
|
+ EXPECT_EQ(7, values[1]);
|
|
|
+ EXPECT_EQ(256, values[2]);
|
|
|
+ EXPECT_EQ(1111, values[3]);
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to verify that the definition can be created
|
|
|
+// for the option that comprises string value in the UTF8 format.
|
|
|
+TEST_F(OptionDefinitionTest, utf8StringTokenized) {
|
|
|
+ // Let's create some dummy option.
|
|
|
+ const uint16_t opt_code = 80;
|
|
|
+ OptionDefinition opt_def("OPTION_WITH_STRING", opt_code, "string");
|
|
|
+
|
|
|
+ std::vector<std::string> values;
|
|
|
+ values.push_back("Hello World");
|
|
|
+ values.push_back("this string should not be included in the option");
|
|
|
+ OptionPtr option_v6;
|
|
|
+ EXPECT_NO_THROW(
|
|
|
+ option_v6 = opt_def.optionFactory(Option::V6, opt_code, values);
|
|
|
+ );
|
|
|
+ ASSERT_TRUE(option_v6);
|
|
|
+ ASSERT_TRUE(typeid(*option_v6) == typeid(Option));
|
|
|
+ std::vector<uint8_t> data = option_v6->getData();
|
|
|
+ std::vector<uint8_t> ref_data(values[0].c_str(), values[0].c_str()
|
|
|
+ + values[0].length());
|
|
|
+ EXPECT_TRUE(std::equal(ref_data.begin(), ref_data.end(), data.begin()));
|
|
|
+}
|
|
|
+
|
|
|
+// The purpose of this test is to check that non-integer data type can't
|
|
|
+// be used for factoryInteger function.
|
|
|
+TEST_F(OptionDefinitionTest, integerInvalidType) {
|
|
|
+ // The template function factoryInteger<> accepts integer values only
|
|
|
+ // as template typename. Here we try passing different type and
|
|
|
+ // see if it rejects it.
|
|
|
+ OptionBuffer buf(1);
|
|
|
+ EXPECT_THROW(
|
|
|
+ OptionDefinition::factoryInteger<bool>(Option::V6, D6O_PREFERENCE,
|
|
|
+ buf.begin(), buf.end()),
|
|
|
+ isc::dhcp::InvalidDataType
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+// The purpose of this test is to verify that helper methods
|
|
|
+// haveIA6Format and haveIAAddr6Format can be used to determine
|
|
|
+// IA_NA and IAADDR option formats.
|
|
|
TEST_F(OptionDefinitionTest, recognizeFormat) {
|
|
|
// IA_NA option format.
|
|
|
OptionDefinition opt_def1("OPTION_IA_NA", D6O_IA_NA, "record");
|