libb10_hooks_la_SOURCES += callout_manager.cc callout_manager.h
libb10_hooks_la_SOURCES += hooks.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_CXXFLAGS = $(AM_CXXFLAGS)
libb10_hooks_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
+libb10_hooks_la_LDFLAGS = $(AM_LDFLAGS) -ldl
libb10_hooks_la_LIBADD =
libb10_hooks_la_LIBADD += $(top_builddir)/src/lib/log/libb10-log.la
libb10_hooks_la_LIBADD += $(top_builddir)/src/lib/util/libb10-util.la
#include <hooks/library_handle.h>
// Version 1.0
-static const int BIND10_HOOKS_VERSION = (1 << 16 + 0);
+static const int BIND10_HOOKS_VERSION = 1;
#endif // HOOKS_H
namespace hooks {
class CalloutManager;
+class LibraryManager;
/// @brief Library manager
///
/// callouts from all hooks and closes the library.
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:
/// @brief Constructor
///
/// @param manager CalloutManager object
LibraryManager(const std::string& name, int index,
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
///
/// Open the library and check the version. If all is OK, load all
///
/// @return Name of this library
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:
void* dl_handle_; ///< Handle returned by dlopen
int index_; ///< Index associated with this library
boost::shared_ptr<CalloutManager> manager_;
///< 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
TESTS_ENVIRONMENT = \
$(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_CXXFLAGS = $(AM_CXXFLAGS)
libbco_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
/// @file
/// @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
/// are assumed to be "standard" callouts.
return (callout_manager_);
}
- boost::shared_ptr<ServerHooks> getServerHooks() {
- return (hooks_);
- }
-
/// Static variable used for accumulating information
static int callout_value_;
/// Callout manager used for the test
boost::shared_ptr<CalloutManager> callout_manager_;
-
- /// Server hooks
- boost::shared_ptr<ServerHooks> hooks_;
};
// Definition of the static variable.
--- /dev/null
+// 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);
+}
+
+};
--- /dev/null
+// 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
using namespace isc::hooks;
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 {
+// 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
// 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
// library. This should load all callouts.
LibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY),
- 0, co_manager);
+ 0, getCalloutManager());
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
// always comes first. This sets the context value to 10.
// First callout adds 5 to the context value.
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
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.
- co_manager->callCallouts(three_index, callout_handle);
+ co_manager->callCallouts(gamma_index_, callout_handle);
int result;
callout_handle.getArgument("result", result);
EXPECT_EQ(105, result);
--- /dev/null
+// 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);
+}
+
+};