Parcourir la source

[2980] Basic library manager functionality present

Able to open and close libraries, check for the version()
function and call it.
Stephen Morris il y a 12 ans
Parent
commit
0a4612cfe5

+ 2 - 1
src/lib/hooks/Makefile.am

@@ -18,11 +18,12 @@ libb10_hooks_la_SOURCES += callout_handle.cc callout_handle.h
 libb10_hooks_la_SOURCES += callout_manager.cc callout_manager.h
 libb10_hooks_la_SOURCES += callout_manager.cc callout_manager.h
 libb10_hooks_la_SOURCES += hooks.h
 libb10_hooks_la_SOURCES += hooks.h
 libb10_hooks_la_SOURCES += library_handle.cc library_handle.h
 libb10_hooks_la_SOURCES += library_handle.cc library_handle.h
-libb10_hooks_la_SOURCES += library_manager.h
+libb10_hooks_la_SOURCES += library_manager.cc library_manager.h
 libb10_hooks_la_SOURCES += server_hooks.cc server_hooks.h
 libb10_hooks_la_SOURCES += server_hooks.cc server_hooks.h
 
 
 libb10_hooks_la_CXXFLAGS = $(AM_CXXFLAGS)
 libb10_hooks_la_CXXFLAGS = $(AM_CXXFLAGS)
 libb10_hooks_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
 libb10_hooks_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
+libb10_hooks_la_LDFLAGS  = $(AM_LDFLAGS) -ldl
 libb10_hooks_la_LIBADD  =
 libb10_hooks_la_LIBADD  =
 libb10_hooks_la_LIBADD += $(top_builddir)/src/lib/log/libb10-log.la
 libb10_hooks_la_LIBADD += $(top_builddir)/src/lib/log/libb10-log.la
 libb10_hooks_la_LIBADD += $(top_builddir)/src/lib/util/libb10-util.la
 libb10_hooks_la_LIBADD += $(top_builddir)/src/lib/util/libb10-util.la

+ 1 - 1
src/lib/hooks/hooks.h

@@ -19,6 +19,6 @@
 #include <hooks/library_handle.h>
 #include <hooks/library_handle.h>
 
 
 // Version 1.0
 // Version 1.0
-static const int BIND10_HOOKS_VERSION = (1 << 16 + 0);
+static const int BIND10_HOOKS_VERSION = 1;
 
 
 #endif  // HOOKS_H
 #endif  // HOOKS_H

+ 56 - 8
src/lib/hooks/library_manager.h

@@ -23,6 +23,7 @@ namespace isc {
 namespace hooks {
 namespace hooks {
 
 
 class CalloutManager;
 class CalloutManager;
+class LibraryManager;
 
 
 /// @brief Library manager
 /// @brief Library manager
 ///
 ///
@@ -38,6 +39,12 @@ class CalloutManager;
 /// callouts from all hooks and closes the library.
 /// callouts from all hooks and closes the library.
 
 
 class LibraryManager {
 class LibraryManager {
+private:
+    /// Useful typedefs for the framework functions
+    typedef int (*version_function_ptr)();          ///< version() signature
+    typedef int (*load_function_ptr)();             ///< load() signature
+    typedef int (*unload_function_ptr)(LibraryHandle&); ///< unload() signature
+
 public:
 public:
     /// @brief Constructor
     /// @brief Constructor
     ///
     ///
@@ -49,11 +56,19 @@ public:
     /// @param manager CalloutManager object
     /// @param manager CalloutManager object
     LibraryManager(const std::string& name, int index,
     LibraryManager(const std::string& name, int index,
                    const boost::shared_ptr<CalloutManager>& manager)
                    const boost::shared_ptr<CalloutManager>& manager)
-        : dl_handle_(NULL), index_(index), manager_(manager), name_(name),
-          load_func_(NULL), unload_func_(NULL),
-          version_func_(NULL)
+        : dl_handle_(NULL), index_(index), manager_(manager),
+          library_name_(name), load_func_(NULL), unload_func_(NULL)
     {}
     {}
 
 
+    /// @brief Destructor
+    ///
+    /// If the library is open, closes it.  This is principally a safety
+    /// feature to ensure closure in the case of an exception destroying
+    /// this object.
+    ~LibraryManager() {
+        static_cast<void>(closeLibrary());
+    }
+
     /// @brief Loads a library
     /// @brief Loads a library
     ///
     ///
     /// Open the library and check the version.  If all is OK, load all
     /// Open the library and check the version.  If all is OK, load all
@@ -70,19 +85,52 @@ public:
     ///
     ///
     /// @return Name of this library
     /// @return Name of this library
     std::string getName() const {
     std::string getName() const {
-        return (name_);
+        return (library_name_);
     }
     }
 
 
+protected:
+    // The following methods are protected as they are accessed in testing.
+
+    /// @brief Open library
+    ///
+    /// Opens the library associated with this LibraryManager.  A message is
+    /// logged on an error.
+    ///
+    /// @return true if the library opened successfully, false otherwise.
+    bool openLibrary();
+
+    /// @brief Close library
+    ///
+    /// Closes the library associated with this LibraryManager.  A message is
+    /// logged on an error.
+    ///
+    /// @return true if the library closed successfully, false otherwise.
+    ///         "true" is also returned if the library were already closed
+    ///         when this method was called.
+    bool closeLibrary();
+
+
+    /// @brief Check library version
+    ///
+    /// With the library open, accesses the "version()" function and, if
+    /// present, checks the returned value against the hooks version symbol
+    /// for the currently running BIND 10.
+    ///
+    /// If there is no version() function, or if there is a mismatch in
+    /// version number, a message logged.
+    ///
+    /// @return bool true if the check succeeded
+    bool checkVersion() const;
+
 private:
 private:
     void*       dl_handle_;     ///< Handle returned by dlopen
     void*       dl_handle_;     ///< Handle returned by dlopen
     int         index_;         ///< Index associated with this library
     int         index_;         ///< Index associated with this library
     boost::shared_ptr<CalloutManager> manager_;
     boost::shared_ptr<CalloutManager> manager_;
                                 ///< Callout manager for registration
                                 ///< Callout manager for registration
-    std::string name_;          ///< Name of the library
+    std::string library_name_;  ///< Name of the library
 
 
-    void*       load_func_;     ///< Pointer to the "load" function
-    void*       unload_func_;   ///< Pointer to the "unload" function
-    void*       version_func_;  ///< Pointer to the "version" function
+    load_function_ptr       load_func_;     ///< Pointer to "load" function
+    unload_function_ptr     unload_func_;   ///< Pointer to "unload" function
 };
 };
 
 
 } // namespace hooks
 } // namespace hooks

+ 15 - 2
src/lib/hooks/tests/Makefile.am

@@ -24,8 +24,21 @@ CLEANFILES = *.gcno *.gcda
 TESTS_ENVIRONMENT = \
 TESTS_ENVIRONMENT = \
 	$(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
 	$(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
 
 
-# Build shared libraries for testing.  The Basic Callout Library
-lib_LTLIBRARIES = libbco.la
+# Build shared libraries for testing.
+lib_LTLIBRARIES = libnv.la libiv.la libbco.la
+ 
+# No version function
+libnv_la_SOURCES  = no_version_library.cc
+libnv_la_CXXFLAGS = $(AM_CXXFLAGS)
+libnv_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
+ 
+# Incorrect version function
+libiv_la_SOURCES  = incorrect_version_library.cc
+libiv_la_CXXFLAGS = $(AM_CXXFLAGS)
+libiv_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
+
+
+# The basic callout library
 libbco_la_SOURCES  = basic_callout_library.cc
 libbco_la_SOURCES  = basic_callout_library.cc
 libbco_la_CXXFLAGS = $(AM_CXXFLAGS)
 libbco_la_CXXFLAGS = $(AM_CXXFLAGS)
 libbco_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
 libbco_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)

+ 4 - 2
src/lib/hooks/tests/basic_callout_library.cc

@@ -15,8 +15,10 @@
 /// @file
 /// @file
 /// @brief Basic Callout Library
 /// @brief Basic Callout Library
 ///
 ///
-/// This file is built into a shared library and is loaded by the LibraryManager
-/// test.  The characteristics of this library are:
+/// This is a test file for the LibraryManager test.  It produces a library
+/// that allows for tests of the basic library manager functions.
+///
+/// The characteristics of this library are:
 ///
 ///
 /// - Only the "version" framework function is supplied.  The other callouts
 /// - Only the "version" framework function is supplied.  The other callouts
 ///   are assumed to be "standard" callouts.
 ///   are assumed to be "standard" callouts.

+ 0 - 7
src/lib/hooks/tests/callout_manager_unittest.cc

@@ -76,10 +76,6 @@ public:
         return (callout_manager_);
         return (callout_manager_);
     }
     }
 
 
-    boost::shared_ptr<ServerHooks> getServerHooks() {
-        return (hooks_);
-    }
-
     /// Static variable used for accumulating information
     /// Static variable used for accumulating information
     static int callout_value_;
     static int callout_value_;
 
 
@@ -96,9 +92,6 @@ private:
 
 
     /// Callout manager used for the test
     /// Callout manager used for the test
     boost::shared_ptr<CalloutManager> callout_manager_;
     boost::shared_ptr<CalloutManager> callout_manager_;
-
-    /// Server hooks
-    boost::shared_ptr<ServerHooks> hooks_;
 };
 };
 
 
 // Definition of the static variable.
 // Definition of the static variable.

+ 29 - 0
src/lib/hooks/tests/incorrect_version_library.cc

@@ -0,0 +1,29 @@
+// Copyright (C) 2013  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.
+
+/// @file
+/// @brief Incorrect version function test
+/// This is a test file for the LibraryManager test.  It produces a library
+/// that contans a "version" function but which returns an incorrect version
+/// number.
+
+#include <hooks/hooks.h>
+
+extern "C" {
+
+int version() {
+    return (BIND10_HOOKS_VERSION + 1);
+}
+
+};

+ 241 - 0
src/lib/hooks/tests/library_manager_unittest.cc

@@ -0,0 +1,241 @@
+// Copyright (C) 2013  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 <hooks/callout_handle.h>
+#include <hooks/callout_manager.h>
+#include <hooks/library_manager.h>
+#include <hooks/server_hooks.h>
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+using namespace isc;
+using namespace isc::hooks;
+using namespace std;
+
+/// @brief Library manager test class
+
+class LibraryManagerTest : public ::testing::Test {
+public:
+    /// @brief Constructor
+    ///
+    /// Sets up a collection of three LibraryHandle objects to use in the test.
+    LibraryManagerTest() {
+
+        // Set up the server hooks.  There is sone singleton for all tests,
+        // so reset it and explicitly set up the hooks for the test.
+        ServerHooks& hooks = ServerHooks::getServerHooks();
+        hooks.reset();
+        alpha_index_ = hooks.registerHook("alpha");
+        beta_index_ = hooks.registerHook("beta");
+        gamma_index_ = hooks.registerHook("gamma");
+
+        // Set up the callout manager with these hooks.  Assume a maximum of
+        // four libraries.
+        callout_manager_.reset(new CalloutManager(1));
+
+        // Set up the callout handle.
+        callout_handle_.reset(new CalloutHandle(callout_manager_));
+    }
+
+    /// @brief Return the callout handle
+    CalloutHandle& getCalloutHandle() {
+        return (*callout_handle_);
+    }
+
+    /// @brief Return the callout manager
+    boost::shared_ptr<CalloutManager> getCalloutManager() {
+        return (callout_manager_);
+    }
+
+    /// Hook indexes.  These are somewhat ubiquitous, so are made public for
+    /// ease of reference instead of being accessible by a function.
+    int alpha_index_;
+    int beta_index_;
+    int gamma_index_;
+
+private:
+    /// Callout handle used in calls
+    boost::shared_ptr<CalloutHandle> callout_handle_;
+
+    /// Callout manager used for the test
+    boost::shared_ptr<CalloutManager> callout_manager_;
+};
+
+
+/// @brief Library manager class
+///
+/// This is an instance of the LibraryManager class but with the protected
+/// methods made public for test purposes.
+
+class PublicLibraryManager : public isc::hooks::LibraryManager {
+public:
+    /// @brief Constructor
+    ///
+    /// Stores the library name.  The actual loading is done in loadLibrary().
+    ///
+    /// @param name Name of the library to load.  This should be an absolute
+    ///        path name.
+    /// @param index Index of this library
+    /// @param manager CalloutManager object
+    PublicLibraryManager(const std::string& name, int index,
+                         const boost::shared_ptr<CalloutManager>& manager)
+        : LibraryManager(name, index, manager)
+    {}
+
+    /// Public methods that call protected methods on the superclass
+    //@{
+    /// @brief Open library
+    ///
+    /// Opens the library associated with this LibraryManager.  A message is
+    /// logged on an error.
+    ///
+    /// @return true if the library opened successfully, false otherwise.
+    bool openLibrary() {
+        return (LibraryManager::openLibrary());
+    }
+
+    /// @brief Close library
+    ///
+    /// Closes the library associated with this LibraryManager.  A message is
+    /// logged on an error.
+    ///
+    /// @return true if the library closed successfully, false otherwise.
+    bool closeLibrary() {
+        return (LibraryManager::closeLibrary());
+    }
+
+
+    /// @brief Check library version
+    ///
+    /// With the library open, accesses the "version()" function and, if
+    /// present, checks the returned value against the hooks version symbol
+    /// for the currently running BIND 10.
+    ///
+    /// If there is no version() function, or if there is a mismatch in
+    /// version number, a message logged.
+    ///
+    /// @return bool true if the check succeeded
+    bool checkVersion() const {
+        return (LibraryManager::checkVersion());
+    }
+
+    //@}
+};
+
+// Names of the libraries used in these tests.  These libraries are built using
+// libtool, so we need to look in the hidden ".libs" directory to locate the
+// .so file.  Note that we access the .so file - libtool creates this as a
+// like to the real shared library.
+static const char* NOT_PRESENT_LIBRARY = "/home/stephen/bind10/src/lib/hooks/tests/.libs/libnothere.so";
+static const char* NO_VERSION_LIBRARY = "/home/stephen/bind10/src/lib/hooks/tests/.libs/libnv.so";
+static const char* INCORRECT_VERSION_LIBRARY = "/home/stephen/bind10/src/lib/hooks/tests/.libs/libiv.so";
+static const char* BASIC_CALLOUT_LIBRARY = "/home/stephen/bind10/src/lib/hooks/tests/.libs/libbco.so";
+
+
+namespace {
+
+// Tests that OpenLibrary reports an error for an unknown library.
+
+TEST_F(LibraryManagerTest, NonExistentLibrary) {
+    // Check that opening a non-existent library fails.
+    PublicLibraryManager lib_manager(std::string(NOT_PRESENT_LIBRARY),
+                                     0, getCalloutManager());
+    EXPECT_FALSE(lib_manager.openLibrary());
+}
+
+// Tests that OpenLibrary handles the case of no version present.
+
+TEST_F(LibraryManagerTest, NoVersionFunction) {
+    PublicLibraryManager lib_manager(std::string(NO_VERSION_LIBRARY),
+                                     0, getCalloutManager());
+    // Open should succeed.
+    EXPECT_TRUE(lib_manager.openLibrary());
+
+    // Version check should fail.
+    EXPECT_FALSE(lib_manager.checkVersion());
+
+    // Tidy up.
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
+// Tests that OpenLibrary reports an error for an unknown library.
+
+TEST_F(LibraryManagerTest, IncorrectVersionReturned) {
+    PublicLibraryManager lib_manager(std::string(INCORRECT_VERSION_LIBRARY),
+                                     0, getCalloutManager());
+    // Open should succeed.
+    EXPECT_TRUE(lib_manager.openLibrary());
+
+    // Version check should fail.
+    EXPECT_FALSE(lib_manager.checkVersion());
+
+    // Tidy up.
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
+// Tests that the openLibrary() and closeLibrary() methods work.
+
+TEST_F(LibraryManagerTest, OpenClose) {
+
+    // Create the library manager.
+    PublicLibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY),
+                                     0, getCalloutManager());
+
+    // Open and close the library
+    EXPECT_TRUE(lib_manager.openLibrary());
+    EXPECT_TRUE(lib_manager.closeLibrary());
+
+    // Check that closing an already closed library causes no problems.
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
+// Checks the basic functionality - loads a library where the callouts are
+// named after the hooks, calls the callouts and checks the results.
+
+TEST_F(LibraryManagerTest, BasicCalloutTest) {
+
+    // Load the only library, specifying the index of 0 as it's the only
+    // library.  This should load all callouts.
+    LibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY),
+                               0, getCalloutManager());
+    EXPECT_NO_THROW(lib_manager.loadLibrary());
+
+    // Set up abbreviations...
+    boost::shared_ptr<CalloutManager> co_manager = getCalloutManager();
+    CalloutHandle& callout_handle = getCalloutHandle();
+
+    // Now execute the callouts in the order expected.  context_create
+    // always comes first.  This sets the context value to 10.
+    co_manager->callCallouts(ServerHooks::CONTEXT_CREATE, callout_handle);
+
+    // First callout adds 5 to the context value.
+    callout_handle.setArgument("data_1", static_cast<int>(5));
+    co_manager->callCallouts(alpha_index_, callout_handle);
+
+    // Second callout multiples the context value by 7
+    callout_handle.setArgument("data_2", static_cast<int>(7));
+    co_manager->callCallouts(beta_index_, callout_handle);
+
+    // Third callour retrieves the context value.
+    co_manager->callCallouts(gamma_index_, callout_handle);
+    int result;
+    callout_handle.getArgument("result", result);
+    EXPECT_EQ(105, result);
+}
+
+} // Anonymous namespace

+ 178 - 18
src/lib/hooks/tests/library_manager_unittest.cc.in

@@ -27,34 +27,194 @@ using namespace isc;
 using namespace isc::hooks;
 using namespace isc::hooks;
 using namespace std;
 using namespace std;
 
 
-// Names of the libraries used in these tests
-static const char* BASIC_CALLOUT_LIBRARY = "@builddir@/.libs/libbco.so";
+/// @brief Library manager test class
+
+class LibraryManagerTest : public ::testing::Test {
+public:
+    /// @brief Constructor
+    ///
+    /// Sets up a collection of three LibraryHandle objects to use in the test.
+    LibraryManagerTest() {
+
+        // Set up the server hooks.  There is sone singleton for all tests,
+        // so reset it and explicitly set up the hooks for the test.
+        ServerHooks& hooks = ServerHooks::getServerHooks();
+        hooks.reset();
+        alpha_index_ = hooks.registerHook("alpha");
+        beta_index_ = hooks.registerHook("beta");
+        gamma_index_ = hooks.registerHook("gamma");
+
+        // Set up the callout manager with these hooks.  Assume a maximum of
+        // four libraries.
+        callout_manager_.reset(new CalloutManager(1));
+
+        // Set up the callout handle.
+        callout_handle_.reset(new CalloutHandle(callout_manager_));
+    }
+
+    /// @brief Return the callout handle
+    CalloutHandle& getCalloutHandle() {
+        return (*callout_handle_);
+    }
+
+    /// @brief Return the callout manager
+    boost::shared_ptr<CalloutManager> getCalloutManager() {
+        return (callout_manager_);
+    }
+
+    /// Hook indexes.  These are somewhat ubiquitous, so are made public for
+    /// ease of reference instead of being accessible by a function.
+    int alpha_index_;
+    int beta_index_;
+    int gamma_index_;
+
+private:
+    /// Callout handle used in calls
+    boost::shared_ptr<CalloutHandle> callout_handle_;
+
+    /// Callout manager used for the test
+    boost::shared_ptr<CalloutManager> callout_manager_;
+};
+
+
+/// @brief Library manager class
+///
+/// This is an instance of the LibraryManager class but with the protected
+/// methods made public for test purposes.
+
+class PublicLibraryManager : public isc::hooks::LibraryManager {
+public:
+    /// @brief Constructor
+    ///
+    /// Stores the library name.  The actual loading is done in loadLibrary().
+    ///
+    /// @param name Name of the library to load.  This should be an absolute
+    ///        path name.
+    /// @param index Index of this library
+    /// @param manager CalloutManager object
+    PublicLibraryManager(const std::string& name, int index,
+                         const boost::shared_ptr<CalloutManager>& manager)
+        : LibraryManager(name, index, manager)
+    {}
+
+    /// Public methods that call protected methods on the superclass
+    //@{
+    /// @brief Open library
+    ///
+    /// Opens the library associated with this LibraryManager.  A message is
+    /// logged on an error.
+    ///
+    /// @return true if the library opened successfully, false otherwise.
+    bool openLibrary() {
+        return (LibraryManager::openLibrary());
+    }
+
+    /// @brief Close library
+    ///
+    /// Closes the library associated with this LibraryManager.  A message is
+    /// logged on an error.
+    ///
+    /// @return true if the library closed successfully, false otherwise.
+    bool closeLibrary() {
+        return (LibraryManager::closeLibrary());
+    }
+
+
+    /// @brief Check library version
+    ///
+    /// With the library open, accesses the "version()" function and, if
+    /// present, checks the returned value against the hooks version symbol
+    /// for the currently running BIND 10.
+    ///
+    /// If there is no version() function, or if there is a mismatch in
+    /// version number, a message logged.
+    ///
+    /// @return bool true if the check succeeded
+    bool checkVersion() const {
+        return (LibraryManager::checkVersion());
+    }
+
+    //@}
+};
+
+// Names of the libraries used in these tests.  These libraries are built using
+// libtool, so we need to look in the hidden ".libs" directory to locate the
+// .so file.  Note that we access the .so file - libtool creates this as a
+// like to the real shared library.
+static const char* NOT_PRESENT_LIBRARY = "@abs_builddir@/.libs/libnothere.so";
+static const char* NO_VERSION_LIBRARY = "@abs_builddir@/.libs/libnv.so";
+static const char* INCORRECT_VERSION_LIBRARY = "@abs_builddir@/.libs/libiv.so";
+static const char* BASIC_CALLOUT_LIBRARY = "@abs_builddir@/.libs/libbco.so";
 
 
 
 
 namespace {
 namespace {
 
 
+// Tests that OpenLibrary reports an error for an unknown library.
+
+TEST_F(LibraryManagerTest, NonExistentLibrary) {
+    // Check that opening a non-existent library fails.
+    PublicLibraryManager lib_manager(std::string(NOT_PRESENT_LIBRARY),
+                                     0, getCalloutManager());
+    EXPECT_FALSE(lib_manager.openLibrary());
+}
+
+// Tests that OpenLibrary handles the case of no version present.
+
+TEST_F(LibraryManagerTest, NoVersionFunction) {
+    PublicLibraryManager lib_manager(std::string(NO_VERSION_LIBRARY),
+                                     0, getCalloutManager());
+    // Open should succeed.
+    EXPECT_TRUE(lib_manager.openLibrary());
+
+    // Version check should fail.
+    EXPECT_FALSE(lib_manager.checkVersion());
+
+    // Tidy up.
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
+// Tests that OpenLibrary reports an error for an unknown library.
+
+TEST_F(LibraryManagerTest, IncorrectVersionReturned) {
+    PublicLibraryManager lib_manager(std::string(INCORRECT_VERSION_LIBRARY),
+                                     0, getCalloutManager());
+    // Open should succeed.
+    EXPECT_TRUE(lib_manager.openLibrary());
+
+    // Version check should fail.
+    EXPECT_FALSE(lib_manager.checkVersion());
+
+    // Tidy up.
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
+// Tests that the openLibrary() and closeLibrary() methods work.
+
+TEST_F(LibraryManagerTest, OpenClose) {
+
+    // Create the library manager.
+    PublicLibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY),
+                                     0, getCalloutManager());
+
+    // Open and close the library
+    EXPECT_TRUE(lib_manager.openLibrary());
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
 // Checks the basic functionality - loads a library where the callouts are
 // Checks the basic functionality - loads a library where the callouts are
 // named after the hooks, calls the callouts and checks the results.
 // named after the hooks, calls the callouts and checks the results.
 
 
-TEST(LibraryManagerTest, BasicCalloutTest) {
-    // Set up the hooks we expect.
-    ServerHooks& hooks = ServerHooks::getServerHooks();
-    hooks.reset();
-    int one_index = hooks.registerHook("basic_one");
-    int two_index = hooks.registerHook("basic_two");
-    int three_index = hooks.registerHook("basic_three");
-
-    // Set up the callout manager with one library.
-    boost::shared_ptr<CalloutManager> co_manager(new CalloutManager(1));
+TEST_F(LibraryManagerTest, BasicCalloutTest) {
 
 
     // Load the only library, specifying the index of 0 as it's the only
     // Load the only library, specifying the index of 0 as it's the only
     // library.  This should load all callouts.
     // library.  This should load all callouts.
     LibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY),
     LibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY),
-                               0, co_manager);
+                               0, getCalloutManager());
     EXPECT_NO_THROW(lib_manager.loadLibrary());
     EXPECT_NO_THROW(lib_manager.loadLibrary());
 
 
-    // Create the callout handle...
-    CalloutHandle callout_handle(co_manager);
+    // Set up abbreviations...
+    boost::shared_ptr<CalloutManager> co_manager = getCalloutManager();
+    CalloutHandle& callout_handle = getCalloutHandle();
 
 
     // Now execute the callouts in the order expected.  context_create
     // Now execute the callouts in the order expected.  context_create
     // always comes first.  This sets the context value to 10.
     // always comes first.  This sets the context value to 10.
@@ -62,14 +222,14 @@ TEST(LibraryManagerTest, BasicCalloutTest) {
 
 
     // First callout adds 5 to the context value.
     // First callout adds 5 to the context value.
     callout_handle.setArgument("data_1", static_cast<int>(5));
     callout_handle.setArgument("data_1", static_cast<int>(5));
-    co_manager->callCallouts(one_index, callout_handle);
+    co_manager->callCallouts(alpha_index_, callout_handle);
 
 
     // Second callout multiples the context value by 7
     // Second callout multiples the context value by 7
     callout_handle.setArgument("data_2", static_cast<int>(7));
     callout_handle.setArgument("data_2", static_cast<int>(7));
-    co_manager->callCallouts(two_index, callout_handle);
+    co_manager->callCallouts(beta_index_, callout_handle);
 
 
     // Third callour retrieves the context value.
     // Third callour retrieves the context value.
-    co_manager->callCallouts(three_index, callout_handle);
+    co_manager->callCallouts(gamma_index_, callout_handle);
     int result;
     int result;
     callout_handle.getArgument("result", result);
     callout_handle.getArgument("result", result);
     EXPECT_EQ(105, result);
     EXPECT_EQ(105, result);

+ 27 - 0
src/lib/hooks/tests/no_version_library.cc

@@ -0,0 +1,27 @@
+// Copyright (C) 2013  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.
+
+/// @file
+/// @brief No version function library
+///
+/// This is a test file for the LibraryManager test.  It produces a library
+/// that does not have a "version" function.
+
+extern "C" {
+
+int no_version() {
+    return (0);
+}
+
+};