diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 49352b2567..2ea7af9c34 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -354,6 +354,9 @@ Dhcpv4Srv::~Dhcpv4Srv() { // The lease manager was instantiated during DHCPv4Srv configuration, // so we should clean up after ourselves. LeaseMgrFactory::destroy(); + + // Explicitly unload hooks + HooksManager::getHooksManager().unloadLibraries(); } void diff --git a/src/bin/dhcp4/tests/hooks_unittest.cc b/src/bin/dhcp4/tests/hooks_unittest.cc index 80836a37dc..7a2e0a8843 100644 --- a/src/bin/dhcp4/tests/hooks_unittest.cc +++ b/src/bin/dhcp4/tests/hooks_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2016 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 @@ -17,6 +17,9 @@ #include #include #include +#include +#include + #include using namespace std; @@ -555,6 +558,37 @@ Lease4Ptr HooksDhcpv4SrvTest::callback_lease4_; const Subnet4Collection* HooksDhcpv4SrvTest::callback_subnet4collection_; vector HooksDhcpv4SrvTest::callback_argument_names_; +/// @brief Fixture class used to do basic library load/unload tests +class LoadUnloadDhcpv4SrvTest : public ::testing::Test { +public: + /// @brief Pointer to the tested server object + boost::shared_ptr server_; + + LoadUnloadDhcpv4SrvTest() { + reset(); + } + + /// @brief Destructor + ~LoadUnloadDhcpv4SrvTest() { + server_.reset(); + reset(); + }; + + /// @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(remove(LOAD_MARKER_FILE)); + static_cast(remove(UNLOAD_MARKER_FILE)); + CfgMgr::instance().clear(); + } +}; + // Checks if callouts installed on pkt4_receive are indeed called and the // all necessary parameters are passed. // @@ -1573,3 +1607,43 @@ TEST_F(HooksDhcpv4SrvTest, HooksDeclineDrop) { EXPECT_EQ(addr, from_mgr->addr_); EXPECT_EQ(addr, callback_lease4_->addr_); } + + +// Verifies that libraries are unloaded by server destruction +// The callout libraries write their library index number to a marker +// file upon load and unload, making it simple to test whether or not +// the load and unload callouts have been invoked. +TEST_F(LoadUnloadDhcpv4SrvTest, unloadLibaries) { + + ASSERT_NO_THROW(server_.reset(new NakedDhcpv4Srv())); + + // Ensure no marker files to start with. + ASSERT_FALSE(checkMarkerFileExists(LOAD_MARKER_FILE)); + ASSERT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE)); + + // Load two libraries + std::vector libraries; + libraries.push_back(CALLOUT_LIBRARY_1); + libraries.push_back(CALLOUT_LIBRARY_2); + HooksManager::loadLibraries(libraries); + + // Check they are loaded. + std::vector loaded_libraries = + HooksManager::getLibraryNames(); + ASSERT_TRUE(libraries == loaded_libraries); + + // ... which also included checking that the marker file created by the + // 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. + EXPECT_TRUE(checkMarkerFile(LOAD_MARKER_FILE, "12")); + EXPECT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE)); + + server_.reset(); + + // 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, "12")); +} diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 704d63aac8..c99d4d322a 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -214,6 +214,9 @@ Dhcpv6Srv::~Dhcpv6Srv() { IfaceMgr::instance().closeSockets(); LeaseMgrFactory::destroy(); + + // Explicitly unload hooks + HooksManager::getHooksManager().unloadLibraries(); } void Dhcpv6Srv::shutdown() { diff --git a/src/bin/dhcp6/tests/hooks_unittest.cc b/src/bin/dhcp6/tests/hooks_unittest.cc index ee43ae2cf0..7907174422 100644 --- a/src/bin/dhcp6/tests/hooks_unittest.cc +++ b/src/bin/dhcp6/tests/hooks_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2013-2016 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 @@ -24,6 +24,9 @@ #include #include #include +#include +#include + #include #include #include @@ -544,6 +547,38 @@ vector HooksDhcpv6SrvTest::callback_argument_names_; Lease6Ptr HooksDhcpv6SrvTest::callback_lease6_; boost::shared_ptr HooksDhcpv6SrvTest::callback_ia_na_; +/// @brief Fixture class used to do basic library load/unload tests +class LoadUnloadDhcpv6SrvTest : public ::testing::Test { +public: + /// @brief Pointer to the tested server object + boost::shared_ptr server_; + + LoadUnloadDhcpv6SrvTest() { + reset(); + } + + /// @brief Destructor + ~LoadUnloadDhcpv6SrvTest() { + server_.reset(); + reset(); + }; + + /// @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(remove(LOAD_MARKER_FILE)); + static_cast(remove(UNLOAD_MARKER_FILE)); + + CfgMgr::instance().clear(); + } +}; + // Checks if callouts installed on pkt6_receive are indeed called and the // all necessary parameters are passed. // @@ -1614,4 +1649,43 @@ TEST_F(HooksDhcpv6SrvTest, lease6DeclineDrop) { EXPECT_EQ(Lease::STATE_DEFAULT, from_mgr->state_); } +// Verifies that libraries are unloaded by server destruction +// The callout libraries write their library index number to a marker +// file upon load and unload, making it simple to test whether or not +// the load and unload callouts have been invoked. +TEST_F(LoadUnloadDhcpv6SrvTest, unloadLibaries) { + + ASSERT_NO_THROW(server_.reset(new NakedDhcpv6Srv(0))); + + // Ensure no marker files to start with. + ASSERT_FALSE(checkMarkerFileExists(LOAD_MARKER_FILE)); + ASSERT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE)); + + // Load two libraries + std::vector libraries; + libraries.push_back(CALLOUT_LIBRARY_1); + libraries.push_back(CALLOUT_LIBRARY_2); + HooksManager::loadLibraries(libraries); + + // Check they are loaded. + std::vector loaded_libraries = + HooksManager::getLibraryNames(); + ASSERT_TRUE(libraries == loaded_libraries); + + // ... which also included checking that the marker file created by the + // 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. + EXPECT_TRUE(checkMarkerFile(LOAD_MARKER_FILE, "12")); + EXPECT_FALSE(checkMarkerFileExists(UNLOAD_MARKER_FILE)); + + server_.reset(); + + // 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, "12")); +} + } // end of anonymous namespace