BIND 10 trac2974, updated. 0df2936c8f985071e97fb17d9685266fc0d443a5 [2974] Final check of documentation for the hooks data structures
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Jun 10 18:28:38 UTC 2013
The branch, trac2974 has been updated
via 0df2936c8f985071e97fb17d9685266fc0d443a5 (commit)
via b1c398bbc0d7b7b066347cff13ea8fb310bf4f10 (commit)
via 777c26581b971935e9d77cc1b70f0909ab3534e6 (commit)
via 347a2846eaacb84791fedcda6537d2fd8be6160f (commit)
via bc6a657a16a55350992cbe251f010d0a46d11dea (commit)
via 946f8117826ae2df528c76901f6e1426cdf614e0 (commit)
from ab1890f4594c873aca0b7f483234de5cd3e5e01c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 0df2936c8f985071e97fb17d9685266fc0d443a5
Author: Stephen Morris <stephen at isc.org>
Date: Mon Jun 10 19:27:33 2013 +0100
[2974] Final check of documentation for the hooks data structures
commit b1c398bbc0d7b7b066347cff13ea8fb310bf4f10
Author: Stephen Morris <stephen at isc.org>
Date: Mon Jun 10 17:23:48 2013 +0100
[2974] Updated CalloutHandle to use the new CalloutManager
commit 777c26581b971935e9d77cc1b70f0909ab3534e6
Author: Stephen Morris <stephen at isc.org>
Date: Mon Jun 10 13:49:36 2013 +0100
[2974] Updated CalloutHandle in line with new CalloutManager
commit 347a2846eaacb84791fedcda6537d2fd8be6160f
Author: Stephen Morris <stephen at isc.org>
Date: Mon Jun 10 13:01:17 2013 +0100
[2974] Add getNumLibraries() method to CalloutManager.
commit bc6a657a16a55350992cbe251f010d0a46d11dea
Author: Stephen Morris <stephen at isc.org>
Date: Mon Jun 10 12:33:01 2013 +0100
[2974] CalloutManager now maintains c oncept of "current library"
The responsibility of maintaining this information has been moved
from the LibraryHandle. As a result, LibraryHandle is now a shell
providing a restricted access to the CalloutManager, ensuring that
callouts can only register/deregister callouts within their own
library.
commit 946f8117826ae2df528c76901f6e1426cdf614e0
Author: Stephen Morris <stephen at isc.org>
Date: Mon Jun 10 10:38:51 2013 +0100
[2974] Updated CalloutManager tests.
-----------------------------------------------------------------------
Summary of changes:
src/lib/util/Makefile.am | 2 +-
src/lib/util/hooks/callout_handle.cc | 46 +-
src/lib/util/hooks/callout_handle.h | 49 +-
src/lib/util/hooks/callout_manager.cc | 101 ++--
src/lib/util/hooks/callout_manager.h | 227 +++++++--
src/lib/util/hooks/library_handle.cc | 6 +-
src/lib/util/hooks/library_handle.h | 53 +-
src/lib/util/hooks/server_hooks.cc | 18 +-
src/lib/util/hooks/server_hooks.h | 45 +-
src/lib/util/tests/Makefile.am | 5 +-
src/lib/util/tests/callout_handle_unittest.cc | 45 +-
src/lib/util/tests/callout_manager_unittest.cc | 638 ++++++++++++++++--------
src/lib/util/tests/handles_unittest.cc | 470 ++++++++++++-----
src/lib/util/tests/library_handle_unittest.cc | 303 -----------
src/lib/util/tests/server_hooks_unittest.cc | 10 +-
15 files changed, 1135 insertions(+), 883 deletions(-)
delete mode 100644 src/lib/util/tests/library_handle_unittest.cc
-----------------------------------------------------------------------
diff --git a/src/lib/util/Makefile.am b/src/lib/util/Makefile.am
index 9c66fd5..6d07ac8 100644
--- a/src/lib/util/Makefile.am
+++ b/src/lib/util/Makefile.am
@@ -38,7 +38,7 @@ libb10_util_la_SOURCES += encode/base_n.cc encode/hex.h
libb10_util_la_SOURCES += encode/binary_from_base32hex.h
libb10_util_la_SOURCES += encode/binary_from_base16.h
libb10_util_la_SOURCES += hooks/callout_manager.h hooks/callout_manager.cc
-# libb10_util_la_SOURCES += hooks/callout_handle.h hooks/callout_handle.cc
+libb10_util_la_SOURCES += hooks/callout_handle.h hooks/callout_handle.cc
libb10_util_la_SOURCES += hooks/library_handle.h hooks/library_handle.cc
libb10_util_la_SOURCES += hooks/server_hooks.h hooks/server_hooks.cc
libb10_util_la_SOURCES += random/qid_gen.h random/qid_gen.cc
diff --git a/src/lib/util/hooks/callout_handle.cc b/src/lib/util/hooks/callout_handle.cc
index 38058e9..5b6b3b2 100644
--- a/src/lib/util/hooks/callout_handle.cc
+++ b/src/lib/util/hooks/callout_handle.cc
@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <util/hooks/callout_handle.h>
+#include <util/hooks/callout_manager.h>
#include <util/hooks/library_handle.h>
#include <util/hooks/server_hooks.h>
@@ -27,16 +28,13 @@ namespace isc {
namespace util {
// Constructor.
-CalloutHandle::CalloutHandle(
- boost::shared_ptr<LibraryHandleCollection>& collection)
- : arguments_(), context_collection_(), library_collection_(collection),
- skip_(false) {
+CalloutHandle::CalloutHandle(const boost::shared_ptr<CalloutManager>& manager)
+ : arguments_(), context_collection_(), manager_(manager), skip_(false) {
// Call the "context_create" hook. We should be OK doing this - although
// the constructor has not finished running, all the member variables
// have been created.
- int status = library_collection_->callCallouts(ServerHooks::CONTEXT_CREATE,
- *this);
+ int status = manager_->callCallouts(ServerHooks::CONTEXT_CREATE, *this);
if (status > 0) {
isc_throw(ContextCreateFail, "error code of " << status << " returned "
"from context_create callout during the creation of a "
@@ -50,11 +48,10 @@ CalloutHandle::~CalloutHandle() {
// Call the "context_destroy" hook. We should be OK doing this - although
// the destructor is being called, all the member variables are still in
// existence.
- int status = library_collection_->callCallouts(ServerHooks::CONTEXT_DESTROY,
- *this);
+ int status = manager_->callCallouts(ServerHooks::CONTEXT_DESTROY, *this);
if (status > 0) {
// An exception is thrown on failure. This may be severe, but if
- // none is thrown a resoucre leak in a library (signalled by the
+ // none is thrown a resource leak in a library (signalled by the
// context_destroy callout returning an error) may be difficult to
// trace.
isc_throw(ContextDestroyFail, "error code of " << status << " returned "
@@ -77,30 +74,12 @@ CalloutHandle::getArgumentNames() const {
return (names);
}
-// Return the "current" library handle.
+// Return the library handle allowing the callout to access the CalloutManager
+// registration/deregistration functions.
LibraryHandle&
CalloutHandle::getLibraryHandle() const {
- boost::shared_ptr<LibraryHandle> handle =
- library_collection_->getLibraryHandle();
-
- // Return refernce to this library handle. This remains valid even
- // after this method returns, because this object maintains a shared
- // pointer to the LibraryHandleCollection, which in turn maintains
- // a shared pointer to the LibraryHandle in question.
- return (*handle);
-}
-
-// Check the current library index.
-
-int
-CalloutHandle::getLibraryIndex() const {
- int curidx = library_collection_->getLibraryIndex();
- if (curidx < 0) {
- isc_throw(InvalidIndex, "current library handle index is not valid");
- }
-
- return (curidx);
+ return (manager_->getLibraryHandle());
}
// Return the context for the currently pointed-to library. This version is
@@ -109,7 +88,7 @@ CalloutHandle::getLibraryIndex() const {
CalloutHandle::ElementCollection&
CalloutHandle::getContextForLibrary() {
- int libindex = getLibraryIndex();
+ int libindex = manager_->getLibraryIndex();
// Access a reference to the element collection for the given index,
// creating a new element collection if necessary, and return it.
@@ -121,13 +100,14 @@ CalloutHandle::getContextForLibrary() {
const CalloutHandle::ElementCollection&
CalloutHandle::getContextForLibrary() const {
- int libindex = getLibraryIndex();
+ int libindex = manager_->getLibraryIndex();
ContextCollection::const_iterator libcontext =
context_collection_.find(libindex);
if (libcontext == context_collection_.end()) {
isc_throw(NoSuchCalloutContext, "unable to find callout context "
- "associated with the current library handle");
+ "associated with the current library index (" << libindex <<
+ ")");
}
// Return a reference to the context's element collection.
diff --git a/src/lib/util/hooks/callout_handle.h b/src/lib/util/hooks/callout_handle.h
index 87d9cb7..ad3ef67 100644
--- a/src/lib/util/hooks/callout_handle.h
+++ b/src/lib/util/hooks/callout_handle.h
@@ -16,6 +16,7 @@
#define CALLOUT_HANDLE_H
#include <exceptions/exceptions.h>
+#include <util/hooks/library_handle.h>
#include <boost/any.hpp>
#include <boost/shared_ptr.hpp>
@@ -100,17 +101,22 @@ class LibraryHandle;
/// "context_destroy" callout. The information is accessed through the
/// {get,set}Context() methods.
///
-/// - Per-library context. Each library has a context associated with it that
-/// is independent of the packet. All callouts in the library share the
-/// information in the context, regardless of the packet being processed.
-/// The context is typically created in the library's "load()" method and
-/// destroyed in its "unload()" method. The information is available by
-/// obtaining the handle to the library through this class's
-/// getLibraryHandle() method, then calling {get,set}Context() on the
-/// object returned.
+/// - Per-library handle. Allows the callout to dynamically register and
+/// deregister callouts. (In the latter case, only functions registered by
+/// functions in the same library as the callout doing the deregistration
+/// can be removed: callouts registered by other libraries cannot be
+/// modified.)
class CalloutHandle {
public:
+ /// Callout success return status - the next callout in the list for the
+ /// hook will be called.
+ static const int SUCCESS = 0;
+
+ /// Callout complete return status - the callout has succeeded, but
+ /// remaining callouts on this hook (including any from other libraries)
+ /// should not be run.
+ static const int COMPLETE = 1;
/// Typedef to allow abbreviation of iterator specification in methods.
/// The std::string is the argument name and the "boost::any" is the
@@ -120,8 +126,8 @@ public:
/// Typedef to allow abbreviations in specifications when accessing
/// context. The ElementCollection is the name/value collection for
/// a particular context. The "int" corresponds to the index of an
- /// associated library handle - there is a 1:1 correspondence between
- /// library handles and a name.value collection.
+ /// associated library - there is a 1:1 correspondence between libraries
+ /// and a name.value collection.
///
/// The collection of contexts is stored in a map, as not every library
/// will require creation of a context associated with each packet. In
@@ -136,12 +142,12 @@ public:
/// hook.
///
/// @param manager Pointer to the callout manager object.
- CalloutHandle(boost::shared_ptr<CalloutManager>& /* manager */) {}
+ CalloutHandle(const boost::shared_ptr<CalloutManager>& manager);
/// @brief Destructor
///
/// Calls the context_destroy callback to release any per-packet context.
- ~CalloutHandle() {}
+ ~CalloutHandle();
/// @brief Set argument
///
@@ -149,7 +155,7 @@ public:
/// already exist.
///
/// @param name Name of the argument.
- /// @param value Value to set
+ /// @param value Value to set. That can be of any data type.
template <typename T>
void setArgument(const std::string& name, T value) {
arguments_[name] = value;
@@ -183,7 +189,7 @@ public:
/// Returns a vector holding the names of arguments in the argument
/// vector.
///
- /// @return Vector of strings reflecting argument names
+ /// @return Vector of strings reflecting argument names.
std::vector<std::string> getArgumentNames() const;
/// @brief Delete argument
@@ -234,15 +240,14 @@ public:
/// Returns a reference to the current library handle. This function is
/// only available when called by a callout (which in turn is called
/// through the "callCallouts" method), as it is only then that the current
- /// library index is valid. A callout would use this method to get to
- /// the context associated with the library in which it resides.
+ /// library index is valid. A callout uses the library handle to
+ /// dynamically register or deregister callouts.
///
- /// @return Reference to the current library handle.
+ /// @return Reference to the library handle.
///
- /// @throw InvalidIndex thrown if this method is called outside of the
- /// "callCallouts() method. (Exception is so-named because the
- /// index used to access the library handle in the collection
- /// is not valid at that point.)
+ /// @throw InvalidIndex thrown if this method is called when the current
+ /// library index is invalid (typically if it is called outside of
+ /// the active callout).
LibraryHandle& getLibraryHandle() const;
/// @brief Set context
@@ -278,7 +283,7 @@ public:
if (element_ptr == lib_context.end()) {
isc_throw(NoSuchCalloutContext, "unable to find callout context "
"item " << name << " in the context associated with "
- "current library handle");
+ "current library");
}
value = boost::any_cast<T>(element_ptr->second);
diff --git a/src/lib/util/hooks/callout_manager.cc b/src/lib/util/hooks/callout_manager.cc
index 4006103..32afc9f 100644
--- a/src/lib/util/hooks/callout_manager.cc
+++ b/src/lib/util/hooks/callout_manager.cc
@@ -15,6 +15,8 @@
#include <util/hooks/callout_handle.h>
#include <util/hooks/callout_manager.h>
+#include <boost/static_assert.hpp>
+
#include <algorithm>
#include <functional>
#include <utility>
@@ -25,11 +27,13 @@ using namespace isc::util;
namespace isc {
namespace util {
-// Register a callout for a particular library.
+// Register a callout for the current library.
void
-CalloutManager::registerCallout(int libindex, const std::string& name,
- CalloutPtr callout) {
+CalloutManager::registerCallout(const std::string& name, CalloutPtr callout) {
+ // Sanity check that the current library index is set to a valid value.
+ checkLibraryIndex(current_library_);
+
// Get the index associated with this hook (validating the name in the
// process).
int hook_index = hooks_->getIndex(name);
@@ -39,22 +43,21 @@ CalloutManager::registerCallout(int libindex, const std::string& name,
// the present index.
for (CalloutVector::iterator i = hook_vector_[hook_index].begin();
i != hook_vector_[hook_index].end(); ++i) {
- if (i->first > libindex) {
- // Found an element whose library number is greater than ours,
- // so insert the new element ahead of this one.
- hook_vector_[hook_index].insert(i,
- std::make_pair(libindex, callout));
+ if (i->first > current_library_) {
+ // Found an element whose library index number is greater than the
+ // current index, so insert the new element ahead of this one.
+ hook_vector_[hook_index].insert(i, make_pair(current_library_,
+ callout));
return;
}
}
- // Reach the end of the vector, so no element in the (possibly empty)
- // set of callouts with a library index greater that the one related to
- // this callout, insert at the end.
- hook_vector_[hook_index].push_back(std::make_pair(libindex, callout));
+ // Reached the end of the vector, so there is no element in the (possibly
+ // empty) set of callouts with a library index greater than the current
+ // library index. Inset the callout at the end of the list.
+ hook_vector_[hook_index].push_back(make_pair(current_library_, callout));
}
-
// Check if callouts are present for a given hook index.
bool
@@ -73,34 +76,51 @@ CalloutManager::callCallouts(int hook_index, CalloutHandle& callout_handle) {
// Validate the hook index.
checkHookIndex(hook_index);
- // Clear the "skip" flag so we don't carry state from a previous
- // call.
+ // Clear the "skip" flag so we don't carry state from a previous call.
callout_handle.setSkip(false);
- // Call all the callouts, stopping if the "skip" flag is set or if a
- // non-zero status is returned.
- int status = 0;
- for (CalloutVector::const_iterator i = hook_vector_[hook_index].begin();
- i != hook_vector_[hook_index].end() && (status == 0); ++i) {
+ // Duplicate the callout vector for this hook and work through that.
+ // This step is needed because we allow dynamic registration and
+ // deregistration of callouts. If a callout attached to a hook modified
+ // the list of callouts, the underlying CalloutVector would change and
+ // potentially affect the iteration through that vector.
+ CalloutVector callouts(hook_vector_[hook_index]);
+
+ // Call all the callouts, stopping if a non SUCCESS status is returned.
+ int status = CalloutHandle::SUCCESS;
+ for (CalloutVector::const_iterator i = callouts.begin();
+ i != callouts.end() && (status == CalloutHandle::SUCCESS); ++i) {
+ // In case the callout tries to register or deregister a callout, set
+ // the current library index to the index associated with library
+ // that registered the callout being called.
+ current_library_ = i->first;
+
+ // Call the callout
status = (*i->second)(callout_handle);
}
+ // Reset the current library index to an invalid value to catch any
+ // programming errors.
+ current_library_ = -1;
+
+
return (status);
}
-// Deregister a callout registered by a library on a particular hook.
+// Deregister a callout registered by the current library on a particular hook.
bool
-CalloutManager::deregisterCallout(int library_index, const std::string& name,
- CalloutPtr callout) {
+CalloutManager::deregisterCallout(const std::string& name, CalloutPtr callout) {
+ // Sanity check that the current library index is set to a valid value.
+ checkLibraryIndex(current_library_);
// Get the index associated with this hook (validating the name in the
// process).
int hook_index = hooks_->getIndex(name);
- /// Construct a CalloutEntry matching the specified library and the callout
+ /// Construct a CalloutEntry matching the current library and the callout
/// we want to remove.
- CalloutEntry target(library_index, callout);
+ CalloutEntry target(current_library_, callout);
/// To decide if any entries were removed, we'll record the initial size
/// of the callout vector for the hook, and compare it with the size after
@@ -129,22 +149,21 @@ CalloutManager::deregisterCallout(int library_index, const std::string& name,
// Deregister all callouts on a given hook.
bool
-CalloutManager::deregisterAllCallouts(int library_index,
- const std::string& name) {
+CalloutManager::deregisterAllCallouts(const std::string& name) {
// Get the index associated with this hook (validating the name in the
// process).
int hook_index = hooks_->getIndex(name);
- /// Construct a CalloutEntry matching the specified library we want to
- /// remove (the callout pointer is NULL as we are not checking that).
- CalloutEntry target(library_index, NULL);
+ /// Construct a CalloutEntry matching the current library (the callout
+ /// pointer is NULL as we are not checking that).
+ CalloutEntry target(current_library_, NULL);
/// To decide if any entries were removed, we'll record the initial size
/// of the callout vector for the hook, and compare it with the size after
/// the removal.
size_t initial_size = hook_vector_[hook_index].size();
-/*
+
// Remove all callouts matching this library.
hook_vector_[hook_index].erase(remove_if(hook_vector_[hook_index].begin(),
hook_vector_[hook_index].end(),
@@ -152,27 +171,9 @@ CalloutManager::deregisterAllCallouts(int library_index,
target)),
hook_vector_[hook_index].end());
- // Return an indication of whether anything was removed. */
+ // Return an indication of whether anything was removed.
return (initial_size != hook_vector_[hook_index].size());
}
-// CalloutManager methods.
-
-// Return pointer to the current library handle.
-
-boost::shared_ptr<LibraryHandle>
-CalloutManager::createHandle() {
- // Index is equal to the size of the current collection of handles
- // (guarantees that every handle has a unique index, and that index
- // is a pointer to the handle in the collection of handles.)
- boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(handles_.size(),
- this));
-
- // Add to the current collection of handles.
- handles_.push_back(handle);
-
- return (handle);
-}
-
} // namespace util
} // namespace isc
diff --git a/src/lib/util/hooks/callout_manager.h b/src/lib/util/hooks/callout_manager.h
index bfe88c9..542afd0 100644
--- a/src/lib/util/hooks/callout_manager.h
+++ b/src/lib/util/hooks/callout_manager.h
@@ -27,33 +27,62 @@
namespace isc {
namespace util {
+/// @brief No such library
+///
+/// Thrown if an attempt is made to set the current library index to a value
+/// that is invalid for the number of loaded libraries.
+class NoSuchLibrary : public Exception {
+public:
+ NoSuchLibrary(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) {}
+};
+
/// @brief Callout Manager
///
/// This class manages the registration, deregistration and execution of the
/// library callouts.
///
-/// It is constructed using a @ref isc::util::ServerHooks object that holds the
-/// list of hooks registered for the server, which it uses to create the
-/// hook vector. This is a vector represting the callouts for each hook. Each
-/// element is itself a vector of callouts registered by the loaded libraries.
+/// In operation, the class needs to know two items of data:
+///
+/// - The list of server hooks, which is used in two ways. Firstly, when a
+/// callout registers or deregisters a hook, it does so by name: the
+/// @ref isc::util::ServerHooks object supplies the names of registered
+/// hooks. Secondly, when the callouts associated with a hook are called by
+/// the server, the server supplies the index of the relevant hook: this is
+/// validated by reference to the list of hook.
///
-/// The class also holds the collection of library handles, used to allow the
-/// libraries to manipulate their callout list.
+/// - The number of loaded libraries. Each callout registered by a user
+/// library is associated with that library, the callout manager storing both
+/// a pointer to the callout and the index of the library in the list of
+/// loaded libraries. Callouts are allowed to dynamically register and
+/// deregister callouts in the same library (including themselves): they
+/// cannot affect callouts registered by another library. When calling a
+/// callout, the callout manager maintains the idea of a "current library
+/// index": if the callout calls one of the callout registration functions
+/// (indirectly via the @ref LibraryHandle object), the registration
+/// functions use the "current library index" in their processing.
+///
+/// These two items of data are supplied when an object of this class is
+/// constructed.
+///
+/// Note that the callout function do not access the library manager: instead,
+/// they use a LibraryHandle object. This contains an internal pointer to
+/// the CalloutManager, but provides a restricted interface. In that way,
+/// callouts are unable to affect callouts supplied by other libraries.
class CalloutManager {
private:
// Private typedefs
- /// Vector of library handles.
- typedef std::vector<boost::shared_ptr<LibraryHandle> > HandleVector;
-
/// Element in the vector of callouts. The elements in the pair are the
- /// library index and the pointer to the callout.
+ /// index of the library from which this callout was registered, and a#
+ /// pointer to the callout itself.
typedef std::pair<int, CalloutPtr> CalloutEntry;
- /// Entry in the list of callouts for an individual hook.
+ /// An element in the hook vector. Each element is a vector of callouts
+ /// associated with a given hook.
typedef std::vector<CalloutEntry> CalloutVector;
public:
@@ -61,35 +90,52 @@ public:
/// @brief Constructor
///
/// Initializes member variables, in particular sizing the hook vector
- /// (the vector of callouts) to the appropriate size.
+ /// (the vector of callout vectors) to the appropriate size.
///
- /// @param hook Collection of known hook names.
- CalloutManager(const boost::shared_ptr<ServerHooks>& hooks) :
- hooks_(hooks), handles_(), hook_vector_(hooks->getCount())
- {}
+ /// @param hooks Collection of known hook names.
+ /// @param num_libraries Number of loaded libraries.
+ ///
+ /// @throw isc::BadValue if the number of libraries is less than or equal
+ /// to 0, or if the pointer to the server hooks object is empty.
+ CalloutManager(const boost::shared_ptr<ServerHooks>& hooks,
+ int num_libraries)
+ : current_library_(-1), hooks_(hooks), hook_vector_(),
+ library_handle_(this), num_libraries_(num_libraries)
+ {
+ if (!hooks) {
+ isc_throw(isc::BadValue, "must pass a pointer to a valid server "
+ "hooks object to the CalloutManager");
+ } else if (num_libraries <= 0) {
+ isc_throw(isc::BadValue, "number of libraries passed to the "
+ "CalloutManager must be >= 0");
+ }
- /// @brief Register a callout on a hook
+ // Parameters OK, do operations that depend on them.
+ hook_vector_.resize(hooks_->getCount());
+ }
+
+ /// @brief Register a callout on a hook for the current library
///
- /// Registers a callout function for a particular library with a given hook.
- /// The callout is added to the end of the callouts for this library that
- /// are associated with that hook.
+ /// Registers a callout function for the current library with a given hook
+ /// (the index of the "current library" being given by the current_library_
+ /// member). The callout is added to the end of the callouts for this
+ /// library that are associated with that hook.
///
- /// @param libindex Index of the library registering the callout
/// @param name Name of the hook to which the callout is added.
/// @param callout Pointer to the callout function to be registered.
///
/// @throw NoSuchHook The hook name is unrecognised.
/// @throw Unexpected The hook name is valid but an internal data structure
/// is of the wrong size.
- void registerCallout(int libindex, const std::string& name,
- CalloutPtr callout);
+ void registerCallout(const std::string& name, CalloutPtr callout);
- /// @brief De-Register a callout on a hook
+ /// @brief De-Register a callout on a hook for the current library
///
- /// Searches through the functions registered by the specified library with
- /// the named hook and removes all entries matching the callout.
+ /// Searches through the functions registered by the the current library
+ /// (the index of the "current library" being given by the current_library_
+ /// member) with the named hook and removes all entries matching the
+ /// callout.
///
- /// @param libindex Index of the library deregistering the callout
/// @param name Name of the hook from which the callout is removed.
/// @param callout Pointer to the callout function to be removed.
///
@@ -98,54 +144,100 @@ public:
/// @throw NoSuchHook The hook name is unrecognised.
/// @throw Unexpected The hook name is valid but an internal data structure
/// is of the wrong size.
- bool deregisterCallout(int libindex, const std::string& name,
- CalloutPtr callout);
+ bool deregisterCallout(const std::string& name, CalloutPtr callout);
- /// @brief Removes all callouts on a hook
+ /// @brief Removes all callouts on a hook for the current library
///
/// Removes all callouts associated with a given hook that were registered
- /// by the specified library.
+ /// by the current library (the index of the "current library" being given
+ /// by the current_library_ member).
///
- /// @param libindex Index of the library deregistering the callouts
/// @param name Name of the hook from which the callouts are removed.
///
/// @return true if one or more callouts were deregistered.
///
/// @throw NoSuchHook Thrown if the hook name is unrecognised.
- bool deregisterAllCallouts(int libindex, const std::string& name);
+ bool deregisterAllCallouts(const std::string& name);
/// @brief Checks if callouts are present on a hook
///
/// Checks all loaded libraries and returns true if at least one callout
/// has been registered by any of them for the given hook.
///
- /// @param index Hook index for which callouts are checked.
+ /// @param hook_index Hook index for which callouts are checked.
///
/// @return true if callouts are present, false if not.
///
/// @throw NoSuchHook Given index does not correspond to a valid hook.
- bool calloutsPresent(int index) const;
+ bool calloutsPresent(int hook_index) const;
/// @brief Calls the callouts for a given hook
///
/// Iterates through the libray handles and calls the callouts associated
/// with the given hook index.
///
- /// @param index Index of the hook to call.
+ /// @note This method invalidates the current library index set with
+ /// setLibraryIndex().
+ ///
+ /// @param hook_index Index of the hook to call.
/// @param callout_handle Reference to the CalloutHandle object for the
/// current object being processed.
///
/// @return Status return.
- int callCallouts(int index, CalloutHandle& callout_handle);
+ int callCallouts(int hook_index, CalloutHandle& callout_handle);
+
+ /// @brief Get number of libraries
+ ///
+ /// Returns the number of libraries that this CalloutManager is expected
+ /// to serve. This is the number passed to its constructor.
+ ///
+ /// @return Number of libraries server by this CalloutManager.
+ int getNumLibraries() const {
+ return (num_libraries_);
+ }
+
+ /// @brief Get current library index
+ ///
+ /// Returns the index of the "current" library. This the index associated
+ /// with the currently executing callout when callCallouts is executing.
+ /// When callCallouts() is not executing (as is the case when the load()
+ /// function in a user-library is called during the library load process),
+ /// the index can be set by setLibraryIndex().
+ ///
+ /// @note The value set by this method is lost after a call to
+ /// callCallouts.
+ ///
+ /// @return Current library index.
+ int getLibraryIndex() const {
+ return (current_library_);
+ }
+ /// @brief Set current library index
+ ///
+ /// Sets the current library index. This must be in the range 0 to
+ /// (numlib - 1), where "numlib" is the number of libraries loaded in the
+ /// system, this figure being passed to this object at construction time.
+ ///
+ /// @param library_index New library index.
+ ///
+ /// @throw NoSuchLibrary if the index is not valid.
+ void setLibraryIndex(int library_index) {
+ checkLibraryIndex(library_index);
+ current_library_ = library_index;
+ }
- /// @brief Create library handle
+ /// @brief Return library handle
+ ///
+ /// The library handle is available to the user callout via the callout
+ /// handle object. It provides a cut-down view of the CalloutManager,
+ /// allowing the callout to register and deregister callouts in the
+ /// library of which it is part, whilst denying access to anything that
+ /// may affect other libraries.
///
- /// Creates a library handle. The handle is used when loading a library in
- /// that the callouts are associated with the given library and when calling
- /// a callout: the handle for the library can be obtained to allow dynamic
- /// registration and de-registration.
- boost::shared_ptr<LibraryHandle> createHandle();
+ /// @return Reference to callout handle for this manager
+ LibraryHandle& getLibraryHandle() {
+ return (library_handle_);
+ }
private:
/// @brief Check hook index
@@ -154,7 +246,7 @@ private:
///
/// @param index Hook index to test
///
- /// @throw NoSuchHook
+ /// @throw NoSuchHook Hooks does not exist.
void checkHookIndex(int hook_index) const {
if ((hook_index < 0) || (hook_index >= hook_vector_.size())) {
isc_throw(NoSuchHook, "hook index " << hook_index <<
@@ -162,32 +254,61 @@ private:
}
}
+ /// @brief Check library index
+ ///
+ /// Ensures that the current library index is valid. This is called by
+ /// the hook registration functions.
+ ///
+ /// @param library_index Value to check for validity as a library index.
+ ///
+ /// @throw NoSuchLibrary Library index is not valid.
+ void checkLibraryIndex(int library_index) const {
+ if ((library_index < 0) || (library_index >= num_libraries_)) {
+ isc_throw(NoSuchLibrary, "library index " << library_index <<
+ " is not valid for the number of loaded libraries (" <<
+ num_libraries_ << ")");
+ }
+ }
+
/// @brief Compare two callout entries for library equality
///
- /// This is used in callout removal code. It just checks whether two
- /// entries have the same library element.
+ /// This is used in callout removal code when all callouts on a hook for a
+ /// given library are being removed. It checks whether two callout entries
+ /// have the same library index.
///
/// @param ent1 First callout entry to check
/// @param ent2 Second callout entry to check
///
/// @return bool true if the library entries are the same
- class CalloutLibraryEqual {
+ class CalloutLibraryEqual :
+ public std::binary_function<CalloutEntry, CalloutEntry, bool> {
public:
- bool operator()(const CalloutEntry& ent1, const CalloutEntry& ent2) {
+ bool operator()(const CalloutEntry& ent1,
+ const CalloutEntry& ent2) const {
return (ent1.first == ent2.first);
}
};
- /// List of server hooks. This is used
- boost::shared_ptr<ServerHooks> hooks_;
+ /// Current library index. When a call is made to any of the callout
+ /// registration methods, this variable indicates the index of the user
+ /// library that should be associated with the call.
+ int current_library_;
- /// Vector of pointers to library handles.
- HandleVector handles_;
+ /// List of server hooks.
+ boost::shared_ptr<ServerHooks> hooks_;
/// Vector of callout vectors. There is one entry in this outer vector for
- /// each hook.
+ /// each hook. Each element is itself a vector, with one entry for each
+ /// callout registered for that hook.
std::vector<CalloutVector> hook_vector_;
+ /// LibraryHandle object user by the callout to access the callout
+ /// registration methods on this CalloutManager object.
+ LibraryHandle library_handle_;
+
+ /// Number of libraries.
+ int num_libraries_;
+
};
} // namespace util
diff --git a/src/lib/util/hooks/library_handle.cc b/src/lib/util/hooks/library_handle.cc
index 3ea2192..0a65e54 100644
--- a/src/lib/util/hooks/library_handle.cc
+++ b/src/lib/util/hooks/library_handle.cc
@@ -22,17 +22,17 @@ namespace util {
void
LibraryHandle::registerCallout(const std::string& name, CalloutPtr callout) {
- callout_manager_->registerCallout(library_index_, name, callout);
+ callout_manager_->registerCallout(name, callout);
}
bool
LibraryHandle::deregisterCallout(const std::string& name, CalloutPtr callout) {
- return (callout_manager_->deregisterCallout(library_index_, name, callout));
+ return (callout_manager_->deregisterCallout(name, callout));
}
bool
LibraryHandle::deregisterAllCallouts(const std::string& name) {
- return (callout_manager_->deregisterAllCallouts(library_index_, name));
+ return (callout_manager_->deregisterAllCallouts(name));
}
} // namespace util
diff --git a/src/lib/util/hooks/library_handle.h b/src/lib/util/hooks/library_handle.h
index 9b90245..43a78a1 100644
--- a/src/lib/util/hooks/library_handle.h
+++ b/src/lib/util/hooks/library_handle.h
@@ -35,31 +35,37 @@ extern "C" {
/// either by the library's load() function, or by one of the callouts
/// themselves.
///
-/// It is really little more than a shell around the CalloutManager/ By
-/// presenting this object to the user-library callouts, callouts can manage the
-/// callout list for their own library, but cannot affect the callouts
+/// It is really little more than a shell around the CalloutManager. By
+/// presenting this object to the user-library callouts, callouts can manage
+/// the callout list for their own library, but cannot affect the callouts
/// registered by other libraries.
+///
+/// (This restriction is achieved by the CalloutManager maintaining the concept
+/// of the "current library". When a callout is registered - either by the
+/// library's load() function, or by a callout in the library - the registration
+/// information includes the library active at the time. When that callout is
+/// called, the CalloutManager uses that information to set the "current
+/// library": the registration functions only operator on data whose
+/// associated library is equal to the "current library".)
class LibraryHandle {
public:
/// @brief Constructor
///
- /// @param hooks Library index. A number (starting at 0) that represents
- /// the index of the library in the list of libraries loaded by the
- /// server.
- /// @param collection Back pointer to the containing CalloutManager.
+ /// @param manager Back pointer to the containing CalloutManager.
/// This pointer is used to access appropriate methods in that
- /// object.
- LibraryHandle(int library_index, CalloutManager* collection)
- : library_index_(library_index), callout_manager_(collection)
+ /// object. Note that the "raw" pointer is safe - the only
+ /// instance of the LibraryHandle in the system is as a member of
+ /// the CalloutManager to which it points.
+ LibraryHandle(CalloutManager* manager) : callout_manager_(manager)
{}
/// @brief Register a callout on a hook
///
/// Registers a callout function with a given hook. The callout is added
- /// to the end of the callouts for this library that are associated with
- /// that hook.
+ /// to the end of the callouts for the current library that are associated
+ /// with that hook.
///
/// @param name Name of the hook to which the callout is added.
/// @param callout Pointer to the callout function to be registered.
@@ -71,9 +77,9 @@ public:
/// @brief De-Register a callout on a hook
///
- /// Searches through the functions registered by this library with the named
- /// hook and removes all entries matching the callout. It does not affect
- /// callouts registered by other libraries.
+ /// Searches through the functions registered by the current library with
+ /// the named hook and removes all entries matching the callout. It does
+ /// not affect callouts registered by other libraries.
///
/// @param name Name of the hook from which the callout is removed.
/// @param callout Pointer to the callout function to be removed.
@@ -88,8 +94,8 @@ public:
/// @brief Removes all callouts on a hook
///
/// Removes all callouts associated with a given hook that were registered.
- /// by this library. It does not affect callouts that were registered by
- /// other libraries.
+ /// by the current library. It does not affect callouts that were
+ /// registered by other libraries.
///
/// @param name Name of the hook from which the callouts are removed.
///
@@ -98,20 +104,7 @@ public:
/// @throw NoSuchHook Thrown if the hook name is unrecognised.
bool deregisterAllCallouts(const std::string& name);
- /// @brief Return handle index
- ///
- /// For test purposes only, this returns the index allocated to this
- /// LibraryHandle.
- ///
- /// @return Handle index
- int getIndex() const {
- return (library_index_);
- }
-
private:
- /// Index of this handle in the library handle list
- int library_index_;
-
/// Back pointer to the collection object for the library
CalloutManager* callout_manager_;
};
diff --git a/src/lib/util/hooks/server_hooks.cc b/src/lib/util/hooks/server_hooks.cc
index 9bb903b..478d94c 100644
--- a/src/lib/util/hooks/server_hooks.cc
+++ b/src/lib/util/hooks/server_hooks.cc
@@ -42,7 +42,7 @@ ServerHooks::ServerHooks() {
// Register a hook. The index assigned to the hook is the current number
// of entries in the collection, so ensuring that hook indexes are unique
-// (and non-negative).
+// and non-negative.
int
ServerHooks::registerHook(const string& name) {
@@ -63,7 +63,7 @@ ServerHooks::registerHook(const string& name) {
return (index);
}
-// Find the index associated with a hook name or return -1 if not found
+// Find the index associated with a hook name.
int
ServerHooks::getIndex(const string& name) const {
@@ -94,13 +94,6 @@ ServerHooks::getHookNames() const {
// Hook registration function methods
-// Constructor - add a registration function to the function vector
-
-HookRegistrationFunction::HookRegistrationFunction(
- HookRegistrationFunction::RegistrationFunctionPtr reg_func) {
- getFunctionVector().push_back(reg_func);
-}
-
// Access the hook registration function vector itself
std::vector<HookRegistrationFunction::RegistrationFunctionPtr>&
@@ -109,6 +102,13 @@ HookRegistrationFunction::getFunctionVector() {
return (reg_functions);
}
+// Constructor - add a registration function to the function vector
+
+HookRegistrationFunction::HookRegistrationFunction(
+ HookRegistrationFunction::RegistrationFunctionPtr reg_func) {
+ getFunctionVector().push_back(reg_func);
+}
+
// Execute all registered registration functions
void
diff --git a/src/lib/util/hooks/server_hooks.h b/src/lib/util/hooks/server_hooks.h
index ca978f5..ce41fa0 100644
--- a/src/lib/util/hooks/server_hooks.h
+++ b/src/lib/util/hooks/server_hooks.h
@@ -128,12 +128,12 @@ private:
///
/// All hooks must be registered before libraries are loaded and callouts
/// assigned to them. One way of doing this is to have a global list of hooks:
-/// the addition of any hook anywhere would require updating the list. The
-/// other way, chosen here, is to have each component in BIND 10 register the
-/// hooks they are using.
+/// the addition of any hook anywhere would require updating the list. This
+/// is possible and, if desired, the author of a server can do it.
///
-/// The chosen method requires that each component create a hook registration
-/// function of the form:
+/// An alternative is the option provided here, where each component of BIND 10
+/// registers the hooks they are using. To do this, the component should
+/// create a hook registration function of the form:
///
/// @code
/// static int hook1_num = -1; // Initialize number for hook 1
@@ -145,21 +145,21 @@ private:
/// }
/// @endcode
///
-/// The server then calls each of these hook registration functions during its
-/// initialization before loading the libraries.
-///
-/// It is to avoid the need to add an explicit call to each of the hook
-/// registration functions to the server initialization code that this class
-/// has been created. Declaring an object of this class in the same file as
-/// the registration function and passing the registration function as an
-/// argument, e.g.
+/// ... which registers the hooks and stores the associated hook index. To
+/// avoid the need to add an explicit call to each of the hook registration
+/// functions to the server initialization code, the component should declare
+/// an object of this class in the same file as the registration function,
+/// but outside of any function. The declaration should include the name
+/// of the registration function, i.e.
///
/// @code
/// HookRegistrationFunction f(myModuleRegisterHooks);
/// @code
///
-/// is sufficient to add the registration function to a list of such functions.
-/// The server will execute all functions in the list wh3en it starts.
+/// The constructor of this object will run prior to main() getting called and
+/// will add the registration function to a list of such functions. The server
+/// then calls the static class method "execute()" to run all the declared
+/// registration functions.
class HookRegistrationFunction {
public:
@@ -177,14 +177,14 @@ public:
///
/// One of the problems with functions run prior to starting main() is the
/// "static initialization fiasco". This occurs because the order in which
- /// objects outside functions is not defined. So if this constructor were
- /// to depend on a vector declared externally, we would not be able to
- /// guarantee that the vector had been initialised proerly before we used
- /// it.
+ /// objects outside functions are constructed is not defined. So if this
+ /// constructor were to depend on a vector declared externally, we would
+ /// not be able to guarantee that the vector had been initialised properly
+ /// before we used it.
///
/// To get round this situation, the vector is declared statically within
- /// a function. The first time the function is called, the object is
- /// initialized.
+ /// a static function. The first time the function is called, the vector
+ /// is initialized before it is used.
///
/// This function returns a reference to the vector used to hold the
/// pointers.
@@ -200,9 +200,6 @@ public:
/// @param hooks ServerHooks object to which hook information will be added.
static void execute(ServerHooks& hooks);
};
-/// to the constructor
-/// any function
-///
} // namespace util
} // namespace isc
diff --git a/src/lib/util/tests/Makefile.am b/src/lib/util/tests/Makefile.am
index 55c4fa9..ceb8b95 100644
--- a/src/lib/util/tests/Makefile.am
+++ b/src/lib/util/tests/Makefile.am
@@ -25,15 +25,14 @@ run_unittests_SOURCES = run_unittests.cc
run_unittests_SOURCES += base32hex_unittest.cc
run_unittests_SOURCES += base64_unittest.cc
run_unittests_SOURCES += buffer_unittest.cc
-# run_unittests_SOURCES += callout_handle_unittest.cc
+run_unittests_SOURCES += callout_handle_unittest.cc
run_unittests_SOURCES += callout_manager_unittest.cc
run_unittests_SOURCES += fd_share_tests.cc
run_unittests_SOURCES += fd_tests.cc
run_unittests_SOURCES += filename_unittest.cc
run_unittests_SOURCES += hex_unittest.cc
-# run_unittests_SOURCES += handles_unittest.cc
+run_unittests_SOURCES += handles_unittest.cc
run_unittests_SOURCES += io_utilities_unittest.cc
-# run_unittests_SOURCES += library_handle_unittest.cc
run_unittests_SOURCES += lru_list_unittest.cc
run_unittests_SOURCES += memory_segment_local_unittest.cc
if USE_SHARED_MEMORY
diff --git a/src/lib/util/tests/callout_handle_unittest.cc b/src/lib/util/tests/callout_handle_unittest.cc
index 705c9d7..635e570 100644
--- a/src/lib/util/tests/callout_handle_unittest.cc
+++ b/src/lib/util/tests/callout_handle_unittest.cc
@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <util/hooks/callout_handle.h>
+#include <util/hooks/callout_manager.h>
#include <util/hooks/library_handle.h>
#include <util/hooks/server_hooks.h>
@@ -25,23 +26,35 @@ using namespace std;
namespace {
+/// @file
+/// @brief Holds the CalloutHandle argument tests
+///
+/// Additional testing of the CalloutHandle - together with the interaction
+/// of the LibraryHandle - is done in the handles_unittests set of tests.
+
class CalloutHandleTest : public ::testing::Test {
public:
/// @brief Constructor
///
- /// Sets up an appropriate number of server hooks to pass to the
- /// constructed callout handle objects.
- CalloutHandleTest() : collection_(new LibraryHandleCollection()) {
- }
+ /// Sets up a callout manager to be referenced by the CalloutHandle in
+ /// these tests. (The "4" for the number of libraries in the
+ /// CalloutManager is arbitrary - it is not used in these tests.)
+ CalloutHandleTest()
+ : hooks_(new ServerHooks()), manager_(new CalloutManager(hooks_, 4))
+ {}
/// Obtain hook manager
- boost::shared_ptr<LibraryHandleCollection>& getLibraryHandleCollection() {
- return (collection_);
+ boost::shared_ptr<CalloutManager>& getCalloutManager() {
+ return (manager_);
}
private:
- boost::shared_ptr<LibraryHandleCollection> collection_;
+ /// List of server hooks
+ boost::shared_ptr<ServerHooks> hooks_;
+
+ /// Callout manager accessed by this CalloutHandle.
+ boost::shared_ptr<CalloutManager> manager_;
};
// *** Argument Tests ***
@@ -53,7 +66,7 @@ private:
// are distinct.
TEST_F(CalloutHandleTest, ArgumentDistinctSimpleType) {
- CalloutHandle handle(getLibraryHandleCollection());
+ CalloutHandle handle(getCalloutManager());
// Store and retrieve an int (random value).
int a = 42;
@@ -86,7 +99,7 @@ TEST_F(CalloutHandleTest, ArgumentDistinctSimpleType) {
// Test that trying to get an unknown argument throws an exception.
TEST_F(CalloutHandleTest, ArgumentUnknownName) {
- CalloutHandle handle(getLibraryHandleCollection());
+ CalloutHandle handle(getCalloutManager());
// Set an integer
int a = 42;
@@ -107,7 +120,7 @@ TEST_F(CalloutHandleTest, ArgumentUnknownName) {
// exception.
TEST_F(CalloutHandleTest, ArgumentIncorrectType) {
- CalloutHandle handle(getLibraryHandleCollection());
+ CalloutHandle handle(getCalloutManager());
// Set an integer
int a = 42;
@@ -136,7 +149,7 @@ struct Beta {
};
TEST_F(CalloutHandleTest, ComplexTypes) {
- CalloutHandle handle(getLibraryHandleCollection());
+ CalloutHandle handle(getCalloutManager());
// Declare two variables of different (complex) types. (Note as to the
// variable names: aleph and beth are the first two letters of the Hebrew
@@ -175,7 +188,7 @@ TEST_F(CalloutHandleTest, ComplexTypes) {
// that a "pointer to X" is not the same as a "pointer to const X".
TEST_F(CalloutHandleTest, PointerTypes) {
- CalloutHandle handle(getLibraryHandleCollection());
+ CalloutHandle handle(getCalloutManager());
// Declare a couple of variables, const and non-const.
Alpha aleph(5, 10);
@@ -209,7 +222,7 @@ TEST_F(CalloutHandleTest, PointerTypes) {
// Check that we can get the names of the arguments.
TEST_F(CalloutHandleTest, ContextItemNames) {
- CalloutHandle handle(getLibraryHandleCollection());
+ CalloutHandle handle(getCalloutManager());
vector<string> expected_names;
int value = 42;
@@ -233,7 +246,7 @@ TEST_F(CalloutHandleTest, ContextItemNames) {
// Test that we can delete an argument.
TEST_F(CalloutHandleTest, DeleteArgument) {
- CalloutHandle handle(getLibraryHandleCollection());
+ CalloutHandle handle(getCalloutManager());
int one = 1;
int two = 2;
@@ -275,7 +288,7 @@ TEST_F(CalloutHandleTest, DeleteArgument) {
// Test that we can delete all arguments.
TEST_F(CalloutHandleTest, DeleteAllArguments) {
- CalloutHandle handle(getLibraryHandleCollection());
+ CalloutHandle handle(getCalloutManager());
int one = 1;
int two = 2;
@@ -302,7 +315,7 @@ TEST_F(CalloutHandleTest, DeleteAllArguments) {
// Test the "skip" flag.
TEST_F(CalloutHandleTest, SkipFlag) {
- CalloutHandle handle(getLibraryHandleCollection());
+ CalloutHandle handle(getCalloutManager());
// Should be false on construction.
EXPECT_FALSE(handle.getSkip());
diff --git a/src/lib/util/tests/callout_manager_unittest.cc b/src/lib/util/tests/callout_manager_unittest.cc
index 0294305..8f35be3 100644
--- a/src/lib/util/tests/callout_manager_unittest.cc
+++ b/src/lib/util/tests/callout_manager_unittest.cc
@@ -18,12 +18,21 @@
#include <util/hooks/library_handle.h>
#include <util/hooks/server_hooks.h>
+#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
#include <algorithm>
#include <string>
#include <vector>
+/// @file
+/// @brief CalloutManager and LibraryHandle tests
+///
+/// These set of tests check the CalloutManager and LibraryHandle. They are
+/// together in the same file because the LibraryHandle is little more than a
+/// restricted interface to the CalloutManager, and a lot of the support
+/// structure for the tests is common.
+
using namespace isc;
using namespace isc::util;
using namespace std;
@@ -38,19 +47,14 @@ public:
CalloutManagerTest() : hooks_(new ServerHooks()) {
// Set up the server hooks
- one_index_ = hooks_->registerHook("one");
- two_index_ = hooks_->registerHook("two");
- three_index_ = hooks_->registerHook("three");
- four_index_ = hooks_->registerHook("four");
-
- // Set up the callout manager with these hooks
- callout_manager_.reset(new CalloutManager(hooks_));
+ alpha_index_ = hooks_->registerHook("alpha");
+ beta_index_ = hooks_->registerHook("beta");
+ gamma_index_ = hooks_->registerHook("gamma");
+ delta_index_ = hooks_->registerHook("delta");
- // Set up four library handles.
- library_handle_.push_back(callout_manager_->createHandle());
- library_handle_.push_back(callout_manager_->createHandle());
- library_handle_.push_back(callout_manager_->createHandle());
- library_handle_.push_back(callout_manager_->createHandle());
+ // Set up the callout manager with these hooks. Assume a maximum of
+ // four libraries.
+ callout_manager_.reset(new CalloutManager(hooks_, 4));
// Set up the callout handle.
callout_handle_.reset(new CalloutHandle(callout_manager_));
@@ -66,38 +70,36 @@ public:
return (callout_manager_);
}
+ boost::shared_ptr<ServerHooks> getServerHooks() {
+ return (hooks_);
+ }
+
/// Static variable used for accumulating information
static int callout_value_;
/// Hook indexes. These are somewhat ubiquitous, so are made public for
/// ease of reference instead of being accessible by a function.
- int one_index_;
- int two_index_;
- int three_index_;
- int four_index_;
+ int alpha_index_;
+ int beta_index_;
+ int gamma_index_;
+ int delta_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_;
/// Server hooks
boost::shared_ptr<ServerHooks> hooks_;
-
- /// Set up three library handles.
- std::vector<boost::shared_ptr<LibraryHandle> > library_handle_;
-
- /// Callout handle used in calls
- boost::shared_ptr<CalloutHandle> callout_handle_;
-
};
// Definition of the static variable.
int CalloutManagerTest::callout_value_ = 0;
-// *** Callout Tests ***
+// Callout definitions
//
-// The next set of tests check that callouts can be called.
-
// The callouts defined here are structured in such a way that it is possible
// to determine the order in which they are called and whether they are called
// at all. The method used is simple - after a sequence of callouts, the digits
@@ -166,103 +168,170 @@ int manager_four_error(CalloutHandle& handle) {
}; // extern "C"
+// *** Callout Tests ***
+//
+// The next set of tests check that callouts can be called.
+
+// Constructor - check that we trap bad parameters.
+
+TEST_F(CalloutManagerTest, BadConstructorParameters) {
+ boost::scoped_ptr<CalloutManager> cm;
+
+ // Invalid number of libraries
+ EXPECT_THROW(cm.reset(new CalloutManager(getServerHooks(), 0)), BadValue);
+ EXPECT_THROW(cm.reset(new CalloutManager(getServerHooks(), -1)), BadValue);
+
+ // Invalid server hooks pointer.
+ boost::shared_ptr<ServerHooks> sh;
+ EXPECT_THROW(cm.reset(new CalloutManager(sh, 4)), BadValue);
+}
+
+// Check the number of libraries is reported successfully.
+
+TEST_F(CalloutManagerTest, GetNumLibraries) {
+ boost::scoped_ptr<CalloutManager> cm;
+
+ // Check two valid values of number of libraries to ensure that the
+ // GetNumLibraries() returns the value set.
+ EXPECT_NO_THROW(cm.reset(new CalloutManager(getServerHooks(), 4)));
+ EXPECT_EQ(4, cm->getNumLibraries());
+
+ EXPECT_NO_THROW(cm.reset(new CalloutManager(getServerHooks(), 42)));
+ EXPECT_EQ(42, cm->getNumLibraries());
+}
+
+// Check that we can only set the current library index to the correct values.
+
+TEST_F(CalloutManagerTest, CheckLibraryIndex) {
+ // Check valid indexes
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_NO_THROW(getCalloutManager()->setLibraryIndex(i));
+ }
+
+ // Check invalid ones
+ EXPECT_THROW(getCalloutManager()->setLibraryIndex(-1), NoSuchLibrary);
+ EXPECT_THROW(getCalloutManager()->setLibraryIndex(5), NoSuchLibrary);
+}
+
+// Check that we can only register callouts on valid hook names.
+
+TEST_F(CalloutManagerTest, ValidHookNames) {
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_NO_THROW(getCalloutManager()->registerCallout("alpha", manager_one));
+ EXPECT_THROW(getCalloutManager()->registerCallout("unknown", manager_one),
+ NoSuchHook);
+}
+
+
// Check we can register callouts appropriately.
TEST_F(CalloutManagerTest, RegisterCallout) {
// Ensure that no callouts are attached to any of the hooks.
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(two_index_));
-
- // Set up so that hooks "one" and "two" have callouts attached from a
- // single library.
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
- getCalloutManager()->registerCallout(0, "one", manager_one);
- getCalloutManager()->registerCallout(1, "two", manager_two);
+ // Set up so that hooks "alpha" and "beta" have callouts attached from a
+ // different libraries.
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", manager_one);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("beta", manager_two);
// Check all is as expected.
- EXPECT_TRUE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_TRUE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_TRUE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
int status = 0;
- // Check that calling the callouts returns as expected.
+ // Check that calling the callouts returns as expected. (This is also a
+ // test of the callCallouts method.)
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(1, callout_value_);
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(two_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(2, callout_value_);
- // Register some more callouts from different libraries on hook 1.
- getCalloutManager()->registerCallout(2, "one", manager_three);
- getCalloutManager()->registerCallout(2, "one", manager_four);
- getCalloutManager()->registerCallout(3, "one", manager_five);
+ // Register some more callouts from different libraries on hook "alpha".
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", manager_three);
+ getCalloutManager()->registerCallout("alpha", manager_four);
+ getCalloutManager()->setLibraryIndex(3);
+ getCalloutManager()->registerCallout("alpha", manager_five);
// Check it is as expected.
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(1345, callout_value_);
+ // ... and check the additional callouts were not registered on the "beta"
+ // hook.
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(two_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(2, callout_value_);
- // Add another callout to hook one from library iindex 2 - this should
+ // Add another callout to hook "alpha" from library index 2 - this should
// appear at the end of the callout list for that library.
- getCalloutManager()->registerCallout(2, "one", manager_six);
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", manager_six);
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(13465, callout_value_);
// Add a callout from library index 1 - this should appear between the
// callouts from library index 0 and linrary index 2.
- getCalloutManager()->registerCallout(1, "one", manager_seven);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", manager_seven);
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(173465, callout_value_);
-
-
}
// Check the "calloutsPresent()" method.
TEST_F(CalloutManagerTest, CalloutsPresent) {
// Ensure that no callouts are attached to any of the hooks.
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
- // Set up so that hooks "one", "two" and "four" have callouts attached
- // to them, and callout "three" does not. (In the statements below, the
+ // Set up so that hooks "alpha", "beta" and "delta" have callouts attached
+ // to them, and callout "gamma" does not. (In the statements below, the
// exact callouts attached to a hook are not relevant - only the fact
// that some callouts are). Chose the libraries for which the callouts
// are registered randomly.
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", manager_one);
- getCalloutManager()->registerCallout(0, "one", manager_one);
-
- getCalloutManager()->registerCallout(1, "one", manager_two);
- getCalloutManager()->registerCallout(1, "two", manager_two);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ getCalloutManager()->registerCallout("beta", manager_two);
- getCalloutManager()->registerCallout(3, "one", manager_three);
- getCalloutManager()->registerCallout(3, "four", manager_four);
+ getCalloutManager()->setLibraryIndex(3);
+ getCalloutManager()->registerCallout("alpha", manager_three);
+ getCalloutManager()->registerCallout("delta", manager_four);
// Check all is as expected.
- EXPECT_TRUE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_TRUE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_TRUE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_TRUE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_TRUE(getCalloutManager()->calloutsPresent(delta_index_));
- // Check we fail on an invalid index.
+ // Check we fail on an invalid hook index.
EXPECT_THROW(getCalloutManager()->calloutsPresent(42), NoSuchHook);
EXPECT_THROW(getCalloutManager()->calloutsPresent(-1), NoSuchHook);
}
@@ -271,53 +340,64 @@ TEST_F(CalloutManagerTest, CalloutsPresent) {
TEST_F(CalloutManagerTest, CallNoCallouts) {
// Ensure that no callouts are attached to any of the hooks.
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
// Call the callouts on an arbitrary hook and ensure that nothing happens.
callout_value_ = 475;
- int status = getCalloutManager()->callCallouts(one_index_,
+ int status = getCalloutManager()->callCallouts(alpha_index_,
getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(475, callout_value_); // Unchanged
}
-// Test that the callouts are called in the correct order.
+// Test that the callouts are called in the correct order (i.e. the callouts
+// from the first library in the order they were registered, then the callouts
+// from the second library in the order they were registered etc.)
TEST_F(CalloutManagerTest, CallCalloutsSuccess) {
// Ensure that no callouts are attached to any of the hooks.
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
int status = 0;
- // Each library contributes one callout on hook "one".
+ // Each library contributes one callout on hook "alpha".
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "one", manager_one);
- getCalloutManager()->registerCallout(1, "one", manager_two);
- getCalloutManager()->registerCallout(2, "one", manager_three);
- getCalloutManager()->registerCallout(3, "one", manager_four);
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", manager_one);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", manager_three);
+ getCalloutManager()->setLibraryIndex(3);
+ getCalloutManager()->registerCallout("alpha", manager_four);
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(1234, callout_value_);
- // Do a random selection of callouts on hook "two".
+ // Do a random selection of callouts on hook "beta".
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "two", manager_one);
- getCalloutManager()->registerCallout(0, "two", manager_three);
- getCalloutManager()->registerCallout(1, "two", manager_two);
- getCalloutManager()->registerCallout(3, "two", manager_four);
- status = getCalloutManager()->callCallouts(two_index_, getCalloutHandle());
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("beta", manager_one);
+ getCalloutManager()->registerCallout("beta", manager_three);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("beta", manager_two);
+ getCalloutManager()->setLibraryIndex(3);
+ getCalloutManager()->registerCallout("beta", manager_four);
+ status = getCalloutManager()->callCallouts(beta_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(1324, callout_value_);
// Ensure that calling the callouts on a hook with no callouts works.
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(three_index_,
+ status = getCalloutManager()->callCallouts(gamma_index_,
getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(0, callout_value_);
@@ -331,63 +411,80 @@ TEST_F(CalloutManagerTest, CallCalloutsSuccess) {
TEST_F(CalloutManagerTest, CallCalloutsError) {
// Ensure that no callouts are attached to any of the hooks.
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
int status = 0;
- // Each library contributing one callout on hook "one". The first callout
+ // Each library contributing one callout on hook "alpha". The first callout
// returns an error (after adding its value to the result).
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "one", manager_one_error);
- getCalloutManager()->registerCallout(1, "one", manager_two);
- getCalloutManager()->registerCallout(2, "one", manager_three);
- getCalloutManager()->registerCallout(3, "one", manager_four);
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", manager_one_error);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", manager_three);
+ getCalloutManager()->setLibraryIndex(3);
+ getCalloutManager()->registerCallout("alpha", manager_four);
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(1, status);
EXPECT_EQ(1, callout_value_);
- // Each library contributing multiple callouts on hook "two". The last
+ // Each library contributing multiple callouts on hook "beta". The last
// callout on the first library returns an error.
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "two", manager_one);
- getCalloutManager()->registerCallout(0, "two", manager_one_error);
- getCalloutManager()->registerCallout(1, "two", manager_two);
- getCalloutManager()->registerCallout(1, "two", manager_two);
- getCalloutManager()->registerCallout(1, "two", manager_three);
- getCalloutManager()->registerCallout(1, "two", manager_three);
- getCalloutManager()->registerCallout(3, "two", manager_four);
- getCalloutManager()->registerCallout(3, "two", manager_four);
- status = getCalloutManager()->callCallouts(two_index_, getCalloutHandle());
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("beta", manager_one);
+ getCalloutManager()->registerCallout("beta", manager_one_error);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("beta", manager_two);
+ getCalloutManager()->registerCallout("beta", manager_two);
+ getCalloutManager()->registerCallout("beta", manager_three);
+ getCalloutManager()->registerCallout("beta", manager_three);
+ getCalloutManager()->setLibraryIndex(3);
+ getCalloutManager()->registerCallout("beta", manager_four);
+ getCalloutManager()->registerCallout("beta", manager_four);
+ status = getCalloutManager()->callCallouts(beta_index_,
+ getCalloutHandle());
EXPECT_EQ(1, status);
EXPECT_EQ(11, callout_value_);
// A callout in a random position in the callout list returns an error.
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "three", manager_one);
- getCalloutManager()->registerCallout(0, "three", manager_one);
- getCalloutManager()->registerCallout(1, "three", manager_two);
- getCalloutManager()->registerCallout(1, "three", manager_two);
- getCalloutManager()->registerCallout(3, "three", manager_four_error);
- getCalloutManager()->registerCallout(3, "three", manager_four);
- status = getCalloutManager()->callCallouts(three_index_,
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("gamma", manager_one);
+ getCalloutManager()->registerCallout("gamma", manager_one);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("gamma", manager_two);
+ getCalloutManager()->registerCallout("gamma", manager_two);
+ getCalloutManager()->setLibraryIndex(3);
+ getCalloutManager()->registerCallout("gamma", manager_four_error);
+ getCalloutManager()->registerCallout("gamma", manager_four);
+ status = getCalloutManager()->callCallouts(gamma_index_,
getCalloutHandle());
EXPECT_EQ(1, status);
EXPECT_EQ(11224, callout_value_);
// The last callout on a hook returns an error.
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "four", manager_one);
- getCalloutManager()->registerCallout(0, "four", manager_one);
- getCalloutManager()->registerCallout(1, "four", manager_two);
- getCalloutManager()->registerCallout(1, "four", manager_two);
- getCalloutManager()->registerCallout(2, "four", manager_three);
- getCalloutManager()->registerCallout(2, "four", manager_three);
- getCalloutManager()->registerCallout(3, "four", manager_four);
- getCalloutManager()->registerCallout(3, "four", manager_four_error);
- status = getCalloutManager()->callCallouts(four_index_, getCalloutHandle());
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("delta", manager_one);
+ getCalloutManager()->registerCallout("delta", manager_one);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("delta", manager_two);
+ getCalloutManager()->registerCallout("delta", manager_two);
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("delta", manager_three);
+ getCalloutManager()->registerCallout("delta", manager_three);
+ getCalloutManager()->setLibraryIndex(3);
+ getCalloutManager()->registerCallout("delta", manager_four);
+ getCalloutManager()->registerCallout("delta", manager_four_error);
+ status = getCalloutManager()->callCallouts(delta_index_,
+ getCalloutHandle());
EXPECT_EQ(1, status);
EXPECT_EQ(11223344, callout_value_);
}
@@ -396,24 +493,29 @@ TEST_F(CalloutManagerTest, CallCalloutsError) {
TEST_F(CalloutManagerTest, DeregisterSingleCallout) {
// Ensure that no callouts are attached to any of the hooks.
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
int status = 0;
- // Each library contributes one callout on hook "one".
+ // Add a callout to hook "alpha" and check it is added correctly.
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "one", manager_two);
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(2, callout_value_);
- // Remove it and check that the no callouts are present.
- EXPECT_TRUE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_two));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
+ // Remove it and check that the no callouts are present. We have to reset
+ // the current library index here as it was invalidated by the call
+ // to callCallouts().
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
}
// Now test that we can deregister a single callout on a hook that has multiple
@@ -421,34 +523,41 @@ TEST_F(CalloutManagerTest, DeregisterSingleCallout) {
TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) {
// Ensure that no callouts are attached to any of the hooks.
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
int status = 0;
- // Each library contributes one callout on hook "one".
+ // Add multiple callouts to hook "alpha".
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "one", manager_one);
- getCalloutManager()->registerCallout(0, "one", manager_two);
- getCalloutManager()->registerCallout(0, "one", manager_three);
- getCalloutManager()->registerCallout(0, "one", manager_four);
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", manager_one);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ getCalloutManager()->registerCallout("alpha", manager_three);
+ getCalloutManager()->registerCallout("alpha", manager_four);
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(1234, callout_value_);
- // Remove the manager_two callout.
- EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_two));
+ // Remove the manager_two callout. We have to reset the current library
+ // index here as it was invalidated by the call to callCallouts().
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(134, callout_value_);
// Try removing it again.
- EXPECT_FALSE(getCalloutManager()->deregisterCallout(0, "one", manager_two));
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", manager_two));
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(134, callout_value_);
@@ -458,90 +567,221 @@ TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) {
TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) {
// Ensure that no callouts are attached to any of the hooks.
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
int status = 0;
- // Each library contributes one callout on hook "one".
+ // Each library contributes one callout on hook "alpha".
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "one", manager_one);
- getCalloutManager()->registerCallout(0, "one", manager_one);
- getCalloutManager()->registerCallout(0, "one", manager_two);
- getCalloutManager()->registerCallout(0, "one", manager_two);
- getCalloutManager()->registerCallout(0, "one", manager_three);
- getCalloutManager()->registerCallout(0, "one", manager_three);
- getCalloutManager()->registerCallout(0, "one", manager_four);
- getCalloutManager()->registerCallout(0, "one", manager_four);
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", manager_one);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ getCalloutManager()->registerCallout("alpha", manager_one);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ getCalloutManager()->registerCallout("alpha", manager_three);
+ getCalloutManager()->registerCallout("alpha", manager_four);
+ getCalloutManager()->registerCallout("alpha", manager_three);
+ getCalloutManager()->registerCallout("alpha", manager_four);
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
- EXPECT_EQ(11223344, callout_value_);
+ EXPECT_EQ(12123434, callout_value_);
- // Remove the manager_two callout.
- EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_two));
+ // Remove the manager_two callouts. We have to reset the current library
+ // index here as it was invalidated by the call to callCallouts().
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
- EXPECT_EQ(113344, callout_value_);
+ EXPECT_EQ(113434, callout_value_);
- // Try removing multiple callouts from the end of the list.
- EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_four));
+ // Try removing multiple callouts that includes one at the end of the
+ // list of callouts.
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_four));
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(1133, callout_value_);
// ... and from the start.
- EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_one));
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_one));
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(33, callout_value_);
// ... and the remaining callouts.
- EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one",
- manager_three));
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_three));
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(0, callout_value_);
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
}
-// Check we can deregister multiple callouts from multiple libraries
+// Check we can deregister multiple callouts from multiple libraries.
TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsMultipleLibraries) {
// Ensure that no callouts are attached to any of the hooks.
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(two_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(three_index_));
- EXPECT_FALSE(getCalloutManager()->calloutsPresent(four_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
int status = 0;
- // Each library contributes two callouts to hook "one".
+ // Each library contributes two callouts to hook "alpha".
callout_value_ = 0;
- getCalloutManager()->registerCallout(0, "one", manager_one);
- getCalloutManager()->registerCallout(0, "one", manager_two);
- getCalloutManager()->registerCallout(1, "one", manager_three);
- getCalloutManager()->registerCallout(1, "one", manager_four);
- getCalloutManager()->registerCallout(2, "one", manager_five);
- getCalloutManager()->registerCallout(2, "one", manager_two);
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", manager_one);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", manager_three);
+ getCalloutManager()->registerCallout("alpha", manager_four);
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", manager_five);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(123452, callout_value_);
// Remove the manager_two callout from library 0. It should not affect
- // the second manager_two callout.
- EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_two));
+ // the second manager_two callout registered by library 2.
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
callout_value_ = 0;
- status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle());
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
EXPECT_EQ(0, status);
EXPECT_EQ(13452, callout_value_);
}
+// Check we can deregister all callouts from a single library.
+
+TEST_F(CalloutManagerTest, DeregisterAllCallouts) {
+ // Ensure that no callouts are attached to hook one.
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+
+ int status = 0;
+
+ // Each library contributes two callouts to hook "alpha".
+ callout_value_ = 0;
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", manager_one);
+ getCalloutManager()->registerCallout("alpha", manager_two);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", manager_three);
+ getCalloutManager()->registerCallout("alpha", manager_four);
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", manager_five);
+ getCalloutManager()->registerCallout("alpha", manager_six);
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
+ EXPECT_EQ(0, status);
+ EXPECT_EQ(123456, callout_value_);
+
+ // Remove all callouts from library index 1.
+ getCalloutManager()->setLibraryIndex(1);
+ EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
+ callout_value_ = 0;
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
+ EXPECT_EQ(0, status);
+ EXPECT_EQ(1256, callout_value_);
+
+ // Remove all callouts from library index 2.
+ getCalloutManager()->setLibraryIndex(2);
+ EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
+ callout_value_ = 0;
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
+ EXPECT_EQ(0, status);
+ EXPECT_EQ(12, callout_value_);
+}
+
+// Library handle tests. As by inspection the LibraryHandle can be seen to be
+// little more than shell around CalloutManager, only a basic set of tests
+// is done concerning registration and deregistration of functions.
+//
+// More extensive tests (i.e. checking that when a callout is called it can
+// only register and deregister callouts within its library) require that
+// the CalloutHandle object pass the appropriate LibraryHandle to the
+// callout. These tests are done in the handles_unittest tests.
+
+TEST_F(CalloutManagerTest, LibraryHandleRegistration) {
+ // Ensure that no callouts are attached to any of the hooks.
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+
+ // Set up so that hooks "alpha" and "beta" have callouts attached from a
+ // different libraries.
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->getLibraryHandle().registerCallout("alpha",
+ manager_one);
+ getCalloutManager()->getLibraryHandle().registerCallout("alpha",
+ manager_two);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->getLibraryHandle().registerCallout("alpha",
+ manager_three);
+ getCalloutManager()->getLibraryHandle().registerCallout("alpha",
+ manager_four);
+
+ // Check all is as expected.
+ EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+ EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
+
+ int status = 0;
+
+ // Check that calling the callouts returns as expected. (This is also a
+ // test of the callCallouts method.)
+ callout_value_ = 0;
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
+ EXPECT_EQ(0, status);
+ EXPECT_EQ(1234, callout_value_);
+
+ // Deregister a callout on library index 0 (after we check we can't
+ // deregister it through library index 1).
+ getCalloutManager()->setLibraryIndex(1);
+ EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+ callout_value_ = 0;
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
+ EXPECT_EQ(0, status);
+ EXPECT_EQ(1234, callout_value_);
+
+ getCalloutManager()->setLibraryIndex(0);
+ EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+ callout_value_ = 0;
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
+ EXPECT_EQ(0, status);
+ EXPECT_EQ(134, callout_value_);
+
+ // Deregister all callouts on library index 1.
+ getCalloutManager()->setLibraryIndex(1);
+ EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
+ callout_value_ = 0;
+ status = getCalloutManager()->callCallouts(alpha_index_,
+ getCalloutHandle());
+ EXPECT_EQ(0, status);
+ EXPECT_EQ(1, callout_value_);
+}
+
+
} // Anonymous namespace
diff --git a/src/lib/util/tests/handles_unittest.cc b/src/lib/util/tests/handles_unittest.cc
index 34ecc51..7bcc232 100644
--- a/src/lib/util/tests/handles_unittest.cc
+++ b/src/lib/util/tests/handles_unittest.cc
@@ -13,10 +13,12 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <util/hooks/callout_handle.h>
+#include <util/hooks/callout_manager.h>
#include <util/hooks/library_handle.h>
#include <util/hooks/server_hooks.h>
#include <boost/lexical_cast.hpp>
+#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
#include <algorithm>
@@ -35,14 +37,52 @@
/// - The various methods manipulating the items in the CalloutHandle's context
/// work correctly.
///
-/// Some minor interactions between the two classes are checked in the unit
-/// tests for each class (mainly the use of the "skip" flag).
+/// - An active callout can only modify the registration of callouts registered
+/// by its own library.
using namespace isc::util;
using namespace std;
namespace {
+class HandlesTest : public ::testing::Test {
+public:
+ /// @brief Constructor
+ ///
+ /// Sets up the various elements used in each test.
+ HandlesTest() : hooks_(new ServerHooks()), manager_()
+ {
+ // Set up four hooks, although through gamma
+ alpha_index_ = hooks_->registerHook("alpha");
+ beta_index_ = hooks_->registerHook("beta");
+ gamma_index_ = hooks_->registerHook("gamma");
+ delta_index_ = hooks_->registerHook("delta");
+
+ // Set up for three libraries.
+ manager_.reset(new CalloutManager(hooks_, 3));
+ }
+
+ /// @brief Return callout manager
+ boost::shared_ptr<CalloutManager> getCalloutManager() {
+ return (manager_);
+ }
+
+ /// Hook indexes - these are frequently accessed, so are accessed directly.
+ int alpha_index_;
+ int beta_index_;
+ int gamma_index_;
+ int delta_index_;
+
+private:
+ /// Server hooks
+ boost::shared_ptr<ServerHooks> hooks_;
+
+ /// Callout manager. Declared static so that the callout functions can
+ /// access it.
+ boost::shared_ptr<CalloutManager> manager_;
+
+};
+
// The next set of functions define the callouts used by the tests. They
// manipulate the data in such a way that callouts called - and the order in
// which they were called - can be determined. The functions also check that
@@ -59,7 +99,7 @@ namespace {
// identification has been set in the callout handle).
//
// For simplicity, and to cut down the number of functions actually written,
-// the callout indicator ("a" or "b") ) used in the in the CalloutHandle
+// the callout indicator ("1" or "2") ) used in the in the CalloutHandle
// functions is passed via a CalloutArgument. The argument is named "string":
// use of a name the same as that of one of the context elements serves as a
// check that the argument name space and argument context space are separate.
@@ -140,7 +180,7 @@ execute(CalloutHandle& callout_handle, int library_num, int callout_num) {
string_value = "";
}
- // Update the values and set them.
+ // Update the values and set them back in the callout context.
int_value += idata;
callout_handle.setContext("int", int_value);
@@ -228,71 +268,59 @@ print3(CalloutHandle& callout_handle) {
// This test checks the many-faced nature of the context for the CalloutContext.
-TEST(HandlesTest, ContextAccessCheck) {
- // Create the LibraryHandleCollection with a set of four callouts (the test
- // does not use the context_create and context_destroy callouts).
-
- boost::shared_ptr<ServerHooks> server_hooks(new ServerHooks());
- const int one_index = server_hooks->registerHook("one");
- const int two_index = server_hooks->registerHook("two");
- const int three_index = server_hooks->registerHook("three");
- const int four_index = server_hooks->registerHook("four");
-
- // Create the library handle collection and the library handles.
- boost::shared_ptr<LibraryHandleCollection>
- collection(new LibraryHandleCollection());
-
- boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout11);
- handle->registerCallout("two", callout12);
- handle->registerCallout("three", callout13);
- handle->registerCallout("four", print1);
- collection->addLibraryHandle(handle);
-
- handle.reset(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout21);
- handle->registerCallout("two", callout22);
- handle->registerCallout("three", callout23);
- handle->registerCallout("four", print2);
- collection->addLibraryHandle(handle);
-
- handle.reset(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout31);
- handle->registerCallout("two", callout32);
- handle->registerCallout("three", callout33);
- handle->registerCallout("four", print3);
- collection->addLibraryHandle(handle);
+TEST_F(HandlesTest, ContextAccessCheck) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Library 0.
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("beta", callout12);
+ getCalloutManager()->registerCallout("gamma", callout13);
+ getCalloutManager()->registerCallout("delta", print1);
+
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", callout21);
+ getCalloutManager()->registerCallout("beta", callout22);
+ getCalloutManager()->registerCallout("gamma", callout23);
+ getCalloutManager()->registerCallout("delta", print2);
+
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", callout31);
+ getCalloutManager()->registerCallout("beta", callout32);
+ getCalloutManager()->registerCallout("gamma", callout33);
+ getCalloutManager()->registerCallout("delta", print3);
// Create the callout handles and distinguish them by setting the
// "handle_num" argument.
- CalloutHandle callout_handle_1(collection);
+ CalloutHandle callout_handle_1(getCalloutManager());
callout_handle_1.setArgument("handle_num", static_cast<int>(1));
- CalloutHandle callout_handle_2(collection);
+ CalloutHandle callout_handle_2(getCalloutManager());
callout_handle_2.setArgument("handle_num", static_cast<int>(2));
// Now call the callouts attached to the first three hooks. Each hook is
// called twice (once for each callout handle) before the next hook is
// called.
- collection->callCallouts(one_index, callout_handle_1);
- collection->callCallouts(one_index, callout_handle_2);
- collection->callCallouts(two_index, callout_handle_1);
- collection->callCallouts(two_index, callout_handle_2);
- collection->callCallouts(three_index, callout_handle_1);
- collection->callCallouts(three_index, callout_handle_2);
-
- // Get the results for each callout. Explicitly zero the variables before
- // getting the results so we are certain that the values are the results
- // of the callouts.
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_2);
+ getCalloutManager()->callCallouts(gamma_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(gamma_index_, callout_handle_2);
+
+ // Get the results for each callout (the callout on hook "delta" copies
+ // the context values into a location the test can access). Explicitly
+ // zero the variables before getting the results so we are certain that
+ // the values are the results of the callouts.
zero_results();
- collection->callCallouts(four_index, callout_handle_1);
// To explain the expected callout context results.
//
- // The callout handle maintains a separate context for each library. When
+ // Each callout handle maintains a separate context for each library. When
// the first call to callCallouts() is made, "111" gets appended to
- // the context for library 1 maintained by by the callout handle, "211"
+ // the context for library 1 maintained by the first callout handle, "211"
// gets appended to the context maintained for library 2, and "311" to
// the context maintained for library 3. In each case, the first digit
// corresponds to the library number, the second to the callout number and
@@ -307,9 +335,9 @@ TEST(HandlesTest, ContextAccessCheck) {
// always 2. These additions don't affect the contexts maintained by
// callout handle 1.
//
- // The process is then repeated for hooks "two" and "three" which, for
- // callout handle 1, append "121", "221" and "321" for hook "two" and "311",
- // "321" and "331" for hook "three".
+ // The process is then repeated for hooks "beta" and "gamma" which, for
+ // callout handle 1, append "121", "221" and "321" for hook "beta" and
+ // "311", "321" and "331" for hook "gamma".
//
// The expected integer values can be found by summing up the values
// corresponding to the elements of the strings.
@@ -318,6 +346,7 @@ TEST(HandlesTest, ContextAccessCheck) {
// handle "1", so the following results are checking the context values
// maintained in that callout handle.
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
EXPECT_EQ("111121131", resultCalloutString(0));
EXPECT_EQ("211221231", resultCalloutString(1));
EXPECT_EQ("311321331", resultCalloutString(2));
@@ -329,7 +358,7 @@ TEST(HandlesTest, ContextAccessCheck) {
// Repeat the checks for callout 2.
zero_results();
- collection->callCallouts(four_index, callout_handle_2);
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
EXPECT_EQ((112 + 122 + 132), resultCalloutInt(0));
EXPECT_EQ((212 + 222 + 232), resultCalloutInt(1));
@@ -340,7 +369,7 @@ TEST(HandlesTest, ContextAccessCheck) {
EXPECT_EQ("312322332", resultCalloutString(2));
}
-// Now repeat the test, but add a deletion callout to the list. The "two"
+// Now repeat the test, but add a deletion callout to the list. The "beta"
// hook of library 2 will have an additional callout to delete the "int"
// element: the same hook for library 3 will delete both elements. In
// addition, the names of context elements for the libraries at this point
@@ -395,70 +424,55 @@ printContextNames3(CalloutHandle& handle) {
// Perform the test including deletion of context items.
-TEST(HandlesTest, ContextDeletionCheck) {
- // Create the LibraryHandleCollection with a set of four callouts
- // (the test does not use the context_create and context_destroy callouts.)
-
- boost::shared_ptr<ServerHooks> server_hooks(new ServerHooks());
- const int one_index = server_hooks->registerHook("one");
- const int two_index = server_hooks->registerHook("two");
- const int three_index = server_hooks->registerHook("three");
- const int four_index = server_hooks->registerHook("four");
-
- // Create the library handle collection and the library handles.
- boost::shared_ptr<LibraryHandleCollection>
- collection(new LibraryHandleCollection());
-
- boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout11);
- handle->registerCallout("two", callout12);
- handle->registerCallout("two", printContextNames1);
- handle->registerCallout("three", callout13);
- handle->registerCallout("four", print1);
- collection->addLibraryHandle(handle);
-
- handle.reset(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout21);
- handle->registerCallout("two", callout22);
- handle->registerCallout("two", deleteIntContextItem);
- handle->registerCallout("two", printContextNames2);
- handle->registerCallout("three", callout23);
- handle->registerCallout("four", print2);
- collection->addLibraryHandle(handle);
-
- handle.reset(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout31);
- handle->registerCallout("two", callout32);
- handle->registerCallout("two", deleteAllContextItems);
- handle->registerCallout("two", printContextNames3);
- handle->registerCallout("three", callout33);
- handle->registerCallout("four", print3);
- collection->addLibraryHandle(handle);
+TEST_F(HandlesTest, ContextDeletionCheck) {
+
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("beta", callout12);
+ getCalloutManager()->registerCallout("beta", printContextNames1);
+ getCalloutManager()->registerCallout("gamma", callout13);
+ getCalloutManager()->registerCallout("delta", print1);
+
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", callout21);
+ getCalloutManager()->registerCallout("beta", callout22);
+ getCalloutManager()->registerCallout("beta", deleteIntContextItem);
+ getCalloutManager()->registerCallout("beta", printContextNames2);
+ getCalloutManager()->registerCallout("gamma", callout23);
+ getCalloutManager()->registerCallout("delta", print2);
+
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", callout31);
+ getCalloutManager()->registerCallout("beta", callout32);
+ getCalloutManager()->registerCallout("beta", deleteAllContextItems);
+ getCalloutManager()->registerCallout("beta", printContextNames3);
+ getCalloutManager()->registerCallout("gamma", callout33);
+ getCalloutManager()->registerCallout("delta", print3);
// Create the callout handles and distinguish them by setting the "long"
// argument.
- CalloutHandle callout_handle_1(collection);
+ CalloutHandle callout_handle_1(getCalloutManager());
callout_handle_1.setArgument("handle_num", static_cast<int>(1));
- CalloutHandle callout_handle_2(collection);
+ CalloutHandle callout_handle_2(getCalloutManager());
callout_handle_2.setArgument("handle_num", static_cast<int>(2));
// Now call the callouts attached to the first three hooks. Each hook is
// called twice (once for each callout handle) before the next hook is
// called.
- collection->callCallouts(one_index, callout_handle_1);
- collection->callCallouts(one_index, callout_handle_2);
- collection->callCallouts(two_index, callout_handle_1);
- collection->callCallouts(two_index, callout_handle_2);
- collection->callCallouts(three_index, callout_handle_1);
- collection->callCallouts(three_index, callout_handle_2);
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_2);
+ getCalloutManager()->callCallouts(gamma_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(gamma_index_, callout_handle_2);
// Get the results for each callout. Explicitly zero the variables before
// getting the results so we are certain that the values are the results
// of the callouts.
zero_results();
- collection->callCallouts(four_index, callout_handle_1);
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
// The logic by which the expected results are arrived at is described
// in the ContextAccessCheck test. The results here are different
@@ -475,7 +489,7 @@ TEST(HandlesTest, ContextDeletionCheck) {
// Repeat the checks for callout handle 2.
zero_results();
- collection->callCallouts(four_index, callout_handle_2);
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
EXPECT_EQ((112 + 122 + 132), resultCalloutInt(0));
EXPECT_EQ(( 232), resultCalloutInt(1));
@@ -486,7 +500,7 @@ TEST(HandlesTest, ContextDeletionCheck) {
EXPECT_EQ( "332", resultCalloutString(2));
// ... and check what the names of the context items are after the callouts
- // for hook "two". We know they are in sorted order.
+ // for hook "beta". We know they are in sorted order.
EXPECT_EQ(2, getItemNames(0).size());
EXPECT_EQ(string("int"), getItemNames(0)[0]);
@@ -507,29 +521,20 @@ int returnError(CalloutHandle&) {
return (1);
}
-TEST(HandlesTest, ConstructionDestructionCallouts) {
- // Create the LibraryHandleCollection comprising two LibraryHandles.
- // Register callouts for the context_create and context_destroy hooks.
-
- boost::shared_ptr<ServerHooks> server_hooks(new ServerHooks());
+TEST_F(HandlesTest, ConstructionDestructionCallouts) {
- // Create the library handle collection and the library handles.
- boost::shared_ptr<LibraryHandleCollection>
- collection(new LibraryHandleCollection());
-
- boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(server_hooks));
- handle->registerCallout("context_create", callout11);
- handle->registerCallout("context_create", print1);
- handle->registerCallout("context_destroy", callout12);
- handle->registerCallout("context_destroy", print1);
- collection->addLibraryHandle(handle);
+ // Register context callouts.
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("context_create", callout11);
+ getCalloutManager()->registerCallout("context_create", print1);
+ getCalloutManager()->registerCallout("context_destroy", callout12);
+ getCalloutManager()->registerCallout("context_destroy", print1);
// Create the CalloutHandle and check that the constructor callout
// has run.
zero_results();
- boost::shared_ptr<CalloutHandle>
- callout_handle(new CalloutHandle(collection));
-
+ boost::scoped_ptr<CalloutHandle>
+ callout_handle(new CalloutHandle(getCalloutManager()));
EXPECT_EQ("110", resultCalloutString(0));
EXPECT_EQ(110, resultCalloutInt(0));
@@ -544,19 +549,220 @@ TEST(HandlesTest, ConstructionDestructionCallouts) {
EXPECT_EQ((110 + 120), resultCalloutInt(0));
// Test that the destructor throws an error if the context_destroy
- // callout returns an error.
- handle->registerCallout("context_destroy", returnError);
- callout_handle.reset(new CalloutHandle(collection));
+ // callout returns an error. (As the constructor and destructor will
+ // have implicitly run the CalloutManager's callCallouts method, we need
+ // to set the library index again.)
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("context_destroy", returnError);
+ callout_handle.reset(new CalloutHandle(getCalloutManager()));
EXPECT_THROW(callout_handle.reset(), ContextDestroyFail);
// We don't know what callout_handle is pointing to - it could be to a
// half-destroyed object - so use a new CalloutHandle to test construction
// failure.
- handle->registerCallout("context_create", returnError);
- boost::shared_ptr<CalloutHandle> callout_handle2;
- EXPECT_THROW(callout_handle2.reset(new CalloutHandle(collection)),
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("context_create", returnError);
+ boost::scoped_ptr<CalloutHandle> callout_handle2;
+ EXPECT_THROW(callout_handle2.reset(new CalloutHandle(getCalloutManager())),
ContextCreateFail);
+}
+
+// Dynamic callout registration and deregistration.
+// The following are the dynamic registration/deregistration callouts.
+
+
+// Add callout_78_alpha - adds a callout to hook alpha that appends "78x"
+// (where "x" is the callout handle) to the current output.
+int
+callout78(CalloutHandle& callout_handle) {
+ return (execute(callout_handle, 7, 8));
+}
+
+int
+add_callout78_alpha(CalloutHandle& callout_handle) {
+ callout_handle.getLibraryHandle().registerCallout("alpha", callout78);
+ return (0);
+}
+
+int
+delete_callout78_alpha(CalloutHandle& callout_handle) {
+ static_cast<void>(
+ callout_handle.getLibraryHandle().deregisterCallout("alpha",
+ callout78));
+ return (0);
+}
+
+// Check that a callout can register another callout on a different hook.
+
+TEST_F(HandlesTest, DynamicRegistrationAnotherHook) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Set up callouts on "alpha".
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("delta", print1);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", callout21);
+ getCalloutManager()->registerCallout("delta", print2);
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", callout31);
+ getCalloutManager()->registerCallout("delta", print3);
+
+ // ... and on "beta", set up the function to add a hook to alpha (but only
+ // for library 1).
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("beta", add_callout78_alpha);
+
+ // See what we get for calling the callouts on alpha first.
+ CalloutHandle callout_handle_1(getCalloutManager());
+ callout_handle_1.setArgument("handle_num", static_cast<int>(1));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
+ EXPECT_EQ("111", resultCalloutString(0));
+ EXPECT_EQ("211", resultCalloutString(1));
+ EXPECT_EQ("311", resultCalloutString(2));
+
+ // All as expected, now call the callouts on beta. This should add a
+ // callout to the list of callouts for alpha, which we should see when
+ // we run the test again.
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_1);
+
+ // Use a new callout handle so as to get fresh callout context.
+ CalloutHandle callout_handle_2(getCalloutManager());
+ callout_handle_2.setArgument("handle_num", static_cast<int>(2));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
+ EXPECT_EQ("112", resultCalloutString(0));
+ EXPECT_EQ("212782", resultCalloutString(1));
+ EXPECT_EQ("312", resultCalloutString(2));
+}
+
+// Check that a callout can register another callout on the same hook.
+// Note that the registration only applies to a subsequent invocation of
+// callCallouts, not to the current one. In other words, if
+//
+// * the callout list for a library is "A then B then C"
+// * when callCallouts is executed "B" adds "D" to that list,
+//
+// ... the current execution of callCallouts only executes A, B and C. A
+// subsequent invocation will execute A, B, C then D.
+
+TEST_F(HandlesTest, DynamicRegistrationSameHook) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Set up callouts on "alpha".
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("alpha", add_callout78_alpha);
+ getCalloutManager()->registerCallout("delta", print1);
+
+ // See what we get for calling the callouts on alpha first.
+ CalloutHandle callout_handle_1(getCalloutManager());
+ callout_handle_1.setArgument("handle_num", static_cast<int>(1));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
+ EXPECT_EQ("111", resultCalloutString(0));
+
+ // Run it again - we should have added something to this hook.
+ CalloutHandle callout_handle_2(getCalloutManager());
+ callout_handle_2.setArgument("handle_num", static_cast<int>(2));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
+ EXPECT_EQ("112782", resultCalloutString(0));
+
+ // And a third time...
+ CalloutHandle callout_handle_3(getCalloutManager());
+ callout_handle_3.setArgument("handle_num", static_cast<int>(3));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_3);
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_3);
+ EXPECT_EQ("113783783", resultCalloutString(0));
+}
+
+// Deregistration of a callout from a different hook
+
+TEST_F(HandlesTest, DynamicDeregistrationDifferentHook) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Set up callouts on "alpha".
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("alpha", callout78);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("delta", print1);
+
+ getCalloutManager()->registerCallout("beta", delete_callout78_alpha);
+
+ // Call the callouts on alpha
+ CalloutHandle callout_handle_1(getCalloutManager());
+ callout_handle_1.setArgument("handle_num", static_cast<int>(1));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
+ EXPECT_EQ("111781111", resultCalloutString(0));
+
+ // Run the callouts on hook beta to remove the callout on alpha.
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_1);
+
+ // The run of the callouts should have altered the callout list on the
+ // first library for hook alpha, so call again to make sure.
+ CalloutHandle callout_handle_2(getCalloutManager());
+ callout_handle_2.setArgument("handle_num", static_cast<int>(2));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
+ EXPECT_EQ("112112", resultCalloutString(0));
+}
+
+// Deregistration of a callout from the same hook
+
+TEST_F(HandlesTest, DynamicDeregistrationSameHook) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Set up callouts on "alpha".
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("alpha", delete_callout78_alpha);
+ getCalloutManager()->registerCallout("alpha", callout78);
+ getCalloutManager()->registerCallout("delta", print1);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", callout21);
+ getCalloutManager()->registerCallout("alpha", callout78);
+ getCalloutManager()->registerCallout("delta", print2);
+
+ // Call the callouts on alpha
+ CalloutHandle callout_handle_1(getCalloutManager());
+ callout_handle_1.setArgument("handle_num", static_cast<int>(1));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
+ EXPECT_EQ("111781", resultCalloutString(0));
+ EXPECT_EQ("211781", resultCalloutString(1));
+
+ // The run of the callouts should have altered the callout list on the
+ // first library for hook alpha, so call again to make sure.
+ CalloutHandle callout_handle_2(getCalloutManager());
+ callout_handle_2.setArgument("handle_num", static_cast<int>(2));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
+ EXPECT_EQ("112", resultCalloutString(0));
+ EXPECT_EQ("212782", resultCalloutString(1));
}
diff --git a/src/lib/util/tests/library_handle_unittest.cc b/src/lib/util/tests/library_handle_unittest.cc
deleted file mode 100644
index f8e54aa..0000000
--- a/src/lib/util/tests/library_handle_unittest.cc
+++ /dev/null
@@ -1,303 +0,0 @@
-// 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 <util/hooks/callout_handle.h>
-#include <util/hooks/library_handle.h>
-#include <util/hooks/server_hooks.h>
-
-#include <gtest/gtest.h>
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-using namespace isc::util;
-using namespace std;
-
-namespace {
-
-class LibraryHandleTest : public ::testing::Test {
-public:
- /// @brief Constructor
- ///
- /// Sets up an appropriate number of server hooks to pass to the
- /// constructed callout handle objects.
- LibraryHandleTest() : hooks_(new ServerHooks()) {
- hooks_->registerHook("alpha");
- hooks_->registerHook("beta");
- hooks_->registerHook("gamma");
- collection_.reset(new LibraryHandleCollection(hooks_));
-
- // Also initialize the variable used to pass information back from the
- // callouts to the tests.
- callout_value = 0;
- }
-
- /// Obtain constructed server hooks.
- boost::shared_ptr<ServerHooks>& getServerHooks() {
- return (hooks_);
- }
-
- /// Obtain constructed hook manager.
- boost::shared_ptr<LibraryHandleCollection>& getLibraryHandleCollection() {
- return (collection_);
- }
-
- /// Variable for callouts test. This is public and static to allow non-
- /// member functions to access it. It is initialized every time a new
- /// test starts.
- static int callout_value;
-
-private:
- boost::shared_ptr<ServerHooks> hooks_;
- boost::shared_ptr<LibraryHandleCollection> collection_;
- boost::shared_ptr<LibraryHandle> handle_0_;
- boost::shared_ptr<LibraryHandle> handle_1_;
-};
-
-// Definition of the static variable.
-int LibraryHandleTest::callout_value = 0;
-
-// The next set of tests check that callouts can be registered.
-
-// The callouts defined here are structured in such a way that it is possible
-// to determine the order in which they are called and whether they are called
-// at all. The method used is simple - after a sequence of callouts, the digits
-// in the value, reading left to right, determines the order of the callouts
-// called. For example, callout one followed by two followed by three followed
-// by two followed by one results in a value of 12321.
-//
-// Functions return a zero to indicate success.
-
-extern "C" {
-int one(CalloutHandle&) {
- LibraryHandleTest::callout_value =
- 10 * LibraryHandleTest::callout_value + 1;
- return (0);
-}
-
-int two(CalloutHandle&) {
- LibraryHandleTest::callout_value =
- 10 * LibraryHandleTest::callout_value + 2;
- return (0);
-}
-
-int three(CalloutHandle&) {
- LibraryHandleTest::callout_value =
- 10 * LibraryHandleTest::callout_value + 3;
- return (0);
-}
-
-// The next function is a duplicate of "one", but returns an error status.
-
-int one_error(CalloutHandle& handle) {
- static_cast<void>(one(handle));
- return (1);
-}
-
-// The next function is a duplicate of "one", but sets the skip flag.
-
-int one_skip(CalloutHandle& handle) {
- handle.setSkip(true);
- return (one(handle));
-}
-
-}; // extern "C"
-
-// Check that we can register callouts on a particular hook.
-
-TEST_F(LibraryHandleTest, RegisterSingleCallout) {
- LibraryHandle handle(getServerHooks());
-
- // Register callouts for hooks alpha and see that it is registered.
- EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
- handle.registerCallout("alpha", one);
- EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-
- // Do the same for beta (which checks that the hooks are independent).
- EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("beta")));
- handle.registerCallout("beta", one);
- EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("beta")));
-}
-
-// Check that we can call a single callout on a particular hook. Refer to the
-// above definition of the callouts "one" and "two" to understand the expected
-// return values.
-
-TEST_F(LibraryHandleTest, CallSingleCallout) {
- LibraryHandle handle(getServerHooks());
-
- // Register callout for hook alpha...
- EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
- handle.registerCallout("alpha", one);
- EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-
- // Call it.
- EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
- int index = getServerHooks()->getIndex("alpha");
- CalloutHandle callout_handle(getLibraryHandleCollection());
- int status = handle.callCallouts(index, callout_handle);
-
- EXPECT_EQ(0, status);
- EXPECT_EQ(1, LibraryHandleTest::callout_value);
-
-}
-
-// Check that we can register two callouts for a hook and that they are called
-// in order.
-
-TEST_F(LibraryHandleTest, TwoCallouts) {
- LibraryHandle handle(getServerHooks());
-
- // Register two callouts for hook alpha.
- handle.registerCallout("alpha", one);
- handle.registerCallout("alpha", two);
-
- // Call them.
- EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
- int index = getServerHooks()->getIndex("alpha");
- CalloutHandle callout_handle(getLibraryHandleCollection());
- int status = handle.callCallouts(index, callout_handle);
-
- EXPECT_EQ(0, status);
- EXPECT_EQ(12, LibraryHandleTest::callout_value);
-}
-
-// Check that we can register two callouts for a hook and that the second is not
-// called if the first returns a non-zero status.
-
-TEST_F(LibraryHandleTest, TwoCalloutsWithError) {
- LibraryHandle handle(getServerHooks());
-
- // Register callout for hook alpha...
- handle.registerCallout("alpha", one_error);
- handle.registerCallout("alpha", two);
-
- // Call them.
- EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
- int index = getServerHooks()->getIndex("alpha");
- CalloutHandle callout_handle(getLibraryHandleCollection());
- int status = handle.callCallouts(index, callout_handle);
-
- EXPECT_EQ(1, status);
- EXPECT_EQ(1, LibraryHandleTest::callout_value);
-}
-
-// Check that we can register two callouts for a hook and that the second is not
-// called if the first szets the callout "skip" flag.
-
-TEST_F(LibraryHandleTest, TwoCalloutsWithSkip) {
- LibraryHandle handle(getServerHooks());
-
- // Register callout for hook alpha.
- handle.registerCallout("alpha", one_skip);
- handle.registerCallout("alpha", two);
-
- // Call them.
- EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
- int index = getServerHooks()->getIndex("alpha");
- CalloutHandle callout_handle(getLibraryHandleCollection());
- int status = handle.callCallouts(index, callout_handle);
-
- EXPECT_EQ(0, status);
- EXPECT_EQ(1, LibraryHandleTest::callout_value);
-}
-
-// Check that a callout can be registered more than once.
-
-TEST_F(LibraryHandleTest, MultipleRegistration) {
- LibraryHandle handle(getServerHooks());
-
- // Register callouts for hook alpha.
- handle.registerCallout("alpha", one);
- handle.registerCallout("alpha", two);
- handle.registerCallout("alpha", one);
-
- // Call them.
- EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
- int index = getServerHooks()->getIndex("alpha");
- CalloutHandle callout_handle(getLibraryHandleCollection());
- int status = handle.callCallouts(index, callout_handle);
-
- EXPECT_EQ(0, status);
- EXPECT_EQ(121, LibraryHandleTest::callout_value);
-}
-
-// Check that a callout can be deregistered.
-
-TEST_F(LibraryHandleTest, Deregister) {
- LibraryHandle handle(getServerHooks());
-
- // Register callouts for hook alpha...
- handle.registerCallout("alpha", one);
- handle.registerCallout("alpha", two);
- handle.registerCallout("alpha", one);
-
- // Get rid of all the "one" callbacks.
- handle.deregisterCallout("alpha", one);
-
- // Call it.
- EXPECT_EQ(0, LibraryHandleTest::callout_value);
-
- int index = getServerHooks()->getIndex("alpha");
- CalloutHandle callout_handle(getLibraryHandleCollection());
- int status = handle.callCallouts(index, callout_handle);
-
- EXPECT_EQ(0, status);
- EXPECT_EQ(2, LibraryHandleTest::callout_value);
-}
-
-// Check that all callouts can be deregistered.
-
-TEST_F(LibraryHandleTest, DeregisterAll) {
- LibraryHandle handle(getServerHooks());
-
- // Register callouts for hook alpha...
- EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
- handle.registerCallout("alpha", one);
- handle.registerCallout("alpha", two);
- EXPECT_TRUE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-
- // ... and remove them.
- handle.deregisterAll("alpha");
- EXPECT_FALSE(handle.calloutsPresent(getServerHooks()->getIndex("alpha")));
-}
-
-// Add checks that invalid names etc. all throw. With the base hooks added
-// by the constructor, there are five valid hooks, with valid indexes 0 to 4.
-
-TEST_F(LibraryHandleTest, InvalidNameAndIndex) {
- LibraryHandle handle(getServerHooks());
-
- EXPECT_THROW(handle.registerCallout("omega", one), NoSuchHook);
- EXPECT_THROW(handle.deregisterCallout("omega", one), NoSuchHook);
- EXPECT_THROW(handle.deregisterAll("omega"), NoSuchHook);
-
- EXPECT_THROW(static_cast<void>(handle.calloutsPresent(-1)), NoSuchHook);
- EXPECT_THROW(static_cast<void>(handle.calloutsPresent(5)), NoSuchHook);
-
- CalloutHandle callout_handle(getLibraryHandleCollection());
- EXPECT_THROW(static_cast<void>(handle.callCallouts(-1, callout_handle)),
- NoSuchHook);
- EXPECT_THROW(static_cast<void>(handle.callCallouts(10, callout_handle)),
- NoSuchHook);
-}
-
-
-} // Anonymous namespace
diff --git a/src/lib/util/tests/server_hooks_unittest.cc b/src/lib/util/tests/server_hooks_unittest.cc
index 287c4fe..f029ad2 100644
--- a/src/lib/util/tests/server_hooks_unittest.cc
+++ b/src/lib/util/tests/server_hooks_unittest.cc
@@ -179,14 +179,14 @@ TEST(HookRegistrationFunction, Registration) {
// Should have two hook registration functions registered.
EXPECT_EQ(2, HookRegistrationFunction::getFunctionVector().size());
- // Execute the functions and check that four new hooks were defined.
-
+ // Execute the functions and check that four new hooks were defined (two
+ // from each function).
ServerHooks hooks;
EXPECT_EQ(2, hooks.getCount());
HookRegistrationFunction::execute(hooks);
EXPECT_EQ(6, hooks.getCount());
- // Check the hook names
+ // Check the hook names are as expected.
vector<string> names = hooks.getHookNames();
ASSERT_EQ(6, names.size());
sort(names.begin(), names.end());
@@ -222,13 +222,13 @@ TEST(HookRegistrationFunction, Registration) {
HookRegistrationFunction f3(registerEpsilon);
EXPECT_EQ(1, HookRegistrationFunction::getFunctionVector().size());
- // Execute it and check that the hook was registered.
+ // Execute it...
ServerHooks hooks2;
EXPECT_EQ(0, epsilon);
EXPECT_EQ(2, hooks2.getCount());
HookRegistrationFunction::execute(hooks2);
- // Should be three hooks, with the new one assigned an index of 2.
+ // There should be three hooks, with the new one assigned an index of 2.
names = hooks2.getHookNames();
ASSERT_EQ(3, names.size());
sort(names.begin(), names.end());
More information about the bind10-changes
mailing list