|
@@ -39,24 +39,63 @@ using namespace isc::util;
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
+/// @brief Type of the "copy" operation to be performed in a test.
|
|
|
+///
|
|
|
+/// Possible operations are:
|
|
|
+/// - copy construction,
|
|
|
+/// - cloning with Option::clone,
|
|
|
+/// - assignment.
|
|
|
enum OpType {
|
|
|
COPY,
|
|
|
CLONE,
|
|
|
ASSIGN
|
|
|
};
|
|
|
|
|
|
+/// @brief Generic test for deep copy of an option.
|
|
|
+///
|
|
|
+/// This test can use one of the three supported operations to deep copy
|
|
|
+/// an option: copy construction, cloning or assignment.
|
|
|
+///
|
|
|
+/// After copying the option the following parameters checked if they
|
|
|
+/// have been copied (copied by the Option class):
|
|
|
+/// - universe,
|
|
|
+/// - option type,
|
|
|
+/// - encapsulated space,
|
|
|
+/// - data.
|
|
|
+///
|
|
|
+/// This test also checks that the sub options have been copied by checking
|
|
|
+/// that:
|
|
|
+/// - options' types match,
|
|
|
+/// - binary representations are equal,
|
|
|
+/// - pointers to the options are unequal (to make sure that the option has
|
|
|
+/// been copied, rather than the pointer).
|
|
|
+///
|
|
|
+/// @param op_type Copy operation to be performed.
|
|
|
+/// @param option Source option.
|
|
|
+/// @param option_copy Destination option. Note that this option may be
|
|
|
+/// initially set to a non-null value. For the "copy" and "clone" operations
|
|
|
+/// the pointer will be reset, so there is no sense to initialize this
|
|
|
+/// object to a non-null value. However, for the assignment testing it is
|
|
|
+/// recommended to initialize the option_copy to point to an option having
|
|
|
+/// different parameters to verify that all parameters have been overriden
|
|
|
+/// by the assignment operation.
|
|
|
template<typename OptionType>
|
|
|
void testCopyAssign(const OpType& op_type,
|
|
|
boost::shared_ptr<OptionType>& option,
|
|
|
boost::shared_ptr<OptionType>& option_copy) {
|
|
|
+ // Set the encapsulated to 'foo' because tests usually don't set that
|
|
|
+ // value.
|
|
|
option->setEncapsulatedSpace("foo");
|
|
|
|
|
|
+ // Create two sub options of different types to later check that they
|
|
|
+ // are copied.
|
|
|
OptionUint16Ptr sub1 = OptionUint16Ptr(new OptionUint16(Option::V4, 10, 234));
|
|
|
Option4AddrLstPtr sub2 =
|
|
|
Option4AddrLstPtr(new Option4AddrLst(11, IOAddress("192.0.2.3")));
|
|
|
option->addOption(sub1);
|
|
|
option->addOption(sub2);
|
|
|
|
|
|
+ // Copy option by copy construction, cloning or assignment.
|
|
|
switch (op_type) {
|
|
|
case COPY:
|
|
|
option_copy.reset(new OptionType(*option));
|
|
@@ -74,6 +113,7 @@ void testCopyAssign(const OpType& op_type,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // Verify that basic parameters have been copied.
|
|
|
EXPECT_EQ(option->getUniverse(), option_copy->getUniverse());
|
|
|
EXPECT_EQ(option->getType(), option_copy->getType());
|
|
|
EXPECT_EQ(option->len(), option_copy->len());
|
|
@@ -81,20 +121,27 @@ void testCopyAssign(const OpType& op_type,
|
|
|
EXPECT_TRUE(std::equal(option->getData().begin(), option->getData().end(),
|
|
|
option_copy->getData().begin()));
|
|
|
|
|
|
+ // Retrieve sub options so as they can be compared.
|
|
|
const OptionCollection& option_subs = option->getOptions();
|
|
|
const OptionCollection& option_copy_subs = option_copy->getOptions();
|
|
|
-
|
|
|
ASSERT_EQ(option_subs.size(), option_copy_subs.size());
|
|
|
+
|
|
|
+ // Iterate over source options.
|
|
|
OptionCollection::const_iterator it_copy = option_copy_subs.begin();
|
|
|
for (OptionCollection::const_iterator it = option_subs.begin();
|
|
|
it != option_subs.end(); ++it, ++it_copy) {
|
|
|
+ // The option codes should be equal in both containers.
|
|
|
EXPECT_EQ(it->first, it_copy->first);
|
|
|
+ // Pointers must be unequal because the expectation is that options
|
|
|
+ // are copied, rather than pointers.
|
|
|
EXPECT_NE(it->second, it_copy->second);
|
|
|
Option* opt_ptr = it->second.get();
|
|
|
Option* opt_copy_ptr = it_copy->second.get();
|
|
|
+ // The C++ types must match.
|
|
|
EXPECT_TRUE(typeid(*opt_ptr) == typeid(*opt_copy_ptr));
|
|
|
}
|
|
|
|
|
|
+ // Final check is to compare their binary representations.
|
|
|
std::vector<uint8_t> buf = option->toBinary(true);
|
|
|
std::vector<uint8_t> buf_copy = option_copy->toBinary(true);
|
|
|
|
|
@@ -102,6 +149,11 @@ void testCopyAssign(const OpType& op_type,
|
|
|
EXPECT_TRUE(std::equal(buf_copy.begin(), buf_copy.end(), buf.begin()));
|
|
|
}
|
|
|
|
|
|
+// **************************** Option ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by Option type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOption(const OpType& op_type) {
|
|
|
OptionBuffer buf(10, 1);
|
|
|
OptionPtr option(new Option(Option::V4, 1, buf));
|
|
@@ -109,16 +161,22 @@ void testOption(const OpType& op_type) {
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Save binary representation of the original option. We will
|
|
|
+ // be later comparing it with a copied option to make sure that
|
|
|
+ // modification of the original option doesn't affect the copy.
|
|
|
std::vector<uint8_t> binary_copy = option_copy->toBinary(true);
|
|
|
|
|
|
+ // Modify the original option.
|
|
|
OptionBuffer buf_modified(10, 2);
|
|
|
option->setData(buf_modified.begin(), buf_modified.end());
|
|
|
|
|
|
- std::vector<uint8_t> binary_modified = option->toBinary(true);
|
|
|
+ // Retrieve the binary representation of the copy to verify that
|
|
|
+ // it hasn't been modified.
|
|
|
+ std::vector<uint8_t> binary_copy_after = option_copy->toBinary(true);
|
|
|
|
|
|
- ASSERT_EQ(binary_modified.size(), binary_copy.size());
|
|
|
- EXPECT_FALSE(std::equal(binary_copy.begin(), binary_copy.end(),
|
|
|
- binary_modified.begin()));
|
|
|
+ ASSERT_EQ(binary_copy.size(), binary_copy_after.size());
|
|
|
+ EXPECT_TRUE(std::equal(binary_copy_after.begin(), binary_copy_after.end(),
|
|
|
+ binary_copy.begin()));
|
|
|
}
|
|
|
|
|
|
TEST(OptionCopyTest, optionConstructor) {
|
|
@@ -133,18 +191,21 @@ TEST(OptionCopyTest, optionAssignment) {
|
|
|
testOption(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// **************************** OptionInt ***************************
|
|
|
|
|
|
+/// @brief Test deep copy of option encapsualated by OptionInt type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOptionInt(const OpType& op_type) {
|
|
|
OptionUint16Ptr option(new OptionUint16(Option::V4, 1, 12345));
|
|
|
OptionUint16Ptr option_copy(new OptionUint16(Option::V6, 10, 11111));
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
- ASSERT_EQ(12345, option->getValue());
|
|
|
- ASSERT_EQ(12345, option_copy->getValue());
|
|
|
-
|
|
|
+ // Modify value in the original option.
|
|
|
option->setValue(9);
|
|
|
- ASSERT_EQ(9, option->getValue());
|
|
|
+
|
|
|
+ // The value in the copy should not be affected.
|
|
|
EXPECT_EQ(12345, option_copy->getValue());
|
|
|
}
|
|
|
|
|
@@ -160,6 +221,11 @@ TEST(OptionCopyTest, optionIntAssignment) {
|
|
|
testOptionInt(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// ************************* OptionIntArray ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by OptionIntArray type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOptionIntArray(const OpType& op_type) {
|
|
|
OptionUint32ArrayPtr option(new OptionUint32Array(Option::V4, 1));;
|
|
|
option->addValue(2345);
|
|
@@ -170,8 +236,10 @@ void testOptionIntArray(const OpType& op_type) {
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the values in the original option.
|
|
|
option->setValues(std::vector<uint32_t>(2, 7));
|
|
|
|
|
|
+ // The values in the copy should not be affected.
|
|
|
std::vector<uint32_t> values_copy = option_copy->getValues();
|
|
|
ASSERT_EQ(2, values_copy.size());
|
|
|
EXPECT_EQ(2345, values_copy[0]);
|
|
@@ -190,6 +258,18 @@ TEST(OptionCopyTest, optionIntArrayAssignment) {
|
|
|
testOptionIntArray(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// ************************* Option4AddrLst ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by Option4AddrLst or
|
|
|
+/// Option6AddrLst type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
+/// @param option_address Address carried in the source option.
|
|
|
+/// @param option_copy_address Address carried in the destination option.
|
|
|
+/// @param option_modified_address Address to which the original address
|
|
|
+/// is modified to check that this modification doesn't affect option
|
|
|
+/// copy.
|
|
|
+/// @tparam OptionType Option4AddrLst or Option6AddrLst.
|
|
|
template<typename OptionType>
|
|
|
void testOptionAddrLst(const OpType& op_type,
|
|
|
const IOAddress& option_address,
|
|
@@ -201,12 +281,18 @@ void testOptionAddrLst(const OpType& op_type,
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the address in the original option.
|
|
|
option->setAddress(option_modified_address);
|
|
|
+
|
|
|
+ // The address in the copy should not be affected.
|
|
|
typename OptionType::AddressContainer addrs_copy = option_copy->getAddresses();
|
|
|
ASSERT_EQ(1, addrs_copy.size());
|
|
|
EXPECT_EQ(option_address.toText(), addrs_copy[0].toText());
|
|
|
}
|
|
|
|
|
|
+/// @brief Test deep copy of option encapsualated by Option4AddrLst type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOption4AddrLst(const OpType& op_type) {
|
|
|
testOptionAddrLst<Option4AddrLst>(op_type,
|
|
|
IOAddress("127.0.0.1"),
|
|
@@ -214,13 +300,6 @@ void testOption4AddrLst(const OpType& op_type) {
|
|
|
IOAddress("127.0.0.1"));
|
|
|
}
|
|
|
|
|
|
-void testOption6AddrLst(const OpType& op_type) {
|
|
|
- testOptionAddrLst<Option6AddrLst>(op_type,
|
|
|
- IOAddress("2001:db8:1::2"),
|
|
|
- IOAddress("3001::cafe"),
|
|
|
- IOAddress("3000:1::1"));
|
|
|
-}
|
|
|
-
|
|
|
TEST(OptionCopyTest, option4AddrLstConstructor) {
|
|
|
testOption4AddrLst(COPY);
|
|
|
}
|
|
@@ -233,6 +312,18 @@ TEST(OptionCopyTest, option4AddrLstAssignment) {
|
|
|
testOption4AddrLst(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// ************************* Option6AddrLst ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by Option6AddrLst type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
+void testOption6AddrLst(const OpType& op_type) {
|
|
|
+ testOptionAddrLst<Option6AddrLst>(op_type,
|
|
|
+ IOAddress("2001:db8:1::2"),
|
|
|
+ IOAddress("3001::cafe"),
|
|
|
+ IOAddress("3000:1::1"));
|
|
|
+}
|
|
|
+
|
|
|
TEST(OptionCopyTest, option6AddrLstConstructor) {
|
|
|
testOption6AddrLst(COPY);
|
|
|
}
|
|
@@ -245,6 +336,11 @@ TEST(OptionCopyTest, option6AddrLstAssignment) {
|
|
|
testOption6AddrLst(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// *************************** Option6IA ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by Option6IA type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOption6IA(const OpType& op_type) {
|
|
|
Option6IAPtr option(new Option6IA(D6O_IA_NA, 1234));
|
|
|
option->setT1(1000);
|
|
@@ -253,10 +349,12 @@ void testOption6IA(const OpType& op_type) {
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the values in the original option.
|
|
|
option->setT1(3000);
|
|
|
option->setT2(4000);
|
|
|
option->setIAID(5678);
|
|
|
|
|
|
+ // The values in the copy should not be affected.
|
|
|
EXPECT_EQ(1000, option_copy->getT1());
|
|
|
EXPECT_EQ(2000, option_copy->getT2());
|
|
|
EXPECT_EQ(1234, option_copy->getIAID());
|
|
@@ -274,6 +372,11 @@ TEST(OptionCopyTest, option6IAAssignment) {
|
|
|
testOption6IA(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// *************************** Option6IAAddr ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by Option6IAAddr type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOption6IAAddr(const OpType& op_type) {
|
|
|
Option6IAAddrPtr option(new Option6IAAddr(D6O_IAADDR,
|
|
|
IOAddress("2001:db8:1::1"),
|
|
@@ -284,10 +387,12 @@ void testOption6IAAddr(const OpType& op_type) {
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the values in the original option.
|
|
|
option->setAddress(IOAddress("2001:db8:1::3"));
|
|
|
option->setPreferred(1000);
|
|
|
option->setValid(2000);
|
|
|
|
|
|
+ // The values in the copy should not be affected.
|
|
|
EXPECT_EQ("2001:db8:1::1", option_copy->getAddress().toText());
|
|
|
EXPECT_EQ(60, option_copy->getPreferred());
|
|
|
EXPECT_EQ(90, option_copy->getValid());
|
|
@@ -305,6 +410,11 @@ TEST(OptionCopyTest, option6IAAddrAssignment) {
|
|
|
testOption6IAAddr(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// *************************** Option6IAPrefix ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by Option6IAPrefix type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOption6IAPrefix(const OpType& op_type) {
|
|
|
Option6IAPrefixPtr option(new Option6IAPrefix(D6O_IAPREFIX,
|
|
|
IOAddress("3000::"),
|
|
@@ -315,10 +425,12 @@ void testOption6IAPrefix(const OpType& op_type) {
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the values in the original option.
|
|
|
option->setPrefix(IOAddress("3002::"), 32);
|
|
|
option->setPreferred(1000);
|
|
|
option->setValid(2000);
|
|
|
|
|
|
+ // The values in the copy should not be affected.
|
|
|
EXPECT_EQ("3000::", option_copy->getAddress().toText());
|
|
|
EXPECT_EQ(64, option_copy->getLength());
|
|
|
EXPECT_EQ(60, option_copy->getPreferred());
|
|
@@ -337,6 +449,11 @@ TEST(OptionCopyTest, option6IAPrefixAssignment) {
|
|
|
testOption6IAPrefix(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// *************************** Option6StatusCode ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by Option6StatusCode type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOption6StatusCode(const OpType& op_type) {
|
|
|
Option6StatusCodePtr option(new Option6StatusCode(STATUS_NoBinding,
|
|
|
"no binding"));
|
|
@@ -345,9 +462,11 @@ void testOption6StatusCode(const OpType& op_type) {
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the values in the original option.
|
|
|
option->setStatusCode(STATUS_NoAddrsAvail);
|
|
|
option->setStatusMessage("foo");
|
|
|
|
|
|
+ // The values in the copy should not be affected.
|
|
|
EXPECT_EQ(STATUS_NoBinding, option_copy->getStatusCode());
|
|
|
EXPECT_EQ("no binding", option_copy->getStatusMessage());
|
|
|
}
|
|
@@ -364,6 +483,11 @@ TEST(OptionCopyTest, option6StatusCodeAssignment) {
|
|
|
testOption6StatusCode(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// *************************** OptionString ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by OptionString type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOptionString(const OpType& op_type) {
|
|
|
OptionStringPtr option(new OptionString(Option::V4, 1, "option value"));
|
|
|
OptionStringPtr option_copy(new OptionString(Option::V6, 10,
|
|
@@ -371,7 +495,10 @@ void testOptionString(const OpType& op_type) {
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the string in the original option.
|
|
|
option->setValue("foo");
|
|
|
+
|
|
|
+ // The string in the copy should not be affected.
|
|
|
EXPECT_EQ("option value", option_copy->getValue());
|
|
|
}
|
|
|
|
|
@@ -387,13 +514,21 @@ TEST(OptionCopyTest, optionStringAssignment) {
|
|
|
testOptionString(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// *************************** OptionVendor ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by OptionVendor type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOptionVendor(const OpType& op_type) {
|
|
|
OptionVendorPtr option(new OptionVendor(Option::V4, 2986));
|
|
|
OptionVendorPtr option_copy(new OptionVendor(Option::V6, 1111));
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the vendor id in the original option.
|
|
|
option->setVendorId(2222);
|
|
|
+
|
|
|
+ // The vendor id in the copy should not be affected.
|
|
|
EXPECT_EQ(2986, option_copy->getVendorId());
|
|
|
}
|
|
|
|
|
@@ -409,11 +544,19 @@ TEST(OptionCopyTest, optionVendorAssignment) {
|
|
|
testOptionVendor(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// *********************** OptionVendorClass ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by OptionVendorClass type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOptionVendorClass(const OpType& op_type) {
|
|
|
+ // Create a DHCPv4 option with a single tuple.
|
|
|
OptionVendorClassPtr option(new OptionVendorClass(Option::V4, 2986));
|
|
|
OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
|
|
|
tuple = "vendor-class-value";
|
|
|
option->setTuple(0, tuple);
|
|
|
+
|
|
|
+ // Create a DHCPv6 option with a single tuple.
|
|
|
OptionVendorClassPtr option_copy(new OptionVendorClass(Option::V6,
|
|
|
1111));
|
|
|
OpaqueDataTuple tuple_copy(OpaqueDataTuple::LENGTH_2_BYTES);
|
|
@@ -422,11 +565,14 @@ void testOptionVendorClass(const OpType& op_type) {
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the tuple in the original option and add one more tuple.
|
|
|
tuple = "modified-vendor-class-value";
|
|
|
option->setTuple(0, tuple);
|
|
|
tuple = "another-modified-vendor-class-value";
|
|
|
option->addTuple(tuple);
|
|
|
|
|
|
+ // That change shouldn't affect the orginal option. It should still
|
|
|
+ // contain a single tuple with the original value.
|
|
|
ASSERT_EQ(1, option_copy->getTuplesNum());
|
|
|
tuple = option_copy->getTuple(0);
|
|
|
EXPECT_TRUE(tuple.equals("vendor-class-value"));
|
|
@@ -444,27 +590,52 @@ TEST(OptionCopyTest, optionVendorClassAssignment) {
|
|
|
testOptionVendorClass(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// ************************** Option4ClientFqdn ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by Option4ClientFqdn or
|
|
|
+/// Option6ClientFqdn type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
+/// @param option Option to be copied.
|
|
|
+/// @param option_copy Destination option. Note that this option may be
|
|
|
+/// initially set to a non-null value. For the "copy" and "clone" operations
|
|
|
+/// the pointer will be reset, so there is no sense to initialize this
|
|
|
+/// object to a non-null value. However, for the assignment testing it is
|
|
|
+/// recommended to initialize the option_copy to point to an option having
|
|
|
+/// different parameters to verify that all parameters have been overriden
|
|
|
+/// by the assignment operation.
|
|
|
+///
|
|
|
+/// @tparam OptionType Option4ClientFqdn or Option6ClientFqdn.
|
|
|
template<typename OptionType>
|
|
|
void testOptionClientFqdn(const OpType& op_type,
|
|
|
boost::shared_ptr<OptionType>& option,
|
|
|
boost::shared_ptr<OptionType>& option_copy) {
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the values in the original option.
|
|
|
option->setDomainName("newname", OptionType::PARTIAL);
|
|
|
option->setFlag(OptionType::FLAG_S, false);
|
|
|
option->setFlag(OptionType::FLAG_N, true);
|
|
|
|
|
|
+ // Rcode is carried on the in the DHCPv4 Client FQDN option.
|
|
|
+ // If the OptionType is pointing to a DHCPv6 option the dynamic
|
|
|
+ // cast will result in NULL pointer and we'll not check the
|
|
|
+ // RCODE.
|
|
|
Option4ClientFqdnPtr option4 =
|
|
|
boost::dynamic_pointer_cast<Option4ClientFqdn>(option);
|
|
|
if (option4) {
|
|
|
option4->setRcode(64);
|
|
|
}
|
|
|
|
|
|
+ // Verify that common parameters haven't been modified in the
|
|
|
+ // copied option by the change in the original option.
|
|
|
EXPECT_EQ("myname.example.org.", option_copy->getDomainName());
|
|
|
EXPECT_EQ(OptionType::FULL, option_copy->getDomainNameType());
|
|
|
EXPECT_TRUE(option_copy->getFlag(OptionType::FLAG_S));
|
|
|
EXPECT_FALSE(option_copy->getFlag(OptionType::FLAG_N));
|
|
|
|
|
|
+ // If we're dealing with DHCPv4 Client FQDN, we also need to
|
|
|
+ // test RCODE.
|
|
|
Option4ClientFqdnPtr option_copy4 =
|
|
|
boost::dynamic_pointer_cast<Option4ClientFqdn>(option_copy);
|
|
|
if (option_copy4) {
|
|
@@ -473,6 +644,9 @@ void testOptionClientFqdn(const OpType& op_type,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/// @brief Test deep copy of option encapsualated by Option4ClientFqdn type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOption4ClientFqdn(const OpType& op_type) {
|
|
|
Option4ClientFqdnPtr
|
|
|
option(new Option4ClientFqdn(Option4ClientFqdn::FLAG_S,
|
|
@@ -499,6 +673,11 @@ TEST(OptionCopyTest, option4ClientFqdnAssignment) {
|
|
|
testOption4ClientFqdn(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// ************************** Option6ClientFqdn ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by Option6ClientFqdn type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOption6ClientFqdn(const OpType& op_type) {
|
|
|
Option6ClientFqdnPtr
|
|
|
option(new Option6ClientFqdn(Option6ClientFqdn::FLAG_S,
|
|
@@ -523,15 +702,34 @@ TEST(OptionCopyTest, option6ClientFqdnAssignment) {
|
|
|
testOption6ClientFqdn(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// **************************** OptionCustom ***************************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by OptionCustom type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOptionCustom(const OpType& op_type) {
|
|
|
+ // Create option with a single field carrying 16-bits integer.
|
|
|
OptionDefinition def("foo", 1, "uint16", true);
|
|
|
OptionCustomPtr option(new OptionCustom(def, Option::V4));
|
|
|
- OptionDefinition def_assigned("bar", 10, "record");
|
|
|
- def_assigned.addRecordField("ipv4-address");
|
|
|
- def_assigned.addRecordField("uint32");
|
|
|
- OptionCustomPtr option_copy(new OptionCustom(def_assigned, Option::V6));
|
|
|
+ option->addArrayDataField<uint16_t>(5555);
|
|
|
+
|
|
|
+ // Create option with two fields carrying IPv4 address and 32-bit
|
|
|
+ // integer.
|
|
|
+ OptionDefinition def_copy("bar", 10, "record");
|
|
|
+ def_copy.addRecordField("ipv4-address");
|
|
|
+ def_copy.addRecordField("uint32");
|
|
|
+ OptionCustomPtr option_copy(new OptionCustom(def_copy, Option::V6));
|
|
|
+ option_copy->writeAddress(IOAddress("192.0.0.2"));
|
|
|
+ option_copy->writeInteger<uint32_t>(12, 1);
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
+
|
|
|
+ // Modify the original option value.
|
|
|
+ option->writeInteger<uint16_t>(1000);
|
|
|
+
|
|
|
+ // The copied option should not be affected.
|
|
|
+ ASSERT_EQ(1, option_copy->getDataFieldsNum());
|
|
|
+ EXPECT_EQ(5555, option_copy->readInteger<uint16_t>());
|
|
|
}
|
|
|
|
|
|
TEST(OptionCopyTest, optionCustomConstructor) {
|
|
@@ -546,6 +744,11 @@ TEST(OptionCopyTest, optionCustomAssignment) {
|
|
|
testOptionCustom(ASSIGN);
|
|
|
}
|
|
|
|
|
|
+// ************************ OptionOpaqueDataTuples ***********************
|
|
|
+
|
|
|
+/// @brief Test deep copy of option encapsualated by OptionOpaqueDataTuples type.
|
|
|
+///
|
|
|
+/// @param op_type Copy operation type.
|
|
|
void testOptionOpaqueDataTuples(const OpType& op_type) {
|
|
|
OptionOpaqueDataTuplesPtr option(new OptionOpaqueDataTuples(Option::V4, 1));
|
|
|
OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
|
|
@@ -560,11 +763,13 @@ void testOptionOpaqueDataTuples(const OpType& op_type) {
|
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(testCopyAssign(op_type, option, option_copy));
|
|
|
|
|
|
+ // Modify the value in the first tuple and add one more tuple.
|
|
|
tuple = "modified-first-tuple";
|
|
|
option->setTuple(0, tuple);
|
|
|
tuple = "modified-second-tuple";
|
|
|
- option->addTuple(tuple);
|
|
|
+ option->setTuple(1, tuple);
|
|
|
|
|
|
+ // This should not affect the values in the original option.
|
|
|
ASSERT_EQ(2, option_copy->getTuplesNum());
|
|
|
EXPECT_TRUE(option_copy->getTuple(0).equals("a string"));
|
|
|
EXPECT_TRUE(option_copy->getTuple(1).equals("another string"));
|