// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
-// TODO - This is a temporary implementation of the hooks manager - it is
-// likely to be completely rewritte
-
#include <hooks/callout_handle.h>
#include <hooks/callout_manager.h>
#include <hooks/callout_manager.h>
return (manager);
}
-// Perform conditional initialization if nothing is loaded.
-
-void
-HooksManager::performConditionalInitialization() {
-
- // Nothing present, so create the collection with any empty set of
- // libraries, and get the CalloutManager.
- vector<string> libraries;
- lm_collection_.reset(new LibraryManagerCollection(libraries));
- lm_collection_->loadLibraries();
-
- callout_manager_ = lm_collection_->getCalloutManager();
-}
-
-// Create a callout handle
-
-boost::shared_ptr<CalloutHandle>
-HooksManager::createCalloutHandleInternal() {
- conditionallyInitialize();
- return (boost::shared_ptr<CalloutHandle>(
- new CalloutHandle(callout_manager_)));
-}
-
-boost::shared_ptr<CalloutHandle>
-HooksManager::createCalloutHandle() {
- return (getHooksManager().createCalloutHandleInternal());
-}
-
// Are callouts present?
bool
getHooksManager().unloadLibrariesInternal();
}
+// Create a callout handle
+
+boost::shared_ptr<CalloutHandle>
+HooksManager::createCalloutHandleInternal() {
+ conditionallyInitialize();
+ return (boost::shared_ptr<CalloutHandle>(
+ new CalloutHandle(callout_manager_, lm_collection_)));
+}
+
+boost::shared_ptr<CalloutHandle>
+HooksManager::createCalloutHandle() {
+ return (getHooksManager().createCalloutHandleInternal());
+}
+
+// Perform conditional initialization if nothing is loaded.
+void
+HooksManager::performConditionalInitialization() {
+
+ // Nothing present, so create the collection with any empty set of
+ // libraries, and get the CalloutManager.
+ vector<string> libraries;
+ lm_collection_.reset(new LibraryManagerCollection(libraries));
+ lm_collection_->loadLibraries();
+
+ callout_manager_ = lm_collection_->getCalloutManager();
+}
+
+// Shell around ServerHooks::registerHook()
+
+int
+HooksManager::registerHook(const std::string& name) {
+ return (ServerHooks::getServerHooks().registerHook(name));
+}
} // namespace util
} // namespace isc
#include <hooks/callout_handle.h>
#include <hooks/hooks_manager.h>
+#include <hooks/server_hooks.h>
#include <hooks/tests/common_test_class.h>
#include <hooks/tests/test_libraries.h>
//
// r3 = ((10 * d1 + d1) - d2) * d2 * d3 - d3
{
- SCOPED_TRACE("Doing calculation with libraries loaded");
+ SCOPED_TRACE("Calculation with libraries loaded");
executeCallCallouts(10, 3, 33, 2, 62, 3, 183);
}
// Re-execute the calculation - callouts can be called but as nothing
// happens, the result should always be -1.
{
- SCOPED_TRACE("Doing calculation with libraries not loaded");
+ SCOPED_TRACE("Calculation with libraries not loaded");
executeCallCallouts(-1, 3, -1, 22, -1, 83, -1);
}
}
//
// r3 = ((10 * d1 + d1) - d2) * d2 * d3 - d3
{
- SCOPED_TRACE("Doing calculation with libraries loaded");
+ SCOPED_TRACE("Calculation with libraries loaded");
executeCallCallouts(10, 3, 33, 2, 62, 3, 183);
}
// Re-execute the calculation - callouts can be called but as nothing
// happens, the result should always be -1.
{
- SCOPED_TRACE("Doing calculation with libraries not loaded");
+ SCOPED_TRACE("Calculation with libraries not loaded");
executeCallCallouts(-1, 3, -1, 22, -1, 83, -1);
}
}
+// Test that we can unload a set of libraries while we have a CalloutHandle
+// created on them in existence, and can delete the handle afterwards.
+
+TEST_F(HooksManagerTest, CalloutHandleUnloadLibrary) {
+
+ // Set up the list of libraries to be loaded.
+ std::vector<std::string> library_names;
+ library_names.push_back(std::string(FULL_CALLOUT_LIBRARY));
+
+ // Load the libraries.
+ EXPECT_TRUE(HooksManager::loadLibraries(library_names));
+
+ // Execute the callouts. Thiis library implements:
+ //
+ // r3 = (7 * d1 - d2) * d3
+ {
+ SCOPED_TRACE("Calculation with full callout library loaded");
+ executeCallCallouts(7, 4, 28, 8, 20, 2, 40);
+ }
+
+ // Get an outstanding callout handle on this library.
+ CalloutHandlePtr handle = HooksManager::createCalloutHandle();
+
+ // Execute once of the callouts again to ensure that the handle contains
+ // memory allocated by the library.
+ HooksManager::callCallouts(ServerHooks::CONTEXT_CREATE, *handle);
+
+ // Unload the libraries.
+ HooksManager::unloadLibraries();
+
+ // Deleting the callout handle should not cause a segmentation fault.
+ handle.reset();
+}
+
+// Test that we can load a new set of libraries while we have a CalloutHandle
+// created on them in existence, and can delete the handle afterwards.
+
+TEST_F(HooksManagerTest, CalloutHandleLoadLibrary) {
+
+ // Set up the list of libraries to be loaded.
+ std::vector<std::string> library_names;
+ library_names.push_back(std::string(FULL_CALLOUT_LIBRARY));
+
+ // Load the libraries.
+ EXPECT_TRUE(HooksManager::loadLibraries(library_names));
+
+ // Execute the callouts. Thiis library implements:
+ //
+ // r3 = (7 * d1 - d2) * d3
+ {
+ SCOPED_TRACE("Calculation with full callout library loaded");
+ executeCallCallouts(7, 4, 28, 8, 20, 2, 40);
+ }
+
+ // Get an outstanding callout handle on this library and execute one of
+ // the callouts again to ensure that the handle contains memory allocated
+ // by the library.
+ CalloutHandlePtr handle = HooksManager::createCalloutHandle();
+ HooksManager::callCallouts(ServerHooks::CONTEXT_CREATE, *handle);
+
+ // Load a new library that implements the calculation
+ //
+ // r3 = (10 + d1) * d2 - d3
+ std::vector<std::string> new_library_names;
+ new_library_names.push_back(std::string(BASIC_CALLOUT_LIBRARY));
+
+ // Load the libraries.
+ EXPECT_TRUE(HooksManager::loadLibraries(new_library_names));
+
+ // Execute the calculation. Note that we still have the CalloutHandle
+ // for the old library: however, this should not affect the new calculation.
+ {
+ SCOPED_TRACE("Calculation with basic callout library loaded");
+ executeCallCallouts(10, 7, 17, 3, 51, 16, 35);
+ }
+
+ // Deleting the old callout handle should not cause a segmentation fault.
+ handle.reset();
+}
+
+// This is effectively the same test as the LoadLibraries test.
+
+TEST_F(HooksManagerTest, ReloadSameLibraries) {
+
+ // Set up the list of libraries to be loaded.
+ std::vector<std::string> library_names;
+ library_names.push_back(std::string(FULL_CALLOUT_LIBRARY));
+ library_names.push_back(std::string(BASIC_CALLOUT_LIBRARY));
+
+ // Load the libraries.
+ EXPECT_TRUE(HooksManager::loadLibraries(library_names));
+
+ // Execute the callouts. See the LoadLibraries test for an explanation of
+ // the calculation.
+ {
+ SCOPED_TRACE("Calculation with libraries loaded");
+ executeCallCallouts(10, 3, 33, 2, 62, 3, 183);
+ }
+
+ // Try reloading the libraries and re-execute the calculation - we should
+ // get the same results.
+ EXPECT_NO_THROW(HooksManager::loadLibraries(library_names));
+ {
+ SCOPED_TRACE("Calculation with libraries reloaded");
+ executeCallCallouts(10, 3, 33, 2, 62, 3, 183);
+ }
+}
+
+TEST_F(HooksManagerTest, ReloadLibrariesReverseOrder) {
+
+ // Set up the list of libraries to be loaded and load them.
+ std::vector<std::string> library_names;
+ library_names.push_back(std::string(FULL_CALLOUT_LIBRARY));
+ library_names.push_back(std::string(BASIC_CALLOUT_LIBRARY));
+ EXPECT_TRUE(HooksManager::loadLibraries(library_names));
+
+ // Execute the callouts. The first library implements the calculation.
+ //
+ // r3 = (7 * d1 - d2) * d3
+ //
+ // The last-loaded library implements the calculation
+ //
+ // r3 = (10 + d1) * d2 - d3
+ //
+ // Putting the processing for each library together in the given order
+ // gives.
+ //
+ // r3 = ((10 * d1 + d1) - d2) * d2 * d3 - d3
+ {
+ SCOPED_TRACE("Calculation with libraries loaded");
+ executeCallCallouts(10, 3, 33, 2, 62, 3, 183);
+ }
+
+ // Reload the libraries in the reverse order.
+ std::reverse(library_names.begin(), library_names.end());
+ EXPECT_TRUE(HooksManager::loadLibraries(library_names));
+
+ // The calculation in the reverse order gives:
+ //
+ // r3 = ((((7 + d1) * d1) * d2 - d2) - d3) * d3
+ {
+ SCOPED_TRACE("Calculation with libraries loaded in reverse order");
+ executeCallCallouts(7, 3, 30, 3, 87, 7, 560);
+ }
+}
+
// Check that everything works even with no libraries loaded. First that
// calloutsPresent() always returns false.
executeCallCallouts(-1, 3, -1, 22, -1, 83, -1);
}
+// Test the encapsulation of the ServerHooks::registerHook() method.
+
+TEST_F(HooksManagerTest, RegisterHooks) {
+ ServerHooks::getServerHooks().reset();
+ EXPECT_EQ(2, ServerHooks::getServerHooks().getCount());
+
+ // Check that the hook indexes are as expected. (Use temporary variables
+ // as it appears that Google test can't access the constants.)
+ int sh_cc = ServerHooks::CONTEXT_CREATE;
+ int hm_cc = HooksManager::CONTEXT_CREATE;
+ EXPECT_EQ(sh_cc, hm_cc);
+
+ int sh_cd = ServerHooks::CONTEXT_DESTROY;
+ int hm_cd = HooksManager::CONTEXT_DESTROY;
+ EXPECT_EQ(sh_cd, hm_cd);
+
+ // Register a few hooks and check we have the indexes as expected.
+ EXPECT_EQ(2, HooksManager::registerHook(string("alpha")));
+ EXPECT_EQ(3, HooksManager::registerHook(string("beta")));
+ EXPECT_EQ(4, HooksManager::registerHook(string("gamma")));
+ EXPECT_THROW(static_cast<void>(HooksManager::registerHook(string("alpha"))),
+ DuplicateHook);
+
+ // ... an check the hooks are as we expect.
+ EXPECT_EQ(5, ServerHooks::getServerHooks().getCount());
+ vector<string> names = ServerHooks::getServerHooks().getHookNames();
+ sort(names.begin(), names.end());
+
+ EXPECT_EQ(string("alpha"), names[0]);
+ EXPECT_EQ(string("beta"), names[1]);
+ EXPECT_EQ(string("context_create"), names[2]);
+ EXPECT_EQ(string("context_destroy"), names[3]);
+ EXPECT_EQ(string("gamma"), names[4]);
+}
+
+
} // Anonymous namespace