ctrl_dhcp6_srv_unittest.cc 6.93 KB
Newer Older
1
// Copyright (C) 2012-2013,2015 Internet Systems Consortium, Inc. ("ISC")
2 3 4 5 6 7 8 9 10 11 12 13 14 15
//
// 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>
16

17
#include <cc/command_interpreter.h>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
18
#include <dhcpsrv/cfgmgr.h>
19
#include <dhcp6/ctrl_dhcp6_srv.h>
20 21 22 23
#include <hooks/hooks_manager.h>

#include "marker_file.h"
#include "test_libraries.h"
24

25
#include <boost/scoped_ptr.hpp>
26 27
#include <gtest/gtest.h>

28
using namespace std;
29 30 31 32
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using namespace isc::hooks;
33 34 35 36

namespace {

class NakedControlledDhcpv6Srv: public ControlledDhcpv6Srv {
37
    // "Naked" DHCPv6 server, exposes internal fields
38 39 40 41 42 43 44
public:
    NakedControlledDhcpv6Srv():ControlledDhcpv6Srv(DHCP6_SERVER_PORT + 10000) { }
};

class CtrlDhcpv6SrvTest : public ::testing::Test {
public:
    CtrlDhcpv6SrvTest() {
45
        reset();
46 47 48
    }

    ~CtrlDhcpv6SrvTest() {
49
        reset();
50
    };
51 52 53 54 55 56 57 58 59 60 61 62 63

    /// @brief Reset hooks data
    ///
    /// Resets the data for the hooks-related portion of the test by ensuring
    /// that no libraries are loaded and that any marker files are deleted.
    void reset() {
        // Unload any previously-loaded libraries.
        HooksManager::unloadLibraries();

        // Get rid of any marker files.
        static_cast<void>(unlink(LOAD_MARKER_FILE));
        static_cast<void>(unlink(UNLOAD_MARKER_FILE));
    }
64 65 66 67
};

TEST_F(CtrlDhcpv6SrvTest, commands) {

68 69 70 71
    boost::scoped_ptr<ControlledDhcpv6Srv> srv;
    ASSERT_NO_THROW(
        srv.reset(new ControlledDhcpv6Srv(DHCP6_SERVER_PORT + 10000))
    );
72

73
    // Use empty parameters list
74 75 76
    ElementPtr params(new isc::data::MapElement());
    int rcode = -1;

77
    // Case 1: send bogus command
Tomek Mrugalski's avatar
Tomek Mrugalski committed
78 79
    ConstElementPtr result = ControlledDhcpv6Srv::processCommand("blah", params);
    ConstElementPtr comment = isc::config::parseAnswer(rcode, result);
80 81
    EXPECT_EQ(1, rcode); // expect failure (no such command as blah)

82
    // Case 2: send shutdown command without any parameters
Tomek Mrugalski's avatar
Tomek Mrugalski committed
83 84
    result = ControlledDhcpv6Srv::processCommand("shutdown", params);
    comment = isc::config::parseAnswer(rcode, result);
85 86 87 88 89 90
    EXPECT_EQ(0, rcode); // expect success

    const pid_t pid(getpid());
    ConstElementPtr x(new isc::data::IntElement(pid));
    params->set("pid", x);

91
    // Case 3: send shutdown command with 1 parameter: pid
Tomek Mrugalski's avatar
Tomek Mrugalski committed
92 93
    result = ControlledDhcpv6Srv::processCommand("shutdown", params);
    comment = isc::config::parseAnswer(rcode, result);
94
    EXPECT_EQ(0, rcode); // Expect success
95 96
}

97 98
// Check that the "libreload" command will reload libraries
TEST_F(CtrlDhcpv6SrvTest, libreload) {
Tomek Mrugalski's avatar
Tomek Mrugalski committed
99 100 101 102 103 104 105 106

    // Sending commands for processing now requires a server that can process
    // them.
    boost::scoped_ptr<ControlledDhcpv6Srv> srv;
    ASSERT_NO_THROW(
        srv.reset(new ControlledDhcpv6Srv(0))
    );

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
    // Ensure no marker files to start with.
    ASSERT_FALSE(checkMarkerFileExists(LOAD_MARKER_FILE));
    ASSERT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE));

    // Load two libraries
    std::vector<std::string> libraries;
    libraries.push_back(CALLOUT_LIBRARY_1);
    libraries.push_back(CALLOUT_LIBRARY_2);
    HooksManager::loadLibraries(libraries);

    // Check they are loaded.
    std::vector<std::string> loaded_libraries =
        HooksManager::getLibraryNames();
    ASSERT_TRUE(libraries == loaded_libraries);

    // ... which also included checking that the marker file created by the
123 124 125
    // load functions exists and holds the correct value (of "12" - the
    // first library appends "1" to the file, the second appends "2"). Also
    // check that the unload marker file does not yet exist.
126 127 128 129 130 131 132 133 134 135 136
    EXPECT_TRUE(checkMarkerFile(LOAD_MARKER_FILE, "12"));
    EXPECT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE));

    // Now execute the "libreload" command.  This should cause the libraries
    // to unload and to reload.

    // Use empty parameters list
    ElementPtr params(new isc::data::MapElement());
    int rcode = -1;

    ConstElementPtr result =
Tomek Mrugalski's avatar
Tomek Mrugalski committed
137 138
        ControlledDhcpv6Srv::processCommand("libreload", params);
    ConstElementPtr comment = isc::config::parseAnswer(rcode, result);
139 140 141 142 143 144 145 146 147
    EXPECT_EQ(0, rcode); // Expect success

    // Check that the libraries have unloaded and reloaded.  The libraries are
    // unloaded in the reverse order to which they are loaded.  When they load,
    // they should append information to the loading marker file.
    EXPECT_TRUE(checkMarkerFile(UNLOAD_MARKER_FILE, "21"));
    EXPECT_TRUE(checkMarkerFile(LOAD_MARKER_FILE, "1212"));
}

Tomek Mrugalski's avatar
Tomek Mrugalski committed
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
// Check that the "configReload" command will reload libraries
TEST_F(CtrlDhcpv6SrvTest, configReload) {

    // Sending commands for processing now requires a server that can process
    // them.
    boost::scoped_ptr<ControlledDhcpv6Srv> srv;
    ASSERT_NO_THROW(
        srv.reset(new ControlledDhcpv6Srv(0))
    );

    // Now execute the "libreload" command.  This should cause the libraries
    // to unload and to reload.

    // Use empty parameters list
    // Prepare configuration file.
163 164 165
    string config_txt = "{ \"interfaces-config\": {"
        "  \"interfaces\": [ \"*\" ]"
        "},"
Tomek Mrugalski's avatar
Tomek Mrugalski committed
166 167 168 169
        "\"preferred-lifetime\": 3000,"
        "\"rebind-timer\": 2000, "
        "\"renew-timer\": 1000, "
        "\"subnet6\": [ { "
170
        "    \"pools\": [ { \"pool\": \"2001:db8:1::/80\" } ],"
Tomek Mrugalski's avatar
Tomek Mrugalski committed
171 172 173
        "    \"subnet\": \"2001:db8:1::/64\" "
        " },"
        " {"
174
        "    \"pools\": [ { \"pool\": \"2001:db8:2::/80\" } ],"
Tomek Mrugalski's avatar
Tomek Mrugalski committed
175 176 177 178
        "    \"subnet\": \"2001:db8:2::/64\", "
        "    \"id\": 0"
        " },"
        " {"
179
        "    \"pools\": [ { \"pool\": \"2001:db8:3::/80\" } ],"
Tomek Mrugalski's avatar
Tomek Mrugalski committed
180 181 182 183 184 185 186
        "    \"subnet\": \"2001:db8:3::/64\" "
        " } ],"
        "\"valid-lifetime\": 4000 }";

    ElementPtr config = Element::fromJSON(config_txt);

    // Make sure there are no subnets configured.
187
    CfgMgr::instance().clear();
Tomek Mrugalski's avatar
Tomek Mrugalski committed
188 189 190 191 192 193 194 195 196

    // Now send the command
    int rcode = -1;
    ConstElementPtr result =
        ControlledDhcpv6Srv::processCommand("config-reload", config);
    ConstElementPtr comment = isc::config::parseAnswer(rcode, result);
    EXPECT_EQ(0, rcode); // Expect success

    // Check that the config was indeed applied.
197 198
    const Subnet6Collection* subnets =
        CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->getAll();
Tomek Mrugalski's avatar
Tomek Mrugalski committed
199 200 201
    EXPECT_EQ(3, subnets->size());

    // Clean up after the test.
202
    CfgMgr::instance().clear();
Tomek Mrugalski's avatar
Tomek Mrugalski committed
203 204
}

205
} // End of anonymous namespace