Parcourir la source

[5329] HooksManager now support functions for registering command handlers.

Marcin Siodelski il y a 8 ans
Parent
commit
bc01d351a6

+ 3 - 0
src/lib/hooks/callout_manager.h

@@ -205,6 +205,9 @@ public:
     /// @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.

+ 25 - 0
src/lib/hooks/hooks_manager.cc

@@ -48,6 +48,17 @@ 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
@@ -61,6 +72,20 @@ HooksManager::callCallouts(int index, CalloutHandle& handle) {
     return (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.
 

+ 49 - 0
src/lib/hooks/hooks_manager.h

@@ -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.

+ 36 - 0
src/lib/hooks/tests/full_callout_library.cc

@@ -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);
 }
 

+ 44 - 0
src/lib/hooks/tests/hooks_manager_unittest.cc

@@ -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).
+    void executeCallCommandHandlers(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.
+        CalloutHandlePtr handle = HooksManager::createCalloutHandle();
+
+        // 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);
+        HooksManager::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);
+        HooksManager::callCommandHandlers("command-two", *handle);
+        handle->getArgument(RESULT, result);
+        EXPECT_EQ(r2, result) << "command-two" << COMMON_TEXT;
+    }
+
 private:
     /// To avoid unused variable errors
     std::string dummy(int i) {
@@ -138,6 +174,12 @@ TEST_F(HooksManagerTest, LoadLibraries) {
         executeCallCallouts(10, 3, 33, 2, 62, 3, 183);
     }
 
+    // r2 = 5 * 7 * 10
+    {
+        SCOPED_TRACE("Calculation using command handlers");
+        executeCallCommandHandlers(5, 5, 7, 350);
+    }
+
     // Try unloading the libraries.
     EXPECT_NO_THROW(HooksManager::unloadLibraries());
 
@@ -538,6 +580,8 @@ TEST_F(HooksManagerTest, NoLibrariesCalloutsPresent) {
     EXPECT_FALSE(HooksManager::calloutsPresent(hookpt_one_index_));
     EXPECT_FALSE(HooksManager::calloutsPresent(hookpt_two_index_));
     EXPECT_FALSE(HooksManager::calloutsPresent(hookpt_three_index_));
+    EXPECT_FALSE(HooksManager::commandHandlersPresent("command-one"));
+    EXPECT_FALSE(HooksManager::commandHandlersPresent("command-two"));
 }
 
 TEST_F(HooksManagerTest, NoLibrariesCallCallouts) {