summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc')
-rw-r--r--src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc b/src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc
new file mode 100644
index 0000000..6bbd766
--- /dev/null
+++ b/src/lib/dhcp/tests/option_opaque_data_tuples_unittest.cc
@@ -0,0 +1,253 @@
+// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <exceptions/exceptions.h>
+#include <dhcp/option_opaque_data_tuples.h>
+#include <util/buffer.h>
+#include <gtest/gtest.h>
+
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::util;
+
+namespace {
+
+// This test checks that the DHCPv6 option constructor sets the default
+// properties to the expected values.
+TEST(OptionOpaqueDataTuples, constructor6) {
+ OptionOpaqueDataTuples data_tuple(Option::V6, 60);
+ // Option length is 2 bytes for option code + 2 bytes for option size
+ EXPECT_EQ(4, data_tuple.len());
+ // There should be no tuples.
+ EXPECT_EQ(0, data_tuple.getTuplesNum());
+}
+
+// This test verifies that it is possible to append the opaque data tuple
+// to the option and then retrieve it.
+TEST(OptionOpaqueDataTuples, addTuple) {
+ OptionOpaqueDataTuples data_tuple(Option::V6, 60);
+ // Initially there should be no tuples (for DHCPv6).
+ ASSERT_EQ(0, data_tuple.getTuplesNum());
+ // Create a new tuple and add it to the option.
+ OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
+ tuple = "xyz";
+ data_tuple.addTuple(tuple);
+ // The option should now hold one tuple.
+ ASSERT_EQ(1, data_tuple.getTuplesNum());
+ EXPECT_EQ("xyz", data_tuple.getTuple(0).getText());
+ // Add another tuple.
+ tuple = "abc";
+ data_tuple.addTuple(tuple);
+ // The option should now hold exactly two tuples in the order in which
+ // they were added.
+ ASSERT_EQ(2, data_tuple.getTuplesNum());
+ EXPECT_EQ("xyz", data_tuple.getTuple(0).getText());
+ EXPECT_EQ("abc", data_tuple.getTuple(1).getText());
+
+ // Check that hasTuple correctly identifies existing tuples.
+ EXPECT_TRUE(data_tuple.hasTuple("xyz"));
+ EXPECT_TRUE(data_tuple.hasTuple("abc"));
+ EXPECT_FALSE(data_tuple.hasTuple("other"));
+
+ // Attempt to add the tuple with 1 byte long length field should fail
+ // for DHCPv6 option.
+ OpaqueDataTuple tuple2(OpaqueDataTuple::LENGTH_1_BYTE);
+ EXPECT_THROW(data_tuple.addTuple(tuple2), isc::BadValue);
+
+ // Similarly, adding a tuple with 2 bytes long length field should
+ // fail for DHCPv4 option.
+ OptionOpaqueDataTuples data_tuple2(Option::V4, 65);
+ OpaqueDataTuple tuple3(OpaqueDataTuple::LENGTH_2_BYTES);
+ EXPECT_THROW(data_tuple2.addTuple(tuple3), isc::BadValue);
+}
+
+// This test checks that it is possible to replace existing tuple.
+TEST(OptionOpaqueDataTuples, setTuple) {
+ OptionOpaqueDataTuples data_tuple(Option::V6, 60);
+ // Initially there should be no tuples (for DHCPv6).
+ ASSERT_EQ(0, data_tuple.getTuplesNum());
+ // Add a tuple
+ OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
+ tuple = "xyz";
+ data_tuple.addTuple(tuple);
+
+ // Add another one.
+ tuple = "abc";
+ data_tuple.addTuple(tuple);
+ ASSERT_EQ(2, data_tuple.getTuplesNum());
+ ASSERT_EQ("abc", data_tuple.getTuple(1).getText());
+
+ // Try to replace them with new tuples.
+ tuple = "new_xyz";
+ ASSERT_NO_THROW(data_tuple.setTuple(0, tuple));
+ ASSERT_EQ(2, data_tuple.getTuplesNum());
+ EXPECT_EQ("new_xyz", data_tuple.getTuple(0).getText());
+
+ tuple = "new_abc";
+ ASSERT_NO_THROW(data_tuple.setTuple(1, tuple));
+ ASSERT_EQ(2, data_tuple.getTuplesNum());
+ EXPECT_EQ("new_abc", data_tuple.getTuple(1).getText());
+
+ // For out of range position, exception should be thrown.
+ tuple = "foo";
+ EXPECT_THROW(data_tuple.setTuple(2, tuple), isc::OutOfRange);
+}
+
+// Check that the returned length of the DHCPv6 option is correct.
+TEST(OptionOpaqueDataTuples, len6) {
+ OptionOpaqueDataTuples data_tuple(Option::V6, 60);
+ ASSERT_EQ(4, data_tuple.len());
+ // Add first tuple.
+ OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
+ tuple = "xyz";
+ ASSERT_NO_THROW(data_tuple.addTuple(tuple));
+ // The total length grows by 2 bytes of the length field and 3 bytes
+ // consumed by 'xyz'.
+ EXPECT_EQ(9, data_tuple.len());
+ // Add another tuple and check that the total size gets increased.
+ tuple = "abc";
+ data_tuple.addTuple(tuple);
+ EXPECT_EQ(14, data_tuple.len());
+}
+
+// Check that the DHCPv6 option is rendered to the buffer in wire format.
+TEST(OptionOpaqueDataTuples, pack6) {
+ OptionOpaqueDataTuples data_tuple(Option::V6, 60);
+ ASSERT_EQ(0, data_tuple.getTuplesNum());
+ // Add tuple.
+ OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
+ tuple = "Hello world";
+ data_tuple.addTuple(tuple);
+ // And add another tuple so as resulting option is a bit more complex.
+ tuple = "foo";
+ data_tuple.addTuple(tuple);
+
+ // Render the data to the buffer.
+ OutputBuffer buf(10);
+ ASSERT_NO_THROW(data_tuple.pack(buf));
+ ASSERT_EQ(22, buf.getLength());
+
+ // Prepare reference data.
+ const uint8_t ref[] = {
+ 0x00, 0x3C, 0x00, 0x12, // option 60, length 18
+ 0x00, 0x0B, // tuple length is 11
+ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
+ 0x77, 0x6F, 0x72, 0x6C, 0x64, // world
+ 0x00, 0x03, // tuple length is 3
+ 0x66, 0x6F, 0x6F // foo
+ };
+ // Compare the buffer with reference data.
+ EXPECT_EQ(0, memcmp(static_cast<const void*>(ref),
+ static_cast<const void*>(buf.getData()),
+ buf.getLength()));
+}
+
+// This function checks that the DHCPv6 option with two opaque data tuples
+// is parsed correctly.
+TEST(OptionOpaqueDataTuples, unpack6) {
+ // Prepare data to decode.
+ const uint8_t buf_data[] = {
+ 0x00, 0x0B, // tuple length is 11
+ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
+ 0x77, 0x6F, 0x72, 0x6C, 0x64, // world
+ 0x00, 0x03, // tuple length is 3
+ 0x66, 0x6F, 0x6F // foo
+ };
+ OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+ OptionOpaqueDataTuplesPtr data_tuple;
+ ASSERT_NO_THROW(
+ data_tuple = OptionOpaqueDataTuplesPtr(new OptionOpaqueDataTuples(Option::V6,
+ 60,
+ buf.begin(),
+ buf.end()));
+ );
+ EXPECT_EQ(D6O_BOOTFILE_PARAM, data_tuple->getType());
+ ASSERT_EQ(2, data_tuple->getTuplesNum());
+ EXPECT_EQ("Hello world", data_tuple->getTuple(0).getText());
+ EXPECT_EQ("foo", data_tuple->getTuple(1).getText());
+}
+
+// This test checks that the DHCPv6 option with opaque data of size 0
+// is correctly parsed.
+TEST(OptionOpaqueDataTuples, unpack6EmptyTuple) {
+ // Prepare data to decode.
+ const uint8_t buf_data[] = {0x00, 0x00}; // tuple length is 0
+ OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+ OptionOpaqueDataTuplesPtr data_tuple;
+ ASSERT_NO_THROW(
+ data_tuple = OptionOpaqueDataTuplesPtr(new OptionOpaqueDataTuples(Option::V6,
+ 60,
+ buf.begin(),
+ buf.end()));
+ );
+ EXPECT_EQ(D6O_BOOTFILE_PARAM, data_tuple->getType());
+ ASSERT_EQ(1, data_tuple->getTuplesNum());
+ EXPECT_TRUE(data_tuple->getTuple(0).getText().empty());
+}
+
+// This test checks that exception is thrown when parsing truncated DHCPv6
+// bootfile-param option
+TEST(OptionOpaqueDataTuples, unpack6Truncated) {
+ // Prepare data to decode.
+ const uint8_t buf_data[] = {
+ 0x00, 0x0B, // tuple length is 11
+ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
+ 0x77, 0x6F, 0x72, 0x6C // worl (truncated d!)
+ };
+ OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+ EXPECT_THROW(OptionOpaqueDataTuples (Option::V6, 60, buf.begin(), buf.end()),
+ isc::dhcp::OpaqueDataTupleError);
+}
+
+// This test checks that the DHCPv6 bootfile-param option containing no opaque
+// data is parsed correctly.
+TEST(OptionOpaqueDataTuples, unpack6NoTuple) {
+ // Prepare data to decode.
+ const uint8_t buf_data[] = {
+ };
+ OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+
+ OptionOpaqueDataTuplesPtr data_tuple;
+ ASSERT_NO_THROW(
+ data_tuple = OptionOpaqueDataTuplesPtr(new OptionOpaqueDataTuples(Option::V6,
+ 60,
+ buf.begin(),
+ buf.end()));
+ );
+ EXPECT_EQ(D6O_BOOTFILE_PARAM, data_tuple->getType());
+ EXPECT_EQ(0, data_tuple->getTuplesNum());
+}
+
+// Verifies correctness of the text representation of the DHCPv6 option.
+TEST(OptionOpaqueDataTuples, toText6) {
+ OptionOpaqueDataTuples data_tuple(Option::V6, 60);
+ ASSERT_EQ(0, data_tuple.getTuplesNum());
+ // Lets add a tuple
+ OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_2_BYTES);
+ tuple = "Hello world";
+ data_tuple.addTuple(tuple);
+ // And add another tuple so as resulting option is a bit more complex.
+ tuple = "foo";
+ data_tuple.addTuple(tuple);
+ // Check that the text representation of the option is as expected.
+ EXPECT_EQ("type=60, len=18,"
+ " data-len0=11, data0='Hello world',"
+ " data-len1=3, data1='foo'",
+ data_tuple.toText());
+
+ // Check that indentation works.
+ EXPECT_EQ(" type=60, len=18,"
+ " data-len0=11, data0='Hello world',"
+ " data-len1=3, data1='foo'",
+ data_tuple.toText(2));
+}
+
+} // end of anonymous namespace