diff options
Diffstat (limited to 'src/bin/perfdhcp/tests/packet_storage_unittest.cc')
-rw-r--r-- | src/bin/perfdhcp/tests/packet_storage_unittest.cc | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/bin/perfdhcp/tests/packet_storage_unittest.cc b/src/bin/perfdhcp/tests/packet_storage_unittest.cc new file mode 100644 index 0000000..157da2b --- /dev/null +++ b/src/bin/perfdhcp/tests/packet_storage_unittest.cc @@ -0,0 +1,199 @@ +// Copyright (C) 2013-2015 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 "../packet_storage.h" +#include <dhcp/dhcp6.h> +#include <dhcp/pkt6.h> + +#include <gtest/gtest.h> + +namespace { + +using namespace isc; +using namespace isc::dhcp; +using namespace perfdhcp; + +/// @todo Implement the tests which use Pkt4 objects once the support for +/// DHCPv4 renewals / releases is added. + +/// The number of packets in the test storage. +const unsigned int STORAGE_SIZE = 20; + +/// Test fixture class for PacketStorage container testing. +class PacketStorageTest : public ::testing::Test { +public: + /// \brief Constructor, initializes the storage for each test. + PacketStorageTest() { + for (uint32_t i = 0; i < STORAGE_SIZE; ++i) { + storage_.append(createPacket6(DHCPV6_REPLY, i)); + } + } + + /// \brief Creates an instance of the Pkt6. + /// + /// \param packet_type A type of the packet. + /// \param transid Transaction id. + /// \return An instance of the Pkt6. + Pkt6Ptr createPacket6(const uint16_t packet_type, + const uint32_t transid) { + return (Pkt6Ptr(new Pkt6(packet_type, transid))); + } + + /// Packet storage under test. + PacketStorage<Pkt6> storage_; + +}; + +// This test verifies that the packets in the storage can be accessed +// sequentially and when a packet is returned, it is removed from the +// storage. It also verifies the correctness of the behaviour of the +// empty() and size() functions. +TEST_F(PacketStorageTest, getNext) { + ASSERT_EQ(STORAGE_SIZE, storage_.size()); + for (int i = 0; i < STORAGE_SIZE; ++i) { + Pkt6Ptr packet = storage_.getNext(); + ASSERT_TRUE(packet) << "NULL packet returned by storage_.getNext() for" + << " iteration number " << i; + EXPECT_EQ(i, packet->getTransid()); + EXPECT_EQ(STORAGE_SIZE - i - 1, storage_.size()); + } + EXPECT_TRUE(storage_.empty()); + // When storage is empty, the attempt to get the next packet should + // result in returning NULL pointer. + EXPECT_FALSE(storage_.getNext()); + // Let's try it again to see if the previous call to getNext didn't + // put the storage into the state in which the subsequent calls to + // getNext would result in incorrect behaviour. + EXPECT_FALSE(storage_.getNext()); + + // Let's add a new packet to the empty storage to check that storage + // "recovers" from being empty, i.e. that the internal indicator + // which points to current packet reinitializes correctly. + storage_.append(createPacket6(DHCPV6_REPLY, 100)); + ASSERT_EQ(1, storage_.size()); + Pkt6Ptr packet = storage_.getNext(); + EXPECT_EQ(100, packet->getTransid()); + EXPECT_FALSE(storage_.getNext()); +} + +// This test verifies that the packets in the storage can be accessed +// randomly and when a packet is returned, it is removed from the +// storage. It also verifies the correctness of the behaviour of the +// empty() and size() functions. +TEST_F(PacketStorageTest, getRandom) { + ASSERT_EQ(STORAGE_SIZE, storage_.size()); + int cnt_equals = 0; + for (int i = 0; i < STORAGE_SIZE; ++i) { + Pkt6Ptr packet = storage_.getRandom(); + ASSERT_TRUE(packet) << "NULL packet returned by storage_.getRandom()" + " for iteration number " << i; + EXPECT_EQ(STORAGE_SIZE - i - 1, storage_.size()); + cnt_equals += (i == packet->getTransid() ? 1 : 0); + } + // If the number of times id is equal to i, is the same as the number + // of elements then they were NOT accessed randomly. + // The odds of 20 elements being randomly accessed sequential order + // is nil isn't it? + EXPECT_NE(cnt_equals, STORAGE_SIZE); + + EXPECT_TRUE(storage_.empty()); + // When storage is empty, the attempt to get the random packet should + // result in returning NULL pointer. + EXPECT_FALSE(storage_.getRandom()); + // Let's try it again to see if the previous call to getRandom didn't + // put the storage into the state in which the subsequent calls to + // getRandom would result in incorrect behaviour. + EXPECT_FALSE(storage_.getRandom()); + + // Let's add a new packet to the empty storage to check that storage + // "recovers" from being empty, i.e. that the internal indicator + // which points to the current packet reinitializes correctly. + storage_.append(createPacket6(DHCPV6_REPLY, 100)); + ASSERT_EQ(1, storage_.size()); + Pkt6Ptr packet = storage_.getRandom(); + ASSERT_TRUE(packet); + EXPECT_EQ(100, packet->getTransid()); + EXPECT_FALSE(storage_.getRandom()); +} + +// This test verifies that the packets in the storage can be accessed +// either randomly or sequentially in the same time. It verifies that +// each returned packet is removed from the storage. +TEST_F(PacketStorageTest, getNextAndRandom) { + ASSERT_EQ(STORAGE_SIZE, storage_.size()); + for (int i = 0; i < STORAGE_SIZE / 2; ++i) { + Pkt6Ptr packet_random = storage_.getRandom(); + ASSERT_TRUE(packet_random) << "NULL packet returned by" + " storage_.getRandom() for iteration number " << i; + EXPECT_EQ(STORAGE_SIZE - 2 *i - 1, storage_.size()); + Pkt6Ptr packet_seq = storage_.getNext(); + ASSERT_TRUE(packet_seq) << "NULL packet returned by" + " storage_.getNext() for iteration number " << i; + EXPECT_EQ(STORAGE_SIZE - 2 * i - 2, storage_.size()); + } + EXPECT_TRUE(storage_.empty()); + EXPECT_FALSE(storage_.getRandom()); + EXPECT_FALSE(storage_.getNext()); + + // Append two packets to the storage to check if it can "recover" + // from being empty and that new elements can be accessed. + storage_.append(createPacket6(DHCPV6_REPLY, 100)); + storage_.append(createPacket6(DHCPV6_REPLY, 101)); + ASSERT_EQ(2, storage_.size()); + // The newly added elements haven't been accessed yet. So, if we + // call getNext the first one should be returned. + Pkt6Ptr packet_next = storage_.getNext(); + ASSERT_TRUE(packet_next); + // The first packet has transaction id equal to 100. + EXPECT_EQ(100, packet_next->getTransid()); + // There should be just one packet left in the storage. + ASSERT_EQ(1, storage_.size()); + // The call to getRandom should return the sole packet from the + // storage. + Pkt6Ptr packet_random = storage_.getRandom(); + ASSERT_TRUE(packet_random); + EXPECT_EQ(101, packet_random->getTransid()); + // Any further calls to getRandom and getNext should return NULL. + EXPECT_FALSE(storage_.getRandom()); + EXPECT_FALSE(storage_.getNext()); +} + +// This test verifies that all packets are removed from the storage when +// clear() function is invoked. +TEST_F(PacketStorageTest, clearAll) { + ASSERT_EQ(STORAGE_SIZE, storage_.size()); + ASSERT_NO_THROW(storage_.clear()); + EXPECT_TRUE(storage_.empty()); +} + +// This test verifies that a set of packets can be removed from the +// storage when a number of packets to be removed is specified. If +// number of packets to be removed exceeds the storage size, all +// packets should be removed. +TEST_F(PacketStorageTest, clear) { + // Initially storage should have 20 elements. + ASSERT_EQ(STORAGE_SIZE, storage_.size()); + // Remove 10 of them. + ASSERT_NO_THROW(storage_.clear(10)); + // We should have 10 remaining. + ASSERT_EQ(10, storage_.size()); + + // Check that the retrieval still works after partial clear. + EXPECT_TRUE(storage_.getNext()); + EXPECT_TRUE(storage_.getRandom()); + // We should have 10 - 2 = 8 packets in the storage after retrieval. + ASSERT_EQ(8, storage_.size()); + + // Try to remove more elements that actually is. It + // should result in removal of all elements. + ASSERT_NO_THROW(storage_.clear(15)); + EXPECT_TRUE(storage_.empty()); +} + + +} // anonymous namespace |