diff options
author | Stephen Morris <stephen@isc.org> | 2014-07-30 18:15:45 +0200 |
---|---|---|
committer | Stephen Morris <stephen@isc.org> | 2014-07-30 18:15:45 +0200 |
commit | 1c76dae79952d245d83a3536f7fb2cb3550c2476 (patch) | |
tree | fbdcee4dee2689d0e75b22a6d6f3901b53188a8a /src/bin/perfdhcp/tests/perf_pkt6_unittest.cc | |
parent | [master] Merge branch 'trac3459' (diff) | |
download | kea-1c76dae79952d245d83a3536f7fb2cb3550c2476.tar.xz kea-1c76dae79952d245d83a3536f7fb2cb3550c2476.zip |
[3481] Move perfdhcp source to src/bin/perfdhcp
Also modifiy Makefiles to install perfdhcp into sbin.
Diffstat (limited to 'src/bin/perfdhcp/tests/perf_pkt6_unittest.cc')
-rw-r--r-- | src/bin/perfdhcp/tests/perf_pkt6_unittest.cc | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/src/bin/perfdhcp/tests/perf_pkt6_unittest.cc b/src/bin/perfdhcp/tests/perf_pkt6_unittest.cc new file mode 100644 index 0000000000..02c009ecc4 --- /dev/null +++ b/src/bin/perfdhcp/tests/perf_pkt6_unittest.cc @@ -0,0 +1,327 @@ +// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include <config.h> +#include <iostream> +#include <sstream> +#include <arpa/inet.h> +#include <gtest/gtest.h> + +#include <asiolink/io_address.h> +#include <dhcp/option.h> +#include <dhcp/dhcp6.h> + +#include "../localized_option.h" +#include "../perf_pkt6.h" + +using namespace std; +using namespace isc; +using namespace isc::dhcp; +using namespace isc::perfdhcp; + +typedef PerfPkt6::LocalizedOptionPtr LocalizedOptionPtr; + +namespace { + +class PerfPkt6Test : public ::testing::Test { +public: + PerfPkt6Test() { + } + + /// \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), + /// but we spent some time to make is less ugly than it used to be. + /// + /// \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; + 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; + data[17] = 30; data[18] = 140; data[19] = 155; data[20] = 115; + data[21] = 73; data[22] = 0; data[23] = 3; data[24] = 0; + data[25] = 40; data[26] = 0; data[27] = 0; data[28] = 0; + data[29] = 1; data[30] = 255; data[31] = 255; data[32] = 255; + data[33] = 255; data[34] = 255; data[35] = 255; data[36] = 255; + data[37] = 255; data[38] = 0; data[39] = 5; data[40] = 0; + data[41] = 24; data[42] = 32; data[43] = 1; data[44] = 13; + data[45] = 184; data[46] = 0; data[47] = 1; data[48] = 0; + data[49] = 0; data[50] = 0; data[51] = 0; data[52] = 0; + data[53] = 0; data[54] = 0; data[55] = 0; data[56] = 18; + data[57] = 52; data[58] = 255; data[59] = 255; data[60] = 255; + data[61] = 255; data[62] = 255; data[63] = 255; data[64] = 255; + data[65] = 255; data[66] = 0; data[67] = 23; data[68] = 0; + data[69] = 16; data[70] = 32; data[71] = 1; data[72] = 13; + data[73] = 184; data[74] = 0; data[75] = 1; data[76] = 0; + data[77] = 0; data[78] = 0; data[79] = 0; data[80] = 0; + data[81] = 0; data[82] = 0; data[83] = 0; data[84] = 221; + data[85] = 221; data[86] = 0; data[87] = 8; data[88] = 0; + data[89] = 2; data[90] = 0; data[91] = 100; data[92] = 0; + data[93] = 6; data[94] = 0; data[95] = 2; data[96] = 0; + data[97] = 23; + + PerfPkt6* pkt = new PerfPkt6(data, sizeof(data)); + + 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)); + + return (pkt); + } + + +}; + +TEST_F(PerfPkt6Test, Constructor) { + // Data to be used to create packet. + uint8_t data[] = { 0, 1, 2, 3, 4, 5 }; + + // 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))); + EXPECT_EQ(sizeof(data), pkt1->data_.size()); + EXPECT_EQ(0, memcmp(&pkt1->data_[0], data, sizeof(data))); + EXPECT_EQ(1, pkt1->getTransidOffset()); + + // Test constructor to be used for outgoing messages. + // Use non-zero offset and specify transaction id. + const size_t offset_transid = 10; + const uint32_t transid = 0x010203; + boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data, sizeof(data), + offset_transid, transid)); + EXPECT_EQ(sizeof(data), pkt2->data_.size()); + EXPECT_EQ(0, memcmp(&pkt2->data_[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(capture()); + + // Create some input buffers to initialize options. + uint8_t buf_elapsed_time[] = { 1, 1 }; + uint8_t buf_duid[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; + + // Create options. + const size_t offset_elapsed_time = 86; + OptionBuffer vec_elapsed_time(buf_elapsed_time, + buf_elapsed_time + sizeof(buf_elapsed_time)); + LocalizedOptionPtr pkt1_elapsed_time(new LocalizedOption(Option::V6, + D6O_ELAPSED_TIME, + vec_elapsed_time, + offset_elapsed_time)); + const size_t offset_duid = 4; + OptionBuffer vec_duid(buf_duid, buf_duid + sizeof(buf_duid)); + LocalizedOptionPtr pkt1_duid(new LocalizedOption(Option::V6, + D6O_CLIENTID, + vec_duid, + offset_duid)); + + // Add option to packet and create on-wire format from added options. + // Contents of options will override contents of packet buffer. + ASSERT_NO_THROW(pkt1->addOption(pkt1_elapsed_time)); + ASSERT_NO_THROW(pkt1->addOption(pkt1_duid)); + ASSERT_TRUE(pkt1->rawPack()); + + // Reset so as we can reuse them for another packet. + vec_elapsed_time.clear(); + vec_duid.clear(); + + // Get output buffer from packet 1 to create new packet + // that will be later validated. + util::OutputBuffer pkt1_output = pkt1->getBuffer(); + ASSERT_EQ(pkt1_output.getLength(), pkt1->data_.size()); + 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())); + + // 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, + offset_elapsed_time)); + LocalizedOptionPtr pkt2_duid(new LocalizedOption(Option::V6, + D6O_CLIENTID, + vec_duid, + offset_duid)); + // Add options to packet to pass their offsets. + pkt2->addOption(pkt2_elapsed_time); + pkt2->addOption(pkt2_duid); + + // Unpack: get relevant parts of buffer data into option objects. + 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)); + + // Check if options are present. They have to be there since + // we have added them ourselfs. + ASSERT_TRUE(pkt2_elapsed_time); + ASSERT_TRUE(pkt2_duid); + + // Expecting option contents be the same as original. + 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)); +} + +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) + const size_t offset_serverid[] = { 150, 85 }; + LocalizedOptionPtr pkt1_serverid(new LocalizedOption(Option::V6, + D6O_SERVERID, + vec_server_id, + offset_serverid[0])); + 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, + offset_serverid[1])); + 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); + const size_t offset_duid = 4; + LocalizedOptionPtr pkt1_duid(new LocalizedOption(Option::V6, + D6O_CLIENTID, + vec_duid, + offset_duid)); + 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]; + memset(&data, 0, sizeof(data)); + + const size_t offset_transid[] = { 50, 100 }; + const uint32_t transid = 0x010203; + + // Create dummy packet that is simply filled with zeros. + boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data, + sizeof(data), + offset_transid[0], + transid)); + + // 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 + offset_transid[0], ref_data, 3)); + + + // Out of bounds transaction id offset. + boost::scoped_ptr<PerfPkt6> pkt2(new PerfPkt6(data, + sizeof(data), + offset_transid[1], + transid)); + 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. + const size_t offset_transid[] = { 50, 300 }; + boost::scoped_ptr<PerfPkt6> pkt1(new PerfPkt6(data, + sizeof(data), + offset_transid[0])); + + // 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), + offset_transid[1])); + cout << "Testing out of bounds offset. " + "This may produce spurious errors ..." << endl; + EXPECT_FALSE(pkt2->rawUnpack()); + +} + +} |