1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
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><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

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) {<--- syntax error
    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