From 81784141da4a239663f094e56a6a77643c8f81cb Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Tue, 5 Jun 2012 16:42:21 +0200 Subject: [PATCH] [1955] Added remaining unit tests for PerfPkt4 and cleaned up the code. --- tests/tools/perfdhcp/perf_pkt4.cc | 26 +- tests/tools/perfdhcp/perf_pkt4.h | 14 +- tests/tools/perfdhcp/pkt_transform.cc | 17 +- tests/tools/perfdhcp/pkt_transform.h | 44 ++- .../perfdhcp/tests/perf_pkt4_unittest.cc | 316 +++++++++--------- 5 files changed, 224 insertions(+), 193 deletions(-) diff --git a/tests/tools/perfdhcp/perf_pkt4.cc b/tests/tools/perfdhcp/perf_pkt4.cc index 0f48557a7f..6f09f29539 100644 --- a/tests/tools/perfdhcp/perf_pkt4.cc +++ b/tests/tools/perfdhcp/perf_pkt4.cc @@ -12,8 +12,6 @@ // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. -#include -#include #include #include @@ -27,22 +25,30 @@ using namespace dhcp; namespace isc { namespace perfdhcp { - PerfPkt4::PerfPkt4(const uint8_t* buf, uint32_t len, size_t transid_offset, uint32_t transid) : +PerfPkt4::PerfPkt4(const uint8_t* buf, size_t len) : + Pkt4(buf, len), + transid_offset_(1) { +} + +PerfPkt4::PerfPkt4(const uint8_t* buf, + size_t len, + size_t transid_offset, + uint32_t transid) : Pkt4(buf, len), transid_offset_(transid_offset) { transid_ = transid; } -PerfPkt4::PerfPkt4(const uint8_t* buf, uint32_t len, size_t transid_offset) : +PerfPkt4::PerfPkt4(const uint8_t* buf, size_t len, size_t transid_offset) : Pkt4(buf, len), transid_offset_(transid_offset) { } bool PerfPkt4::rawPack() { - return (PktTransform::pack(dhcp::Option::V4, - data_, - options_, + return (PktTransform::pack(dhcp::Option::V4, + data_, + options_, transid_offset_, transid_, bufferOut_)); @@ -50,9 +56,9 @@ PerfPkt4::rawPack() { bool PerfPkt4::rawUnpack() { - return (PktTransform::unpack(dhcp::Option::V4, - data_, - options_, + return (PktTransform::unpack(dhcp::Option::V4, + data_, + options_, transid_offset_, transid_)); } diff --git a/tests/tools/perfdhcp/perf_pkt4.h b/tests/tools/perfdhcp/perf_pkt4.h index 88128992a1..2cd1c7667d 100644 --- a/tests/tools/perfdhcp/perf_pkt4.h +++ b/tests/tools/perfdhcp/perf_pkt4.h @@ -56,6 +56,16 @@ public: /// Localized option pointer type. typedef boost::shared_ptr LocalizedOptionPtr; + /// \brief Constructor, used for outgoing and incoming messages + /// + /// This constructor initializes transaction id and + /// transaction id offset of the packet with default + /// values. + /// + /// \param buf buffer holding contents of the message. + /// \param len length of the data in the buffer. + PerfPkt4(const uint8_t* buf, size_t len); + /// \brief Constructor, used for outgoing DHCP messages. /// /// Creates new DHCPv4 message using provided buffer. @@ -73,7 +83,7 @@ public: /// \param transid_offset transaction id offset in outgoing message. /// \param transid transaction id to be stored in outgoing message. PerfPkt4(const uint8_t* buf, - uint32_t len, + size_t len, size_t transid_offset, uint32_t transid); @@ -100,7 +110,7 @@ public: /// \param len size of buffer of packet content. /// \param transid_offset transaction id offset in a message. PerfPkt4(const uint8_t* buf, - uint32_t len, + size_t len, size_t transid_offset); /// \brief Returns transaction id offset in packet buffer diff --git a/tests/tools/perfdhcp/pkt_transform.cc b/tests/tools/perfdhcp/pkt_transform.cc index 0a6a00c30b..fc3e1becf6 100644 --- a/tests/tools/perfdhcp/pkt_transform.cc +++ b/tests/tools/perfdhcp/pkt_transform.cc @@ -57,7 +57,7 @@ PktTransform::pack(const Option::Universe universe, out_buffer.skip(transid_offset); try { - if (universe == Option::V6) { + if (universe == Option::V4) { out_buffer.writeUint8(transid >> 24 & 0xFF); } out_buffer.writeUint8(transid >> 16 & 0xFF); @@ -111,7 +111,7 @@ PktTransform::unpack(const Option::Universe universe, } try { - PktTransform::unpackOptions(universe, in_buffer, options); + PktTransform::unpackOptions(in_buffer, options); } catch (const isc::BadValue& e) { cout << "Packet parsing failed: " << e.what() << endl; return (false); @@ -156,8 +156,7 @@ PktTransform::packOptions(const OptionBuffer& in_buffer, } void -PktTransform::unpackOptions(const Option::Universe universe, - const OptionBuffer& in_buffer, +PktTransform::unpackOptions(const OptionBuffer& in_buffer, const Option::OptionCollection& options) { for (Option::OptionCollection::const_iterator it = options.begin(); it != options.end(); ++it) { @@ -168,7 +167,7 @@ PktTransform::unpackOptions(const Option::Universe universe, if (opt_pos == 0) { isc_throw(isc::BadValue, "failed to unpack packet from raw buffer " "(Option position not specified)"); - } else if (opt_pos + 4 > in_buffer.size()) { + } else if (opt_pos + option->getHeaderLen() > in_buffer.size()) { isc_throw(isc::BadValue, "failed to unpack options from from raw buffer " "(Option position out of bounds)"); @@ -177,7 +176,7 @@ PktTransform::unpackOptions(const Option::Universe universe, size_t offset = opt_pos; size_t offset_step = 1; uint16_t opt_type = 0; - if (universe == Option::V6) { + if (option->getUniverse() == Option::V6) { offset_step = 2; // For DHCPv6 option type is in first two octets. opt_type = in_buffer[offset] * 256 + in_buffer[offset + 1]; @@ -195,14 +194,14 @@ PktTransform::unpackOptions(const Option::Universe universe, // Get option length which is supposed to be after option type. offset += offset_step; uint16_t opt_len = in_buffer[offset] * 256 + in_buffer[offset + 1]; - if (universe == Option::V6) { + if (option->getUniverse() == Option::V6) { opt_len = in_buffer[offset] * 256 + in_buffer[offset + 1]; } else { opt_len = in_buffer[offset]; } - + // Check if packet is not truncated. - if (offset + opt_len > in_buffer.size()) { + if (offset + option->getHeaderLen() + opt_len > in_buffer.size()) { isc_throw(isc::BadValue, "failed to unpack option from raw buffer " "(option truncated)"); diff --git a/tests/tools/perfdhcp/pkt_transform.h b/tests/tools/perfdhcp/pkt_transform.h index 8a2b96565d..d30af5ade8 100644 --- a/tests/tools/perfdhcp/pkt_transform.h +++ b/tests/tools/perfdhcp/pkt_transform.h @@ -15,7 +15,6 @@ #ifndef __PKT_TRANSFORM_H #define __PKT_TRANSFORM_H -#include #include #include "localized_option.h" @@ -27,20 +26,20 @@ namespace perfdhcp { /// /// This class provides static functions to read raw /// data from packet buffer and write raw data to packet -/// buffer. When reading data with unpack() method, the -/// corresponding options objects are updated. -/// When writting to the packet buffer with pack() nethod, +/// buffer. When reading data with unpack() method, the +/// corresponding options objects are updated. +/// When writting to the packet buffer with pack() nethod, /// options objects carry input data to be written. -/// This class is used both by \ref PerfPkt4 and +/// This class is used both by \ref PerfPkt4 and /// \ref PerfPkt6 classes in case DHCP packets are created /// from template files. In this case, some of the template -/// packet's options are replaced before sending it to +/// packet's options are replaced before sending it to /// server. Offset of specific options are provided from /// command line by perfdhcp tool user and passed in /// options collection. /// This class also provide mechanism to read some data -/// from incoming packet buffer and update options -/// in options collection with these data. +/// from incoming packet buffer and update options +/// in options collection with these data. /// It is assumed either in case of writting or reading /// that all options have to be added to options collection /// and their offset have to be specified in buffer @@ -54,11 +53,11 @@ public: /// to output buffer. Input buffer must contain whole /// initial packet data. Parts of this data will be /// overriden by options data specified in options - /// collection. Such options must have their offsets in + /// collection. Such options must have their offsets in /// a packet specified (\see LocalizedOption to find out how /// to specify options offset). /// - /// \note Specified options must fit into size of the + /// \note Specified options must fit into size of the /// initial packet data. Call to this function will fail /// if option's offset + its size is out of bounds. /// @@ -71,7 +70,7 @@ public: /// offset /// \param transid transaction id value /// \param out_buffer output buffer holding "packed" data - /// + /// /// \retrun false, if pack operation failed. static bool pack(const dhcp::Option::Universe universe, const dhcp::OptionBuffer& in_buffer, @@ -88,8 +87,8 @@ public: /// \ref isc::dhcp::Pkt6::addOption to specify which options to parse. /// Each option should be of the \ref isc::perfdhcp::LocalizedOption /// type with offset value indicated. - /// Transaction id offset is specified as separate argument and - /// is used to read transaction id value from buffer. + /// Transaction id offset is specified as separate argument and + /// is used to read transaction id value from buffer. /// /// \param universe universe used, V4 or V6 /// \param in_buffer input buffer to be parsed @@ -97,7 +96,7 @@ public: /// \param transid_offset offset of transaction id in input buffer /// \param transid transaction id value read from input buffer /// \return false, if unpack operation failed. - static bool unpack(const dhcp::Option::Universe universe, + static bool unpack(const dhcp::Option::Universe universe, const dhcp::OptionBuffer& in_buffer, const dhcp::Option::OptionCollection& options, const size_t transid_offset, @@ -106,9 +105,9 @@ public: private: /// \brief Replaces options contents of options in a buffer /// - /// The method uses localized options collection added to - /// replace parts of initial packet data (e.g. read from - /// template file). + /// The method uses localized options collection added to + /// replace parts of initial packet data (e.g. read from + /// template file). /// This private method is called from \ref PktTransform::pack /// /// \param in_buffer input buffer holding initial packet data. @@ -123,24 +122,23 @@ private: /// /// The method reads options data from the input buffer /// and stores read data in options objects. Options - /// must have their offsets in a buffer specified + /// must have their offsets in a buffer specified /// (\see LocalizedOption to find out how to specify /// option offset). /// This private method is called by \ref PktTransform::unpack. /// - /// \note This method iterates through all options in + /// \note This method iterates through all options in /// options collection, checks offset of the option /// in input buffer and reads data from the buffer to /// update option's buffer. If provided options collection /// is empty, call to this function will have no effect. - /// + /// /// \param universe universe used, V4 or V6 /// \param in_buffer input buffer to be parsed. - /// \param options oprions collection with their offsets + /// \param options oprions collection with their offsets /// in input buffer specified. /// \throw isc::Unexpected if options unpack failed. - static void unpackOptions(const dhcp::Option::Universe universe, - const dhcp::OptionBuffer& in_buffer, + static void unpackOptions(const dhcp::OptionBuffer& in_buffer, const dhcp::Option::OptionCollection& options); }; diff --git a/tests/tools/perfdhcp/tests/perf_pkt4_unittest.cc b/tests/tools/perfdhcp/tests/perf_pkt4_unittest.cc index 4adeccff64..7379ec6d52 100644 --- a/tests/tools/perfdhcp/tests/perf_pkt4_unittest.cc +++ b/tests/tools/perfdhcp/tests/perf_pkt4_unittest.cc @@ -35,23 +35,6 @@ typedef PerfPkt4::LocalizedOptionPtr LocalizedOptionPtr; namespace { -// a sample data -const uint8_t dummyOp = BOOTREQUEST; -const uint8_t dummyHtype = 6; -const uint8_t dummyHlen = 6; -const uint8_t dummyHops = 13; -const uint32_t dummyTransid = 0x12345678; -const uint16_t dummySecs = 42; -const uint16_t dummyFlags = BOOTP_BROADCAST; - -const IOAddress dummyCiaddr("192.0.2.1"); -const IOAddress dummyYiaddr("1.2.3.4"); -const IOAddress dummySiaddr("192.0.2.255"); -const IOAddress dummyGiaddr("255.255.255.255"); - -// a dummy MAC address -const uint8_t dummyMacAddr[] = {0, 1, 2, 3, 4, 5}; - // a dummy MAC address, padded with 0s const uint8_t dummyChaddr[16] = {0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -70,16 +53,14 @@ public: PerfPkt4Test() { } - /// \brief Returns captured SOLICIT packet. + /// \brief Returns buffer with sample DHCPDISCOVER message. /// - /// 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. + /// This method creates buffer containing on-wire data of + /// DHCPDICOSVER message. This buffer is used by tests below + /// to create DHCPv4 test packets. /// - /// \return pointer to Pkt6 that represents received SOLICIT - std::vector capture() { + /// \return vector containing on-wire data + std::vector& capture() { // That is only part of the header. It contains all "short" fields, // larger fields are constructed separately. @@ -97,28 +78,36 @@ public: 12, 3, 0, 1, 2, // Host name option. 13, 3, 10, 11, 12, // Boot file size option 14, 3, 20, 21, 22, // Merit dump file - 53, 1, 1, // DHCP message type. - 128, 3, 30, 31, 32, + 53, 1, 1, // DHCP message type. + 128, 3, 30, 31, 32, 254, 3, 40, 41, 42, }; // Initialize the vector with the header fields defined above. - vector buf(hdr, hdr + sizeof(hdr)); - - // Append the large header fields. - std::copy(dummyChaddr, dummyChaddr + Pkt4::MAX_CHADDR_LEN, back_inserter(buf)); - std::copy(dummySname, dummySname + Pkt4::MAX_SNAME_LEN, back_inserter(buf)); - std::copy(dummyFile, dummyFile + Pkt4::MAX_FILE_LEN, back_inserter(buf)); - - // Append magic cookie. - buf.push_back(0x63); - buf.push_back(0x82); - buf.push_back(0x53); - buf.push_back(0x63); - - // Append options. - std::copy(v4Opts, v4Opts + sizeof(v4Opts), back_inserter(buf)); - + static std::vector buf(hdr, hdr + sizeof(hdr)); + + // If this is a first call to this function. Initialize + // remaining data. + if (buf.size() == sizeof(hdr)) + { + + // Append the large header fields. + std::copy(dummyChaddr, dummyChaddr + Pkt4::MAX_CHADDR_LEN, + back_inserter(buf)); + std::copy(dummySname, dummySname + Pkt4::MAX_SNAME_LEN, + back_inserter(buf)); + std::copy(dummyFile, dummyFile + Pkt4::MAX_FILE_LEN, + back_inserter(buf)); + + // Append magic cookie. + buf.push_back(0x63); + buf.push_back(0x82); + buf.push_back(0x53); + buf.push_back(0x63); + + // Append options. + std::copy(v4Opts, v4Opts + sizeof(v4Opts), back_inserter(buf)); + } return buf; } }; @@ -137,28 +126,34 @@ TEST_F(PerfPkt4Test, Constructor) { // Test constructor to be used for outgoing messages. // Use non-zero offset and specify transaction id. - boost::scoped_ptr pkt2(new PerfPkt4(data, sizeof(data), 10, 0x010203)); + boost::scoped_ptr pkt2(new PerfPkt4(data, sizeof(data), + 10, 0x010203)); EXPECT_EQ(0x010203, pkt2->getTransid()); EXPECT_EQ(10, pkt2->getTransIdOffset()); + + // Test default constructor. Transaction id offset is expected to be 1. + boost::scoped_ptr pkt3(new PerfPkt4(data, sizeof(data))); + EXPECT_EQ(1, pkt3->getTransIdOffset()); } TEST_F(PerfPkt4Test, RawPack) { // Create new packet. std::vector buf = capture(); - boost::scoped_ptr pkt(new PerfPkt4(&buf[0], buf.size(), 0x1, 1)); + boost::scoped_ptr pkt(new PerfPkt4(&buf[0], buf.size())); // Initialize options data. uint8_t buf_hostname[] = { 12, 3, 4, 5, 6 }; uint8_t buf_boot_filesize[] = { 13, 3, 1, 2, 3 }; OptionBuffer vec_hostname(buf_hostname + 2, buf_hostname + 5); - OptionBuffer vec_boot_filesize(buf_boot_filesize + 2, buf_boot_filesize + 5); + OptionBuffer vec_boot_filesize(buf_boot_filesize + 2, + buf_boot_filesize + 5); // Create options objects. - LocalizedOptionPtr pkt_hostname(new LocalizedOption(Option::V4, + LocalizedOptionPtr pkt_hostname(new LocalizedOption(Option::V4, DHO_HOST_NAME, vec_hostname, 240)); - LocalizedOptionPtr pkt_boot_filesize(new LocalizedOption(Option::V4, + LocalizedOptionPtr pkt_boot_filesize(new LocalizedOption(Option::V4, DHO_BOOT_SIZE, vec_boot_filesize, 245)); @@ -167,7 +162,7 @@ TEST_F(PerfPkt4Test, RawPack) { ASSERT_NO_THROW(pkt->addOption(pkt_boot_filesize)); ASSERT_NO_THROW(pkt->addOption(pkt_hostname)); - // We have valid options addedwith valid offsets so + // We have valid options addedwith valid offsets so // pack operation should succeed. ASSERT_TRUE(pkt->rawPack()); @@ -175,7 +170,8 @@ TEST_F(PerfPkt4Test, RawPack) { // DHO_BOOT_SIZE options. util::OutputBuffer pkt_output = pkt->getBuffer(); ASSERT_EQ(buf.size(), pkt_output.getLength()); - const uint8_t* out_buf_data = static_cast(pkt_output.getData()); + const uint8_t* out_buf_data = + static_cast(pkt_output.getData()); // Check if options we read from buffer is valid. EXPECT_EQ(0, memcmp(buf_hostname, out_buf_data + 240, 5)); @@ -185,43 +181,47 @@ TEST_F(PerfPkt4Test, RawPack) { TEST_F(PerfPkt4Test, RawUnpack) { // Create new packet. std::vector buf = capture(); - boost::scoped_ptr pkt(new PerfPkt4(&buf[0], buf.size(), 0x1, 1)); + boost::scoped_ptr pkt(new PerfPkt4(&buf[0], buf.size())); // Create options (existing in the packet) and specify their offsets. LocalizedOptionPtr opt_merit(new LocalizedOption(Option::V4, DHO_MERIT_DUMP, OptionBuffer(), 250)); - + LocalizedOptionPtr opt_msg_type(new LocalizedOption(Option::V4, DHO_DHCP_MESSAGE_TYPE, - OptionBuffer(), + OptionBuffer(), 255)); // Addition should be successful ASSERT_NO_THROW(pkt->addOption(opt_merit)); ASSERT_NO_THROW(pkt->addOption(opt_msg_type)); - + // Option fit to packet boundaries and offsets are valid, // so this should unpack successfully. ASSERT_TRUE(pkt->rawUnpack()); // At this point we should have updated options data (read from buffer). // Let's try to retrieve them. - opt_merit = boost::dynamic_pointer_cast(pkt->getOption(DHO_MERIT_DUMP)); - opt_msg_type = boost::dynamic_pointer_cast(pkt->getOption(DHO_DHCP_MESSAGE_TYPE)); + opt_merit = boost::dynamic_pointer_cast + (pkt->getOption(DHO_MERIT_DUMP)); + opt_msg_type = boost::dynamic_pointer_cast + (pkt->getOption(DHO_DHCP_MESSAGE_TYPE)); ASSERT_TRUE(opt_merit); ASSERT_TRUE(opt_msg_type); // Get first option payload. OptionBuffer opt_merit_data = opt_merit->getData(); - // Define reference data. - uint8_t buf_merit[] = { 20, 21, 22 }; + // Define reference data. + uint8_t buf_merit[] = { 20, 21, 22 }; // Validate first option data. ASSERT_EQ(sizeof(buf_merit), opt_merit_data.size()); - EXPECT_TRUE(std::equal(opt_merit_data.begin(), opt_merit_data.end(), buf_merit)); - + EXPECT_TRUE(std::equal(opt_merit_data.begin(), + opt_merit_data.end(), + buf_merit)); + // Get second option payload. OptionBuffer opt_msg_type_data = opt_msg_type->getData(); @@ -230,115 +230,133 @@ TEST_F(PerfPkt4Test, RawUnpack) { EXPECT_EQ(1, opt_msg_type_data[0]); } - /* TEST_F(PerfPkt4Test, InvalidOptions) { - // Create packet. - boost::scoped_ptr 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 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()); -} + // Create new packet. + std::vector buf = capture(); + boost::scoped_ptr pkt1(new PerfPkt4(&buf[0], buf.size())); + // Create option with invalid offset. + // This option is at offset 250 (not 251). + LocalizedOptionPtr opt_merit(new LocalizedOption(Option::V4, + DHO_MERIT_DUMP, + OptionBuffer(), + 251)); + ASSERT_NO_THROW(pkt1->addOption(opt_merit)); -TEST_F(PerfPkt4Test, TruncatedPacket) { - cout << "Testing parsing options from truncated packet." - << "This may produce spurious errors" << endl; + cout << "Testing unpack of invalid options. " + << "This may produce spurious errors." << endl; - // Create truncated (in the middle of duid options) - boost::scoped_ptr 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()); + // Unpack is expected to fail because it is supposed to read + // option type from buffer and match it with DHO_MERIT_DUMP. + // It will not match because option is shifted by on byte. + ASSERT_FALSE(pkt1->rawUnpack()); + + // Crete another packet. + boost::scoped_ptr pkt2(new PerfPkt4(&buf[0], buf.size())); + + // Create DHO_DHCP_MESSAGE_TYPE option that has wrong offset. + // With this offset, option goes beyond packet size (268). + LocalizedOptionPtr opt_msg_type(new LocalizedOption(Option::V4, + DHO_DHCP_MESSAGE_TYPE, + OptionBuffer(1, 2), + 266)); + // Adding option is expected to be successful because no + // offset validation takes place at this point. + ASSERT_NO_THROW(pkt2->addOption(opt_msg_type)); + + // This is expected to fail because option is out of bounds. + ASSERT_FALSE(pkt2->rawPack()); } -TEST_F(PerfPkt4Test, PackTransactionId) { - uint8_t data[100] = { 0 }; +TEST_F(PerfPkt4Test, TruncatedPacket) { + // Get the whole packet and truncate it to 249 bytes. + std::vector buf = capture(); + buf.resize(249); + boost::scoped_ptr pkt(new PerfPkt4(&buf[0], buf.size())); + + // Option DHO_BOOT_SIZE is now truncated because whole packet + // is truncated. This option ends at 249 while last index of + // truncated packet is now 248. + LocalizedOptionPtr opt_boot_filesize(new LocalizedOption(Option::V4, + DHO_BOOT_SIZE, + OptionBuffer(3, 1), + 245)); + ASSERT_NO_THROW(pkt->addOption(opt_boot_filesize)); - // Create dummy packet that is simply filled with zeros. - boost::scoped_ptr pkt1(new PerfPkt4(data, - sizeof(data), - 0x010203, - PerfPkt4::Offset(50))); + cout << "Testing pack and unpack of options in truncated " + << "packet. This may produce spurious errors." << endl; - // Reference data are non zero so we can detect them in dummy packet. - uint8_t ref_data[3] = { 1, 2, 3 }; + // Both pack and unpack are expected to fail because + // added option is out of bounds. + EXPECT_FALSE(pkt->rawUnpack()); + EXPECT_FALSE(pkt->rawPack()); +} - // This will store given transaction id in the packet data at - // offset of 50. +TEST_F(PerfPkt4Test, PackTransactionId) { + // Create dummy packet that consists of zeros. + std::vector buf(268, 0); + // Initialize transaction id 0x00000102 at offset 10. + boost::scoped_ptr pkt1(new PerfPkt4(&buf[0], buf.size(), + 10, 0x0102)); + + // Pack will inject transaction id at offset 10 into the + // packet buffer. ASSERT_TRUE(pkt1->rawPack()); - // Get the output buffer so we can validate it. + // Get packet's output buffer and make sure it has valid size. util::OutputBuffer out_buf = pkt1->getBuffer(); - ASSERT_EQ(sizeof(data), out_buf.getLength()); - const uint8_t *out_buf_data = static_cast - (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 pkt2(new PerfPkt4(data, - sizeof(data), - 0x010202, - PerfPkt4::Offset(100))); - cout << "Testing out of bounds offset. " - "This may produce spurious errors ..." << endl; + ASSERT_EQ(buf.size(), out_buf.getLength()); + const uint8_t *out_buf_data = + static_cast(out_buf.getData()); + + // Initialize reference data for transaction id. + const uint8_t ref_data[] = { 0, 0, 1, 2 }; + + // Expect that reference transaction id matches what we have + // read from buffer. + EXPECT_EQ(0, memcmp(ref_data, out_buf_data + 10, 4)); + + cout << "Testing pack with invalid transaction id offset. " + << "This may produce spurious errors" << endl; + + // Create packet with invalid transaction id offset. + // Packet length is 268, transaction id is 4 bytes long so last byte of + // transaction id is out of bounds. + boost::scoped_ptr pkt2(new PerfPkt4(&buf[0], buf.size(), + 265, 0x0102)); EXPECT_FALSE(pkt2->rawPack()); } TEST_F(PerfPkt4Test, UnpackTransactionId) { - // Initialize data for dummy packet (zeros only). - uint8_t data[100] = { 0 }; + // Initialize packet data, lebgth 268, zeros only. + std::vector in_data(268, 0); - // Generate transaction id = 0x010203 and inject at offset = 50. - for (int i = 50; i < 53; ++i) { - data[i] = i - 49; + // Assume that transaction id is at offset 100. + // Fill 4 bytes at offset 100 with dummy transaction id. + for (int i = 100; i < 104; ++i) { + in_data[i] = i - 99; } - // Create packet and point out that transaction id is at offset 50. - boost::scoped_ptr pkt1(new PerfPkt4(data, - sizeof(data), - PerfPkt4::Offset(50))); - // Get transaction id out of buffer and store in class member. + // Create packet from initialized buffer. + boost::scoped_ptr pkt1(new PerfPkt4(&in_data[0], + in_data.size(), + 100)); ASSERT_TRUE(pkt1->rawUnpack()); - // Test value of transaction id. - EXPECT_EQ(0x010203, pkt1->getTransid()); - - // Out of bounds transaction id offset. - boost::scoped_ptr pkt2(new PerfPkt4(data, - sizeof(data), - PerfPkt4::Offset(300))); - cout << "Testing out of bounds offset. " - "This may produce spurious errors ..." << endl; - EXPECT_FALSE(pkt2->rawUnpack()); - } */ + // Get unpacked transaction id and compare with reference. + EXPECT_EQ(0x01020304, pkt1->getTransid()); + + // Create packet with transaction id at invalid offset. + boost::scoped_ptr pkt2(new PerfPkt4(&in_data[0], + in_data.size(), + 270)); + + cout << "Testing unpack of transaction id at invalid offset." + << "This may produce spurious errors." << endl; + + // Unpack is supposed to fail because transaction id is at + // out of bounds offset. + EXPECT_FALSE(pkt2->rawUnpack()); +} } -- GitLab