Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
966cc24a
Commit
966cc24a
authored
Jul 14, 2017
by
Marcin Siodelski
Browse files
[master] Merge branch 'trac5329'
parents
1b27ce48
4f8118c5
Changes
15
Hide whitespace changes
Inline
Side-by-side
src/lib/hooks/callout_manager.cc
View file @
966cc24a
// Copyright (C) 2013-
2015,
2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
...
...
@@ -104,6 +104,27 @@ CalloutManager::calloutsPresent(int hook_index) const {
return
(
!
hook_vector_
[
hook_index
].
empty
());
}
bool
CalloutManager
::
commandHandlersPresent
(
const
std
::
string
&
command_name
)
const
{
// Check if the hook point for the specified command exists.
int
index
=
ServerHooks
::
getServerHooks
().
findIndex
(
ServerHooks
::
commandToHookName
(
command_name
));
if
(
index
>=
0
)
{
// The hook point exits but it is possible that there are no
// callouts/command handlers. This is possible if there was a
// hook library supporting this command attached, but it was
// later unloaded. The hook points are not deregistered in
// this case. Only callouts are deregistered.
// Let's check if callouts are present for this hook point.
return
(
calloutsPresent
(
index
));
}
// Hook point not created, so we don't support this command in
// any of the hooks libraries.
return
(
false
);
}
// Call all the callouts for a given hook.
void
...
...
@@ -191,6 +212,20 @@ CalloutManager::callCallouts(int hook_index, CalloutHandle& callout_handle) {
}
}
void
CalloutManager
::
callCommandHandlers
(
const
std
::
string
&
command_name
,
CalloutHandle
&
callout_handle
)
{
// Get the index of the hook point for the specified command.
// This will throw an exception if the hook point doesn't exist.
// The caller should check if the hook point exists by calling
// commandHandlersPresent.
int
index
=
ServerHooks
::
getServerHooks
().
getIndex
(
ServerHooks
::
commandToHookName
(
command_name
));
// Call the handlers for this command.
callCallouts
(
index
,
callout_handle
);
}
// Deregister a callout registered by the current library on a particular hook.
bool
...
...
@@ -272,5 +307,21 @@ CalloutManager::deregisterAllCallouts(const std::string& name) {
return
(
removed
);
}
void
CalloutManager
::
registerCommandHook
(
const
std
::
string
&
command_name
)
{
ServerHooks
&
hooks
=
ServerHooks
::
getServerHooks
();
int
hook_index
=
hooks
.
findIndex
(
ServerHooks
::
commandToHookName
(
command_name
));
if
(
hook_index
<
0
)
{
// Hook for this command doesn't exist. Let's create one.
hooks
.
registerHook
(
ServerHooks
::
commandToHookName
(
command_name
));
// Callout Manager's vector of hooks have to be resized to hold the
// information about callouts for this new hook point. This should
// add new element at the end of the hook_vector_. The index of this
// element will match the index of the hook point in the ServerHooks
// because ServerHooks allocates indexes incrementally.
hook_vector_
.
resize
(
server_hooks_
.
getCount
());
}
}
}
// namespace util
}
// namespace isc
src/lib/hooks/callout_manager.h
View file @
966cc24a
// Copyright (C) 2013-201
5
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-201
7
Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
...
...
@@ -96,6 +96,36 @@ public:
/// - INT_MAX: used for server-registered callouts called after
/// user-registered callouts.
///
/// Since Kea 1.3.0 release hook libraries can register callouts as control
/// command handlers. Such handlers are associated with dynamically created
/// hook points which names are created after command names. For example,
/// if a command name is 'foo-bar', the name of the hook point to which
/// callouts/command handlers are registered is '$foo_bar'. Prefixing the
/// hook point name with the dollar sign eliminates potential conflicts
/// between hook points dedicated to commands handling and other (fixed)
/// hook points.
///
/// Prefixing hook names for command handlers with a dollar sign precludes
/// auto registration of command handlers, i.e. hooks framework is unable
/// to match hook points with names of functions implementing command
/// handlers, because the dollar sign is not legal in C++ function names.
/// This is intended because we want hook libraries to explicitly register
/// commands handlers for supported commands and not rely on Kea to register
/// hook points for them. Should we find use cases for auto registration of
/// command handlers, we may modify the
/// @ref ServerHooks::commandToHookName to use an encoding of hook
/// point names for command handlers that would only contain characters
/// allowed in function names.
///
/// The @ref CalloutManager::registerCommandHook has been added to allow for
/// dynamically creating hook points for which command handlers are registered.
/// This method is called from the @ref LibraryHandle::registerCommandHandler
/// as a result of registering the command handlers by the hook library in
/// its @c load() function. If the hook point for the given command already
/// exists, this function doesn't do anything. The
/// @ref LibraryHandle::registerCommandHandler can install callouts on this
/// hook point.
///
/// Note that the callout functions do not access the CalloutManager: instead,
/// they use a LibraryHandle object. This contains an internal pointer to
/// the CalloutManager, but provides a restricted interface. In that way,
...
...
@@ -184,6 +214,17 @@ public:
/// @throw NoSuchHook Given index does not correspond to a valid hook.
bool
calloutsPresent
(
int
hook_index
)
const
;
/// @brief Checks if control command handlers are present for the
/// specified command.
///
/// @param command_name Command name for which handlers' presence should
/// be checked.
///
/// @return true if there is a hook point associated with the specified
/// command and callouts/command handlers are installed for this hook
/// point, false otherwise.
bool
commandHandlersPresent
(
const
std
::
string
&
command_name
)
const
;
/// @brief Calls the callouts for a given hook
///
/// Iterates through the libray handles and calls the callouts associated
...
...
@@ -197,6 +238,34 @@ public:
/// current object being processed.
void
callCallouts
(
int
hook_index
,
CalloutHandle
&
callout_handle
);
/// @brief Calls the callouts/command handlers for a given command name.
///
/// Iterates through the library handles and calls the command handlers
/// associated with the given command. It expects that the hook point
/// for this command exists (with a name being a command_name prefixed
/// with a dollar sign and with hyphens replaced with underscores).
///
/// @param command_name Command name for which handlers should be called.
/// @param callout_handle Reference to the CalloutHandle object for the
/// current object being processed.
///
/// @throw NoSuchHook if the hook point for the specified command does
/// not exist.
void
callCommandHandlers
(
const
std
::
string
&
command_name
,
CalloutHandle
&
callout_handle
);
/// @brief Registers a hook point for the specified command name.
///
/// If the hook point for such command already exists, this function
/// doesn't do anything. The registered hook point name is created
/// after command_name by prefixing it with a dollar sign and replacing
/// all hyphens with underscores, e.g. for the 'foo-bar' command the
/// following hook point name will be generated: '$foo_bar'.
///
/// @param command_name Command name for which the hook point should be
/// registered.
void
registerCommandHook
(
const
std
::
string
&
command_name
);
/// @brief Get current hook index
///
/// Made available during callCallouts, this is the index of the hook
...
...
src/lib/hooks/hooks_manager.cc
View file @
966cc24a
...
...
@@ -48,19 +48,44 @@ HooksManager::calloutsPresent(int index) {
return
(
getHooksManager
().
calloutsPresentInternal
(
index
));
}
bool
HooksManager
::
commandHandlersPresentInternal
(
const
std
::
string
&
command_name
)
{
conditionallyInitialize
();
return
(
callout_manager_
->
commandHandlersPresent
(
command_name
));
}
bool
HooksManager
::
commandHandlersPresent
(
const
std
::
string
&
command_name
)
{
return
(
getHooksManager
().
commandHandlersPresentInternal
(
command_name
));
}
// Call the callouts
void
HooksManager
::
callCalloutsInternal
(
int
index
,
CalloutHandle
&
handle
)
{
conditionallyInitialize
();
return
(
callout_manager_
->
callCallouts
(
index
,
handle
)
)
;
callout_manager_
->
callCallouts
(
index
,
handle
);
}
void
HooksManager
::
callCallouts
(
int
index
,
CalloutHandle
&
handle
)
{
return
(
getHooksManager
().
callCalloutsInternal
(
index
,
handle
)
)
;
getHooksManager
().
callCalloutsInternal
(
index
,
handle
);
}
void
HooksManager
::
callCommandHandlersInternal
(
const
std
::
string
&
command_name
,
CalloutHandle
&
handle
)
{
conditionallyInitialize
();
callout_manager_
->
callCommandHandlers
(
command_name
,
handle
);
}
void
HooksManager
::
callCommandHandlers
(
const
std
::
string
&
command_name
,
CalloutHandle
&
handle
)
{
getHooksManager
().
callCommandHandlersInternal
(
command_name
,
handle
);
}
// Load the libraries. This will delete the previously-loaded libraries
// (if present) and load new ones.
...
...
src/lib/hooks/hooks_manager.h
View file @
966cc24a
...
...
@@ -90,6 +90,17 @@ public:
/// @throw NoSuchHook Given index does not correspond to a valid hook.
static
bool
calloutsPresent
(
int
index
);
/// @brief Checks if control command handlers are present for the
/// specified command.
///
/// @param command_name Command name for which handlers' presence should
/// be checked.
///
/// @return true if there is a hook point associated with the specified
/// command and callouts/command handlers are installed for this hook
/// point, false otherwise.
static
bool
commandHandlersPresent
(
const
std
::
string
&
command_name
);
/// @brief Calls the callouts for a given hook
///
/// Iterates through the library handles and calls the callouts associated
...
...
@@ -103,6 +114,22 @@ public:
/// object being processed.
static
void
callCallouts
(
int
index
,
CalloutHandle
&
handle
);
/// @brief Calls the callouts/command handlers for a given command name.
///
/// Iterates through the library handles and calls the command handlers
/// associated with the given command. It expects that the hook point
/// for this command exists (with a name being a command_name prefixed
/// with a dollar sign and with hyphens replaced with underscores).
///
/// @param command_name Command name for which handlers should be called.
/// @param handle Reference to the CalloutHandle object for the current
/// object being processed.
///
/// @throw NoSuchHook if the hook point for the specified command does
/// not exist.
static
void
callCommandHandlers
(
const
std
::
string
&
command_name
,
CalloutHandle
&
handle
);
/// @brief Return pre-callouts library handle
///
/// Returns a library handle that can be used by the server to register
...
...
@@ -253,6 +280,17 @@ private:
/// @throw NoSuchHook Given index does not correspond to a valid hook.
bool
calloutsPresentInternal
(
int
index
);
/// @brief Checks if control command handlers are present for the
/// specified command.
///
/// @param command_name Command name for which handlers' presence should
/// be checked.
///
/// @return true if there is a hook point associated with the specified
/// command and callouts/command handlers are installed for this hook
/// point, false otherwise.
bool
commandHandlersPresentInternal
(
const
std
::
string
&
command_name
);
/// @brief Calls the callouts for a given hook
///
/// @param index Index of the hook to call.
...
...
@@ -260,6 +298,17 @@ private:
/// object being processed.
void
callCalloutsInternal
(
int
index
,
CalloutHandle
&
handle
);
/// @brief Calls the callouts/command handlers for a given command name.
///
/// @param command_name Command name for which handlers should be called.
/// @param handle Reference to the CalloutHandle object for the current
/// object being processed.
///
/// @throw NoSuchHook if the hook point for the specified command does
/// not exist.
void
callCommandHandlersInternal
(
const
std
::
string
&
command_name
,
CalloutHandle
&
handle
);
/// @brief Return callout handle
///
/// @return Shared pointer to a CalloutHandle object.
...
...
src/lib/hooks/library_handle.cc
View file @
966cc24a
// Copyright (C) 2013-201
6
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-201
7
Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
...
...
@@ -8,6 +8,8 @@
#include
<hooks/library_handle.h>
#include
<hooks/hooks_manager.h>
#include
<iostream>
namespace
isc
{
namespace
hooks
{
...
...
@@ -33,6 +35,16 @@ LibraryHandle::registerCallout(const std::string& name, CalloutPtr callout) {
}
}
void
LibraryHandle
::
registerCommandHandler
(
const
std
::
string
&
command_name
,
CalloutPtr
callout
)
{
// Register hook point for this command, if one doesn't exist.
callout_manager_
->
registerCommandHook
(
command_name
);
// Register the command handler as a callout.
registerCallout
(
ServerHooks
::
commandToHookName
(
command_name
),
callout
);
}
bool
LibraryHandle
::
deregisterCallout
(
const
std
::
string
&
name
,
CalloutPtr
callout
)
{
int
saved_index
=
callout_manager_
->
getLibraryIndex
();
...
...
src/lib/hooks/library_handle.h
View file @
966cc24a
...
...
@@ -40,6 +40,22 @@ extern "C" {
/// called, the CalloutManager uses that information to set the "current
/// library": the registration functions only operator on data whose
/// associated library is equal to the "current library".)
///
/// As of Kea 1.3.0 release, the @ref LibraryHandle can be used by the hook
/// libraries to install control command handlers and dynamically register
/// hook points with which the handlers are associated. For example, if the
/// hook library supports control-command 'foo-bar' it should register its
/// handler similarly to this:
/// @code
/// int load(LibraryHandle& libhandle) {
/// libhandle.registerCommandHandler("foo-bar", foo_bar_handler);
/// return (0);
/// }
/// @endcode
///
/// which will result in automatic creation of the hook point for the command
/// (if one doesn't exist) and associating the callout 'foo_bar_handler' with
/// this hook point as a handler for the command.
class
LibraryHandle
{
public:
...
...
@@ -79,6 +95,17 @@ public:
/// is of the wrong size.
void
registerCallout
(
const
std
::
string
&
name
,
CalloutPtr
callout
);
/// @brief Register control command handler
///
/// Registers control command handler by creating a hook point for this
/// command (if it doesn't exist) and associating the callout as a command
/// handler. It is possible to register multiple command handlers for the
/// same control command because command handlers are implemented as callouts.
///
/// @param command_name Command name for which handler should be installed.
/// @param callout Pointer to the command handler implemented as a callout.
void
registerCommandHandler
(
const
std
::
string
&
command_name
,
CalloutPtr
callout
);
/// @brief De-Register a callout on a hook
///
/// Searches through the functions registered by the current library with
...
...
src/lib/hooks/server_hooks.cc
View file @
966cc24a
...
...
@@ -8,6 +8,7 @@
#include
<hooks/hooks_log.h>
#include
<hooks/server_hooks.h>
#include
<algorithm>
#include
<utility>
#include
<vector>
...
...
@@ -137,6 +138,13 @@ ServerHooks::getIndex(const string& name) const {
return
(
i
->
second
);
}
int
ServerHooks
::
findIndex
(
const
std
::
string
&
name
)
const
{
// Get iterator to matching element.
auto
i
=
hooks_
.
find
(
name
);
return
((
i
==
hooks_
.
end
())
?
-
1
:
i
->
second
);
}
// Return vector of hook names. The names are not sorted - it is up to the
// caller to perform sorting if required.
...
...
@@ -165,6 +173,16 @@ ServerHooks::getServerHooksPtr() {
return
(
hooks
);
}
std
::
string
ServerHooks
::
commandToHookName
(
const
std
::
string
&
command_name
)
{
// Prefix the command name with a dollar sign.
std
::
string
hook_name
=
std
::
string
(
"$"
)
+
command_name
;
// Replace all hyphens with underscores.
std
::
replace
(
hook_name
.
begin
(),
hook_name
.
end
(),
'-'
,
'_'
);
return
(
hook_name
);
}
}
// namespace util
}
// namespace isc
src/lib/hooks/server_hooks.h
View file @
966cc24a
...
...
@@ -113,6 +113,17 @@ public:
/// @throw NoSuchHook if the hook name is unknown to the caller.
int
getIndex
(
const
std
::
string
&
name
)
const
;
/// @brief Find hook index
///
/// Provides exception safe method of retrieving an index of the
/// specified hook.
///
/// @param name Name of the hook
///
/// @return Index of the hook if the hook point exists, or -1 if the
/// hook point doesn't exist.
int
findIndex
(
const
std
::
string
&
name
)
const
;
/// @brief Return number of hooks
///
/// Returns the total number of hooks registered.
...
...
@@ -141,6 +152,23 @@ public:
/// @return Pointer to the global ServerHooks object.
static
ServerHooksPtr
getServerHooksPtr
();
/// @brief Generates hook point name for the given control command name.
///
/// This function is called to generate the name of the hook point
/// when the hook point is used to install command handlers for the
/// given control command.
///
/// The name of the hook point is generated as follows:
/// - command name is prefixed with a dollar sign,
/// - all hyphens are replaced with underscores.
///
/// For example, if the command_name is 'foo-bar', the resulting hook
/// point name will be '$foo_bar'.
///
/// @param command_name Command name for which the hook point name is
/// to be generated.
static
std
::
string
commandToHookName
(
const
std
::
string
&
command_name
);
private:
/// @brief Constructor
///
...
...
src/lib/hooks/tests/callout_manager_unittest.cc
View file @
966cc24a
...
...
@@ -867,6 +867,56 @@ TEST_F(CalloutManagerTest, LibraryHandlePrePostUserLibrary) {
EXPECT_EQ
(
154
,
callout_value_
);
}
// Test that control command handlers can be installed as callouts.
TEST_F
(
CalloutManagerTest
,
LibraryHandleRegisterCommandHandler
)
{
CalloutHandle
handle
(
getCalloutManager
());
// Simulate creation of the two hook libraries. Fist library implements two
// handlers for the control command 'command-one'. Second library implements
// two control command handlers: one for the 'command-one', another one for
// 'command-two'. Each of the handlers for the 'command-one' must be called
// and they must be called in the appropriate order. Command handler for
// 'command-two' should also be called.
getCalloutManager
()
->
setLibraryIndex
(
0
);
getCalloutManager
()
->
getLibraryHandle
().
registerCommandHandler
(
"command-one"
,
callout_one
);
getCalloutManager
()
->
getLibraryHandle
().
registerCommandHandler
(
"command-one"
,
callout_four
);
getCalloutManager
()
->
setLibraryIndex
(
1
);
getCalloutManager
()
->
getLibraryHandle
().
registerCommandHandler
(
"command-one"
,
callout_two
);
getCalloutManager
()
->
getLibraryHandle
().
registerCommandHandler
(
"command-two"
,
callout_three
);
// Command handlers are installed for commands: 'command-one' and 'command-two'.
EXPECT_TRUE
(
getCalloutManager
()
->
commandHandlersPresent
(
"command-one"
));
EXPECT_TRUE
(
getCalloutManager
()
->
commandHandlersPresent
(
"command-two"
));
// There should be no handlers installed for 'command-three' and 'command-four'.
EXPECT_FALSE
(
getCalloutManager
()
->
commandHandlersPresent
(
"command-three"
));
EXPECT_FALSE
(
getCalloutManager
()
->
commandHandlersPresent
(
"command-four"
));
// Call handlers for 'command-one'. There should be three handlers called in
// the following order: 1, 4, 2.
callout_value_
=
0
;
ASSERT_NO_THROW
(
getCalloutManager
()
->
callCommandHandlers
(
"command-one"
,
handle
));
EXPECT_EQ
(
142
,
callout_value_
);
// There should be one handler invoked for the 'command-two'. This handler has
// index of 3.
callout_value_
=
0
;
ASSERT_NO_THROW
(
getCalloutManager
()
->
callCommandHandlers
(
"command-two"
,
handle
));
EXPECT_EQ
(
3
,
callout_value_
);
// An attempt to call handlers for the commands for which no hook points
// were created should result in exception.
EXPECT_THROW
(
getCalloutManager
()
->
callCommandHandlers
(
"command-three"
,
handle
),
NoSuchHook
);
EXPECT_THROW
(
getCalloutManager
()
->
callCommandHandlers
(
"command-four"
,
handle
),
NoSuchHook
);
}
// The setting of the hook index is checked in the handles_unittest
// set of tests, as access restrictions mean it is not easily tested
// on its own.
...
...
src/lib/hooks/tests/common_test_class.h
View file @
966cc24a
// Copyright (C) 2013-201
5
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-201
7
Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
...
...
@@ -125,6 +125,46 @@ public:
EXPECT_EQ
(
r3
,
result
)
<<
"hookpt_three"
<<
COMMON_TEXT
;
}
/// @brief Call command handlers test.
///
/// This test is similar to @c executeCallCallouts but it uses
/// @ref CalloutManager::callCommandHandlers to execute the command
/// handlers for the following commands: 'command-one' and 'command-two'.
///
/// @param manager CalloutManager to use for the test
/// @param r1..r2, d1..d2 Data (dN) and expected results (rN).
void
executeCallCommandHandlers
(
const
boost
::
shared_ptr
<
isc
::
hooks
::
CalloutManager
>&
manager
,
int
d1
,
int
r1
,
int
d2
,
int
r2
)
{
static
const
char
*
COMMON_TEXT
=
" command handler returned the wrong value"
;
static
const
char
*
RESULT
=
"result"
;
int
result
;
// Set up a callout handle for the calls.
isc
::
hooks
::
CalloutHandle
handle
(
manager
);
// Initialize the argument RESULT. This simplifies testing by
// eliminating the generation of an exception when we try the unload
// test. In that case, RESULT is unchanged.
handle
.
setArgument
(
RESULT
,
-
1
);
// Perform the first calculation: it should assign the data to the
// result.
handle
.
setArgument
(
"data_1"
,
d1
);
manager
->
callCommandHandlers
(
"command-one"
,
handle
);
handle
.
getArgument
(
RESULT
,
result
);
EXPECT_EQ
(
d1
,
result
)
<<
"command-one"
<<
COMMON_TEXT
;
// Perform the second calculation: it should multiply the data by 10
// and return in the result.
handle
.
setArgument
(
"data_2"
,
d2
);
manager
->
callCommandHandlers
(
"command-two"
,
handle
);
handle
.
getArgument
(
RESULT
,
result
);
EXPECT_EQ
(
r2
,
result
)
<<
"command-two"
<<
COMMON_TEXT
;
}
/// Hook indexes. These are are made public for ease of reference.
int
hookpt_one_index_
;
int
hookpt_two_index_
;
...
...
src/lib/hooks/tests/full_callout_library.cc
View file @
966cc24a
...
...
@@ -101,6 +101,38 @@ hook_nonstandard_three(CalloutHandle& handle) {
return
(
0
);
}
// First command handler assigns data to a result.
static
int
command_handler_one
(
CalloutHandle
&
handle
)
{
int
data
;
handle
.
getArgument
(
"data_1"
,
data
);
int
result
;
handle
.
getArgument
(
"result"
,
result
);
result
=
data
;
handle
.
setArgument
(
"result"
,
result
);
return
(
0
);
}
// Second command handler multiples the result by data by 10.
static
int
command_handler_two
(
CalloutHandle
&
handle
)
{
int
data
;
handle
.
getArgument
(
"data_2"
,
data
);
int
result
;
handle
.
getArgument
(
"result"
,
result
);
result
*=
data
*
10
;
handle
.
setArgument
(
"result"
,
result
);
return
(
0
);
}
// Framework functions
int
...
...
@@ -118,6 +150,10 @@ load(LibraryHandle& handle) {
handle
.
registerCallout
(
"hookpt_two"
,
hook_nonstandard_two
);
handle
.
registerCallout
(
"hookpt_three"
,
hook_nonstandard_three
);
// Register command_handler_one as control command handler.
handle
.
registerCommandHandler
(
"command-one"
,
command_handler_one
);
handle
.
registerCommandHandler
(
"command-two"
,
command_handler_two
);
return
(
0
);
}
...
...
src/lib/hooks/tests/hooks_manager_unittest.cc
View file @
966cc24a
...
...
@@ -93,6 +93,42 @@ public:
EXPECT_EQ
(
r3
,
result
)
<<
"hookpt_three"
<<
COMMON_TEXT
;
}
/// @brief Call command handlers test.
///
/// This test is similar to @c executeCallCallouts but it uses
/// @ref HooksManager::callCommandHandlers to execute the command
/// handlers for the following commands: 'command-one' and 'command-two'.
///
/// @param r1..r2, d1..d2 Data (dN) and expected results (rN).