// PERFORMANCE OF THIS SOFTWARE.
#include <util/hooks/callout_handle.h>
+#include <util/hooks/callout_manager.h>
#include <util/hooks/library_handle.h>
#include <util/hooks/server_hooks.h>
#include <boost/lexical_cast.hpp>
+#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
#include <algorithm>
/// - The various methods manipulating the items in the CalloutHandle's context
/// work correctly.
///
-/// Some minor interactions between the two classes are checked in the unit
-/// tests for each class (mainly the use of the "skip" flag).
+/// - An active callout can only modify the registration of callouts registered
+/// by its own library.
using namespace isc::util;
using namespace std;
namespace {
+class HandlesTest : public ::testing::Test {
+public:
+ /// @brief Constructor
+ ///
+ /// Sets up the various elements used in each test.
+ HandlesTest() : hooks_(new ServerHooks()), manager_()
+ {
+ // Set up four hooks, although through gamma
+ alpha_index_ = hooks_->registerHook("alpha");
+ beta_index_ = hooks_->registerHook("beta");
+ gamma_index_ = hooks_->registerHook("gamma");
+ delta_index_ = hooks_->registerHook("delta");
+
+ // Set up for three libraries.
+ manager_.reset(new CalloutManager(hooks_, 3));
+ }
+
+ /// @brief Return callout manager
+ boost::shared_ptr<CalloutManager> getCalloutManager() {
+ return (manager_);
+ }
+
+ /// Hook indexes - these are frequently accessed, so are accessed directly.
+ int alpha_index_;
+ int beta_index_;
+ int gamma_index_;
+ int delta_index_;
+
+private:
+ /// Server hooks
+ boost::shared_ptr<ServerHooks> hooks_;
+
+ /// Callout manager. Declared static so that the callout functions can
+ /// access it.
+ boost::shared_ptr<CalloutManager> manager_;
+
+};
+
// The next set of functions define the callouts used by the tests. They
// manipulate the data in such a way that callouts called - and the order in
// which they were called - can be determined. The functions also check that
// identification has been set in the callout handle).
//
// For simplicity, and to cut down the number of functions actually written,
-// the callout indicator ("a" or "b") ) used in the in the CalloutHandle
+// the callout indicator ("1" or "2") ) used in the in the CalloutHandle
// functions is passed via a CalloutArgument. The argument is named "string":
// use of a name the same as that of one of the context elements serves as a
// check that the argument name space and argument context space are separate.
string_value = "";
}
- // Update the values and set them.
+ // Update the values and set them back in the callout context.
int_value += idata;
callout_handle.setContext("int", int_value);
// This test checks the many-faced nature of the context for the CalloutContext.
-TEST(HandlesTest, ContextAccessCheck) {
- // Create the LibraryHandleCollection with a set of four callouts (the test
- // does not use the context_create and context_destroy callouts).
-
- boost::shared_ptr<ServerHooks> server_hooks(new ServerHooks());
- const int one_index = server_hooks->registerHook("one");
- const int two_index = server_hooks->registerHook("two");
- const int three_index = server_hooks->registerHook("three");
- const int four_index = server_hooks->registerHook("four");
-
- // Create the library handle collection and the library handles.
- boost::shared_ptr<LibraryHandleCollection>
- collection(new LibraryHandleCollection());
-
- boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout11);
- handle->registerCallout("two", callout12);
- handle->registerCallout("three", callout13);
- handle->registerCallout("four", print1);
- collection->addLibraryHandle(handle);
-
- handle.reset(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout21);
- handle->registerCallout("two", callout22);
- handle->registerCallout("three", callout23);
- handle->registerCallout("four", print2);
- collection->addLibraryHandle(handle);
-
- handle.reset(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout31);
- handle->registerCallout("two", callout32);
- handle->registerCallout("three", callout33);
- handle->registerCallout("four", print3);
- collection->addLibraryHandle(handle);
+TEST_F(HandlesTest, ContextAccessCheck) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Library 0.
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("beta", callout12);
+ getCalloutManager()->registerCallout("gamma", callout13);
+ getCalloutManager()->registerCallout("delta", print1);
+
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", callout21);
+ getCalloutManager()->registerCallout("beta", callout22);
+ getCalloutManager()->registerCallout("gamma", callout23);
+ getCalloutManager()->registerCallout("delta", print2);
+
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", callout31);
+ getCalloutManager()->registerCallout("beta", callout32);
+ getCalloutManager()->registerCallout("gamma", callout33);
+ getCalloutManager()->registerCallout("delta", print3);
// Create the callout handles and distinguish them by setting the
// "handle_num" argument.
- CalloutHandle callout_handle_1(collection);
+ CalloutHandle callout_handle_1(getCalloutManager());
callout_handle_1.setArgument("handle_num", static_cast<int>(1));
- CalloutHandle callout_handle_2(collection);
+ CalloutHandle callout_handle_2(getCalloutManager());
callout_handle_2.setArgument("handle_num", static_cast<int>(2));
// Now call the callouts attached to the first three hooks. Each hook is
// called twice (once for each callout handle) before the next hook is
// called.
- collection->callCallouts(one_index, callout_handle_1);
- collection->callCallouts(one_index, callout_handle_2);
- collection->callCallouts(two_index, callout_handle_1);
- collection->callCallouts(two_index, callout_handle_2);
- collection->callCallouts(three_index, callout_handle_1);
- collection->callCallouts(three_index, callout_handle_2);
-
- // Get the results for each callout. Explicitly zero the variables before
- // getting the results so we are certain that the values are the results
- // of the callouts.
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_2);
+ getCalloutManager()->callCallouts(gamma_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(gamma_index_, callout_handle_2);
+
+ // Get the results for each callout (the callout on hook "delta" copies
+ // the context values into a location the test can access). Explicitly
+ // zero the variables before getting the results so we are certain that
+ // the values are the results of the callouts.
zero_results();
- collection->callCallouts(four_index, callout_handle_1);
// To explain the expected callout context results.
//
- // The callout handle maintains a separate context for each library. When
+ // Each callout handle maintains a separate context for each library. When
// the first call to callCallouts() is made, "111" gets appended to
- // the context for library 1 maintained by by the callout handle, "211"
+ // the context for library 1 maintained by the first callout handle, "211"
// gets appended to the context maintained for library 2, and "311" to
// the context maintained for library 3. In each case, the first digit
// corresponds to the library number, the second to the callout number and
// always 2. These additions don't affect the contexts maintained by
// callout handle 1.
//
- // The process is then repeated for hooks "two" and "three" which, for
- // callout handle 1, append "121", "221" and "321" for hook "two" and "311",
- // "321" and "331" for hook "three".
+ // The process is then repeated for hooks "beta" and "gamma" which, for
+ // callout handle 1, append "121", "221" and "321" for hook "beta" and
+ // "311", "321" and "331" for hook "gamma".
//
// The expected integer values can be found by summing up the values
// corresponding to the elements of the strings.
// handle "1", so the following results are checking the context values
// maintained in that callout handle.
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
EXPECT_EQ("111121131", resultCalloutString(0));
EXPECT_EQ("211221231", resultCalloutString(1));
EXPECT_EQ("311321331", resultCalloutString(2));
// Repeat the checks for callout 2.
zero_results();
- collection->callCallouts(four_index, callout_handle_2);
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
EXPECT_EQ((112 + 122 + 132), resultCalloutInt(0));
EXPECT_EQ((212 + 222 + 232), resultCalloutInt(1));
EXPECT_EQ("312322332", resultCalloutString(2));
}
-// Now repeat the test, but add a deletion callout to the list. The "two"
+// Now repeat the test, but add a deletion callout to the list. The "beta"
// hook of library 2 will have an additional callout to delete the "int"
// element: the same hook for library 3 will delete both elements. In
// addition, the names of context elements for the libraries at this point
// Perform the test including deletion of context items.
-TEST(HandlesTest, ContextDeletionCheck) {
- // Create the LibraryHandleCollection with a set of four callouts
- // (the test does not use the context_create and context_destroy callouts.)
-
- boost::shared_ptr<ServerHooks> server_hooks(new ServerHooks());
- const int one_index = server_hooks->registerHook("one");
- const int two_index = server_hooks->registerHook("two");
- const int three_index = server_hooks->registerHook("three");
- const int four_index = server_hooks->registerHook("four");
-
- // Create the library handle collection and the library handles.
- boost::shared_ptr<LibraryHandleCollection>
- collection(new LibraryHandleCollection());
-
- boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout11);
- handle->registerCallout("two", callout12);
- handle->registerCallout("two", printContextNames1);
- handle->registerCallout("three", callout13);
- handle->registerCallout("four", print1);
- collection->addLibraryHandle(handle);
-
- handle.reset(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout21);
- handle->registerCallout("two", callout22);
- handle->registerCallout("two", deleteIntContextItem);
- handle->registerCallout("two", printContextNames2);
- handle->registerCallout("three", callout23);
- handle->registerCallout("four", print2);
- collection->addLibraryHandle(handle);
-
- handle.reset(new LibraryHandle(server_hooks));
- handle->registerCallout("one", callout31);
- handle->registerCallout("two", callout32);
- handle->registerCallout("two", deleteAllContextItems);
- handle->registerCallout("two", printContextNames3);
- handle->registerCallout("three", callout33);
- handle->registerCallout("four", print3);
- collection->addLibraryHandle(handle);
+TEST_F(HandlesTest, ContextDeletionCheck) {
+
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("beta", callout12);
+ getCalloutManager()->registerCallout("beta", printContextNames1);
+ getCalloutManager()->registerCallout("gamma", callout13);
+ getCalloutManager()->registerCallout("delta", print1);
+
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", callout21);
+ getCalloutManager()->registerCallout("beta", callout22);
+ getCalloutManager()->registerCallout("beta", deleteIntContextItem);
+ getCalloutManager()->registerCallout("beta", printContextNames2);
+ getCalloutManager()->registerCallout("gamma", callout23);
+ getCalloutManager()->registerCallout("delta", print2);
+
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", callout31);
+ getCalloutManager()->registerCallout("beta", callout32);
+ getCalloutManager()->registerCallout("beta", deleteAllContextItems);
+ getCalloutManager()->registerCallout("beta", printContextNames3);
+ getCalloutManager()->registerCallout("gamma", callout33);
+ getCalloutManager()->registerCallout("delta", print3);
// Create the callout handles and distinguish them by setting the "long"
// argument.
- CalloutHandle callout_handle_1(collection);
+ CalloutHandle callout_handle_1(getCalloutManager());
callout_handle_1.setArgument("handle_num", static_cast<int>(1));
- CalloutHandle callout_handle_2(collection);
+ CalloutHandle callout_handle_2(getCalloutManager());
callout_handle_2.setArgument("handle_num", static_cast<int>(2));
// Now call the callouts attached to the first three hooks. Each hook is
// called twice (once for each callout handle) before the next hook is
// called.
- collection->callCallouts(one_index, callout_handle_1);
- collection->callCallouts(one_index, callout_handle_2);
- collection->callCallouts(two_index, callout_handle_1);
- collection->callCallouts(two_index, callout_handle_2);
- collection->callCallouts(three_index, callout_handle_1);
- collection->callCallouts(three_index, callout_handle_2);
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_2);
+ getCalloutManager()->callCallouts(gamma_index_, callout_handle_1);
+ getCalloutManager()->callCallouts(gamma_index_, callout_handle_2);
// Get the results for each callout. Explicitly zero the variables before
// getting the results so we are certain that the values are the results
// of the callouts.
zero_results();
- collection->callCallouts(four_index, callout_handle_1);
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
// The logic by which the expected results are arrived at is described
// in the ContextAccessCheck test. The results here are different
// Repeat the checks for callout handle 2.
zero_results();
- collection->callCallouts(four_index, callout_handle_2);
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
EXPECT_EQ((112 + 122 + 132), resultCalloutInt(0));
EXPECT_EQ(( 232), resultCalloutInt(1));
EXPECT_EQ( "332", resultCalloutString(2));
// ... and check what the names of the context items are after the callouts
- // for hook "two". We know they are in sorted order.
+ // for hook "beta". We know they are in sorted order.
EXPECT_EQ(2, getItemNames(0).size());
EXPECT_EQ(string("int"), getItemNames(0)[0]);
return (1);
}
-TEST(HandlesTest, ConstructionDestructionCallouts) {
- // Create the LibraryHandleCollection comprising two LibraryHandles.
- // Register callouts for the context_create and context_destroy hooks.
-
- boost::shared_ptr<ServerHooks> server_hooks(new ServerHooks());
+TEST_F(HandlesTest, ConstructionDestructionCallouts) {
- // Create the library handle collection and the library handles.
- boost::shared_ptr<LibraryHandleCollection>
- collection(new LibraryHandleCollection());
-
- boost::shared_ptr<LibraryHandle> handle(new LibraryHandle(server_hooks));
- handle->registerCallout("context_create", callout11);
- handle->registerCallout("context_create", print1);
- handle->registerCallout("context_destroy", callout12);
- handle->registerCallout("context_destroy", print1);
- collection->addLibraryHandle(handle);
+ // Register context callouts.
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("context_create", callout11);
+ getCalloutManager()->registerCallout("context_create", print1);
+ getCalloutManager()->registerCallout("context_destroy", callout12);
+ getCalloutManager()->registerCallout("context_destroy", print1);
// Create the CalloutHandle and check that the constructor callout
// has run.
zero_results();
- boost::shared_ptr<CalloutHandle>
- callout_handle(new CalloutHandle(collection));
-
+ boost::scoped_ptr<CalloutHandle>
+ callout_handle(new CalloutHandle(getCalloutManager()));
EXPECT_EQ("110", resultCalloutString(0));
EXPECT_EQ(110, resultCalloutInt(0));
EXPECT_EQ((110 + 120), resultCalloutInt(0));
// Test that the destructor throws an error if the context_destroy
- // callout returns an error.
- handle->registerCallout("context_destroy", returnError);
- callout_handle.reset(new CalloutHandle(collection));
+ // callout returns an error. (As the constructor and destructor will
+ // have implicitly run the CalloutManager's callCallouts method, we need
+ // to set the library index again.)
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("context_destroy", returnError);
+ callout_handle.reset(new CalloutHandle(getCalloutManager()));
EXPECT_THROW(callout_handle.reset(), ContextDestroyFail);
// We don't know what callout_handle is pointing to - it could be to a
// half-destroyed object - so use a new CalloutHandle to test construction
// failure.
- handle->registerCallout("context_create", returnError);
- boost::shared_ptr<CalloutHandle> callout_handle2;
- EXPECT_THROW(callout_handle2.reset(new CalloutHandle(collection)),
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("context_create", returnError);
+ boost::scoped_ptr<CalloutHandle> callout_handle2;
+ EXPECT_THROW(callout_handle2.reset(new CalloutHandle(getCalloutManager())),
ContextCreateFail);
+}
+
+// Dynamic callout registration and deregistration.
+// The following are the dynamic registration/deregistration callouts.
+
+
+// Add callout_78_alpha - adds a callout to hook alpha that appends "78x"
+// (where "x" is the callout handle) to the current output.
+int
+callout78(CalloutHandle& callout_handle) {
+ return (execute(callout_handle, 7, 8));
+}
+
+int
+add_callout78_alpha(CalloutHandle& callout_handle) {
+ callout_handle.getLibraryHandle().registerCallout("alpha", callout78);
+ return (0);
+}
+
+int
+delete_callout78_alpha(CalloutHandle& callout_handle) {
+ static_cast<void>(
+ callout_handle.getLibraryHandle().deregisterCallout("alpha",
+ callout78));
+ return (0);
+}
+
+// Check that a callout can register another callout on a different hook.
+
+TEST_F(HandlesTest, DynamicRegistrationAnotherHook) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Set up callouts on "alpha".
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("delta", print1);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", callout21);
+ getCalloutManager()->registerCallout("delta", print2);
+ getCalloutManager()->setLibraryIndex(2);
+ getCalloutManager()->registerCallout("alpha", callout31);
+ getCalloutManager()->registerCallout("delta", print3);
+
+ // ... and on "beta", set up the function to add a hook to alpha (but only
+ // for library 1).
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("beta", add_callout78_alpha);
+
+ // See what we get for calling the callouts on alpha first.
+ CalloutHandle callout_handle_1(getCalloutManager());
+ callout_handle_1.setArgument("handle_num", static_cast<int>(1));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
+ EXPECT_EQ("111", resultCalloutString(0));
+ EXPECT_EQ("211", resultCalloutString(1));
+ EXPECT_EQ("311", resultCalloutString(2));
+
+ // All as expected, now call the callouts on beta. This should add a
+ // callout to the list of callouts for alpha, which we should see when
+ // we run the test again.
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_1);
+
+ // Use a new callout handle so as to get fresh callout context.
+ CalloutHandle callout_handle_2(getCalloutManager());
+ callout_handle_2.setArgument("handle_num", static_cast<int>(2));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
+ EXPECT_EQ("112", resultCalloutString(0));
+ EXPECT_EQ("212782", resultCalloutString(1));
+ EXPECT_EQ("312", resultCalloutString(2));
+}
+
+// Check that a callout can register another callout on the same hook.
+// Note that the registration only applies to a subsequent invocation of
+// callCallouts, not to the current one. In other words, if
+//
+// * the callout list for a library is "A then B then C"
+// * when callCallouts is executed "B" adds "D" to that list,
+//
+// ... the current execution of callCallouts only executes A, B and C. A
+// subsequent invocation will execute A, B, C then D.
+
+TEST_F(HandlesTest, DynamicRegistrationSameHook) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Set up callouts on "alpha".
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("alpha", add_callout78_alpha);
+ getCalloutManager()->registerCallout("delta", print1);
+
+ // See what we get for calling the callouts on alpha first.
+ CalloutHandle callout_handle_1(getCalloutManager());
+ callout_handle_1.setArgument("handle_num", static_cast<int>(1));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
+ EXPECT_EQ("111", resultCalloutString(0));
+
+ // Run it again - we should have added something to this hook.
+ CalloutHandle callout_handle_2(getCalloutManager());
+ callout_handle_2.setArgument("handle_num", static_cast<int>(2));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
+ EXPECT_EQ("112782", resultCalloutString(0));
+
+ // And a third time...
+ CalloutHandle callout_handle_3(getCalloutManager());
+ callout_handle_3.setArgument("handle_num", static_cast<int>(3));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_3);
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_3);
+ EXPECT_EQ("113783783", resultCalloutString(0));
+}
+
+// Deregistration of a callout from a different hook
+
+TEST_F(HandlesTest, DynamicDeregistrationDifferentHook) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Set up callouts on "alpha".
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("alpha", callout78);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("delta", print1);
+
+ getCalloutManager()->registerCallout("beta", delete_callout78_alpha);
+
+ // Call the callouts on alpha
+ CalloutHandle callout_handle_1(getCalloutManager());
+ callout_handle_1.setArgument("handle_num", static_cast<int>(1));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
+ EXPECT_EQ("111781111", resultCalloutString(0));
+
+ // Run the callouts on hook beta to remove the callout on alpha.
+ getCalloutManager()->callCallouts(beta_index_, callout_handle_1);
+
+ // The run of the callouts should have altered the callout list on the
+ // first library for hook alpha, so call again to make sure.
+ CalloutHandle callout_handle_2(getCalloutManager());
+ callout_handle_2.setArgument("handle_num", static_cast<int>(2));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
+ EXPECT_EQ("112112", resultCalloutString(0));
+}
+
+// Deregistration of a callout from the same hook
+
+TEST_F(HandlesTest, DynamicDeregistrationSameHook) {
+ // Register callouts for the different libraries.
+ CalloutHandle handle(getCalloutManager());
+
+ // Set up callouts on "alpha".
+ getCalloutManager()->setLibraryIndex(0);
+ getCalloutManager()->registerCallout("alpha", callout11);
+ getCalloutManager()->registerCallout("alpha", delete_callout78_alpha);
+ getCalloutManager()->registerCallout("alpha", callout78);
+ getCalloutManager()->registerCallout("delta", print1);
+ getCalloutManager()->setLibraryIndex(1);
+ getCalloutManager()->registerCallout("alpha", callout21);
+ getCalloutManager()->registerCallout("alpha", callout78);
+ getCalloutManager()->registerCallout("delta", print2);
+
+ // Call the callouts on alpha
+ CalloutHandle callout_handle_1(getCalloutManager());
+ callout_handle_1.setArgument("handle_num", static_cast<int>(1));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_1);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_1);
+ EXPECT_EQ("111781", resultCalloutString(0));
+ EXPECT_EQ("211781", resultCalloutString(1));
+
+ // The run of the callouts should have altered the callout list on the
+ // first library for hook alpha, so call again to make sure.
+ CalloutHandle callout_handle_2(getCalloutManager());
+ callout_handle_2.setArgument("handle_num", static_cast<int>(2));
+ getCalloutManager()->callCallouts(alpha_index_, callout_handle_2);
+
+ zero_results();
+ getCalloutManager()->callCallouts(delta_index_, callout_handle_2);
+ EXPECT_EQ("112", resultCalloutString(0));
+ EXPECT_EQ("212782", resultCalloutString(1));
}