From: Stephen Morris Date: Mon, 10 Jun 2013 11:33:01 +0000 (+0100) Subject: [2974] CalloutManager now maintains c oncept of "current library" X-Git-Tag: bind10-1.2.0beta1-release~402^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bc6a657a16a55350992cbe251f010d0a46d11dea;p=thirdparty%2Fkea.git [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. --- diff --git a/src/lib/util/hooks/callout_manager.cc b/src/lib/util/hooks/callout_manager.cc index 9c91a2a833..0b88888449 100644 --- a/src/lib/util/hooks/callout_manager.cc +++ b/src/lib/util/hooks/callout_manager.cc @@ -28,8 +28,10 @@ namespace util { // Register a callout for a particular 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,11 +41,11 @@ 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) { + if (i->first > current_library_) { // 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)); + hook_vector_[hook_index].insert(i, make_pair(current_library_, + callout)); return; } } @@ -51,7 +53,7 @@ CalloutManager::registerCallout(int libindex, const std::string& name, // 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)); + hook_vector_[hook_index].push_back(make_pair(current_library_, callout)); } // Check if callouts are present for a given hook index. @@ -90,16 +92,17 @@ CalloutManager::callCallouts(int hook_index, CalloutHandle& callout_handle) { // Deregister a callout registered by a 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 @@ -128,16 +131,15 @@ 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 @@ -155,23 +157,5 @@ CalloutManager::deregisterAllCallouts(int library_index, 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 index 23cd13fb96..bc3e58043b 100644 --- a/src/lib/util/hooks/callout_manager.h +++ b/src/lib/util/hooks/callout_manager.h @@ -27,28 +27,49 @@ 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 need to know two items of data: /// -/// The class also holds the collection of library handles, used to allow the -/// libraries to manipulate their callout list. +/// - The list of server hooks. This 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, it supplies the index of the relevant hook: this is validated +/// hook vector (which holds the callouts associated with each hook). +/// +/// - 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 (including themselves), but only callouts in the +/// same 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 in the callout manager (it can do this +/// 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 the class is constructed. 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; @@ -63,33 +84,36 @@ public: /// 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()) + /// @param hooks Collection of known hook names. + /// @param num_libraries Number of loaded libraries. + CalloutManager(const boost::shared_ptr& hooks, + int num_libraries) + : current_library_(-1), hooks_(hooks), hook_vector_(hooks->getCount()), + library_handle_(this), num_libraries_(num_libraries) {} /// @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. + /// 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 /// - /// 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 +122,83 @@ 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 /// /// 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. + /// @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 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 is the value set by setLibraryIndex(). + /// + /// @return Current library index. + int getLibraryIndex() const { + return (current_library_); + } - /// @brief Create library handle + /// @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 and is + /// passed to this object at construction time. /// - /// 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(); + /// @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 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. + /// + /// @return reference to callout handle for this manager + LibraryHandle& getLibraryHandle() { + return (library_handle_); + } private: /// @brief Check hook index @@ -154,7 +207,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,10 +215,27 @@ 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 + 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 @@ -179,16 +249,26 @@ private: } }; + /// 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 is calling the methods. + int current_library_; + /// 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. + /// each hook. Each element is itself a vector, with one entry for each + /// callout registered for that hook. std::vector hook_vector_; + /// LibraryHandle object user by the callout to access the callout + /// registration methods on this CalloutManager object. + LibraryHandle library_handle_; + + /// Number of libraries. libindex_ can vary between 0 and numlib_ - 1. + int num_libraries_; + }; } // namespace util diff --git a/src/lib/util/hooks/library_handle.cc b/src/lib/util/hooks/library_handle.cc index 3ea21922c7..0a65e549a1 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 9b90245e84..82d6f57cf1 100644 --- a/src/lib/util/hooks/library_handle.h +++ b/src/lib/util/hooks/library_handle.h @@ -45,14 +45,10 @@ 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 that /// object. - LibraryHandle(int library_index, CalloutManager* collection) - : library_index_(library_index), callout_manager_(collection) + LibraryHandle(CalloutManager* collection) : callout_manager_(collection) {} /// @brief Register a callout on a hook @@ -98,20 +94,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/tests/Makefile.am b/src/lib/util/tests/Makefile.am index 55c4fa9171..9e90012866 100644 --- a/src/lib/util/tests/Makefile.am +++ b/src/lib/util/tests/Makefile.am @@ -33,7 +33,6 @@ run_unittests_SOURCES += filename_unittest.cc run_unittests_SOURCES += hex_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_manager_unittest.cc b/src/lib/util/tests/callout_manager_unittest.cc index 94fad5cf8d..d2375060ae 100644 --- a/src/lib/util/tests/callout_manager_unittest.cc +++ b/src/lib/util/tests/callout_manager_unittest.cc @@ -24,6 +24,14 @@ #include #include +/// @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; @@ -43,14 +51,9 @@ public: gamma_index_ = hooks_->registerHook("gamma"); delta_index_ = hooks_->registerHook("delta"); - // 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 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_)); @@ -83,12 +86,10 @@ private: /// 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. @@ -166,6 +167,29 @@ int manager_four_error(CalloutHandle& handle) { }; // extern "C" +// 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) { @@ -174,9 +198,11 @@ TEST_F(CalloutManagerTest, RegisterCallout) { EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_)); // Set up so that hooks "alpha" and "beta" have callouts attached from a - // single library. - getCalloutManager()->registerCallout(0, "alpha", manager_one); - getCalloutManager()->registerCallout(1, "beta", manager_two); + // 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(alpha_index_)); @@ -200,9 +226,11 @@ TEST_F(CalloutManagerTest, RegisterCallout) { EXPECT_EQ(2, callout_value_); // Register some more callouts from different libraries on hook "alpha". - getCalloutManager()->registerCallout(2, "alpha", manager_three); - getCalloutManager()->registerCallout(2, "alpha", manager_four); - getCalloutManager()->registerCallout(3, "alpha", manager_five); + 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; @@ -216,9 +244,10 @@ TEST_F(CalloutManagerTest, RegisterCallout) { EXPECT_EQ(0, status); EXPECT_EQ(2, callout_value_); - // Add another callout to hook "alpha" 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, "alpha", manager_six); + getCalloutManager()->setLibraryIndex(2); + getCalloutManager()->registerCallout("alpha", manager_six); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -227,14 +256,13 @@ TEST_F(CalloutManagerTest, RegisterCallout) { // Add a callout from library index 1 - this should appear between the // callouts from library index 0 and linrary index 2. - getCalloutManager()->registerCallout(1, "alpha", manager_seven); + getCalloutManager()->setLibraryIndex(1); + getCalloutManager()->registerCallout("alpha", manager_seven); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); EXPECT_EQ(0, status); EXPECT_EQ(173465, callout_value_); - - } // Check the "calloutsPresent()" method. @@ -252,13 +280,16 @@ TEST_F(CalloutManagerTest, CalloutsPresent) { // that some callouts are). Chose the libraries for which the callouts // are registered randomly. - getCalloutManager()->registerCallout(0, "alpha", manager_one); + getCalloutManager()->setLibraryIndex(0); + getCalloutManager()->registerCallout("alpha", manager_one); - getCalloutManager()->registerCallout(1, "alpha", manager_two); - getCalloutManager()->registerCallout(1, "beta", manager_two); + getCalloutManager()->setLibraryIndex(1); + getCalloutManager()->registerCallout("alpha", manager_two); + getCalloutManager()->registerCallout("beta", manager_two); - getCalloutManager()->registerCallout(3, "alpha", manager_three); - getCalloutManager()->registerCallout(3, "delta", manager_four); + getCalloutManager()->setLibraryIndex(3); + getCalloutManager()->registerCallout("alpha", manager_three); + getCalloutManager()->registerCallout("delta", manager_four); // Check all is as expected. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_)); @@ -303,10 +334,14 @@ TEST_F(CalloutManagerTest, CallCalloutsSuccess) { // Each library contributes one callout on hook "alpha". callout_value_ = 0; - getCalloutManager()->registerCallout(0, "alpha", manager_one); - getCalloutManager()->registerCallout(1, "alpha", manager_two); - getCalloutManager()->registerCallout(2, "alpha", manager_three); - getCalloutManager()->registerCallout(3, "alpha", manager_four); + 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); @@ -314,10 +349,13 @@ TEST_F(CalloutManagerTest, CallCalloutsSuccess) { // Do a random selection of callouts on hook "beta". callout_value_ = 0; - getCalloutManager()->registerCallout(0, "beta", manager_one); - getCalloutManager()->registerCallout(0, "beta", manager_three); - getCalloutManager()->registerCallout(1, "beta", manager_two); - getCalloutManager()->registerCallout(3, "beta", manager_four); + 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); @@ -349,10 +387,14 @@ TEST_F(CalloutManagerTest, CallCalloutsError) { // 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, "alpha", manager_one_error); - getCalloutManager()->registerCallout(1, "alpha", manager_two); - getCalloutManager()->registerCallout(2, "alpha", manager_three); - getCalloutManager()->registerCallout(3, "alpha", manager_four); + 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); @@ -361,14 +403,17 @@ TEST_F(CalloutManagerTest, CallCalloutsError) { // Each library contributing multiple callouts on hook "beta". The last // callout on the first library returns an error. callout_value_ = 0; - getCalloutManager()->registerCallout(0, "beta", manager_one); - getCalloutManager()->registerCallout(0, "beta", manager_one_error); - getCalloutManager()->registerCallout(1, "beta", manager_two); - getCalloutManager()->registerCallout(1, "beta", manager_two); - getCalloutManager()->registerCallout(1, "beta", manager_three); - getCalloutManager()->registerCallout(1, "beta", manager_three); - getCalloutManager()->registerCallout(3, "beta", manager_four); - getCalloutManager()->registerCallout(3, "beta", manager_four); + 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); @@ -376,12 +421,15 @@ TEST_F(CalloutManagerTest, CallCalloutsError) { // A callout in a random position in the callout list returns an error. callout_value_ = 0; - getCalloutManager()->registerCallout(0, "gamma", manager_one); - getCalloutManager()->registerCallout(0, "gamma", manager_one); - getCalloutManager()->registerCallout(1, "gamma", manager_two); - getCalloutManager()->registerCallout(1, "gamma", manager_two); - getCalloutManager()->registerCallout(3, "gamma", manager_four_error); - getCalloutManager()->registerCallout(3, "gamma", manager_four); + 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); @@ -389,14 +437,18 @@ TEST_F(CalloutManagerTest, CallCalloutsError) { // The last callout on a hook returns an error. callout_value_ = 0; - getCalloutManager()->registerCallout(0, "delta", manager_one); - getCalloutManager()->registerCallout(0, "delta", manager_one); - getCalloutManager()->registerCallout(1, "delta", manager_two); - getCalloutManager()->registerCallout(1, "delta", manager_two); - getCalloutManager()->registerCallout(2, "delta", manager_three); - getCalloutManager()->registerCallout(2, "delta", manager_three); - getCalloutManager()->registerCallout(3, "delta", manager_four); - getCalloutManager()->registerCallout(3, "delta", manager_four_error); + 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); @@ -416,7 +468,8 @@ TEST_F(CalloutManagerTest, DeregisterSingleCallout) { // Add a callout to hook "alpha" and check it is added correctly. callout_value_ = 0; - getCalloutManager()->registerCallout(0, "alpha", manager_two); + getCalloutManager()->setLibraryIndex(0); + getCalloutManager()->registerCallout("alpha", manager_two); status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); EXPECT_EQ(0, status); @@ -424,8 +477,7 @@ TEST_F(CalloutManagerTest, DeregisterSingleCallout) { // Remove it and check that the no callouts are present. EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_)); - EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha", - manager_two)); + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two)); EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_)); } @@ -443,18 +495,18 @@ TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) { // Add multiple callouts to hook "alpha". callout_value_ = 0; - getCalloutManager()->registerCallout(0, "alpha", manager_one); - getCalloutManager()->registerCallout(0, "alpha", manager_two); - getCalloutManager()->registerCallout(0, "alpha", manager_three); - getCalloutManager()->registerCallout(0, "alpha", manager_four); + 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, "alpha", - manager_two)); + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two)); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -462,8 +514,7 @@ TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) { EXPECT_EQ(134, callout_value_); // Try removing it again. - EXPECT_FALSE(getCalloutManager()->deregisterCallout(0, "alpha", - manager_two)); + EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", manager_two)); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -485,22 +536,22 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) { // Each library contributes one callout on hook "alpha". callout_value_ = 0; - getCalloutManager()->registerCallout(0, "alpha", manager_one); - getCalloutManager()->registerCallout(0, "alpha", manager_two); - getCalloutManager()->registerCallout(0, "alpha", manager_one); - getCalloutManager()->registerCallout(0, "alpha", manager_two); - getCalloutManager()->registerCallout(0, "alpha", manager_three); - getCalloutManager()->registerCallout(0, "alpha", manager_four); - getCalloutManager()->registerCallout(0, "alpha", manager_three); - getCalloutManager()->registerCallout(0, "alpha", manager_four); + 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(12123434, callout_value_); // Remove the manager_two callouts. - EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha", - manager_two)); + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two)); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -509,8 +560,7 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) { // Try removing multiple callouts that includes one at the end of the // list of callouts. - EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha", - manager_four)); + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_four)); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -518,8 +568,7 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) { EXPECT_EQ(1133, callout_value_); // ... and from the start. - EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha", - manager_one)); + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_one)); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -527,8 +576,7 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) { EXPECT_EQ(33, callout_value_); // ... and the remaining callouts. - EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha", - manager_three)); + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_three)); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -551,12 +599,15 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsMultipleLibraries) { // Each library contributes two callouts to hook "alpha". callout_value_ = 0; - getCalloutManager()->registerCallout(0, "alpha", manager_one); - getCalloutManager()->registerCallout(0, "alpha", manager_two); - getCalloutManager()->registerCallout(1, "alpha", manager_three); - getCalloutManager()->registerCallout(1, "alpha", manager_four); - getCalloutManager()->registerCallout(2, "alpha", manager_five); - getCalloutManager()->registerCallout(2, "alpha", manager_two); + 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); @@ -564,8 +615,8 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsMultipleLibraries) { // Remove the manager_two callout from library 0. It should not affect // the second manager_two callout registered by library 2. - EXPECT_TRUE(getCalloutManager()->deregisterCallout(0, "alpha", - manager_two)); + getCalloutManager()->setLibraryIndex(0); + EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two)); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -583,19 +634,23 @@ TEST_F(CalloutManagerTest, DeregisterAllCallouts) { // Each library contributes two callouts to hook "alpha". callout_value_ = 0; - getCalloutManager()->registerCallout(0, "alpha", manager_one); - getCalloutManager()->registerCallout(0, "alpha", manager_two); - getCalloutManager()->registerCallout(1, "alpha", manager_three); - getCalloutManager()->registerCallout(1, "alpha", manager_four); - getCalloutManager()->registerCallout(2, "alpha", manager_five); - getCalloutManager()->registerCallout(2, "alpha", manager_six); + 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. - EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts(1, "alpha")); + getCalloutManager()->setLibraryIndex(1); + EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha")); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -603,7 +658,8 @@ TEST_F(CalloutManagerTest, DeregisterAllCallouts) { EXPECT_EQ(1256, callout_value_); // Remove all callouts from library index 2. - EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts(2, "alpha")); + getCalloutManager()->setLibraryIndex(2); + EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha")); callout_value_ = 0; status = getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle()); @@ -611,5 +667,76 @@ TEST_F(CalloutManagerTest, DeregisterAllCallouts) { 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 CalloutHandle 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/library_handle_unittest.cc b/src/lib/util/tests/library_handle_unittest.cc deleted file mode 100644 index f8e54aaf86..0000000000 --- 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 -#include -#include - -#include - -#include -#include -#include - -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& getServerHooks() { - return (hooks_); - } - - /// Obtain constructed hook manager. - boost::shared_ptr& 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 hooks_; - boost::shared_ptr collection_; - boost::shared_ptr handle_0_; - boost::shared_ptr 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(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(handle.calloutsPresent(-1)), NoSuchHook); - EXPECT_THROW(static_cast(handle.calloutsPresent(5)), NoSuchHook); - - CalloutHandle callout_handle(getLibraryHandleCollection()); - EXPECT_THROW(static_cast(handle.callCallouts(-1, callout_handle)), - NoSuchHook); - EXPECT_THROW(static_cast(handle.callCallouts(10, callout_handle)), - NoSuchHook); -} - - -} // Anonymous namespace