From: Stephen Morris Date: Fri, 7 Jun 2013 16:07:11 +0000 (+0100) Subject: [2974] Created CalloutManager X-Git-Tag: bind10-1.2.0beta1-release~402^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=71376fdfd9be70f5dc7f28fcec5bb75fbeb27ccd;p=thirdparty%2Fkea.git [2974] Created CalloutManager The LibraryHandleCollection, as a result of comments, has morphed into the general class for handling callouts. This commit reflects that change. --- diff --git a/src/lib/util/Makefile.am b/src/lib/util/Makefile.am index bae2a80bf6..0f22a74a21 100644 --- a/src/lib/util/Makefile.am +++ b/src/lib/util/Makefile.am @@ -37,8 +37,8 @@ libb10_util_la_SOURCES += encode/base32hex_from_binary.h 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_handle.h hooks/callout_handle.cc -libb10_util_la_SOURCES += hooks/library_handle.h hooks/library_handle.cc +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/server_hooks.h hooks/server_hooks.cc libb10_util_la_SOURCES += random/qid_gen.h random/qid_gen.cc libb10_util_la_SOURCES += random/random_number_generator.h diff --git a/src/lib/util/hooks/callout_handle.h b/src/lib/util/hooks/callout_handle.h index 3d09c457c9..87d9cb7a0c 100644 --- a/src/lib/util/hooks/callout_handle.h +++ b/src/lib/util/hooks/callout_handle.h @@ -73,8 +73,8 @@ public: // Forward declaration of the library handle and related collection classes. +class CalloutManager; class LibraryHandle; -class LibraryHandleCollection; /// @brief Per-packet callout handle /// @@ -135,13 +135,13 @@ public: /// Creates the object and calls the callouts on the "context_create" /// hook. /// - /// @param manager Pointer to the collection of library handles. - CalloutHandle(boost::shared_ptr& collection); + /// @param manager Pointer to the callout manager object. + CalloutHandle(boost::shared_ptr& /* manager */) {} /// @brief Destructor /// /// Calls the context_destroy callback to release any per-packet context. - ~CalloutHandle(); + ~CalloutHandle() {} /// @brief Set argument /// @@ -364,9 +364,8 @@ private: /// Context collection - there is one entry per library context. ContextCollection context_collection_; - /// Library handle collection, used to obtain the correct library handle - /// during a call to a callout. - boost::shared_ptr library_collection_; + /// Callout manager. + boost::shared_ptr manager_; /// "Skip" flag, indicating if the caller should bypass remaining callouts. bool skip_; diff --git a/src/lib/util/hooks/callout_manager.cc b/src/lib/util/hooks/callout_manager.cc new file mode 100644 index 0000000000..1cae83f0b4 --- /dev/null +++ b/src/lib/util/hooks/callout_manager.cc @@ -0,0 +1,195 @@ +// 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 +#include + +#include +#include +#include + +using namespace std; +using namespace isc::util; + +namespace isc { +namespace util { + +// Callout manipulation - all deferred to the CalloutManager. + +void +LibraryHandle::registerCallout(const std::string& name, CalloutPtr callout) { + callout_manager_->registerCallout(library_index_, name, callout); +} + +bool +LibraryHandle::deregisterCallout(const std::string& name, CalloutPtr callout) { + return (callout_manager_->deregisterCallout(library_index_, name, callout)); +} + +bool +LibraryHandle::deregisterAllCallouts(const std::string& name) { + return (callout_manager_->deregisterAllCallouts(library_index_, name)); +} + +// Register a callout for a particular library. + +void +CalloutManager::registerCallout(int libindex, const std::string& name, + CalloutPtr callout) { + // Get the index associated with this hook (validating the name in the + // process). + int hook_index = hooks_->getIndex(name); + + // Iterate through the callout vector for the hook from start to end, + // looking for the first entry where the library index is greater than + // 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)); + 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)); +} + + +// Check if callouts are present for a given hook index. + +bool +CalloutManager::calloutsPresent(int hook_index) const { + // Validate the hook index. + checkHookIndex(hook_index); + + // Valid, so are there any callouts associated with that hook? + return (!hook_vector_[hook_index].empty()); +} + +// Call all the callouts for a given hook. + +int +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. + 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) { + status = (*i->second)(callout_handle); + } + + return (status); +} + +// Deregister a callout registered by a library on a particular hook. + +bool +CalloutManager::deregisterCallout(int library_index, const std::string& name, + CalloutPtr callout) { + + // 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 + /// we want to remove. + CalloutEntry target(library_index, 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 + /// the removal. + size_t initial_size = hook_vector_[hook_index].size(); + + // The next bit is standard STL (see "Item 33" in "Effective STL" by + // Scott Meyers). + // + // remove_if reorders the hook vector so that all items not matching + // the predicate are at the start of the vector and returns a pointer + // to the next element. (In this case, the predicate is that the item + // is equal to the value of the passed callout.) The erase() call + // removes everything from that element to the end of the vector, i.e. + // all the matching elements. + hook_vector_[hook_index].erase(remove_if(hook_vector_[hook_index].begin(), + hook_vector_[hook_index].end(), + bind1st(equal_to(), + target)), + hook_vector_[hook_index].end()); + + // Return an indication of whether anything was removed. + return (initial_size != hook_vector_[hook_index].size()); +} + +// Deregister all callouts on a given hook. + +bool +CalloutManager::deregisterAllCallouts(int library_index, + 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); + + /// 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(), + bind1st(CalloutLibraryEqual(), + target)), + hook_vector_[hook_index].end()); + + // 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 +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 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 new file mode 100644 index 0000000000..f1b8d8cc62 --- /dev/null +++ b/src/lib/util/hooks/callout_manager.h @@ -0,0 +1,315 @@ +// 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. + +#ifndef LIBRARY_HANDLE_H +#define LIBRARY_HANDLE_H + +#include +#include + +#include + +#include +#include + +namespace isc { +namespace util { + +/// @brief No Such Context +/// +/// Thrown if an attempt is made to obtain context that has not been previously +/// set. + +class NoSuchLibraryContext : public Exception { +public: + NoSuchLibraryContext(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) {} +}; + +/// @brief Invalid index +/// +/// Thrown if an attempt is made to obtain a library handle but the current +/// library handle index is invalid. This will occur if the method +/// CalloutManager::getHandleVector() is called outside of a callout. + +class InvalidIndex : public Exception { +public: + InvalidIndex(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) {} +}; + +// Forward declarations +class CalloutHandle; +class CalloutManager; + +/// Typedef for a callout pointer. (Callouts must have "C" linkage.) +extern "C" { + typedef int (*CalloutPtr)(CalloutHandle&); +}; + + + + +/// @brief Library handle +/// +/// This class is used to manage a loaded library. It is used by the user +/// library to register callouts. +/// +/// The main processing is done by the CalloutManager class. By +/// presenting this object to the user-library callouts, they can manage the +/// callout list for their own library, but cannot affect the callouts registered +/// by other libraries. + +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. + /// This pointer is used to access appropriate methods in the collection + /// object. + LibraryHandle(int library_index, CalloutManager* collection) + : library_index_(library_index), callout_manager_(collection) + {} + + /// @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. + /// + /// @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(const std::string& name, CalloutPtr callout); + + /// @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. + /// + /// @param name Name of the hook from which the callout is removed. + /// @param callout Pointer to the callout function to be removed. + /// + /// @return true if a one or more callouts were deregistered. + /// + /// @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(const std::string& name, CalloutPtr callout); + + /// @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. + /// + /// @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(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_; +}; + + +/// @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. +/// +/// The class also holds the collection of library handles, used to allow the +/// libraries to manipulate their callout list. + +class CalloutManager { +private: + + // Private typedefs + + /// Vector of library handles. + typedef std::vector > HandleVector; + + /// Element in the vector of callouts. The elements in the pair are the + /// library index and the pointer to the callout. + typedef std::pair CalloutEntry; + + /// Entry in the list of callouts for an individual hook. + typedef std::vector CalloutVector; + +public: + + /// @brief Constructor + /// + /// Initializes member variables, in particular sizing the hook vector + /// (the vector of callouts) to the appropriate size. + /// + /// @param hook Collection of known hook names. + CalloutManager(const boost::shared_ptr& hooks) : + hooks_(hooks), handles_(), hook_vector_(hooks->getCount()) + {} + + /// @brief Register a callout on a hook + /// + /// 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. + /// + /// @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); + + /// @brief De-Register a callout on a hook + /// + /// Searches through the functions registered by the specified library 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. + /// + /// @return true if a one or more callouts were deregistered. + /// + /// @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); + + /// @brief Removes all callouts on a hook + /// + /// Removes all callouts associated with a given hook that were registered + /// by the specified library. + /// + /// @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); + + /// @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. + /// + /// @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; + + /// @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. + /// @param callout_handle Reference to the CalloutHandle object for the + /// current object being processed. + /// + /// @return Status return. + int callCallouts(int index, CalloutHandle& callout_handle); + + + /// @brief Create library handle + /// + /// 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 createHandle(); + +private: + /// @brief Check hook index + /// + /// Ensures that the passed hook index is valid. + /// + /// @param index Hook index to test + /// + /// @throw NoSuchHook + void checkHookIndex(int hook_index) const { + if ((hook_index < 0) || (hook_index >= hook_vector_.size())) { + isc_throw(NoSuchHook, "hook index " << hook_index << + " is not valid for the list of registered hooks"); + } + } + + /// @brief Compare two callout entries for library equality + /// + /// This is used in callout removal code. + /// + /// @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 { + public: + bool operator()(const CalloutEntry& ent1, const CalloutEntry& ent2) { + return (ent1.first == ent2.first); + } + }; + + /// List of server hooks. This is used + boost::shared_ptr hooks_; + + /// Vector of pointers to library handles. + HandleVector handles_; + + /// Vector of callout vectors. There is one entry in this outer vector for + /// each hook. + std::vector hook_vector_; + +}; + +} // namespace util +} // namespace isc + +#endif // LIBRARY_HANDLE_H diff --git a/src/lib/util/hooks/library_handle.cc b/src/lib/util/hooks/library_handle.cc deleted file mode 100644 index 529989818a..0000000000 --- a/src/lib/util/hooks/library_handle.cc +++ /dev/null @@ -1,187 +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 -#include - -#include -#include - -using namespace std; -using namespace isc::util; - -namespace isc { -namespace util { - -// Check that an index is valid for the hook vector. - -void -LibraryHandle::checkHookIndex(int index) const { - if ((index < 0) || (index >= hook_vector_.size())) { - isc_throw(NoSuchHook, "hook index " << index << " is invalid for the " - " size of the hook vector (" << hook_vector_.size() << ")"); - } -} - -// Register a callout for a hook, adding it to run after any previously -// registered callouts on that hook. - -void -LibraryHandle::registerCallout(const std::string& name, CalloutPtr callout) { - - // Get index of hook in the hook vector, validating the hook name as we - // do so. - int index = hooks_->getIndex(name); - - // Index valid, so add the callout to the end of the list of callouts. - hook_vector_[index].push_back(callout); -} - -// Check if callouts are present for a given hook index. - -bool -LibraryHandle::calloutsPresent(int index) const { - // Validate the hook index. - checkHookIndex(index); - - // Valid, so are there any callouts associated with that hook? - return (!hook_vector_[index].empty()); -} - -// Call all the callouts for a given hook. - -int -LibraryHandle::callCallouts(int index, CalloutHandle& callout_handle) { - // Validate the hook index. - checkHookIndex(index); - - // Call all the callouts, stopping if the "skip" flag is set or if a - // non-zero status is returned. - int status = 0; - for (int i = 0; - (i < hook_vector_[index].size()) && !callout_handle.getSkip() && - (status == 0); - ++i) { - status = (*hook_vector_[index][i])(callout_handle); - } - - return (status); -} - -// Deregister a callout on a given hook. - -void -LibraryHandle::deregisterCallout(const std::string& name, CalloutPtr callout) { - - // Get the index associated with this hook (validating the name in the - // process). - int index = hooks_->getIndex(name); - - if (!hook_vector_[index].empty()) { - // The next bit is standard STL (see "Item 33" in "Effective STL" by - // Scott Meyers). - // - // remove_if reorders the hook vector so that all items not matching - // the predicate are at the start of the vector and returns a pointer - // to the next element. (In this case, the predicate is that the item - // is equal to the value of the passed callout.) The erase() call - // removes everything from that element to the end of the vector, i.e. - // all the matching elements. - hook_vector_[index].erase(remove_if(hook_vector_[index].begin(), - hook_vector_[index].end(), - bind1st(equal_to(), - callout)), - hook_vector_[index].end()); - } -} - -// Deregister all callouts on a given hook. - -void -LibraryHandle::deregisterAll(const std::string& name) { - - // Get the index associated with this hook (validating the name in the - // process). - int index = hooks_->getIndex(name); - - // Get rid of everything. - hook_vector_[index].clear(); -} - -// LibraryHandleCollection methods. - -// Return pointer to the current library handle. - -boost::shared_ptr -LibraryHandleCollection::getLibraryHandle() const { - if ((curidx_ < 0) || (curidx_ >= handles_.size())) { - isc_throw(InvalidIndex, "current library handle index of (" << - curidx_ << ") is not valid for the library handle vector " - "(size = " << handles_.size() << ")"); - } - - return (handles_[curidx_]); -} - -// Check if a any of the libraries have at least one callout present on a given -// hook. - -bool -LibraryHandleCollection::calloutsPresent(int index) const { - - // Method returns false if no LibraryHandles are present. Otherwise, - // the validity of the index is checked by the calloutsPresent() method - // on the first handle processed. - bool present = false; - for (int i = 0; (i < handles_.size()) && !present; ++i) { - present = handles_[i]->calloutsPresent(index); - } - - return (present); -} - -// Call all the callouts for a given hook. - -int -LibraryHandleCollection::callCallouts(int index, - CalloutHandle& callout_handle) { - - // Don't validate the hook index here as it is checked in the call to the - // callCallouts() method of the first library handle. - - // Clear the skip flag before we start so that no state from a previous - // call of a hook accidentally leaks through. - callout_handle.setSkip(false); - - // Call all the callouts, stopping if the "skip" flag is set or if a - // non-zero status is returned. Note that we iterate using the current - // index as the counter to allow callout handle object to retrieve the - // current LibraryHandle. - int status = 0; - for (curidx_ = 0; - (curidx_ < handles_.size()) && !callout_handle.getSkip() && - (status == 0); - ++curidx_) { - status = handles_[curidx_]->callCallouts(index, callout_handle); - } - - // Reset current index to an invalid value as we are no longer calling - // the callouts. - curidx_ = -1; - - return (status); -} - -} // namespace util -} // namespace isc diff --git a/src/lib/util/hooks/library_handle.h b/src/lib/util/hooks/library_handle.h deleted file mode 100644 index 790f0ea7ea..0000000000 --- a/src/lib/util/hooks/library_handle.h +++ /dev/null @@ -1,264 +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. - -#ifndef LIBRARY_HANDLE_H -#define LIBRARY_HANDLE_H - -#include -#include - -#include - -#include -#include - -namespace isc { -namespace util { - -/// @brief No Such Context -/// -/// Thrown if an attempt is made to obtain context that has not been previously -/// set. - -class NoSuchLibraryContext : public Exception { -public: - NoSuchLibraryContext(const char* file, size_t line, const char* what) : - isc::Exception(file, line, what) {} -}; - -/// @brief Invalid index -/// -/// Thrown if an attempt is made to obtain a library handle but the current -/// library handle index is invalid. This will occur if the method -/// LibraryHandleCollection::getLibraryHandle() is called outside of a callout. - -class InvalidIndex : public Exception { -public: - InvalidIndex(const char* file, size_t line, const char* what) : - isc::Exception(file, line, what) {} -}; - -// Forward declaration for CalloutHandle -class CalloutHandle; - -/// Typedef for a callout pointer. (Callouts must have "C" linkage.) -extern "C" { - typedef int (*CalloutPtr)(CalloutHandle&); -}; - - -/// @brief Library handle -/// -/// This class is used to manage a loaded library. It is used by the user -/// library to register callouts and by the HookManager to call them. -/// -/// The functions related to loading and unloading the asssociated library are -/// handled in the related LibraryManager class - there is a 1:1 correspondence -/// between LibraryManager and LibraryHandle objects. The separation prevents -/// the user library callouts from tinkering around with the loading and -/// unloading of libraries. - -class LibraryHandle { -public: - - /// @brief Constructor - /// - /// This is passed the ServerHooks object, which is used both to size the - /// internal hook vector and in the registration of callouts. - /// - /// @param hooks Pointer to the hooks registered by the server. - LibraryHandle(boost::shared_ptr& hooks) - : hooks_(hooks), hook_vector_(hooks->getCount()) - {} - - /// @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 associated with the hook. - /// - /// @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(const std::string& name, CalloutPtr callout); - - /// @brief De-Register a callout on a hook - /// - /// Searches through the functions associated with the named hook and - /// removes all entries matching the callout. If there are no matching - /// callouts, the result is a no-op. - /// - /// @param name Name of the hook from which the callout is removed. - /// @param callout Pointer to the callout function to be removed. - /// - /// @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 deregisterCallout(const std::string& name, CalloutPtr callout); - - /// @brief Removes all callouts on a hook - /// - /// Removes all callouts associated with a given hook. This is a no-op - /// if there are no callouts associated with the hook. - /// - /// @param name Name of the hook from which the callouts are removed. - /// - /// @throw NoSuchHook Thrown if the hook name is unrecognised. - void deregisterAll(const std::string& name); - - /// @brief Checks if callouts are present on a hook - /// - /// @param index Hook index for which callouts are checked. - /// - /// @return true if callouts are present, false if not. - /// - /// @throw NoSuchHook Thrown if the index is not valid. - bool calloutsPresent(int index) const; - - /// @brief Calls the callouts for a given hook - /// - /// Calls the callouts associated with the given hook index. - /// - /// @param 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); - -private: - - /// @brief Check hook index - /// - /// Checks that the hook index is valid for the hook vector. If not, - /// an exception is thrown. - /// - /// @param index Hooks index to check. - /// - /// @throw NoSuchHook The index is not valid for the hook vector (i.e. - /// less than zero or equal to or greater than the size of the - /// vector). - void checkHookIndex(int index) const; - - // Member variables - - /// Pointer to the list of hooks registered by the server - boost::shared_ptr hooks_; - - /// Each element in the following vector corresponds to a single hook and - /// is an ordered list of callouts for that hook. - std::vector > hook_vector_; -}; - - -/// @brief Collection of Library Handles -/// -/// This simple class is a collection of handles for all libraries loaded. -/// It is pointed to by the CalloutHandle object and is used by that object -/// to locate the correct LibraryHandle should one be requested by a callout -/// function. -/// -/// To do this, the class contains an index indicating the "current" handle. -/// This is updated during the calling of callouts: prior to calling a callout -/// associated with a particular LibraryHandle, the index is updated to point to -/// that handle. If the callout requests access to the LibraryHandle, it is -/// passed a reference to the correct one. - -class LibraryHandleCollection { -private: - - /// Private typedef to abbreviate statements in class methods. - typedef std::vector > HandleVector; - -public: - - /// @brief Constructor - /// - /// Initializes member variables, in particular setting the "current library - /// handle index" to an invalid value. - LibraryHandleCollection() : curidx_(-1), handles_() - {} - - /// @brief Add library handle - /// - /// Adds a library handle to the collection. The collection is ordered, - /// and this adds a library handle to the end of it. - /// - /// @param library_handle Pointer to the a library handle to be added. - void addLibraryHandle(const boost::shared_ptr& handle) { - handles_.push_back(handle); - } - - /// @brief Return current library index - /// - /// Returns the value of the "current library index". Although a callout - /// callout can retrieve this information, it is of limited use: the - /// value is intended for use by the CalloutHandle object to access the - /// per-library context. - /// - /// @return Current library index value - int getLibraryIndex() const { - return (curidx_); - } - - /// @brief Get current library handle - /// - /// Returns a pointer to the current library handle. This method can - /// only be called while the code is iterating through the list of - /// library handles: calling it at any other time is meaningless and will - /// cause an exception to be thrown. - /// - /// @return Pointer to current library handle. This is the handle for the - /// library on which the callout currently running is associated. - boost::shared_ptr getLibraryHandle() const; - - /// @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. - /// - /// @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; - - /// @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. - /// @param callout_handle Reference to the CalloutHandle object for the - /// current object being processed. - /// - /// @return Status return. - int callCallouts(int index, CalloutHandle& callout_handle); - -private: - /// Index of the library handle on which the currently called callout is - /// registered. - int curidx_; - - /// Vector of pointers to library handles. - HandleVector handles_; -}; - -} // namespace util -} // namespace isc - -#endif // LIBRARY_HANDLE_H diff --git a/src/lib/util/tests/Makefile.am b/src/lib/util/tests/Makefile.am index c968e566aa..55c4fa9171 100644 --- a/src/lib/util/tests/Makefile.am +++ b/src/lib/util/tests/Makefile.am @@ -25,15 +25,15 @@ 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 += library_handle_collection_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_manager_unittest.cc b/src/lib/util/tests/callout_manager_unittest.cc new file mode 100644 index 0000000000..214eec2338 --- /dev/null +++ b/src/lib/util/tests/callout_manager_unittest.cc @@ -0,0 +1,546 @@ +// 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 +#include +#include +#include + +#include + +#include +#include +#include + +using namespace isc; +using namespace isc::util; +using namespace std; + +namespace { + +class CalloutManagerTest : public ::testing::Test { +public: + /// @brief Constructor + /// + /// Sets up a collection of three LibraryHandle objects to use in the test. + 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_)); + + // 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 handle. + callout_handle_.reset(new CalloutHandle(callout_manager_)); + } + + /// @brief Return the callout handle + CalloutHandle& getCalloutHandle() { + return (*callout_handle_); + } + + /// @brief Return the callout manager + boost::shared_ptr getCalloutManager() { + return (callout_manager_); + } + + /// 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_; + +private: + /// Callout manager used for the test + boost::shared_ptr callout_manager_; + + /// Server hooks + boost::shared_ptr hooks_; + + /// Set up three library handles. + std::vector > library_handle_; + + /// Callout handle used in calls + boost::shared_ptr callout_handle_; + +}; + +// Definition of the static variable. +int CalloutManagerTest::callout_value_ = 0; + +// *** Callout Tests *** +// +// 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 +// 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 manager_general(int number) { + CalloutManagerTest::callout_value_ = + 10 * CalloutManagerTest::callout_value_ + number; + return (0); +} + +int manager_one(CalloutHandle&) { + return (manager_general(1)); +} + +int manager_two(CalloutHandle&) { + return (manager_general(2)); +} + +int manager_three(CalloutHandle&) { + return (manager_general(3)); +} + +int manager_four(CalloutHandle&) { + return (manager_general(4)); +} + +int manager_five(CalloutHandle&) { + return (manager_general(5)); +} + +int manager_six(CalloutHandle&) { + return (manager_general(6)); +} + +int manager_seven(CalloutHandle&) { + return (manager_general(7)); +} + +// The next functions are duplicates of some of the above, but return an error. + +int manager_one_error(CalloutHandle& handle) { + (void) manager_one(handle); + return (1); +} + +int manager_two_error(CalloutHandle& handle) { + (void) manager_two(handle); + return (1); +} + +int manager_three_error(CalloutHandle& handle) { + (void) manager_three(handle); + return (1); +} + +int manager_four_error(CalloutHandle& handle) { + (void) manager_four(handle); + return (1); +} + +}; // extern "C" + +// 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. + + getCalloutManager()->registerCallout(0, "one", manager_one); + getCalloutManager()->registerCallout(1, "two", 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_)); + + int status = 0; + + // Check that calling the callouts returns as expected. + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(1, callout_value_); + + callout_value_ = 0; + status = getCalloutManager()->callCallouts(two_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); + + // Check it is as expected. + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(1345, callout_value_); + + callout_value_ = 0; + status = getCalloutManager()->callCallouts(two_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(2, callout_value_); + + // Add another callout to hook one from library iindex 2 - this should + // appear at the end of the callout list for that library. + getCalloutManager()->registerCallout(2, "one", manager_six); + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_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); + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_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_)); + + // Set up so that hooks "one", "two" and "four" have callouts attached + // to them, and callout "three" 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()->registerCallout(0, "one", manager_one); + + getCalloutManager()->registerCallout(1, "one", manager_two); + getCalloutManager()->registerCallout(1, "two", manager_two); + + getCalloutManager()->registerCallout(3, "one", manager_three); + getCalloutManager()->registerCallout(3, "four", 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_)); + + // Check we fail on an invalid index. + EXPECT_THROW(getCalloutManager()->calloutsPresent(42), NoSuchHook); + EXPECT_THROW(getCalloutManager()->calloutsPresent(-1), NoSuchHook); +} + +// Test that calling a hook with no callouts on it returns success. + +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_)); + + // Call the callouts on an arbitrary hook and ensure that nothing happens. + callout_value_ = 475; + int status = getCalloutManager()->callCallouts(one_index_, + getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(475, callout_value_); // Unchanged +} + +// Test that the callouts are called in the correct order. + +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_)); + + int status = 0; + + // Each library contributes one callout on hook "one". + 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()); + EXPECT_EQ(0, status); + EXPECT_EQ(1234, callout_value_); + + // Do a random selection of callouts on hook "two". + 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()); + 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_, + getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(0, callout_value_); +} + +// Test that the callouts are called in order, but that callouts occurring +// after a callout that returns an error are not called. +// +// (Note: in this test, the callouts that return an error set the value of +// callout_value_ before they return the error code.) + +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_)); + + int status = 0; + + // Each library contributing one callout on hook "one". 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()); + EXPECT_EQ(1, status); + EXPECT_EQ(1, callout_value_); + + // Each library contributing multiple callouts on hook "two". 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()); + 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_, + 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()); + EXPECT_EQ(1, status); + EXPECT_EQ(11223344, callout_value_); +} + +// Now test that we can deregister a single callout on a hook. + +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_)); + + int status = 0; + + // Each library contributes one callout on hook "one". + callout_value_ = 0; + getCalloutManager()->registerCallout(0, "one", manager_two); + status = getCalloutManager()->callCallouts(one_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_)); +} + +// Now test that we can deregister a single callout on a hook that has multiple +// callouts from the same library. + +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_)); + + int status = 0; + + // Each library contributes one callout on hook "one". + 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()); + EXPECT_EQ(0, status); + EXPECT_EQ(1234, callout_value_); + + // Remove the manager_two callout. + EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_two)); + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(134, callout_value_); + + // Try removing it again. + EXPECT_FALSE(getCalloutManager()->deregisterCallout(0, "one", manager_two)); + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(134, callout_value_); + +} + +// Check we can deregister multiple callouts from the same library. + +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_)); + + int status = 0; + + // Each library contributes one callout on hook "one". + 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()); + EXPECT_EQ(0, status); + EXPECT_EQ(11223344, callout_value_); + + // Remove the manager_two callout. + EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_two)); + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(113344, callout_value_); + + // Try removing multiple callouts from the end of the list. + EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_four)); + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(1133, callout_value_); + + // ... and from the start. + EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", manager_one)); + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(33, callout_value_); + + // ... and the remaining callouts. + EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "one", + manager_three)); + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(0, callout_value_); + + EXPECT_FALSE(getCalloutManager()->calloutsPresent(one_index_)); +} + +// 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_)); + + int status = 0; + + // Each library contributes two callouts to hook "one". + 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()); + 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)); + callout_value_ = 0; + status = getCalloutManager()->callCallouts(one_index_, getCalloutHandle()); + EXPECT_EQ(0, status); + EXPECT_EQ(13452, callout_value_); +} + + +} // Anonymous namespace diff --git a/src/lib/util/tests/library_handle_collection_unittest.cc b/src/lib/util/tests/library_handle_collection_unittest.cc deleted file mode 100644 index 953c300173..0000000000 --- a/src/lib/util/tests/library_handle_collection_unittest.cc +++ /dev/null @@ -1,447 +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 -#include -#include -#include - -#include - -#include -#include -#include - -using namespace isc; -using namespace isc::util; -using namespace std; - -namespace { - -/// @brief No such hook -/// -/// Thrown if an attempt it made to obtain an invalid library handle. -class InvalidIndex : public isc::Exception { -public: - InvalidIndex(const char* file, size_t line, const char* what) : - isc::Exception(file, line, what) {} -}; - -class LibraryHandleCollectionTest : public ::testing::Test { -public: - /// @brief Constructor - /// - /// Sets up a collection of three LibraryHandle objects to use in the test. - LibraryHandleCollectionTest() - : collection_(new LibraryHandleCollection()), handles_(), - hooks_(new ServerHooks()) { - - // Set up the server hooks - hooks_->registerHook("one"); - hooks_->registerHook("two"); - hooks_->registerHook("three"); - hooks_->registerHook("four"); - - // Set up the library handles and collection. - for (int i = 0; i < 4; ++i) { - boost::shared_ptr handle(new LibraryHandle(hooks_)); - handles_.push_back(handle); - collection_->addLibraryHandle(handle); - } - - callout_value_ = 0; - } - - /// @brief Obtain constructed server hooks - /// - /// @return Reference to shared pointer pointing to server hooks object. - boost::shared_ptr& getServerHooks() { - return (hooks_); - } - - /// @brief Obtain LibraryHandleCollection object - /// - /// @return Reference to shared pointer pointing to handle collection - boost::shared_ptr& getLibraryHandleCollection() { - return (collection_); - } - - /// @brief Obtain individual LibraryHandle. - /// - /// @param i Index of the library handle required. - /// - /// @return Reference to shared pointer pointing to the relevant handle. - /// - /// @throws InvalidIndex if the requested index is not valid. - boost::shared_ptr& getLibraryHandle(int i) { - if ((i < 0) || (i >= handles_.size())) { - isc_throw(InvalidIndex, "handle index of " << i << " not valid for " - " size of handle vector (" << handles_.size() << ")"); - } - return (handles_[i]); - } - - /// 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: - - /// Library handle collection and the individual handles (as the - /// collection has no method for accessing an individual member). - boost::shared_ptr collection_; - std::vector > handles_; - - /// Server hooks and hooks manager - boost::shared_ptr hooks_; -}; - -// Definition of the static variable. -int LibraryHandleCollectionTest::callout_value_ = 0; - -// *** Callout Tests *** -// -// 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 -// 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 collection_one(CalloutHandle&) { - LibraryHandleCollectionTest::callout_value_ = - 10 * LibraryHandleCollectionTest::callout_value_ + 1; - return (0); -} - -int collection_two(CalloutHandle&) { - LibraryHandleCollectionTest::callout_value_ = - 10 * LibraryHandleCollectionTest::callout_value_ + 2; - return (0); -} - -int collection_three(CalloutHandle&) { - LibraryHandleCollectionTest::callout_value_ = - 10 * LibraryHandleCollectionTest::callout_value_ + 3; - return (0); -} - -int collection_four(CalloutHandle&) { - LibraryHandleCollectionTest::callout_value_ = - 10 * LibraryHandleCollectionTest::callout_value_ + 4; - return (0); -} - -// The next functions are duplicates of the above, but return an error. - -int collection_one_error(CalloutHandle& handle) { - (void) collection_one(handle); - return (1); -} - -int collection_two_error(CalloutHandle& handle) { - (void) collection_two(handle); - return (1); -} - -int collection_three_error(CalloutHandle& handle) { - (void) collection_three(handle); - return (1); -} - -int collection_four_error(CalloutHandle& handle) { - (void) collection_four(handle); - return (1); -} - -// The next functions are duplicates of the above, but set the skip flag. - -int collection_one_skip(CalloutHandle& handle) { - handle.setSkip(true); - return (collection_one(handle)); -} - -int collection_two_skip(CalloutHandle& handle) { - handle.setSkip(true); - return (collection_two(handle)); -} - -int collection_three_skip(CalloutHandle& handle) { - handle.setSkip(true); - return (collection_three(handle)); -} - -int collection_four_skip(CalloutHandle& handle) { - handle.setSkip(true); - return (collection_four(handle)); -} - -}; // extern "C" - -// Check the "calloutsPresent()" method. -// -// Note: as we needed to use the addHandleMethod() to set up the handles to -// which the callouts are attached, this can also be construed as a test -// of the addLibraryHandle method as well. - -TEST_F(LibraryHandleCollectionTest, CalloutsPresent) { - const int one_index = getServerHooks()->getIndex("one"); - const int two_index = getServerHooks()->getIndex("two"); - const int three_index = getServerHooks()->getIndex("three"); - const int four_index = getServerHooks()->getIndex("four"); - - // Ensure that no callouts are attached to any of the hooks. - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(one_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(two_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(three_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(four_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 - // exact callouts attached to a hook are not relevant - only the fact - // that some callouts are). - - getLibraryHandle(0)->registerCallout("one", collection_one); - - getLibraryHandle(1)->registerCallout("one", collection_two); - getLibraryHandle(1)->registerCallout("two", collection_two); - - getLibraryHandle(3)->registerCallout("one", collection_four); - getLibraryHandle(3)->registerCallout("four", collection_two); - - // Check all is as expected. - EXPECT_TRUE(getLibraryHandleCollection()->calloutsPresent(one_index)); - EXPECT_TRUE(getLibraryHandleCollection()->calloutsPresent(two_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(three_index)); - EXPECT_TRUE(getLibraryHandleCollection()->calloutsPresent(four_index)); - - // Check we fail on an invalid index. - EXPECT_THROW(getLibraryHandleCollection()->calloutsPresent(42), NoSuchHook); - EXPECT_THROW(getLibraryHandleCollection()->calloutsPresent(-1), NoSuchHook); - - // Check we get a negative result on an empty collection. - LibraryHandleCollection empty_collection; - EXPECT_FALSE(empty_collection.calloutsPresent(-1)); -} - -// Test that the callouts are called in the correct order. - -TEST_F(LibraryHandleCollectionTest, CallCalloutsSuccess) { - const int one_index = getServerHooks()->getIndex("one"); - const int two_index = getServerHooks()->getIndex("two"); - const int three_index = getServerHooks()->getIndex("three"); - const int four_index = getServerHooks()->getIndex("four"); - - // Ensure that no callouts are attached to any of the hooks. - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(one_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(two_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(three_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(four_index)); - - // Set up different sequences of callouts on different handles. - CalloutHandle callout_handle(getLibraryHandleCollection()); - int status; - - // Each library contributing one callout on hook "one". - callout_value_ = 0; - getLibraryHandle(0)->registerCallout("one", collection_one); - getLibraryHandle(1)->registerCallout("one", collection_two); - getLibraryHandle(2)->registerCallout("one", collection_three); - getLibraryHandle(3)->registerCallout("one", collection_four); - status = getLibraryHandleCollection()->callCallouts(one_index, - callout_handle); - EXPECT_EQ(0, status); - EXPECT_EQ(1234, callout_value_); - - // Do a random selection of callouts on hook "two". - callout_value_ = 0; - getLibraryHandle(0)->registerCallout("two", collection_one); - getLibraryHandle(0)->registerCallout("two", collection_one); - getLibraryHandle(1)->registerCallout("two", collection_two); - getLibraryHandle(3)->registerCallout("two", collection_four); - status = getLibraryHandleCollection()->callCallouts(two_index, - callout_handle); - EXPECT_EQ(0, status); - EXPECT_EQ(1124, callout_value_); - - // Ensure that calling the callouts on a hook with no callouts works. - callout_value_ = 0; - status = getLibraryHandleCollection()->callCallouts(three_index, - callout_handle); - EXPECT_EQ(0, status); - EXPECT_EQ(0, callout_value_); -} - -// Test that the callouts are called in order, but that callouts occurring -// after a callout that returns an error are not called. -// -// (Note: in this test, the callouts that return an error set the value of -// callout_value_ before they return the error code.) - -TEST_F(LibraryHandleCollectionTest, CallCalloutsError) { - const int one_index = getServerHooks()->getIndex("one"); - const int two_index = getServerHooks()->getIndex("two"); - const int three_index = getServerHooks()->getIndex("three"); - const int four_index = getServerHooks()->getIndex("four"); - - // Ensure that no callouts are attached to any of the hooks. - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(one_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(two_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(three_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(four_index)); - - // Set up different sequences of callouts on different handles. - CalloutHandle callout_handle(getLibraryHandleCollection()); - int status; - - // Each library contributing one callout on hook "one". The first callout - // returns an error. - callout_value_ = 0; - getLibraryHandle(0)->registerCallout("one", collection_one_error); - getLibraryHandle(1)->registerCallout("one", collection_two); - getLibraryHandle(2)->registerCallout("one", collection_three); - getLibraryHandle(3)->registerCallout("one", collection_four); - status = getLibraryHandleCollection()->callCallouts(one_index, - callout_handle); - EXPECT_EQ(1, status); - EXPECT_EQ(1, callout_value_); - - // Each library contributing multiple callouts on hook "two". The last - // callout on the first library returns an error. - callout_value_ = 0; - getLibraryHandle(0)->registerCallout("two", collection_one); - getLibraryHandle(0)->registerCallout("two", collection_one_error); - getLibraryHandle(1)->registerCallout("two", collection_two); - getLibraryHandle(1)->registerCallout("two", collection_two); - getLibraryHandle(1)->registerCallout("two", collection_three); - getLibraryHandle(1)->registerCallout("two", collection_three); - getLibraryHandle(3)->registerCallout("two", collection_four); - getLibraryHandle(3)->registerCallout("two", collection_four); - status = getLibraryHandleCollection()->callCallouts(two_index, - callout_handle); - 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; - getLibraryHandle(0)->registerCallout("three", collection_one); - getLibraryHandle(0)->registerCallout("three", collection_one); - getLibraryHandle(1)->registerCallout("three", collection_two); - getLibraryHandle(1)->registerCallout("three", collection_two); - getLibraryHandle(3)->registerCallout("three", collection_four_error); - getLibraryHandle(3)->registerCallout("three", collection_four); - status = getLibraryHandleCollection()->callCallouts(three_index, - callout_handle); - EXPECT_EQ(1, status); - EXPECT_EQ(11224, callout_value_); - - // The last callout on a hook returns an error. - callout_value_ = 0; - getLibraryHandle(0)->registerCallout("four", collection_one); - getLibraryHandle(0)->registerCallout("four", collection_one); - getLibraryHandle(1)->registerCallout("four", collection_two); - getLibraryHandle(1)->registerCallout("four", collection_two); - getLibraryHandle(2)->registerCallout("four", collection_three); - getLibraryHandle(2)->registerCallout("four", collection_three); - getLibraryHandle(3)->registerCallout("four", collection_four); - getLibraryHandle(3)->registerCallout("four", collection_four_error); - status = getLibraryHandleCollection()->callCallouts(four_index, - callout_handle); - EXPECT_EQ(1, status); - EXPECT_EQ(11223344, callout_value_); -} - -// Same test as CallCalloutsSucess, but with functions returning a "skip" -// instead. - -TEST_F(LibraryHandleCollectionTest, CallCalloutsSkip) { - const int one_index = getServerHooks()->getIndex("one"); - const int two_index = getServerHooks()->getIndex("two"); - const int three_index = getServerHooks()->getIndex("three"); - const int four_index = getServerHooks()->getIndex("four"); - - // Ensure that no callouts are attached to any of the hooks. - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(one_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(two_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(three_index)); - EXPECT_FALSE(getLibraryHandleCollection()->calloutsPresent(four_index)); - - // Set up different sequences of callouts on different handles. - CalloutHandle callout_handle(getLibraryHandleCollection()); - int status; - - // Each library contributing one callout on hook "one". The first callout - // sets the "skip" flag. - callout_value_ = 0; - getLibraryHandle(0)->registerCallout("one", collection_one_skip); - getLibraryHandle(1)->registerCallout("one", collection_two); - getLibraryHandle(2)->registerCallout("one", collection_three); - getLibraryHandle(3)->registerCallout("one", collection_four); - status = getLibraryHandleCollection()->callCallouts(one_index, - callout_handle); - EXPECT_EQ(0, status); - EXPECT_EQ(1, callout_value_); - - // Each library contributing multiple callouts on hook "two". The last - // callout on the first library sets the "skip" flag. - callout_value_ = 0; - getLibraryHandle(0)->registerCallout("two", collection_one); - getLibraryHandle(0)->registerCallout("two", collection_one_skip); - getLibraryHandle(1)->registerCallout("two", collection_two); - getLibraryHandle(1)->registerCallout("two", collection_two); - getLibraryHandle(1)->registerCallout("two", collection_three); - getLibraryHandle(1)->registerCallout("two", collection_three); - getLibraryHandle(3)->registerCallout("two", collection_four); - getLibraryHandle(3)->registerCallout("two", collection_four); - status = getLibraryHandleCollection()->callCallouts(two_index, - callout_handle); - EXPECT_EQ(0, status); - EXPECT_EQ(11, callout_value_); - - // A callout in a random position in the callout list sets the "skip" flag. - callout_value_ = 0; - getLibraryHandle(0)->registerCallout("three", collection_one); - getLibraryHandle(0)->registerCallout("three", collection_one); - getLibraryHandle(1)->registerCallout("three", collection_two); - getLibraryHandle(1)->registerCallout("three", collection_two); - getLibraryHandle(3)->registerCallout("three", collection_four_skip); - getLibraryHandle(3)->registerCallout("three", collection_four); - status = getLibraryHandleCollection()->callCallouts(three_index, - callout_handle); - EXPECT_EQ(0, status); - EXPECT_EQ(11224, callout_value_); - - // The last callout on a hook sets the "skip" flag. - callout_value_ = 0; - getLibraryHandle(0)->registerCallout("four", collection_one); - getLibraryHandle(0)->registerCallout("four", collection_one); - getLibraryHandle(1)->registerCallout("four", collection_two); - getLibraryHandle(1)->registerCallout("four", collection_two); - getLibraryHandle(2)->registerCallout("four", collection_three); - getLibraryHandle(2)->registerCallout("four", collection_three); - getLibraryHandle(3)->registerCallout("four", collection_four); - getLibraryHandle(3)->registerCallout("four", collection_four_skip); - status = getLibraryHandleCollection()->callCallouts(four_index, - callout_handle); - EXPECT_EQ(0, status); - EXPECT_EQ(11223344, callout_value_); -} - -} // Anonymous namespace diff --git a/src/lib/util/tests/library_handle_unittest.cc b/src/lib/util/tests/library_handle_unittest.cc index a07ff4b5fa..f8e54aaf86 100644 --- a/src/lib/util/tests/library_handle_unittest.cc +++ b/src/lib/util/tests/library_handle_unittest.cc @@ -33,12 +33,11 @@ public: /// /// Sets up an appropriate number of server hooks to pass to the /// constructed callout handle objects. - LibraryHandleTest() - : hooks_(new ServerHooks()), - collection_(new LibraryHandleCollection()) { + 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. @@ -63,6 +62,8 @@ public: private: boost::shared_ptr hooks_; boost::shared_ptr collection_; + boost::shared_ptr handle_0_; + boost::shared_ptr handle_1_; }; // Definition of the static variable.