From 424dc6fb659365952b9c94285eae1630e8928053 Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Tue, 10 Nov 2015 10:05:56 +0100 Subject: [PATCH] [4106] Added unit test for the DHCPv6 IPC endpoint. --- src/bin/dhcp6/tests/Makefile.am | 2 +- .../dhcp6/tests/dhcp6_dhcp4o6_ipc_unittest.cc | 129 ++++++++++++++++++ src/lib/dhcp/tests/pkt_filter6_test_stub.cc | 27 +++- src/lib/dhcp/tests/pkt_filter6_test_stub.h | 7 + 4 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 src/bin/dhcp6/tests/dhcp6_dhcp4o6_ipc_unittest.cc diff --git a/src/bin/dhcp6/tests/Makefile.am b/src/bin/dhcp6/tests/Makefile.am index 10fe4c35a8..70ac65bb48 100644 --- a/src/bin/dhcp6/tests/Makefile.am +++ b/src/bin/dhcp6/tests/Makefile.am @@ -93,8 +93,8 @@ dhcp6_unittests_SOURCES += confirm_unittest.cc dhcp6_unittests_SOURCES += infrequest_unittest.cc dhcp6_unittests_SOURCES += decline_unittest.cc dhcp6_unittests_SOURCES += dhcp6_message_test.cc dhcp6_message_test.h - dhcp6_unittests_SOURCES += kea_controller_unittest.cc +dhcp6_unittests_SOURCES += dhcp6_dhcp4o6_ipc_unittest.cc nodist_dhcp6_unittests_SOURCES = marker_file.h test_libraries.h diff --git a/src/bin/dhcp6/tests/dhcp6_dhcp4o6_ipc_unittest.cc b/src/bin/dhcp6/tests/dhcp6_dhcp4o6_ipc_unittest.cc new file mode 100644 index 0000000000..1650207992 --- /dev/null +++ b/src/bin/dhcp6/tests/dhcp6_dhcp4o6_ipc_unittest.cc @@ -0,0 +1,129 @@ +// Copyright (C) 2015 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 +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace isc; +using namespace isc::asiolink; +using namespace isc::dhcp; +using namespace isc::dhcp::test; +using namespace isc::util; + +namespace { + +/// @brief Port number used in tests. +const uint16_t TEST_PORT = 32000; + +/// @brief Define short name for the test IPC. +typedef Dhcp4o6TestIpc TestIpc; + +/// @brief Test fixture class for DHCPv4 endpoint of DHCPv4o6 IPC. +class Dhcp4o6IpcTest : public ::testing::Test { +public: + + /// @brief Constructor + /// + /// Configures IPC to use a test port. It also provides a fake + /// configuration of interfaces and opens IPv6 sockets. + Dhcp4o6IpcTest() + : iface_mgr_test_config_(true) { + IfaceMgr::instance().openSockets6(); + configurePort(TEST_PORT); + } + + /// @brief Configure DHCP4o6 port. + /// + /// @param port New port. + void configurePort(const uint16_t port); + + /// @brief Creates an instance of the DHCPv4o6 Message option. + /// + /// @return Pointer to the instance of the DHCPv4-query Message option. + OptionPtr createDHCPv4MsgOption() const; + +private: + + /// @brief Provides fake configuration of interfaces. + IfaceMgrTestConfig iface_mgr_test_config_; +}; + +void +Dhcp4o6IpcTest::configurePort(const uint16_t port) { + CfgMgr::instance().getStagingCfg()->setDhcp4o6Port(port); +} + +OptionPtr +Dhcp4o6IpcTest::createDHCPv4MsgOption() const { + // Create the DHCPv4 message. + Pkt4Ptr pkt(new Pkt4(DHCPREQUEST, 1234)); + // Make a wire representation of the DHCPv4 message. + pkt->pack(); + OutputBuffer& output_buffer = pkt->getBuffer(); + const uint8_t* data = static_cast(output_buffer.getData()); + OptionBuffer option_buffer(data, data + output_buffer.getLength()); + + // Create the DHCPv4 Message option holding the created message. + OptionPtr opt_msg(new Option(Option::V6, D6O_DHCPV4_MSG, option_buffer)); + return (opt_msg); +} + +// This test verifies that the DHCPv4 endpoint of the DHCPv4o6 IPC can +// receive messages. +TEST_F(Dhcp4o6IpcTest, receive) { + // Create instance of the IPC endpoint under test. + Dhcp4o6Ipc& ipc = Dhcp4o6Ipc::instance(); + // Create instance of the IPC endpoint being used as a source of messages. + TestIpc src_ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V4); + + // Open both endpoints. + ASSERT_NO_THROW(ipc.open()); + ASSERT_NO_THROW(src_ipc.open()); + + // Create message to be sent over IPC. + Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234)); + pkt->addOption(createDHCPv4MsgOption()); + pkt->setIface("eth0"); + pkt->setRemoteAddr(IOAddress("2001:db8:1::123")); + ASSERT_NO_THROW(pkt->pack()); + + // Send and wait up to 1 second to receive it. + ASSERT_NO_THROW(src_ipc.send(pkt)); + ASSERT_NO_THROW(IfaceMgr::instance().receive6(1, 0)); + + // The stub packet filter exposes static function to retrieve messages + // sent over the fake sockets/interfaces. This is the message that the + // IPC endpoint should forward to the client after receiving it + // from the DHCPv4 server. + Pkt6Ptr forwarded = PktFilter6TestStub::popSent(); + ASSERT_TRUE(forwarded); + + // Verify the packet received. + EXPECT_EQ(DHCP6_CLIENT_PORT, forwarded->getRemotePort()); + EXPECT_EQ(forwarded->getType(), pkt->getType()); + EXPECT_TRUE(forwarded->getOption(D6O_DHCPV4_MSG)); + EXPECT_EQ("eth0", forwarded->getIface()); + EXPECT_EQ("2001:db8:1::123", forwarded->getRemoteAddr().toText()); +} + +} // end of anonymous namespace diff --git a/src/lib/dhcp/tests/pkt_filter6_test_stub.cc b/src/lib/dhcp/tests/pkt_filter6_test_stub.cc index 3b4edba83a..ff9f1e9e44 100644 --- a/src/lib/dhcp/tests/pkt_filter6_test_stub.cc +++ b/src/lib/dhcp/tests/pkt_filter6_test_stub.cc @@ -13,14 +13,25 @@ // PERFORMANCE OF THIS SOFTWARE. #include - #include +#include + +namespace { + +/// @brief Retrieves a queue of sent messages. +std::list& getSent() { + static std::list sent; + return (sent); +} + +} namespace isc { namespace dhcp { namespace test { PktFilter6TestStub::PktFilter6TestStub() { + getSent().clear(); } SocketInfo @@ -42,10 +53,22 @@ PktFilter6TestStub::joinMulticast(int, const std::string&, } int -PktFilter6TestStub::send(const Iface&, uint16_t, const Pkt6Ptr&) { +PktFilter6TestStub::send(const Iface&, uint16_t, const Pkt6Ptr& pkt) { + getSent().push_back(pkt); return (0); } +Pkt6Ptr +PktFilter6TestStub::popSent() { + std::list& sent = getSent(); + if (sent.empty()) { + return (Pkt6Ptr()); + } + Pkt6Ptr pkt = sent.front(); + sent.pop_front(); + return (pkt); +} + } } } diff --git a/src/lib/dhcp/tests/pkt_filter6_test_stub.h b/src/lib/dhcp/tests/pkt_filter6_test_stub.h index 8a0c567029..831bad89e4 100644 --- a/src/lib/dhcp/tests/pkt_filter6_test_stub.h +++ b/src/lib/dhcp/tests/pkt_filter6_test_stub.h @@ -90,6 +90,13 @@ public: /// @return true if multicast join was successful static bool joinMulticast(int sock, const std::string& ifname, const std::string & mcast); + + /// @brief Retrieve next sent message. + /// + /// @return Pointer to the next sent message or NULL if there are no + /// more messages. + static Pkt6Ptr popSent(); + }; } // namespace isc::dhcp::test -- 2.47.3