|
@@ -33,20 +33,22 @@ using namespace isc::perfdhcp;
|
|
|
typedef PerfPkt6::LocalizedOptionPtr LocalizedOptionPtr;
|
|
|
|
|
|
namespace {
|
|
|
+
|
|
|
class PerfPkt6Test : public ::testing::Test {
|
|
|
public:
|
|
|
PerfPkt6Test() {
|
|
|
}
|
|
|
|
|
|
- /// @brief returns captured actual SOLICIT packet
|
|
|
+ /// \brief Returns captured SOLICIT packet.
|
|
|
///
|
|
|
/// Captured SOLICIT packet with transid=0x3d79fb and options: client-id,
|
|
|
/// in_na, dns-server, elapsed-time, option-request
|
|
|
- /// This code was autogenerated (see src/bin/dhcp6/tests/iface_mgr_unittest.c),
|
|
|
+ /// This code was autogenerated
|
|
|
+ /// (see src/bin/dhcp6/tests/iface_mgr_unittest.c),
|
|
|
/// but we spent some time to make is less ugly than it used to be.
|
|
|
///
|
|
|
- /// @return pointer to Pkt6 that represents received SOLICIT
|
|
|
- PerfPkt6* capture1() {
|
|
|
+ /// \return pointer to Pkt6 that represents received SOLICIT
|
|
|
+ PerfPkt6* capture() {
|
|
|
uint8_t data[98];
|
|
|
data[0] = 1;
|
|
|
data[1] = 1; data[2] = 2; data[3] = 3; data[4] = 0;
|
|
@@ -75,40 +77,86 @@ public:
|
|
|
data[93] = 6; data[94] = 0; data[95] = 2; data[96] = 0;
|
|
|
data[97] = 23;
|
|
|
|
|
|
- PerfPkt6* pkt = new PerfPkt6(data, sizeof(data), 0);
|
|
|
+ PerfPkt6* pkt = new PerfPkt6(data, sizeof(data),
|
|
|
+ 0x1, PerfPkt6::Offset());
|
|
|
+
|
|
|
+ return (pkt);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// \brief Returns truncated SOLICIT packet.
|
|
|
+ ///
|
|
|
+ /// Returns truncated SOLICIT packet which will be used for
|
|
|
+ /// negative tests: e.g. pack options out of packet.
|
|
|
+ ///
|
|
|
+ /// \return pointer to Pkt6 that represents truncated SOLICIT
|
|
|
+ PerfPkt6* captureTruncated() {
|
|
|
+ uint8_t data[17];
|
|
|
+ data[0] = 1;
|
|
|
+ data[1] = 1; data[2] = 2; data[3] = 3; data[4] = 0;
|
|
|
+ data[5] = 1; data[6] = 0; data[7] = 14; data[8] = 0;
|
|
|
+ data[9] = 1; data[10] = 0; data[11] = 1; data[12] = 21;
|
|
|
+ data[13] = 158; data[14] = 60; data[15] = 22; data[16] = 0;
|
|
|
+
|
|
|
+ PerfPkt6* pkt = new PerfPkt6(data, sizeof(data),
|
|
|
+ 0x1, PerfPkt6::Offset());
|
|
|
|
|
|
return (pkt);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
};
|
|
|
|
|
|
TEST_F(PerfPkt6Test, Constructor) {
|
|
|
+ // Data to be used to create packet.
|
|
|
uint8_t data[] = { 0, 1, 2, 3, 4, 5 };
|
|
|
- timespec zero_t_spec;
|
|
|
- memset(&zero_t_spec, 0, sizeof(zero_t_spec));
|
|
|
|
|
|
- boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data, sizeof(data), 1));
|
|
|
- timespec packet_t_spec = pkt1->getTimestamp();
|
|
|
+ // Test constructors of Offset class.
|
|
|
+ PerfPkt6::Offset of1(0);
|
|
|
+ EXPECT_EQ(0, of1.get());
|
|
|
+
|
|
|
+ PerfPkt6::Offset of2;
|
|
|
+ EXPECT_EQ(1, of2.get());
|
|
|
|
|
|
+ PerfPkt6::Offset of3(10);
|
|
|
+ EXPECT_EQ(10, of3.get());
|
|
|
+
|
|
|
+ // Test constructor to be used for incoming messages.
|
|
|
+ // Use default (1) offset value and don't specify transaction id.
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data, sizeof(data),
|
|
|
+ PerfPkt6::Offset()));
|
|
|
EXPECT_EQ(6, pkt1->getData().size());
|
|
|
- EXPECT_EQ(0, memcmp( &pkt1->getData()[0], data, sizeof(data)));
|
|
|
+ EXPECT_EQ(0, memcmp(&pkt1->getData()[0], data, sizeof(data)));
|
|
|
EXPECT_EQ(1, pkt1->getTransIdOffset());
|
|
|
- EXPECT_EQ(0, memcmp(&packet_t_spec, &zero_t_spec, sizeof(zero_t_spec)));
|
|
|
+
|
|
|
+ // Test constructor to be used for outgoing messages.
|
|
|
+ // Use non-zero offset and specify transaction id.
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data, sizeof(data), 0x010203,
|
|
|
+ PerfPkt6::Offset(10)));
|
|
|
+ EXPECT_EQ(6, pkt2->getData().size());
|
|
|
+ EXPECT_EQ(0, memcmp(&pkt2->getData()[0], data, sizeof(data)));
|
|
|
+ EXPECT_EQ(0x010203, pkt2->getTransid());
|
|
|
+ EXPECT_EQ(10, pkt2->getTransIdOffset());
|
|
|
}
|
|
|
|
|
|
TEST_F(PerfPkt6Test, RawPackUnpack) {
|
|
|
// Create first packet.
|
|
|
- boost::scoped_ptr<PerfPkt6> pkt1(capture1());
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt1(capture());
|
|
|
|
|
|
// Create some input buffers to initialize options.
|
|
|
uint8_t buf_elapsed_time[] = { 1, 1 };
|
|
|
uint8_t buf_duid[14] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
|
|
|
|
|
|
// Create options.
|
|
|
- dhcp::OptionBuffer vec_elapsed_time(buf_elapsed_time, buf_elapsed_time + 2);
|
|
|
- dhcp::OptionBuffer vec_duid(buf_duid, buf_duid + 14);
|
|
|
- LocalizedOptionPtr pkt1_elapsed_time(new LocalizedOption(Option::V6, 8, vec_elapsed_time, 86));
|
|
|
- LocalizedOptionPtr pkt1_duid(new LocalizedOption(Option::V6, D6O_CLIENTID, vec_duid, 4));
|
|
|
+ OptionBuffer vec_elapsed_time(buf_elapsed_time, buf_elapsed_time + 2);
|
|
|
+ OptionBuffer vec_duid(buf_duid, buf_duid + 14);
|
|
|
+ LocalizedOptionPtr pkt1_elapsed_time(new LocalizedOption(Option::V6,
|
|
|
+ D6O_ELAPSED_TIME,
|
|
|
+ vec_elapsed_time,
|
|
|
+ 86));
|
|
|
+ LocalizedOptionPtr pkt1_duid(new LocalizedOption(Option::V6,
|
|
|
+ D6O_CLIENTID,
|
|
|
+ vec_duid,
|
|
|
+ 4));
|
|
|
|
|
|
// Add option to packet and create on-wire format from added options.
|
|
|
// Contents of options will override contents of packet buffer.
|
|
@@ -120,17 +168,26 @@ TEST_F(PerfPkt6Test, RawPackUnpack) {
|
|
|
vec_elapsed_time.clear();
|
|
|
vec_duid.clear();
|
|
|
|
|
|
- // Get output buffer from packet 1 to create new packet
|
|
|
+ // Get output buffer from packet 1 to create new packet
|
|
|
// that will be later validated.
|
|
|
- isc::util::OutputBuffer pkt1_output = pkt1->getBuffer();
|
|
|
+ util::OutputBuffer pkt1_output = pkt1->getBuffer();
|
|
|
ASSERT_EQ(pkt1_output.getLength(), pkt1->getData().size());
|
|
|
- boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(static_cast<const uint8_t*>(pkt1_output.getData()),
|
|
|
- pkt1_output.getLength(), 1));
|
|
|
+ const uint8_t* pkt1_output_data = static_cast<const uint8_t*>
|
|
|
+ (pkt1_output.getData());
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(pkt1_output_data,
|
|
|
+ pkt1_output.getLength(),
|
|
|
+ PerfPkt6::Offset()));
|
|
|
|
|
|
- // Create objects specifying options offset in a packet.
|
|
|
+ // Create objects specifying options offset in a packet.
|
|
|
// Offsets will inform pkt2 object where to read data from.
|
|
|
- LocalizedOptionPtr pkt2_elapsed_time(new LocalizedOption(Option::V6, D6O_ELAPSED_TIME, vec_elapsed_time, 86));
|
|
|
- LocalizedOptionPtr pkt2_duid(new LocalizedOption(Option::V6, D6O_CLIENTID, vec_duid, 4));
|
|
|
+ LocalizedOptionPtr pkt2_elapsed_time(new LocalizedOption(Option::V6,
|
|
|
+ D6O_ELAPSED_TIME,
|
|
|
+ vec_elapsed_time,
|
|
|
+ 86));
|
|
|
+ LocalizedOptionPtr pkt2_duid(new LocalizedOption(Option::V6,
|
|
|
+ D6O_CLIENTID,
|
|
|
+ vec_duid,
|
|
|
+ 4));
|
|
|
// Add options to packet to pass their offsets.
|
|
|
pkt2->addOption(pkt2_elapsed_time);
|
|
|
pkt2->addOption(pkt2_duid);
|
|
@@ -139,8 +196,10 @@ TEST_F(PerfPkt6Test, RawPackUnpack) {
|
|
|
ASSERT_TRUE(pkt2->rawUnpack());
|
|
|
|
|
|
// Once option data is stored in options objects we pull it out.
|
|
|
- pkt2_elapsed_time = boost::dynamic_pointer_cast<LocalizedOption>(pkt2->getOption(D6O_ELAPSED_TIME));
|
|
|
- pkt2_duid = boost::dynamic_pointer_cast<LocalizedOption>(pkt2->getOption(D6O_CLIENTID));
|
|
|
+ pkt2_elapsed_time = boost::dynamic_pointer_cast<LocalizedOption>
|
|
|
+ (pkt2->getOption(D6O_ELAPSED_TIME));
|
|
|
+ pkt2_duid = boost::dynamic_pointer_cast<LocalizedOption>
|
|
|
+ (pkt2->getOption(D6O_CLIENTID));
|
|
|
|
|
|
// Check if options are present. They have to be there since
|
|
|
// we have added them ourselfs.
|
|
@@ -151,7 +210,119 @@ TEST_F(PerfPkt6Test, RawPackUnpack) {
|
|
|
OptionBuffer pkt2_elapsed_time_data = pkt2_elapsed_time->getData();
|
|
|
OptionBuffer pkt2_duid_data = pkt2_duid->getData();
|
|
|
EXPECT_EQ(0x0101, pkt2_elapsed_time->getUint16());
|
|
|
- EXPECT_TRUE(std::equal(pkt2_duid_data.begin(), pkt2_duid_data.end(), buf_duid));
|
|
|
+ EXPECT_TRUE(std::equal(pkt2_duid_data.begin(),
|
|
|
+ pkt2_duid_data.end(),
|
|
|
+ buf_duid));
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(PerfPkt6Test, InvalidOptions) {
|
|
|
+ // Create packet.
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt1(capture());
|
|
|
+ OptionBuffer vec_server_id;
|
|
|
+ vec_server_id.resize(10);
|
|
|
+ // Testing invalid offset of the option (greater than packet size)
|
|
|
+ LocalizedOptionPtr pkt1_serverid(new LocalizedOption(Option::V6,
|
|
|
+ D6O_SERVERID,
|
|
|
+ vec_server_id,
|
|
|
+ 150));
|
|
|
+ pkt1->addOption(pkt1_serverid);
|
|
|
+ // Pack has to fail due to invalid offset.
|
|
|
+ EXPECT_FALSE(pkt1->rawPack());
|
|
|
+
|
|
|
+ // Create packet.
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt2(capture());
|
|
|
+ // Testing offset of the option (lower than pakcet size but
|
|
|
+ // tail of the option out of bounds).
|
|
|
+ LocalizedOptionPtr pkt2_serverid(new LocalizedOption(Option::V6,
|
|
|
+ D6O_SERVERID,
|
|
|
+ vec_server_id,
|
|
|
+ 85));
|
|
|
+ pkt2->addOption(pkt2_serverid);
|
|
|
+ // Pack must fail due to invalid offset.
|
|
|
+ EXPECT_FALSE(pkt2->rawPack());
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+TEST_F(PerfPkt6Test, TruncatedPacket) {
|
|
|
+ cout << "Testing parsing options from truncated packet."
|
|
|
+ << "This may produce spurious errors" << endl;
|
|
|
+
|
|
|
+ // Create truncated (in the middle of duid options)
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt1(captureTruncated());
|
|
|
+ OptionBuffer vec_duid;
|
|
|
+ vec_duid.resize(30);
|
|
|
+ LocalizedOptionPtr pkt1_duid(new LocalizedOption(Option::V6,
|
|
|
+ D6O_CLIENTID,
|
|
|
+ vec_duid,
|
|
|
+ 4));
|
|
|
+ pkt1->addOption(pkt1_duid);
|
|
|
+ // Pack/unpack must fail because length of the option read from buffer
|
|
|
+ // will extend over the actual packet length.
|
|
|
+ EXPECT_FALSE(pkt1->rawUnpack());
|
|
|
+ EXPECT_FALSE(pkt1->rawPack());
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(PerfPkt6Test, PackTransactionId) {
|
|
|
+ uint8_t data[100] = { 0 };
|
|
|
+
|
|
|
+ // Create dummy packet that is simply filled with zeros.
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data,
|
|
|
+ sizeof(data),
|
|
|
+ 0x010203,
|
|
|
+ PerfPkt6::Offset(50)));
|
|
|
+
|
|
|
+ // Reference data are non zero so we can detect them in dummy packet.
|
|
|
+ uint8_t ref_data[3] = { 1, 2, 3 };
|
|
|
+
|
|
|
+ // This will store given transaction id in the packet data at
|
|
|
+ // offset of 50.
|
|
|
+ ASSERT_TRUE(pkt1->rawPack());
|
|
|
+
|
|
|
+ // Get the output buffer so we can validate it.
|
|
|
+ util::OutputBuffer out_buf = pkt1->getBuffer();
|
|
|
+ ASSERT_EQ(sizeof(data), out_buf.getLength());
|
|
|
+ const uint8_t *out_buf_data = static_cast<const uint8_t*>
|
|
|
+ (out_buf.getData());
|
|
|
+
|
|
|
+ // Validate transaction id.
|
|
|
+ EXPECT_EQ(0, memcmp(out_buf_data + 50, ref_data, 3));
|
|
|
+
|
|
|
+ // Out of bounds transaction id offset.
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data,
|
|
|
+ sizeof(data),
|
|
|
+ 0x010202,
|
|
|
+ PerfPkt6::Offset(100)));
|
|
|
+ cout << "Testing out of bounds offset. "
|
|
|
+ "This may produce spurious errors ..." << endl;
|
|
|
+ EXPECT_FALSE(pkt2->rawPack());
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(PerfPkt6Test, UnpackTransactionId) {
|
|
|
+ // Initialize data for dummy packet (zeros only).
|
|
|
+ uint8_t data[100] = { 0 };
|
|
|
+
|
|
|
+ // Generate transaction id = 0x010203 and inject at offset = 50.
|
|
|
+ for (int i = 50; i < 53; ++i) {
|
|
|
+ data[i] = i - 49;
|
|
|
+ }
|
|
|
+ // Create packet and point out that transaction id is at offset 50.
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data,
|
|
|
+ sizeof(data),
|
|
|
+ PerfPkt6::Offset(50)));
|
|
|
+
|
|
|
+ // Get transaction id out of buffer and store in class member.
|
|
|
+ ASSERT_TRUE(pkt1->rawUnpack());
|
|
|
+ // Test value of transaction id.
|
|
|
+ EXPECT_EQ(0x010203, pkt1->getTransid());
|
|
|
+
|
|
|
+ // Out of bounds transaction id offset.
|
|
|
+ boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data,
|
|
|
+ sizeof(data),
|
|
|
+ PerfPkt6::Offset(300)));
|
|
|
+ cout << "Testing out of bounds offset. "
|
|
|
+ "This may produce spurious errors ..." << endl;
|
|
|
+ EXPECT_FALSE(pkt2->rawUnpack());
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|