]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[2974] Modifications as a result of review
authorStephen Morris <stephen@isc.org>
Thu, 13 Jun 2013 16:13:24 +0000 (17:13 +0100)
committerStephen Morris <stephen@isc.org>
Thu, 13 Jun 2013 16:13:24 +0000 (17:13 +0100)
src/lib/util/hooks/callout_handle.cc
src/lib/util/hooks/callout_handle.h
src/lib/util/hooks/callout_manager.cc
src/lib/util/hooks/callout_manager.h
src/lib/util/tests/callout_handle_unittest.cc
src/lib/util/tests/callout_manager_unittest.cc
src/lib/util/tests/handles_unittest.cc

index 5b6b3b221a2cffe83ddf086791ba55ce946959f4..8052823a02e30b12c2c32f12a1115ce94934b3f5 100644 (file)
@@ -34,12 +34,7 @@ CalloutHandle::CalloutHandle(const boost::shared_ptr<CalloutManager>& manager)
     // Call the "context_create" hook.  We should be OK doing this - although
     // the constructor has not finished running, all the member variables
     // have been created.
-    int status = manager_->callCallouts(ServerHooks::CONTEXT_CREATE, *this);
-    if (status > 0) {
-        isc_throw(ContextCreateFail, "error code of " << status << " returned "
-                  "from context_create callout during the creation of a "
-                  "ContextHandle object");
-    }
+    manager_->callCallouts(ServerHooks::CONTEXT_CREATE, *this);
 }
 
 // Destructor
@@ -48,16 +43,7 @@ CalloutHandle::~CalloutHandle() {
     // Call the "context_destroy" hook.  We should be OK doing this - although
     // the destructor is being called, all the member variables are still in
     // existence.
-    int status = manager_->callCallouts(ServerHooks::CONTEXT_DESTROY, *this);
-    if (status > 0) {
-        // An exception is thrown on failure.  This may be severe, but if
-        // none is thrown a resource leak in a library (signalled by the
-        // context_destroy callout returning an error) may be difficult to
-        // trace.
-        isc_throw(ContextDestroyFail, "error code of " << status << " returned "
-                  "from context_destroy callout during the destruction of a "
-                  "ContextHandle object");
-    }
+    manager_->callCallouts(ServerHooks::CONTEXT_DESTROY, *this);
 }
 
 // Return the name of all argument items.
index ad3ef673b6cef670f07b33e4cda4584ef7a66d31..00335058ed048beaccadb9368530731eee2fe02d 100644 (file)
@@ -50,28 +50,6 @@ public:
         isc::Exception(file, line, what) {}
 };
 
-/// @brief Context creation failure
-///
-/// Thrown if, during the running of the constructor, the call to the
-/// context_create hook returns an error.
-
-class ContextCreateFail : public Exception {
-public:
-    ContextCreateFail(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// @brief Context destruction failure
-///
-/// Thrown if, during the running of the desstructor, the call to the
-/// context_destroy hook returns an error.
-
-class ContextDestroyFail : public Exception {
-public:
-    ContextDestroyFail(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
 // Forward declaration of the library handle and related collection classes.
 
 class CalloutManager;
@@ -109,14 +87,6 @@ class LibraryHandle;
 
 class CalloutHandle {
 public:
-    /// Callout success return status - the next callout in the list for the
-    /// hook will be called.
-    static const int SUCCESS = 0;
-
-    /// Callout complete return status - the callout has succeeded, but
-    /// remaining callouts on this hook (including any from other libraries)
-    /// should not be run.
-    static const int COMPLETE = 1;
 
     /// Typedef to allow abbreviation of iterator specification in methods.
     /// The std::string is the argument name and the "boost::any" is the
index 32afc9fec180a9e344b77870b8fd6385bd139323..af2061919793a69e9ed1c4065a6a4af44629f133 100644 (file)
@@ -63,7 +63,10 @@ CalloutManager::registerCallout(const std::string& name, CalloutPtr callout) {
 bool
 CalloutManager::calloutsPresent(int hook_index) const {
     // Validate the hook index.
-    checkHookIndex(hook_index);
+    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");
+    }
 
     // Valid, so are there any callouts associated with that hook?
     return (!hook_vector_[hook_index].empty());
@@ -71,40 +74,40 @@ CalloutManager::calloutsPresent(int hook_index) const {
 
 // Call all the callouts for a given hook.
 
-int
+void
 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);
-
-    // Duplicate the callout vector for this hook and work through that.
-    // This step is needed because we allow dynamic registration and
-    // deregistration of callouts.  If a callout attached to a hook modified
-    // the list of callouts, the underlying CalloutVector would change and
-    // potentially affect the iteration through that vector.
-    CalloutVector callouts(hook_vector_[hook_index]);
-
-    // Call all the callouts, stopping if a non SUCCESS status is returned.
-    int status = CalloutHandle::SUCCESS;
-    for (CalloutVector::const_iterator i = callouts.begin();
-         i != callouts.end() && (status == CalloutHandle::SUCCESS); ++i) {
-        // In case the callout tries to register or deregister a callout, set
-        // the current library index to the index associated with library
-        // that registered the callout being called.
-        current_library_ = i->first;
-
-        // Call the callout
-        status = (*i->second)(callout_handle);
-    }
-
-    // Reset the current library index to an invalid value to catch any
-    // programming errors.
-    current_library_ = -1;
 
+    // Only initialize and iterate if there are callouts present.  This check
+    // also catches the case of an invalid index.
+    if (calloutsPresent(hook_index)) {
+
+        // Clear the "skip" flag so we don't carry state from a previous call.
+        callout_handle.setSkip(false);
+
+        // Duplicate the callout vector for this hook and work through that.
+        // This step is needed because we allow dynamic registration and
+        // deregistration of callouts.  If a callout attached to a hook modified
+        // the list of callouts on that hook, the underlying CalloutVector would
+        // change and potentially affect the iteration through that vector.
+        CalloutVector callouts(hook_vector_[hook_index]);
+
+        // Call all the callouts.
+        for (CalloutVector::const_iterator i = callouts.begin();
+             i != callouts.end(); ++i) {
+            // In case the callout tries to register or deregister a callout,
+            // set the current library index to the index associated with the
+            // library that registered the callout being called.
+            current_library_ = i->first;
+
+            // Call the callout
+            // @todo Log the return status if non-zero
+            static_cast<void>((*i->second)(callout_handle));
+        }
 
-    return (status);
+        // Reset the current library index to an invalid value to catch any
+        // programming errors.
+        current_library_ = -1;
+    }
 }
 
 // Deregister a callout registered by the current library on a particular hook.
index 542afd040c77c606e5da28a63b3db3b0acfdfb07..7a224332f17a3d825db851ba8b2bbe56f4ca516d 100644 (file)
@@ -182,9 +182,7 @@ public:
     /// @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 hook_index, CalloutHandle& callout_handle);
+    void callCallouts(int hook_index, CalloutHandle& callout_handle);
 
     /// @brief Get number of libraries
     ///
@@ -240,20 +238,6 @@ public:
     }
 
 private:
-    /// @brief Check hook index
-    ///
-    /// Ensures that the passed hook index is valid.
-    ///
-    /// @param index Hook index to test
-    ///
-    /// @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 <<
-                      " is not valid for the list of registered hooks");
-        }
-    }
-
     /// @brief Check library index
     ///
     /// Ensures that the current library index is valid.  This is called by
index 635e570db19c5782a87198a4bb8ad1dd2e66093b..76e18d8f8b931df623aaa3eb76499c8725faa774 100644 (file)
@@ -225,14 +225,13 @@ TEST_F(CalloutHandleTest, ContextItemNames) {
     CalloutHandle handle(getCalloutManager());
 
     vector<string> expected_names;
-    int value = 42;
 
     expected_names.push_back("faith");
-    handle.setArgument("faith", value++);
+    handle.setArgument("faith", 42);
     expected_names.push_back("hope");
-    handle.setArgument("hope", value++);
+    handle.setArgument("hope", 43);
     expected_names.push_back("charity");
-    handle.setArgument("charity", value++);
+    handle.setArgument("charity", 44);
 
     // Get the names and check against the expected names.  We'll sort
     // both arrays to simplify the checking.
index 8f35be3affab5fffdabd88a9ee00c003a2ebf06a..ca9b8adbcdfd578a631dd0e9bd289f1df9c8ca1d 100644 (file)
@@ -54,10 +54,13 @@ public:
 
         // Set up the callout manager with these hooks.  Assume a maximum of
         // four libraries.
-        callout_manager_.reset(new CalloutManager(hooks_, 4));
+        callout_manager_.reset(new CalloutManager(hooks_, 10));
 
         // Set up the callout handle.
         callout_handle_.reset(new CalloutHandle(callout_manager_));
+
+        // Initialize the static variable.
+        callout_value_ = 0;
     }
 
     /// @brief Return the callout handle
@@ -110,59 +113,59 @@ int CalloutManagerTest::callout_value_ = 0;
 // Functions return a zero to indicate success.
 
 extern "C" {
-int manager_general(int number) {
+int callout_general(int number) {
     CalloutManagerTest::callout_value_ =
         10 * CalloutManagerTest::callout_value_ + number;
     return (0);
 }
 
-int manager_one(CalloutHandle&) {
-    return (manager_general(1));
+int callout_one(CalloutHandle&) {
+    return (callout_general(1));
 }
 
-int manager_two(CalloutHandle&) {
-    return (manager_general(2));
+int callout_two(CalloutHandle&) {
+    return (callout_general(2));
 }
 
-int manager_three(CalloutHandle&) {
-    return (manager_general(3));
+int callout_three(CalloutHandle&) {
+    return (callout_general(3));
 }
 
-int manager_four(CalloutHandle&) {
-    return (manager_general(4));
+int callout_four(CalloutHandle&) {
+    return (callout_general(4));
 }
 
-int manager_five(CalloutHandle&) {
-    return (manager_general(5));
+int callout_five(CalloutHandle&) {
+    return (callout_general(5));
 }
 
-int manager_six(CalloutHandle&) {
-    return (manager_general(6));
+int callout_six(CalloutHandle&) {
+    return (callout_general(6));
 }
 
-int manager_seven(CalloutHandle&) {
-    return (manager_general(7));
+int callout_seven(CalloutHandle&) {
+    return (callout_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);
+int callout_one_error(CalloutHandle& handle) {
+    (void) callout_one(handle);
     return (1);
 }
 
-int manager_two_error(CalloutHandle& handle) {
-    (void) manager_two(handle);
+int callout_two_error(CalloutHandle& handle) {
+    (void) callout_two(handle);
     return (1);
 }
 
-int manager_three_error(CalloutHandle& handle) {
-    (void) manager_three(handle);
+int callout_three_error(CalloutHandle& handle) {
+    (void) callout_three(handle);
     return (1);
 }
 
-int manager_four_error(CalloutHandle& handle) {
-    (void) manager_four(handle);
+int callout_four_error(CalloutHandle& handle) {
+    (void) callout_four(handle);
     return (1);
 }
 
@@ -210,15 +213,15 @@ TEST_F(CalloutManagerTest, CheckLibraryIndex) {
 
     // Check invalid ones
     EXPECT_THROW(getCalloutManager()->setLibraryIndex(-1), NoSuchLibrary);
-    EXPECT_THROW(getCalloutManager()->setLibraryIndex(5), NoSuchLibrary);
+    EXPECT_THROW(getCalloutManager()->setLibraryIndex(15), 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),
+    EXPECT_NO_THROW(getCalloutManager()->registerCallout("alpha", callout_one));
+    EXPECT_THROW(getCalloutManager()->registerCallout("unknown", callout_one),
                                                       NoSuchHook);
 }
 
@@ -233,9 +236,9 @@ TEST_F(CalloutManagerTest, RegisterCallout) {
     // Set up so that hooks "alpha" and "beta" have callouts attached from a
     // different libraries.
     getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->registerCallout("alpha", callout_one);
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("beta", manager_two);
+    getCalloutManager()->registerCallout("beta", callout_two);
 
     // Check all is as expected.
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
@@ -243,60 +246,48 @@ TEST_F(CalloutManagerTest, RegisterCallout) {
     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);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(1, callout_value_);
 
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
     EXPECT_EQ(2, callout_value_);
 
     // Register some more callouts from different libraries on hook "alpha".
     getCalloutManager()->setLibraryIndex(2);
-    getCalloutManager()->registerCallout("alpha", manager_three);
-    getCalloutManager()->registerCallout("alpha", manager_four);
+    getCalloutManager()->registerCallout("alpha", callout_three);
+    getCalloutManager()->registerCallout("alpha", callout_four);
     getCalloutManager()->setLibraryIndex(3);
-    getCalloutManager()->registerCallout("alpha", manager_five);
+    getCalloutManager()->registerCallout("alpha", callout_five);
 
     // Check it is as expected.
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(1345, callout_value_);
 
     // ... and check the additional callouts were not registered on the "beta"
     // hook.
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
     EXPECT_EQ(2, callout_value_);
 
     // Add another callout to hook "alpha" from library index 2 - this should
     // appear at the end of the callout list for that library.
     getCalloutManager()->setLibraryIndex(2);
-    getCalloutManager()->registerCallout("alpha", manager_six);
+    getCalloutManager()->registerCallout("alpha", callout_six);
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     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()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("alpha", manager_seven);
+    getCalloutManager()->registerCallout("alpha", callout_seven);
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(173465, callout_value_);
 }
 
@@ -315,15 +306,15 @@ TEST_F(CalloutManagerTest, CalloutsPresent) {
     // that some callouts are).  Chose the libraries for which the callouts
     // are registered randomly.
     getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->registerCallout("alpha", callout_one);
 
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("alpha", manager_two);
-    getCalloutManager()->registerCallout("beta", manager_two);
+    getCalloutManager()->registerCallout("alpha", callout_two);
+    getCalloutManager()->registerCallout("beta", callout_two);
 
     getCalloutManager()->setLibraryIndex(3);
-    getCalloutManager()->registerCallout("alpha", manager_three);
-    getCalloutManager()->registerCallout("delta", manager_four);
+    getCalloutManager()->registerCallout("alpha", callout_three);
+    getCalloutManager()->registerCallout("delta", callout_four);
 
     // Check all is as expected.
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
@@ -347,9 +338,7 @@ TEST_F(CalloutManagerTest, CallNoCallouts) {
                  
     // Call the callouts on an arbitrary hook and ensure that nothing happens.
     callout_value_ = 475;
-    int status = getCalloutManager()->callCallouts(alpha_index_,
-                                                   getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(475, callout_value_); // Unchanged
 }
 
@@ -364,42 +353,34 @@ TEST_F(CalloutManagerTest, CallCalloutsSuccess) {
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
                  
-    int status = 0;
-
     // Each library contributes one callout on hook "alpha".
     callout_value_ = 0;
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("alpha", manager_one);
+    getCalloutManager()->registerCallout("alpha", callout_one);
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->registerCallout("alpha", callout_two);
     getCalloutManager()->setLibraryIndex(2);
-    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->registerCallout("alpha", callout_three);
     getCalloutManager()->setLibraryIndex(3);
-    getCalloutManager()->registerCallout("alpha", manager_four);
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->registerCallout("alpha", callout_four);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(1234, callout_value_);
 
     // Do a random selection of callouts on hook "beta".
     callout_value_ = 0;
     getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("beta", manager_one);
-    getCalloutManager()->registerCallout("beta", manager_three);
+    getCalloutManager()->registerCallout("beta", callout_one);
+    getCalloutManager()->registerCallout("beta", callout_three);
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("beta", manager_two);
+    getCalloutManager()->registerCallout("beta", callout_two);
     getCalloutManager()->setLibraryIndex(3);
-    getCalloutManager()->registerCallout("beta", manager_four);
-    status = getCalloutManager()->callCallouts(beta_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->registerCallout("beta", callout_four);
+    getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
     EXPECT_EQ(1324, callout_value_);
 
     // Ensure that calling the callouts on a hook with no callouts works.
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(gamma_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(gamma_index_, getCalloutHandle());
     EXPECT_EQ(0, callout_value_);
 }
 
@@ -416,76 +397,66 @@ TEST_F(CalloutManagerTest, CallCalloutsError) {
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
                  
-    int status = 0;
-
     // 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()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("alpha", manager_one_error);
+    getCalloutManager()->registerCallout("alpha", callout_one_error);
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->registerCallout("alpha", callout_two);
     getCalloutManager()->setLibraryIndex(2);
-    getCalloutManager()->registerCallout("alpha", manager_three);
+    getCalloutManager()->registerCallout("alpha", callout_three);
     getCalloutManager()->setLibraryIndex(3);
-    getCalloutManager()->registerCallout("alpha", manager_four);
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(1, status);
-    EXPECT_EQ(1, callout_value_);
+    getCalloutManager()->registerCallout("alpha", callout_four);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
+    EXPECT_EQ(1234, callout_value_);
 
     // Each library contributing multiple callouts on hook "beta". The last
     // callout on the first library returns an error.
     callout_value_ = 0;
     getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("beta", manager_one);
-    getCalloutManager()->registerCallout("beta", manager_one_error);
+    getCalloutManager()->registerCallout("beta", callout_one);
+    getCalloutManager()->registerCallout("beta", callout_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()->registerCallout("beta", callout_two);
+    getCalloutManager()->registerCallout("beta", callout_two);
+    getCalloutManager()->registerCallout("beta", callout_three);
+    getCalloutManager()->registerCallout("beta", callout_three);
     getCalloutManager()->setLibraryIndex(3);
-    getCalloutManager()->registerCallout("beta", manager_four);
-    getCalloutManager()->registerCallout("beta", manager_four);
-    status = getCalloutManager()->callCallouts(beta_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(1, status);
-    EXPECT_EQ(11, callout_value_);
+    getCalloutManager()->registerCallout("beta", callout_four);
+    getCalloutManager()->registerCallout("beta", callout_four);
+    getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
+    EXPECT_EQ(11223344, callout_value_);
 
     // A callout in a random position in the callout list returns an error.
     callout_value_ = 0;
     getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("gamma", manager_one);
-    getCalloutManager()->registerCallout("gamma", manager_one);
+    getCalloutManager()->registerCallout("gamma", callout_one);
+    getCalloutManager()->registerCallout("gamma", callout_one);
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("gamma", manager_two);
-    getCalloutManager()->registerCallout("gamma", manager_two);
+    getCalloutManager()->registerCallout("gamma", callout_two);
+    getCalloutManager()->registerCallout("gamma", callout_two);
     getCalloutManager()->setLibraryIndex(3);
-    getCalloutManager()->registerCallout("gamma", manager_four_error);
-    getCalloutManager()->registerCallout("gamma", manager_four);
-    status = getCalloutManager()->callCallouts(gamma_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(1, status);
-    EXPECT_EQ(11224, callout_value_);
+    getCalloutManager()->registerCallout("gamma", callout_four_error);
+    getCalloutManager()->registerCallout("gamma", callout_four);
+    getCalloutManager()->callCallouts(gamma_index_, getCalloutHandle());
+    EXPECT_EQ(112244, callout_value_);
 
     // The last callout on a hook returns an error.
     callout_value_ = 0;
     getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("delta", manager_one);
-    getCalloutManager()->registerCallout("delta", manager_one);
+    getCalloutManager()->registerCallout("delta", callout_one);
+    getCalloutManager()->registerCallout("delta", callout_one);
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("delta", manager_two);
-    getCalloutManager()->registerCallout("delta", manager_two);
+    getCalloutManager()->registerCallout("delta", callout_two);
+    getCalloutManager()->registerCallout("delta", callout_two);
     getCalloutManager()->setLibraryIndex(2);
-    getCalloutManager()->registerCallout("delta", manager_three);
-    getCalloutManager()->registerCallout("delta", manager_three);
+    getCalloutManager()->registerCallout("delta", callout_three);
+    getCalloutManager()->registerCallout("delta", callout_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);
+    getCalloutManager()->registerCallout("delta", callout_four);
+    getCalloutManager()->registerCallout("delta", callout_four_error);
+    getCalloutManager()->callCallouts(delta_index_, getCalloutHandle());
     EXPECT_EQ(11223344, callout_value_);
 }
 
@@ -498,15 +469,11 @@ TEST_F(CalloutManagerTest, DeregisterSingleCallout) {
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
                  
-    int status = 0;
-
     // Add a callout to hook "alpha" and check it is added correctly.
     callout_value_ = 0;
     getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("alpha", manager_two);
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->registerCallout("alpha", callout_two);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(2, callout_value_);
 
     // Remove it and check that the no callouts are present.  We have to reset
@@ -514,7 +481,7 @@ TEST_F(CalloutManagerTest, DeregisterSingleCallout) {
     // to callCallouts().
     getCalloutManager()->setLibraryIndex(0);
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
 }
 
@@ -528,37 +495,29 @@ TEST_F(CalloutManagerTest, DeregisterSingleCalloutSameLibrary) {
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
                  
-    int status = 0;
-
     // Add multiple callouts to hook "alpha".
     callout_value_ = 0;
     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);
+    getCalloutManager()->registerCallout("alpha", callout_one);
+    getCalloutManager()->registerCallout("alpha", callout_two);
+    getCalloutManager()->registerCallout("alpha", callout_three);
+    getCalloutManager()->registerCallout("alpha", callout_four);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(1234, callout_value_);
 
-    // Remove the manager_two callout.  We have to reset the current library
+    // Remove the callout_two callout.  We have to reset the current library
     // index here as it was invalidated by the call to callCallouts().
     getCalloutManager()->setLibraryIndex(0);
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(134, callout_value_);
 
     // Try removing it again.
     getCalloutManager()->setLibraryIndex(0);
-    EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+    EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", callout_two));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(134, callout_value_);
 
 }
@@ -572,60 +531,48 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsSameLibrary) {
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
                  
-    int status = 0;
-
     // Each library contributes one callout on hook "alpha".
     callout_value_ = 0;
     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);
+    getCalloutManager()->registerCallout("alpha", callout_one);
+    getCalloutManager()->registerCallout("alpha", callout_two);
+    getCalloutManager()->registerCallout("alpha", callout_one);
+    getCalloutManager()->registerCallout("alpha", callout_two);
+    getCalloutManager()->registerCallout("alpha", callout_three);
+    getCalloutManager()->registerCallout("alpha", callout_four);
+    getCalloutManager()->registerCallout("alpha", callout_three);
+    getCalloutManager()->registerCallout("alpha", callout_four);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(12123434, callout_value_);
 
-    // Remove the manager_two callouts.  We have to reset the current library
+    // Remove the callout_two callouts.  We have to reset the current library
     // index here as it was invalidated by the call to callCallouts().
     getCalloutManager()->setLibraryIndex(0);
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(113434, callout_value_);
 
     // Try removing multiple callouts that includes one at the end of the
     // list of callouts.
     getCalloutManager()->setLibraryIndex(0);
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_four));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_four));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(1133, callout_value_);
 
     // ... and from the start.
     getCalloutManager()->setLibraryIndex(0);
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_one));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_one));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(33, callout_value_);
 
     // ... and the remaining callouts.
     getCalloutManager()->setLibraryIndex(0);
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_three));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_three));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(0, callout_value_);
 
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
@@ -640,32 +587,26 @@ TEST_F(CalloutManagerTest, DeregisterMultipleCalloutsMultipleLibraries) {
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
                  
-    int status = 0;
-
     // Each library contributes two callouts to hook "alpha".
     callout_value_ = 0;
     getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("alpha", manager_one);
-    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->registerCallout("alpha", callout_one);
+    getCalloutManager()->registerCallout("alpha", callout_two);
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("alpha", manager_three);
-    getCalloutManager()->registerCallout("alpha", manager_four);
+    getCalloutManager()->registerCallout("alpha", callout_three);
+    getCalloutManager()->registerCallout("alpha", callout_four);
     getCalloutManager()->setLibraryIndex(2);
-    getCalloutManager()->registerCallout("alpha", manager_five);
-    getCalloutManager()->registerCallout("alpha", manager_two);
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->registerCallout("alpha", callout_five);
+    getCalloutManager()->registerCallout("alpha", callout_two);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(123452, callout_value_);
 
-    // Remove the manager_two callout from library 0.  It should not affect
-    // the second manager_two callout registered by library 2.
+    // Remove the callout_two callout from library 0.  It should not affect
+    // the second callout_two callout registered by library 2.
     getCalloutManager()->setLibraryIndex(0);
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(13452, callout_value_);
 }
 
@@ -675,43 +616,90 @@ TEST_F(CalloutManagerTest, DeregisterAllCallouts) {
     // Ensure that no callouts are attached to hook one.
     EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
                  
-    int status = 0;
-
     // Each library contributes two callouts to hook "alpha".
     callout_value_ = 0;
     getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("alpha", manager_one);
-    getCalloutManager()->registerCallout("alpha", manager_two);
+    getCalloutManager()->registerCallout("alpha", callout_one);
+    getCalloutManager()->registerCallout("alpha", callout_two);
     getCalloutManager()->setLibraryIndex(1);
-    getCalloutManager()->registerCallout("alpha", manager_three);
-    getCalloutManager()->registerCallout("alpha", manager_four);
+    getCalloutManager()->registerCallout("alpha", callout_three);
+    getCalloutManager()->registerCallout("alpha", callout_four);
     getCalloutManager()->setLibraryIndex(2);
-    getCalloutManager()->registerCallout("alpha", manager_five);
-    getCalloutManager()->registerCallout("alpha", manager_six);
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->registerCallout("alpha", callout_five);
+    getCalloutManager()->registerCallout("alpha", callout_six);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(123456, callout_value_);
 
     // Remove all callouts from library index 1.
     getCalloutManager()->setLibraryIndex(1);
     EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(1256, callout_value_);
 
     // Remove all callouts from library index 2.
     getCalloutManager()->setLibraryIndex(2);
     EXPECT_TRUE(getCalloutManager()->deregisterAllCallouts("alpha"));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(12, callout_value_);
 }
 
+// Check that we can register/deregister callouts on different libraries
+// and different hooks, and that the callout instances are regarded as
+// unique and do not affect one another.
+
+TEST_F(CalloutManagerTest, MultipleCalloutsLibrariesHooks) {
+    // Ensure that no callouts are attached to any of the hooks.
+    EXPECT_FALSE(getCalloutManager()->calloutsPresent(alpha_index_));
+    EXPECT_FALSE(getCalloutManager()->calloutsPresent(beta_index_));
+    EXPECT_FALSE(getCalloutManager()->calloutsPresent(gamma_index_));
+    EXPECT_FALSE(getCalloutManager()->calloutsPresent(delta_index_));
+                 
+    // Register callouts on the alpha hook.
+    callout_value_ = 0;
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", callout_one);
+    getCalloutManager()->registerCallout("alpha", callout_two);
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", callout_three);
+    getCalloutManager()->registerCallout("alpha", callout_four);
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", callout_five);
+    getCalloutManager()->registerCallout("alpha", callout_two);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
+    EXPECT_EQ(123452, callout_value_);
+
+    // Register the same callouts on the beta hook, and check that those
+    // on the alpha hook are not affected.
+    callout_value_ = 0;
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("beta", callout_five);
+    getCalloutManager()->registerCallout("beta", callout_one);
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("beta", callout_four);
+    getCalloutManager()->registerCallout("beta", callout_three);
+    getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
+    EXPECT_EQ(5143, callout_value_);
+
+    // Check that the order of callouts on the alpha hook has not been affected.
+    callout_value_ = 0;
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
+    EXPECT_EQ(123452, callout_value_);
+
+    // Remove callout four from beta and check that alpha is not affected.
+    getCalloutManager()->setLibraryIndex(2);
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("beta", callout_four));
+
+    callout_value_ = 0;
+    getCalloutManager()->callCallouts(beta_index_, getCalloutHandle());
+    EXPECT_EQ(513, callout_value_);
+
+    callout_value_ = 0;
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
+    EXPECT_EQ(123452, 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.
@@ -729,14 +717,14 @@ TEST_F(CalloutManagerTest, LibraryHandleRegistration) {
     // different libraries.
     getCalloutManager()->setLibraryIndex(0);
     getCalloutManager()->getLibraryHandle().registerCallout("alpha",
-                                                            manager_one);
+                                                            callout_one);
     getCalloutManager()->getLibraryHandle().registerCallout("alpha",
-                                                            manager_two);
+                                                            callout_two);
     getCalloutManager()->setLibraryIndex(1);
     getCalloutManager()->getLibraryHandle().registerCallout("alpha",
-                                                            manager_three);
+                                                            callout_three);
     getCalloutManager()->getLibraryHandle().registerCallout("alpha",
-                                                            manager_four);
+                                                            callout_four);
 
     // Check all is as expected.
     EXPECT_TRUE(getCalloutManager()->calloutsPresent(alpha_index_));
@@ -744,41 +732,31 @@ TEST_F(CalloutManagerTest, LibraryHandleRegistration) {
     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);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     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));
+    EXPECT_FALSE(getCalloutManager()->deregisterCallout("alpha", callout_two));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(1234, callout_value_);
 
     getCalloutManager()->setLibraryIndex(0);
-    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", manager_two));
+    EXPECT_TRUE(getCalloutManager()->deregisterCallout("alpha", callout_two));
     callout_value_ = 0;
-    status = getCalloutManager()->callCallouts(alpha_index_,
-                                               getCalloutHandle());
-    EXPECT_EQ(0, status);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     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);
+    getCalloutManager()->callCallouts(alpha_index_, getCalloutHandle());
     EXPECT_EQ(1, callout_value_);
 }
 
index 7bcc232aef9dfe9a2447394013100010df3213f7..a8d23417fc0dd4682196283bd21271a0da566279 100644 (file)
@@ -60,6 +60,9 @@ public:
 
         // Set up for three libraries.
         manager_.reset(new CalloutManager(hooks_, 3));
+
+        // Initialize remaining variables.
+        common_string_ = "";
     }
 
     /// @brief Return callout manager
@@ -73,6 +76,9 @@ public:
     int gamma_index_;
     int delta_index_;
 
+    /// String accessible by all callouts whatever the library
+    static std::string common_string_;
+
 private:
     /// Server hooks 
     boost::shared_ptr<ServerHooks> hooks_;
@@ -80,9 +86,12 @@ private:
     /// Callout manager.  Declared static so that the callout functions can
     /// access it.
     boost::shared_ptr<CalloutManager> manager_;
-
 };
 
+/// Define the common string
+std::string HandlesTest::common_string_;
+
+
 // The next set of functions define the callouts used by the tests.  They
 // manipulate the data in such a way that callouts called - and the order in
 // which they were called - can be determined.  The functions also check that
@@ -547,24 +556,6 @@ TEST_F(HandlesTest, ConstructionDestructionCallouts) {
 
     EXPECT_EQ("110120", resultCalloutString(0));
     EXPECT_EQ((110 + 120), resultCalloutInt(0));
-
-    // Test that the destructor throws an error if the context_destroy
-    // callout returns an error. (As the constructor and destructor will
-    // have implicitly run the CalloutManager's callCallouts method, we need
-    // to set the library index again.)
-    getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("context_destroy", returnError);
-    callout_handle.reset(new CalloutHandle(getCalloutManager()));
-    EXPECT_THROW(callout_handle.reset(), ContextDestroyFail);
-
-    // We don't know what callout_handle is pointing to - it could be to a
-    // half-destroyed object - so use a new CalloutHandle to test construction
-    // failure.
-    getCalloutManager()->setLibraryIndex(0);
-    getCalloutManager()->registerCallout("context_create", returnError);
-    boost::scoped_ptr<CalloutHandle> callout_handle2;
-    EXPECT_THROW(callout_handle2.reset(new CalloutHandle(getCalloutManager())),
-                 ContextCreateFail);
 }
 
 // Dynamic callout registration and deregistration.
@@ -765,6 +756,167 @@ TEST_F(HandlesTest, DynamicDeregistrationSameHook) {
     EXPECT_EQ("212782", resultCalloutString(1));
 }
 
+// Testing the operation of the "skip" flag.  Callouts print the value
+// they see in the flag and either leave it unchanged, set it or clear it.
+
+int
+calloutPrintSkip(CalloutHandle& handle) {
+    static const std::string YES("Y");
+    static const std::string NO("N");
+
+    HandlesTest::common_string_ = HandlesTest::common_string_ +
+        (handle.getSkip() ? YES : NO);
+    return (0);
+}
+
+int
+calloutSetSkip(CalloutHandle& handle) {
+    static_cast<void>(calloutPrintSkip(handle));
+    handle.setSkip(true);
+    return (0);
+}
+
+int
+calloutClearSkip(CalloutHandle& handle) {
+    static_cast<void>(calloutPrintSkip(handle));
+    handle.setSkip(false);
+    return (0);
+}
+
+// Do a series of tests, returning with the skip flag set "true".
+
+TEST_F(HandlesTest, ReturnSkipSet) {
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", calloutPrintSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", calloutPrintSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", calloutPrintSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+
+    CalloutHandle callout_handle(getCalloutManager());
+    getCalloutManager()->callCallouts(alpha_index_, callout_handle);
+
+    // Check result.  For each of visual checking, the expected string is
+    // divided into sections corresponding to the blocks of callouts above.
+    EXPECT_EQ(std::string("NNYY" "NNYYN" "NNYN"), common_string_);
+
+    // ... and check that the skip flag on exit from callCallouts is set.
+    EXPECT_TRUE(callout_handle.getSkip());
+}
+
+// Repeat the test, returning with the skip flag clear.
+TEST_F(HandlesTest, ReturnSkipClear) {
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", calloutPrintSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+    getCalloutManager()->registerCallout("alpha", calloutPrintSkip);
+    getCalloutManager()->registerCallout("alpha", calloutSetSkip);
+    getCalloutManager()->registerCallout("alpha", calloutClearSkip);
+
+    CalloutHandle callout_handle(getCalloutManager());
+    getCalloutManager()->callCallouts(alpha_index_, callout_handle);
+
+    // Check result.  For each of visual checking, the expected string is
+    // divided into sections corresponding to the blocks of callouts above.
+    EXPECT_EQ(std::string("NYY" "NNYNYN" "NNNY"), common_string_);
+
+    // ... and check that the skip flag on exit from callCallouts is set.
+    EXPECT_FALSE(callout_handle.getSkip());
+}
+
+// The next set of callouts do a similar thing to the above "skip" tests,
+// but alter the value of a string argument.  This is for testing that the
+// a callout is able to change an argument and return it to the caller.
+
+const char* MODIFIED_ARG = "modified_arg";
+
+int
+calloutSetArgumentCommon(CalloutHandle& handle, const char* what) {
+    std::string modified_arg = "";
+
+    handle.getArgument(MODIFIED_ARG, modified_arg);
+    modified_arg = modified_arg + std::string(what);
+    handle.setArgument(MODIFIED_ARG, modified_arg);
+    return (0);
+}
+
+int
+calloutSetArgumentYes(CalloutHandle& handle) {
+    return (calloutSetArgumentCommon(handle, "Y"));
+}
+
+int
+calloutSetArgumentNo(CalloutHandle& handle) {
+    return (calloutSetArgumentCommon(handle, "N"));
+}
+
+// ... and a callout to just copy the argument to the "common_string_" variable
+// but otherwise not alter it.
+
+int
+calloutPrintArgument(CalloutHandle& handle) {
+    handle.getArgument(MODIFIED_ARG, HandlesTest::common_string_);
+    return (0);
+}
+
+TEST_F(HandlesTest, CheckModifiedArgument) {
+    getCalloutManager()->setLibraryIndex(0);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentYes);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentNo);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentNo);
+
+    getCalloutManager()->setLibraryIndex(1);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentYes);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentYes);
+    getCalloutManager()->registerCallout("alpha", calloutPrintArgument);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentNo);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentNo);
+
+    getCalloutManager()->setLibraryIndex(2);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentYes);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentNo);
+    getCalloutManager()->registerCallout("alpha", calloutSetArgumentYes);
+
+    // Create the argument with an initial empty string value.  Then call the
+    // sequence of callouts above.
+    CalloutHandle callout_handle(getCalloutManager());
+    std::string modified_arg = "";
+    callout_handle.setArgument(MODIFIED_ARG, modified_arg);
+    getCalloutManager()->callCallouts(alpha_index_, callout_handle);
+
+    // Check the intermediate and results.  For visual checking, the expected
+    // string is divided into sections corresponding to the blocks of callouts
+    // above.
+    EXPECT_EQ(std::string("YNN" "YY"), common_string_);
+
+    callout_handle.getArgument(MODIFIED_ARG, modified_arg);
+    EXPECT_EQ(std::string("YNN" "YYNN" "YNY"), modified_arg);
+}
+
 
 } // Anonymous namespace