mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-02 15:05:16 +00:00
[#939] Adding more unit tests
Also removing OutOfRange check from OptionOpaqueDataTuples#unpack(begin, end). Also updating AUTHORS and the ChangeLog.
This commit is contained in:
2
AUTHORS
2
AUTHORS
@@ -31,7 +31,7 @@ Primary developers:
|
|||||||
- Slawek Figiel (documentation)
|
- Slawek Figiel (documentation)
|
||||||
- Dan Theisen (documentation, option handling, shell scripts)
|
- Dan Theisen (documentation, option handling, shell scripts)
|
||||||
- Marcin Godzina (documentation, release engineering, testing)
|
- Marcin Godzina (documentation, release engineering, testing)
|
||||||
- Piotrek Zadroga (documentation)
|
- Piotrek Zadroga (documentation, options handling)
|
||||||
|
|
||||||
Former developers who are no longer active:
|
Former developers who are no longer active:
|
||||||
- Stephen Morris (Hooks, MySQL)
|
- Stephen Morris (Hooks, MySQL)
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
2116. [func] piotrek
|
||||||
|
Added support of Secure Zero Touch Provisioning options as per
|
||||||
|
RFC8572. Kea can now handle DHCPv4 Option code #143 and DHCPv6
|
||||||
|
Option code #136.
|
||||||
|
|
||||||
2115. [func] tmark
|
2115. [func] tmark
|
||||||
Added the parameter, offer-lifetime, to kea-dhcp4. When
|
Added the parameter, offer-lifetime, to kea-dhcp4. When
|
||||||
greater than zero, the server temporarily allocates and
|
greater than zero, the server temporarily allocates and
|
||||||
|
@@ -55,10 +55,9 @@ OptionOpaqueDataTuples::pack(isc::util::OutputBuffer& buf, bool check) const {
|
|||||||
void
|
void
|
||||||
OptionOpaqueDataTuples::unpack(OptionBufferConstIter begin,
|
OptionOpaqueDataTuples::unpack(OptionBufferConstIter begin,
|
||||||
OptionBufferConstIter end) {
|
OptionBufferConstIter end) {
|
||||||
if (std::distance(begin, end) < getMinimalLength() - getHeaderLen()) {
|
// We are skipping typical OutOfRange check for Option#unpack(begin, end),
|
||||||
isc_throw(OutOfRange, "parsed data tuples option data truncated to"
|
// since empty collection of tuples is also a valid case where
|
||||||
" size " << std::distance(begin, end));
|
// std::distance(begin, end) = 0
|
||||||
}
|
|
||||||
|
|
||||||
// Start reading opaque data.
|
// Start reading opaque data.
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
@@ -149,13 +149,6 @@ private:
|
|||||||
/// @brief length of the field which holds he size of the tuple.
|
/// @brief length of the field which holds he size of the tuple.
|
||||||
OpaqueDataTuple::LengthFieldType length_field_type_;
|
OpaqueDataTuple::LengthFieldType length_field_type_;
|
||||||
|
|
||||||
/// @brief Returns minimal length of the option for the given universe.
|
|
||||||
/// Currently this class is only used for a DHCPv6 option it may be expanded
|
|
||||||
/// for DHCPv4 in the future.
|
|
||||||
uint16_t getMinimalLength() const {
|
|
||||||
return (4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Collection of opaque data tuples carried by the option.
|
/// @brief Collection of opaque data tuples carried by the option.
|
||||||
TuplesCollection tuples_;
|
TuplesCollection tuples_;
|
||||||
|
|
||||||
|
@@ -17,6 +17,16 @@ using namespace isc::util;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
// This test checks that the DHCPv4 option constructor sets the default
|
||||||
|
// properties to the expected values.
|
||||||
|
TEST(OptionOpaqueDataTuples, constructor4) {
|
||||||
|
OptionOpaqueDataTuples data_tuple(Option::V4, 200);
|
||||||
|
// Option length is 1 byte for option code + 1 byte for option size
|
||||||
|
EXPECT_EQ(2, data_tuple.len());
|
||||||
|
// There should be no tuples.
|
||||||
|
EXPECT_EQ(0, data_tuple.getTuplesNum());
|
||||||
|
}
|
||||||
|
|
||||||
// This test checks that the DHCPv6 option constructor sets the default
|
// This test checks that the DHCPv6 option constructor sets the default
|
||||||
// properties to the expected values.
|
// properties to the expected values.
|
||||||
TEST(OptionOpaqueDataTuples, constructor6) {
|
TEST(OptionOpaqueDataTuples, constructor6) {
|
||||||
@@ -98,6 +108,23 @@ TEST(OptionOpaqueDataTuples, setTuple) {
|
|||||||
EXPECT_THROW(data_tuple.setTuple(2, tuple), isc::OutOfRange);
|
EXPECT_THROW(data_tuple.setTuple(2, tuple), isc::OutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the returned length of the DHCPv4 option is correct.
|
||||||
|
TEST(OptionOpaqueDataTuples, len4) {
|
||||||
|
OptionOpaqueDataTuples data_tuple(Option::V4, 200);
|
||||||
|
ASSERT_EQ(2, data_tuple.len());
|
||||||
|
// Add first tuple.
|
||||||
|
OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
|
||||||
|
tuple = "xyz";
|
||||||
|
ASSERT_NO_THROW(data_tuple.addTuple(tuple));
|
||||||
|
// The total length grows by 1 byte of the length field and 3 bytes
|
||||||
|
// consumed by 'xyz'.
|
||||||
|
EXPECT_EQ(6, data_tuple.len());
|
||||||
|
// Add another tuple and check that the total size gets increased.
|
||||||
|
tuple = "abc";
|
||||||
|
data_tuple.addTuple(tuple);
|
||||||
|
EXPECT_EQ(10, data_tuple.len());
|
||||||
|
}
|
||||||
|
|
||||||
// Check that the returned length of the DHCPv4 option is correct when
|
// Check that the returned length of the DHCPv4 option is correct when
|
||||||
// LTF is passed explicitly in constructor.
|
// LTF is passed explicitly in constructor.
|
||||||
TEST(OptionOpaqueDataTuples, len4_constructor_with_ltf) {
|
TEST(OptionOpaqueDataTuples, len4_constructor_with_ltf) {
|
||||||
@@ -134,6 +161,71 @@ TEST(OptionOpaqueDataTuples, len6) {
|
|||||||
EXPECT_EQ(14, data_tuple.len());
|
EXPECT_EQ(14, data_tuple.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the DHCPv4 option is rendered to the buffer in wire format.
|
||||||
|
TEST(OptionOpaqueDataTuples, pack4) {
|
||||||
|
OptionOpaqueDataTuples data_tuple(Option::V4, 200);
|
||||||
|
ASSERT_EQ(0, data_tuple.getTuplesNum());
|
||||||
|
// Add tuple.
|
||||||
|
OpaqueDataTuple tuple(OpaqueDataTuple::LENGTH_1_BYTE);
|
||||||
|
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(18, buf.getLength());
|
||||||
|
|
||||||
|
// Prepare reference data.
|
||||||
|
const uint8_t ref[] = {
|
||||||
|
0xC8, 0x10, // option 200, length 16
|
||||||
|
0x0B, // tuple length is 11
|
||||||
|
0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
|
||||||
|
0x77, 0x6F, 0x72, 0x6C, 0x64, // world
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the DHCPv4 option is rendered to the buffer in wire format,
|
||||||
|
// when tuple's length field is coded on 2 octets.
|
||||||
|
TEST(OptionOpaqueDataTuples, pack4_with_ltf) {
|
||||||
|
OptionOpaqueDataTuples data_tuple(Option::V4, 143, OpaqueDataTuple::LENGTH_2_BYTES);
|
||||||
|
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(20, buf.getLength());
|
||||||
|
|
||||||
|
// Prepare reference data.
|
||||||
|
const uint8_t ref[] = {
|
||||||
|
0x8F, 0x12, // option 143, 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()));
|
||||||
|
}
|
||||||
|
|
||||||
// Check that the DHCPv6 option is rendered to the buffer in wire format.
|
// Check that the DHCPv6 option is rendered to the buffer in wire format.
|
||||||
TEST(OptionOpaqueDataTuples, pack6) {
|
TEST(OptionOpaqueDataTuples, pack6) {
|
||||||
OptionOpaqueDataTuples data_tuple(Option::V6, 60);
|
OptionOpaqueDataTuples data_tuple(Option::V6, 60);
|
||||||
@@ -166,6 +258,33 @@ TEST(OptionOpaqueDataTuples, pack6) {
|
|||||||
buf.getLength()));
|
buf.getLength()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function checks that the DHCPv4 option with two opaque data tuples
|
||||||
|
// is parsed correctly.
|
||||||
|
TEST(OptionOpaqueDataTuples, unpack4) {
|
||||||
|
// Prepare data to decode.
|
||||||
|
const uint8_t buf_data[] = {
|
||||||
|
0x0B, // tuple length is 11
|
||||||
|
0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, // Hello<space>
|
||||||
|
0x77, 0x6F, 0x72, 0x6C, 0x64, // world
|
||||||
|
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::V4,
|
||||||
|
143,
|
||||||
|
buf.begin(),
|
||||||
|
buf.end()));
|
||||||
|
);
|
||||||
|
EXPECT_EQ(DHO_V4_SZTP_REDIRECT, 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 function checks that the DHCPv4 option with two opaque data tuples
|
// This function checks that the DHCPv4 option with two opaque data tuples
|
||||||
// is parsed correctly. Tuple's LTF is passed explicitly in constructor.
|
// is parsed correctly. Tuple's LTF is passed explicitly in constructor.
|
||||||
TEST(OptionOpaqueDataTuples, unpack4_constructor_with_ltf) {
|
TEST(OptionOpaqueDataTuples, unpack4_constructor_with_ltf) {
|
||||||
@@ -220,6 +339,46 @@ TEST(OptionOpaqueDataTuples, unpack6) {
|
|||||||
EXPECT_EQ("foo", data_tuple->getTuple(1).getText());
|
EXPECT_EQ("foo", data_tuple->getTuple(1).getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test checks that the DHCPv4 option with opaque data of size 0
|
||||||
|
// is correctly parsed.
|
||||||
|
TEST(OptionOpaqueDataTuples, unpack4EmptyTuple) {
|
||||||
|
// Prepare data to decode.
|
||||||
|
const uint8_t buf_data[] = {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::V4,
|
||||||
|
124,
|
||||||
|
buf.begin(),
|
||||||
|
buf.end()));
|
||||||
|
);
|
||||||
|
EXPECT_EQ(DHO_VIVCO_SUBOPTIONS, data_tuple->getType());
|
||||||
|
ASSERT_EQ(1, data_tuple->getTuplesNum());
|
||||||
|
EXPECT_TRUE(data_tuple->getTuple(0).getText().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that the DHCPv4 option with opaque data of size 0
|
||||||
|
// is correctly parsed. Tuple's LTF is passed explicitly in constructor.
|
||||||
|
TEST(OptionOpaqueDataTuples, unpack4EmptyTuple_constructor_with_ltf) {
|
||||||
|
// 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::V4,
|
||||||
|
143,
|
||||||
|
buf.begin(),
|
||||||
|
buf.end(),
|
||||||
|
OpaqueDataTuple::LENGTH_2_BYTES));
|
||||||
|
);
|
||||||
|
EXPECT_EQ(DHO_V4_SZTP_REDIRECT, data_tuple->getType());
|
||||||
|
ASSERT_EQ(1, data_tuple->getTuplesNum());
|
||||||
|
EXPECT_TRUE(data_tuple->getTuple(0).getText().empty());
|
||||||
|
}
|
||||||
|
|
||||||
// This test checks that the DHCPv6 option with opaque data of size 0
|
// This test checks that the DHCPv6 option with opaque data of size 0
|
||||||
// is correctly parsed.
|
// is correctly parsed.
|
||||||
TEST(OptionOpaqueDataTuples, unpack6EmptyTuple) {
|
TEST(OptionOpaqueDataTuples, unpack6EmptyTuple) {
|
||||||
@@ -239,6 +398,39 @@ TEST(OptionOpaqueDataTuples, unpack6EmptyTuple) {
|
|||||||
EXPECT_TRUE(data_tuple->getTuple(0).getText().empty());
|
EXPECT_TRUE(data_tuple->getTuple(0).getText().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test checks that exception is thrown when parsing truncated DHCPv4 option
|
||||||
|
TEST(OptionOpaqueDataTuples, unpack4Truncated) {
|
||||||
|
// Prepare data to decode.
|
||||||
|
const uint8_t buf_data[] = {
|
||||||
|
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::V4, 200, buf.begin(), buf.end()),
|
||||||
|
isc::dhcp::OpaqueDataTupleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that exception is thrown when parsing truncated DHCPv4 option,
|
||||||
|
// when tuple's length field is coded on 2 octets.
|
||||||
|
TEST(OptionOpaqueDataTuples, unpack4Truncated_with_ltf) {
|
||||||
|
// 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::V4,
|
||||||
|
143,
|
||||||
|
buf.begin(),
|
||||||
|
buf.end(),
|
||||||
|
OpaqueDataTuple::LENGTH_2_BYTES),
|
||||||
|
isc::dhcp::OpaqueDataTupleError);
|
||||||
|
}
|
||||||
|
|
||||||
// This test checks that exception is thrown when parsing truncated DHCPv6
|
// This test checks that exception is thrown when parsing truncated DHCPv6
|
||||||
// bootfile-param option
|
// bootfile-param option
|
||||||
TEST(OptionOpaqueDataTuples, unpack6Truncated) {
|
TEST(OptionOpaqueDataTuples, unpack6Truncated) {
|
||||||
@@ -254,6 +446,27 @@ TEST(OptionOpaqueDataTuples, unpack6Truncated) {
|
|||||||
isc::dhcp::OpaqueDataTupleError);
|
isc::dhcp::OpaqueDataTupleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test checks that the DHCPv4 option containing no opaque
|
||||||
|
// data is parsed correctly.
|
||||||
|
TEST(OptionOpaqueDataTuples, unpack4NoTuple) {
|
||||||
|
// 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::V4,
|
||||||
|
143,
|
||||||
|
buf.begin(),
|
||||||
|
buf.end(),
|
||||||
|
OpaqueDataTuple::LENGTH_2_BYTES));
|
||||||
|
);
|
||||||
|
EXPECT_EQ(DHO_V4_SZTP_REDIRECT, data_tuple->getType());
|
||||||
|
EXPECT_EQ(0, data_tuple->getTuplesNum());
|
||||||
|
}
|
||||||
|
|
||||||
// This test checks that the DHCPv6 bootfile-param option containing no opaque
|
// This test checks that the DHCPv6 bootfile-param option containing no opaque
|
||||||
// data is parsed correctly.
|
// data is parsed correctly.
|
||||||
TEST(OptionOpaqueDataTuples, unpack6NoTuple) {
|
TEST(OptionOpaqueDataTuples, unpack6NoTuple) {
|
||||||
@@ -273,6 +486,30 @@ TEST(OptionOpaqueDataTuples, unpack6NoTuple) {
|
|||||||
EXPECT_EQ(0, data_tuple->getTuplesNum());
|
EXPECT_EQ(0, data_tuple->getTuplesNum());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verifies correctness of the text representation of the DHCPv4 option.
|
||||||
|
TEST(OptionOpaqueDataTuples, toText4) {
|
||||||
|
OptionOpaqueDataTuples data_tuple(Option::V4, 143, OpaqueDataTuple::LENGTH_2_BYTES);
|
||||||
|
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=143, len=18,"
|
||||||
|
" data-len0=11, data0='Hello world',"
|
||||||
|
" data-len1=3, data1='foo'",
|
||||||
|
data_tuple.toText());
|
||||||
|
|
||||||
|
// Check that indentation works.
|
||||||
|
EXPECT_EQ(" type=143, len=18,"
|
||||||
|
" data-len0=11, data0='Hello world',"
|
||||||
|
" data-len1=3, data1='foo'",
|
||||||
|
data_tuple.toText(2));
|
||||||
|
}
|
||||||
|
|
||||||
// Verifies correctness of the text representation of the DHCPv6 option.
|
// Verifies correctness of the text representation of the DHCPv6 option.
|
||||||
TEST(OptionOpaqueDataTuples, toText6) {
|
TEST(OptionOpaqueDataTuples, toText6) {
|
||||||
OptionOpaqueDataTuples data_tuple(Option::V6, 60);
|
OptionOpaqueDataTuples data_tuple(Option::V6, 60);
|
||||||
|
Reference in New Issue
Block a user