Commit c3a1bd5a authored by Marcin Siodelski's avatar Marcin Siodelski

[3242] Use library with IfaceMgrTestConfig to test DHCPv4 server.

parent 0b6ff441
This diff is collapsed.
......@@ -21,6 +21,7 @@
#include <dhcp/option_int_array.h>
#include <dhcp/option_custom.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/lease_mgr.h>
......@@ -404,58 +405,11 @@ void Dhcpv4SrvTest::TearDown() {
}
Dhcpv4SrvFakeIfaceTest::Dhcpv4SrvFakeIfaceTest()
: Dhcpv4SrvTest(), current_pkt_filter_() {
// Remove current interface configuration. Instead we want to add
// a couple of fake interfaces.
IfaceMgr& ifacemgr = IfaceMgr::instance();
ifacemgr.closeSockets();
ifacemgr.clearIfaces();
// Add fake interfaces.
ifacemgr.addInterface(createIface("lo", 0, "127.0.0.1"));
ifacemgr.addInterface(createIface("eth0", 1, "192.0.2.1"));
ifacemgr.addInterface(createIface("eth1", 2, "10.0.0.1"));
// In order to use fake interfaces we have to supply the custom
// packet filtering class, which can mimic opening sockets on
// fake interafaces.
current_pkt_filter_.reset(new PktFilterTest());
ifacemgr.setPacketFilter(current_pkt_filter_);
ifacemgr.openSockets4();
}
void
Dhcpv4SrvFakeIfaceTest::TearDown() {
// The base class function restores the original packet filtering class.
Dhcpv4SrvTest::TearDown();
// The base class however, doesn't re-detect real interfaces.
try {
IfaceMgr::instance().clearIfaces();
IfaceMgr::instance().detectIfaces();
Dhcpv4SrvTest::testDiscoverRequest(const uint8_t msg_type) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
} catch (const Exception& ex) {
FAIL() << "Failed to restore interface configuration after using"
" fake interfaces";
}
}
Iface
Dhcpv4SrvFakeIfaceTest::createIface(const std::string& name, const int ifindex,
const std::string& addr) {
Iface iface(name, ifindex);
iface.addAddress(IOAddress(addr));
if (name == "lo") {
iface.flag_loopback_ = true;
}
iface.flag_up_ = true;
iface.flag_running_ = true;
iface.inactive4_ = false;
return (iface);
}
void
Dhcpv4SrvFakeIfaceTest::testDiscoverRequest(const uint8_t msg_type) {
// Create an instance of the tested class.
boost::scoped_ptr<NakedDhcpv4Srv> srv(new NakedDhcpv4Srv(0));
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -267,6 +267,19 @@ public:
/// @return created packet
Pkt4Ptr packetFromCapture(const std::string& hex_string);
/// @brief Tests if Discover or Request message is processed correctly
///
/// This test verifies that the Parameter Request List option is handled
/// correctly, i.e. it checks that certain options are present in the
/// server's response when they are requested and that they are not present
/// when they are not requested or NAK occurs.
///
/// @todo We need an additional test for PRL option using real traffic
/// capture.
///
/// @param msg_type DHCPDISCOVER or DHCPREQUEST
void testDiscoverRequest(const uint8_t msg_type);
/// @brief This function cleans up after the test.
virtual void TearDown();
......@@ -285,62 +298,6 @@ public:
};
/// @brief Test fixture class to be used for tests which require fake
/// interfaces.
///
/// The DHCPv4 server must always append the server identifier to its response.
/// The server identifier is typically an IP address assigned to the interface
/// on which the query has been received. The DHCPv4 server uses IfaceMgr to
/// check this address. In order to test this functionality, a set of interfaces
/// must be known to the test. This test fixture class creates a set of well
/// known (fake) interfaces which can be assigned to the test DHCPv4 messages
/// so as the response (including server identifier) can be validated.
/// The real interfaces are removed from the IfaceMgr in the constructor and
/// they are re-assigned in the destructor.
class Dhcpv4SrvFakeIfaceTest : public Dhcpv4SrvTest {
public:
/// @brief Constructor.
///
/// Creates a set of fake interfaces:
/// - lo, index: 0, address: 127.0.0.1
/// - eth0, index: 1, address: 192.0.3.1
/// - eth1, index: 2, address: 10.0.0.1
///
/// These interfaces replace the real interfaces detected by the IfaceMgr.
Dhcpv4SrvFakeIfaceTest();
/// @brief Restores the original interface configuration.
virtual void TearDown();
/// @brief Creates an instance of the interface.
///
/// @param name Name of the interface.
/// @param ifindex Index of the interface.
/// @param addr IP address assigned to the interface, represented as string.
///
/// @return Iface Instance of the interface.
static Iface createIface(const std::string& name, const int ifindex,
const std::string& addr);
/// @brief Tests if Discover or Request message is processed correctly
///
/// This test verifies that the Parameter Request List option is handled
/// correctly, i.e. it checks that certain options are present in the
/// server's response when they are requested and that they are not present
/// when they are not requested or NAK occurs.
///
/// @todo We need an additional test for PRL option using real traffic
/// capture.
///
/// @param msg_type DHCPDISCOVER or DHCPREQUEST
void testDiscoverRequest(const uint8_t msg_type);
/// @brief Holds a pointer to the packet filter object currently used
/// by the IfaceMgr.
PktFilterTestPtr current_pkt_filter_;
};
/// @brief "Naked" DHCPv4 server, exposes internal fields
class NakedDhcpv4Srv: public Dhcpv4Srv {
public:
......
// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -16,6 +16,7 @@
#include <asiolink/io_address.h>
#include <dhcp/option4_client_fqdn.h>
#include <dhcp/option_int_array.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp4/tests/dhcp4_test_utils.h>
#include <dhcp_ddns/ncr_msg.h>
......@@ -30,9 +31,9 @@ using namespace isc::dhcp_ddns;
namespace {
class NameDhcpv4SrvTest : public Dhcpv4SrvFakeIfaceTest {
class NameDhcpv4SrvTest : public Dhcpv4SrvTest {
public:
NameDhcpv4SrvTest() : Dhcpv4SrvFakeIfaceTest() {
NameDhcpv4SrvTest() : Dhcpv4SrvTest() {
srv_ = new NakedDhcpv4Srv(0);
}
virtual ~NameDhcpv4SrvTest() {
......@@ -110,7 +111,7 @@ public:
const bool include_clientid = true) {
Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(msg_type, 1234));
pkt->setRemoteAddr(IOAddress("192.0.2.3"));
pkt->setIface("eth0");
pkt->setIface("eth1");
// For DISCOVER we don't include server id, because client broadcasts
// the message to all servers.
if (msg_type != DHCPDISCOVER) {
......@@ -574,6 +575,9 @@ TEST_F(NameDhcpv4SrvTest, createNameChangeRequestsLeaseMismatch) {
// Test that the OFFER message generated as a result of the DISCOVER message
// processing will not result in generation of the NameChangeRequests.
TEST_F(NameDhcpv4SrvTest, processDiscover) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
Pkt4Ptr req = generatePktWithFqdn(DHCPDISCOVER, Option4ClientFqdn::FLAG_S |
Option4ClientFqdn::FLAG_E,
"myhost.example.com.",
......@@ -589,6 +593,9 @@ TEST_F(NameDhcpv4SrvTest, processDiscover) {
// Test that server generates client's hostname from the IP address assigned
// to it when DHCPv4 Client FQDN option specifies an empty domain-name.
TEST_F(NameDhcpv4SrvTest, processRequestFqdnEmptyDomainName) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
Pkt4Ptr req = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
Option4ClientFqdn::FLAG_E,
"", Option4ClientFqdn::PARTIAL, true);
......@@ -614,10 +621,13 @@ TEST_F(NameDhcpv4SrvTest, processRequestFqdnEmptyDomainName) {
// Test that server generates client's hostname from the IP address assigned
// to it when Hostname option carries the top level domain-name.
TEST_F(NameDhcpv4SrvTest, processRequestEmptyHostname) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
Pkt4Ptr req = generatePktWithHostname(DHCPREQUEST, ".");
// Set interface for the incoming packet. The server requires it to
// generate client id.
req->setIface("eth0");
req->setIface("eth1");
Pkt4Ptr reply;
ASSERT_NO_THROW(reply = srv_->processRequest(req));
......@@ -640,6 +650,9 @@ TEST_F(NameDhcpv4SrvTest, processRequestEmptyHostname) {
// request but modify the DNS entries for the lease according to the contents
// of the FQDN sent in the second request.
TEST_F(NameDhcpv4SrvTest, processTwoRequestsFqdn) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
Pkt4Ptr req1 = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
Option4ClientFqdn::FLAG_E,
"myhost.example.com.",
......@@ -692,11 +705,14 @@ TEST_F(NameDhcpv4SrvTest, processTwoRequestsFqdn) {
// but modify the DNS entries for the lease according to the contents of the
// Hostname sent in the second request.
TEST_F(NameDhcpv4SrvTest, processTwoRequestsHostname) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
Pkt4Ptr req1 = generatePktWithHostname(DHCPREQUEST, "myhost.example.com.");
// Set interface for the incoming packet. The server requires it to
// generate client id.
req1->setIface("eth0");
req1->setIface("eth1");
Pkt4Ptr reply;
......@@ -719,7 +735,7 @@ TEST_F(NameDhcpv4SrvTest, processTwoRequestsHostname) {
// Set interface for the incoming packet. The server requires it to
// generate client id.
req2->setIface("eth0");
req2->setIface("eth1");
ASSERT_NO_THROW(reply = srv_->processRequest(req2));
......@@ -746,6 +762,9 @@ TEST_F(NameDhcpv4SrvTest, processTwoRequestsHostname) {
// lease, then server genenerates a NameChangeRequest to remove the entries
// corresponding to the lease being released.
TEST_F(NameDhcpv4SrvTest, processRequestRelease) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
Pkt4Ptr req = generatePktWithFqdn(DHCPREQUEST, Option4ClientFqdn::FLAG_S |
Option4ClientFqdn::FLAG_E,
"myhost.example.com.",
......
......@@ -26,7 +26,8 @@ namespace test {
IfaceMgrTestConfig::IfaceMgrTestConfig(const bool default_config) {
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().clearIfaces();
IfaceMgr::instance().setPacketFilter(PktFilterPtr(new PktFilterTestStub()));
packet_filter4_ = PktFilterPtr(new PktFilterTestStub());
IfaceMgr::instance().setPacketFilter(packet_filter4_);
// Create default set of fake interfaces: lo, eth0 and eth1.
if (default_config) {
......@@ -101,6 +102,18 @@ IfaceMgrTestConfig::createIfaces() {
}
void
IfaceMgrTestConfig::setDirectResponse(const bool direct_resp) {
boost::shared_ptr<PktFilterTestStub> stub =
boost::dynamic_pointer_cast<PktFilterTestStub>(getPacketFilter4());
if (!stub) {
isc_throw(isc::Unexpected, "unable to set direct response capability for"
" test packet filter - current packet filter is not"
" of a PktFilterTestStub");
}
stub->direct_response_supported_ = direct_resp;
}
void
IfaceMgrTestConfig::setIfaceFlags(const std::string& name,
const FlagLoopback& loopback,
......
......@@ -144,6 +144,23 @@ public:
/// @brief Creates a default (example) set of fake interfaces.
void createIfaces();
/// @brief Returns currently used packet filter for DHCPv4.
PktFilterPtr getPacketFilter4() const {
return (packet_filter4_);
}
/// @brief Sets the direct response capability for current packet filter.
///
/// The test uses stub implementation of packet filter object. It is
/// possible to configure that object to report having a capability
/// to directly repond to clients which don't have an address yet.
/// This function sets this property for packet filter object.
///
/// @param direct_resp Value to be set.
///
/// @throw isc::Unexpected if unable to set the property.
void setDirectResponse(const bool direct_resp);
/// @brief Sets various flags on the specified interface.
///
/// This function configures interface with new values for flags.
......@@ -162,6 +179,10 @@ public:
const FlagInactive4& inactive4,
const FlagInactive6& inactive6);
private:
/// @brief Currently used packet filter for DHCPv4.
PktFilterPtr packet_filter4_;
};
};
......
......@@ -18,9 +18,13 @@ namespace isc {
namespace dhcp {
namespace test {
PktFilterTestStub::PktFilterTestStub()
: direct_response_supported_(true) {
}
bool
PktFilterTestStub::isDirectResponseSupported() const {
return (true);
return (direct_response_supported_);
}
SocketInfo
......
......@@ -33,6 +33,9 @@ namespace test {
class PktFilterTestStub : public PktFilter {
public:
/// @brief Constructor.
PktFilterTestStub();
/// @brief Checks if the direct DHCPv4 response is supported.
///
/// This function checks if the direct response capability is supported,
......@@ -89,6 +92,8 @@ public:
// Change the scope of the protected function so as they can be unit tested.
using PktFilter::openFallbackSocket;
bool direct_response_supported_;
};
} // namespace isc::dhcp::test
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment