summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcp/tests/packet_queue_mgr4_unittest.cc
blob: 90aa61eebe3e5ed9396c038388ff49e538156285 (plain)
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
// Copyright (C) 2018-2021 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 <dhcp/packet_queue_ring.h>
#include <dhcp/packet_queue_mgr4.h>
#include <dhcp/tests/packet_queue_testutils.h>

#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>

using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::dhcp::test;

/// @brief Convenience function for construction a dhcp-queue-control element map
///
/// @param queue_type logical name of the queue implementation type
/// @param capacity maximum queue capacity
/// @param enable_queue bool value to ascribe to the 'enable-queue' parameter, defaults to true
data::ElementPtr
isc::dhcp::test::makeQueueConfig(const std::string& queue_type, size_t capacity, bool enable_queue /* = true */) {
    data::ElementPtr config = data::Element::createMap();
    config->set("enable-queue", data::Element::create(enable_queue));
    config->set("queue-type", data::Element::create(queue_type));
    config->set("capacity", data::Element::create(static_cast<long int>(capacity)));
    return (config);
}

namespace {

/// @brief Test fixture for exercising the DHCPv4 Packet Queue Manager (PQM)
class PacketQueueMgr4Test : public ::testing::Test {
public:
    /// @brief Constructor
    ///
    /// Note that it instantiates the PQM singleton.
    PacketQueueMgr4Test()
        : default_queue_type_(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4) {
        packet_queue_mgr4_.reset(new PacketQueueMgr4());
    }

    /// @brief Destructor
    virtual ~PacketQueueMgr4Test(){}

    /// @brief Registers a queue type factory
    ///
    /// @param queue_type logical name of the queue implementation
    ///
    /// @return true if the registration succeeded, false otherwise
    bool addCustomQueueType(const std::string& queue_type) {
        bool did_it =
            mgr().registerPacketQueueFactory(queue_type,
                                            [](data::ConstElementPtr parameters)
                                            -> PacketQueue4Ptr {
                std::string queue_type ;
                try {
                    queue_type = data::SimpleParser::getString(parameters, "queue-type");
                } catch (const std::exception& ex) {
                    isc_throw(InvalidQueueParameter,
                              "queue-type missing or invalid: " << ex.what());
                }

                size_t capacity;
                try {
                    capacity = data::SimpleParser::getInteger(parameters, "capacity");
                } catch (const std::exception& ex) {
                    isc_throw(InvalidQueueParameter,
                              "'capacity' missing or invalid: " << ex.what());
                }

                return (PacketQueue4Ptr(new PacketQueueRing4(queue_type, capacity)));
            });

        return did_it;
    }

    /// @brief Fetches a pointer to the PQM singleton
    PacketQueueMgr4& mgr() {
        return (*packet_queue_mgr4_);
    };

    /// @brief Tests the current packet queue info against expected content
    ///
    /// @param exp_json JSON text describing the expected packet queue info
    /// contents
    void checkMyInfo(const std::string& exp_json) {
        checkInfo((mgr().getPacketQueue()), exp_json);
    }

    /// @brief default queue type used for a given test
    std::string default_queue_type_;

    /// @brief Packet Queue manager instance
    PacketQueueMgr4Ptr packet_queue_mgr4_;
};

// Verifies that DHCPv4 PQM provides a default queue factory
TEST_F(PacketQueueMgr4Test, defaultQueue) {
    // Should not be a queue at start-up
    ASSERT_FALSE(mgr().getPacketQueue());

    // Verify that we can create a queue with default factory.
    data::ConstElementPtr config = makeQueueConfig(default_queue_type_, 2000);
    ASSERT_NO_THROW(mgr().createPacketQueue(config));
    CHECK_QUEUE_INFO (mgr().getPacketQueue(), "{ \"capacity\": 2000, \"queue-type\": \""
                      << default_queue_type_ << "\", \"size\": 0 }");
}

// Verifies that PQM registry and creation of custom queue implementations.
TEST_F(PacketQueueMgr4Test, customQueueType) {

    // Verify that we cannot create a queue for a non-existant type
    data::ConstElementPtr config = makeQueueConfig("custom-queue", 2000);
    ASSERT_THROW(mgr().createPacketQueue(config), InvalidQueueType);

    // Register our adjustable-type factory
    ASSERT_TRUE(addCustomQueueType("custom-queue"));

    // Verify that we can create a custom queue.
    ASSERT_NO_THROW(mgr().createPacketQueue(config));
    checkMyInfo("{ \"capacity\": 2000, \"queue-type\": \"custom-queue\", \"size\": 0 }");

    // Now unregister the factory.
    ASSERT_NO_THROW(mgr().unregisterPacketQueueFactory("custom-queue"));
    // Queue should be gone too.
    ASSERT_FALSE(mgr().getPacketQueue());

    // Try and recreate the custom queue, type should be invalid.
    ASSERT_THROW(mgr().createPacketQueue(config), InvalidQueueType);

    // Verify we can create a default type queue with non-default capacity.
    config = makeQueueConfig(default_queue_type_, 2000);
    ASSERT_NO_THROW(mgr().createPacketQueue(config));
    CHECK_QUEUE_INFO (mgr().getPacketQueue(), "{ \"capacity\": 2000, \"queue-type\": \""
                      << default_queue_type_ << "\", \"size\": 0 }");
}

} // end of anonymous namespace