Procházet zdrojové kódy

added detailed help function

prozessorkern před 3 roky
rodič
revize
a5bd5c57ab

+ 1 - 1
api/shellmatta.h

@@ -109,7 +109,7 @@ typedef struct shellmatta_cmd
     char                    *cmd;       /**< command name                           */
     char                    *cmdAlias;  /**< command alias                          */
     char                    *helpText;  /**< help text to print in "help" command   */
-    char                    *usageText; /**< usage text to print on parameter error */
+    char                    *usageText; /**< usage text - printed on "help cmd"     */
     shellmatta_cmdFct_t     cmdFct;     /**< pointer to the cmd callack function    */
     struct shellmatta_cmd   *next;      /**< pointer to next command or NULL        */
 } shellmatta_cmd_t;

+ 2 - 1
makefile

@@ -49,7 +49,8 @@ INTEGRATIONTEST_SOURCES :=  test/integrationtest/test_main.cpp
                             test/integrationtest/test_integration_optLong.cpp   \
                             test/integrationtest/test_integration_continue.cpp  \
                             test/integrationtest/test_integration_busy.cpp      \
-                            test/integrationtest/test_integration_history.cpp
+                            test/integrationtest/test_integration_history.cpp   \
+                            test/integrationtest/test_integration_help.cpp
 
 UNITTEST_CPPOBJ  := $(patsubst %.cpp,$(UNITTEST_OBJ_DIR)%.o,$(UNITTEST_SOURCES))
 

+ 121 - 43
src/shellmatta_utils.c

@@ -267,11 +267,48 @@ void utils_clearInput(shellmatta_instance_t *inst)
     inst->dirty = false;
 }
 
+/**
+ * @brief       prints the usage information of one passed command
+ * @param[in]   inst    handle  shellmatta instance handle
+ * @param[in]   cmd     pointer to a command structure to print
+ * @return      #SHELLMATTA_OK
+ *              #SHELLMATTA_ERROR
+ */
+static shellmatta_retCode_t printUsage(const shellmatta_instance_t *inst, const shellmatta_cmd_t *cmd)
+{
+    shellmatta_retCode_t ret = SHELLMATTA_OK;
+
+    /** -# write the command and alias if configured */
+    SHELLMATTA_RET(ret, inst->write("Help for command: ", 18u));
+    SHELLMATTA_RET(ret, inst->write(cmd->cmd, strlen(cmd->cmd)));
+    if((NULL != cmd->cmdAlias) && (0u != strlen(cmd->cmdAlias)))
+    {
+        SHELLMATTA_RET(ret, inst->write(" (", 2u));
+        SHELLMATTA_RET(ret, inst->write(cmd->cmdAlias, strlen(cmd->cmdAlias)));
+        SHELLMATTA_RET(ret, inst->write(")", 1u));
+    }
+    /** -# write the help text if configured */
+    if((NULL != cmd->helpText) && (0u != strlen(cmd->helpText)))
+    {
+        SHELLMATTA_RET(ret, inst->write("\r\n\r\n", 4u));
+        SHELLMATTA_RET(ret, inst->write(cmd->helpText, strlen(cmd->helpText)));
+    }
+    /** -# write the usage text if configured */
+    if((NULL != cmd->usageText) && (0u != strlen(cmd->usageText)))
+    {
+        SHELLMATTA_RET(ret, inst->write("\r\n\r\nUsage: \r\n", 13u));
+        SHELLMATTA_RET(ret, inst->write(cmd->usageText, strlen(cmd->usageText)));
+    }
+    SHELLMATTA_RET(ret, inst->write("\r\n", 2u));
+
+    return ret;
+}
+
 /**
  * @brief       prints all possible commands with description and usage
  * @param[in]   handle      handle  shellmatta instance handle
- * @param[in]   arguments   not used here
- * @param[in]   length      not used here
+ * @param[in]   arguments   arguments containing a command name or alias
+ * @param[in]   length      length of the arguments
  * @return      #SHELLMATTA_OK
  *              #SHELLMATTA_ERROR (buffer overflow)
  */
@@ -279,72 +316,113 @@ static shellmatta_retCode_t helpCmdFct(const shellmatta_handle_t handle, const c
 {
     shellmatta_retCode_t        ret = SHELLMATTA_OK;
     const shellmatta_instance_t *inst = (const shellmatta_instance_t*) handle;
-    shellmatta_cmd_t            *cmd = inst->cmdList;
+    shellmatta_cmd_t            *cmd            = NULL;
     size_t                      maxCmdLen       = 0u;
     size_t                      maxCmdAliasLen  = 0u;
-    size_t                      maxCmdHelpLen   = 0u;
-    size_t                      cmdLen;
+    size_t                      cmdLen          = 0u;
+    const char                  *subCmd         = NULL;
     size_t                      cmdAliasLen;
-    size_t                      cmdHelpLen;
     uint32_t                    tabCnt;
+    uint32_t                    i;
     static const char           tabBuffer[] = { ' ', ' ', ' ', ' ',
                                                 ' ', ' ', ' ', ' ',
                                                 ' ', ' ', ' ', ' ',
                                                 ' ', ' ', ' ', ' '};
 
-    /** -# loop through all commands to determine the lengths of each cmd */
-    while(NULL != cmd)
+    /** -# check if help is called with a command - find first space */
+    for(i = 1u; i < length; i ++)
     {
-        maxCmdLen           = SHELLMATTA_MAX(maxCmdLen,         strlen(cmd->cmd));
-        if(NULL != cmd->cmdAlias)
-        {
-            maxCmdAliasLen  = SHELLMATTA_MAX(maxCmdAliasLen,    strlen(cmd->cmdAlias));
-        }
-        if(NULL != cmd->helpText)
+        if(' ' == arguments[i - 1])
         {
-            maxCmdHelpLen   = SHELLMATTA_MAX(maxCmdHelpLen,     strlen(cmd->helpText));
+            subCmd  = &(arguments[i]);
+
+            /** -# determine subcommand length*/
+            cmdLen  = 0u;
+            while(      ((i + cmdLen)   <   length)
+                    &&  (' '            !=  arguments[i + cmdLen])
+                    &&  ('\r'           !=  arguments[i + cmdLen])
+                    &&  ('\n'           !=  arguments[i + cmdLen])
+                    &&  ('\0'           !=  arguments[i + cmdLen]))
+            {
+                cmdLen ++;
+            }
+            break;
         }
-        cmd = cmd->next;
     }
 
-    /** -# loop through all commands and print all possible information */
-    cmd = inst->cmdList;
-    while(NULL != cmd)
+    /* print detailled help */
+    if(NULL != subCmd)
     {
-        /** -# determine the length of each field to add padding */
-        cmdLen       = strlen(cmd->cmd);
-        cmdAliasLen  = (NULL != cmd->cmdAlias) ? strlen(cmd->cmdAlias) : 0u;
-        cmdHelpLen   = (NULL != cmd->helpText) ? strlen(cmd->helpText) : 0u;
+        cmd = inst->cmdList;
 
-        inst->write(cmd->cmd, strlen(cmd->cmd));
-        tabCnt = (maxCmdLen - cmdLen) + 2u;
-        SHELLMATTA_PRINT_BUFFER(tabBuffer, tabCnt, inst->write);
-
-        if(NULL != cmd->cmdAlias)
+        /** -# search for a matching command */
+        while (NULL != cmd)
         {
-            inst->write(cmd->cmdAlias, cmdAliasLen);
+            /** -# compare command and alias string and length */
+            if (    ((cmdLen    == strlen(cmd->cmd))
+                    && (0       == strncmp(subCmd, cmd->cmd, cmdLen)))
+                || ((NULL != cmd->cmdAlias)
+                    && (cmdLen  == strlen(cmd->cmdAlias))
+                    && (0       == strncmp(subCmd, cmd->cmdAlias, cmdLen))))
+            {
+                SHELLMATTA_RET(ret, printUsage(inst, cmd));
+                break;
+            }
+
+            cmd = cmd->next;
         }
-        tabCnt = (maxCmdAliasLen - cmdAliasLen) + 2u;
-        SHELLMATTA_PRINT_BUFFER(tabBuffer, tabCnt, inst->write);
+    }
 
-        if(NULL != cmd->helpText)
+    /** -# print help list if no sub cmd was found */
+    if(NULL == cmd)
+    {
+        /** -# loop through all commands to determine the lengths of each cmd */
+        cmd = inst->cmdList;
+        while(NULL != cmd)
         {
-            inst->write(cmd->helpText, cmdHelpLen);
+            maxCmdLen           = SHELLMATTA_MAX(maxCmdLen,         strlen(cmd->cmd));
+            if(NULL != cmd->cmdAlias)
+            {
+                maxCmdAliasLen  = SHELLMATTA_MAX(maxCmdAliasLen,    strlen(cmd->cmdAlias));
+            }
+            cmd = cmd->next;
         }
-        tabCnt = (maxCmdHelpLen - cmdHelpLen) + 2u;
-        SHELLMATTA_PRINT_BUFFER(tabBuffer, tabCnt, inst->write);
 
-        if(NULL != cmd->usageText)
+        /** -# loop through all commands and print all possible information */
+        cmd = inst->cmdList;
+        while(NULL != cmd)
         {
-            inst->write(cmd->usageText, strlen(cmd->usageText));
-        }
-        inst->write("\r\n", 2u);
+            /** -# determine the length of each field to add padding */
+            cmdLen       = strlen(cmd->cmd);
+            cmdAliasLen  = (NULL != cmd->cmdAlias) ? strlen(cmd->cmdAlias) : 0u;
 
-        cmd = cmd->next;
-    }
+            SHELLMATTA_RET(ret, inst->write(cmd->cmd, strlen(cmd->cmd)));
+            tabCnt = (maxCmdLen - cmdLen) + 2u;
+
+            /** -# add padding if there is anything to be printed afterwards */
+            if(    ((NULL != cmd->cmdAlias) && (0u != strlen(cmd->cmdAlias)))
+                || ((NULL != cmd->helpText) && (0u != strlen(cmd->helpText))))
+            {
+                SHELLMATTA_PRINT_BUFFER(tabBuffer, tabCnt, inst->write);
+            }
+
+            if((NULL != cmd->cmdAlias) && (0u != strlen(cmd->cmdAlias)))
+            {
+                SHELLMATTA_RET(ret, inst->write(cmd->cmdAlias, cmdAliasLen));
+            }
+            tabCnt = (maxCmdAliasLen - cmdAliasLen) + 2u;
+
+            if((NULL != cmd->helpText) && (0u != strlen(cmd->helpText)))
+            {
+                SHELLMATTA_PRINT_BUFFER(tabBuffer, tabCnt, inst->write);
+                SHELLMATTA_RET(ret, inst->write(cmd->helpText, strlen(cmd->helpText)));
+            }
+
+            SHELLMATTA_RET(ret, inst->write("\r\n", 2u));
 
-    (void)arguments;
-    (void)length;
+            cmd = cmd->next;
+        }
+    }
 
     return ret;
 }

+ 16 - 4
src/shellmatta_utils.h

@@ -36,6 +36,13 @@
  */
 #define SHELLMATTA_MAX(a,b) (((a) < (b)) ?  (b) : (a))
 
+/**
+ * @brief       sums up #shellmatta_retCode_t
+ * @param[in]   ret         return variable
+ * @param[in]   expression  expression with the return value
+ */
+#define SHELLMATTA_RET(ret, expression) (ret) = (SHELLMATTA_OK != (expression)) ? SHELLMATTA_ERROR : (ret)
+
 /**
  * @brief       calls fct with cnt bytes from buffer (to print cnt same bytes)
  * @param[in]   buffer  buffer to send (shall contain the same char)
@@ -76,16 +83,21 @@ extern const shellmatta_cmd_t helpCmd;
  *  e.g. use _-DSHELLMATTA_HELP_ALIAS=\"?\"_ as compile option to change the alias to ?
  */
 #ifndef SHELLMATTA_HELP_COMMAND
-#define SHELLMATTA_HELP_COMMAND     (char*)"help"                   /**< help command               */
+/** \brief help command                 */
+#define SHELLMATTA_HELP_COMMAND     (char*)"help"
 #endif
 #ifndef SHELLMATTA_HELP_ALIAS
-#define SHELLMATTA_HELP_ALIAS       (char*)"h"                      /**< help command alias         */
+/** \brief help command alias           */
+#define SHELLMATTA_HELP_ALIAS       (char*)"h"
 #endif
 #ifndef SHELLMATTA_HELP_HELP_TEXT
-#define SHELLMATTA_HELP_HELP_TEXT   (char*)"Print this help text"   /**< help command help text     */
+/** \brief help command help text       */
+#define SHELLMATTA_HELP_HELP_TEXT   (char*)"help [command] - print help or usage information"
 #endif
 #ifndef SHELLMATTA_HELP_USAGE_TEXT
-#define SHELLMATTA_HELP_USAGE_TEXT  (char*)"help"                   /**< help command usage text    */
+/** \brief help command usage text      */
+#define SHELLMATTA_HELP_USAGE_TEXT  (char*) "help [command]\r\n"                                                    \
+                                            "\tcommand: optional command name or alias to print detailled help for"
 #endif
 /**
  *  @}

+ 20 - 85
test/integrationtest/test_integration.cpp

@@ -88,71 +88,6 @@ TEST_CASE( "shellmatta empty function" ) {
 
 }
 
-TEST_CASE( "shellmatta help function" ) {
-
-    shellmatta_instance_t inst;
-    shellmatta_handle_t handle;
-    char buffer[1024];
-    char historyBuffer[1024];
-    char *dummyData =   (char*)"?\r\n"
-                        "doSomething  do  Function does something  use me, please\r\n"
-                        "empty                                     \r\n"
-                        "help         ?   Print this help text     help\r\n"
-                        "\r\nshellmatta->";
-
-    shellmatta_doInit(  &inst,
-                        &handle,
-                        buffer,
-                        sizeof(buffer),
-                        historyBuffer,
-                        sizeof(historyBuffer),
-                        "shellmatta->",
-                        NULL,
-                        writeFct);
-    shellmatta_addCmd(handle, &emptyCmd);
-    shellmatta_addCmd(handle, &doSomethingCmd);
-
-    write_callCnt = 0u;
-    memset(write_data, 0, sizeof(write_data));
-    write_length = 0u;
-
-    shellmatta_processData(handle, (char*)"?\r", 2);
-
-    CHECK( write_length == strlen(dummyData));
-    CHECK( strcmp(dummyData, write_data) == 0);
-
-    write_callCnt = 0u;
-    memset(write_data, 0, sizeof(write_data));
-    write_length = 0u;
-
-    dummyData =     (char*)"? 564 321 56 465 46\r\n"
-                    "doSomething  do  Function does something  use me, please\r\n"
-                    "empty                                     \r\n"
-                    "help         ?   Print this help text     help\r\n"
-                    "\r\nshellmatta->";
-
-    shellmatta_processData(handle, (char*)"? 564 321 56 465 46\r", 20);
-
-    CHECK( write_length == strlen(dummyData));
-    CHECK( strcmp(dummyData, write_data) == 0);
-
-
-    write_callCnt = 0u;
-    memset(write_data, 0, sizeof(write_data));
-    write_length = 0u;
-
-    dummyData = (char*)"?r\r\n"
-                "Command: ?r not found"
-                "\r\nshellmatta->";
-
-    shellmatta_processData(handle, (char*)"?r\r", 3);
-
-    CHECK( write_length == 39u);
-    REQUIRE( strcmp(dummyData, write_data) == 0);
-}
-
-
-
 TEST_CASE( "shellmatta heredoc test" ) {
 
     shellmatta_instance_t inst;
@@ -228,8 +163,8 @@ TEST_CASE( "shellmatta remove function" ) {
     char buffer[1024];
     char historyBuffer[1024];
     char *dummyData =   (char*)"?\r\n"
-                        "doSomething  do  Function does something  use me, please\r\n"
-                        "help         ?   Print this help text     help\r\n"
+                        "doSomething  do  Function does something\r\n"
+                        "help         ?   help [command] - print help or usage information\r\n"
                         "\r\nshellmatta->";
 
     shellmatta_doInit(  &inst,
@@ -249,7 +184,7 @@ TEST_CASE( "shellmatta remove function" ) {
 
     shellmatta_processData(handle, (char*)"?\r", 2);
 
-    CHECK( write_length == 123u);
+    CHECK( write_length == strlen(dummyData));
     CHECK( strcmp(dummyData, write_data) == 0);
 
 
@@ -258,13 +193,13 @@ TEST_CASE( "shellmatta remove function" ) {
     write_length = 0u;
 
     dummyData =     (char*)"? 564 321 56 465 46\r\n"
-                    "doSomething  do  Function does something  use me, please\r\n"
-                    "help         ?   Print this help text     help\r\n"
+                    "doSomething  do  Function does something\r\n"
+                    "help         ?   help [command] - print help or usage information\r\n"
                     "\r\nshellmatta->";
 
     shellmatta_processData(handle, (char*)"? 564 321 56 465 46\r", 20);
 
-    CHECK( write_length == 141u);
+    CHECK( write_length == strlen(dummyData));
     CHECK( strcmp(dummyData, write_data) == 0);
 
     write_callCnt = 0u;
@@ -275,10 +210,10 @@ TEST_CASE( "shellmatta remove function" ) {
     shellmatta_processData(handle, (char*)"? 564 321 56 465 46\r", 20);
 
     dummyData =     (char*)"? 564 321 56 465 46\r\n"
-                    "help  ?  Print this help text  help\r\n"
+                    "help  ?  help [command] - print help or usage information\r\n"
                     "\r\nshellmatta->";
 
-    CHECK( write_length == 72u);
+    CHECK( write_length == strlen(dummyData));
     REQUIRE( strcmp(dummyData, write_data) == 0);
 }
 
@@ -289,8 +224,8 @@ TEST_CASE( "shellmatta reset no prompt" ) {
     char buffer[1024];
     char historyBuffer[1024];
     char *dummyData =   (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd?\r\n"
-                        "doSomething  do  Function does something  use me, please\r\n"
-                        "help         ?   Print this help text     help\r\n"
+                        "doSomething  do  Function does something\r\n"
+                        "help         ?   help [command] - print help or usage information\r\n"
                         "\r\nshellmatta->";
 
     shellmatta_doInit(  &inst,
@@ -324,8 +259,8 @@ TEST_CASE( "shellmatta reset with prompt" ) {
     char historyBuffer[1024];
     char *dummyData =   (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd"
                         "\r\nshellmatta->?\r\n"
-                        "doSomething  do  Function does something  use me, please\r\n"
-                        "help         ?   Print this help text     help\r\n"
+                        "doSomething  do  Function does something\r\n"
+                        "help         ?   help [command] - print help or usage information\r\n"
                         "\r\nshellmatta->";
 
     shellmatta_doInit(  &inst,
@@ -358,8 +293,8 @@ TEST_CASE( "shellmatta reset no prompt history buffer" ) {
     char buffer[1024];
     char historyBuffer[1024];
     char *dummyData =   (char*)"?\r\n"
-                        "doSomething  do  Function does something  use me, please\r\n"
-                        "help         ?   Print this help text     help\r\n"
+                        "doSomething  do  Function does something\r\n"
+                        "help         ?   help [command] - print help or usage information\r\n"
                         "\r\nshellmatta->";
 
     shellmatta_doInit(  &inst,
@@ -398,8 +333,8 @@ TEST_CASE( "shellmatta reset no prompt heredoc" ) {
     char buffer[1024];
     char historyBuffer[1024];
     char *dummyData =   (char*)"?\r\n"
-                        "doSomething  do  Function does something  use me, please\r\n"
-                        "help         ?   Print this help text     help\r\n"
+                        "doSomething  do  Function does something\r\n"
+                        "help         ?   help [command] - print help or usage information\r\n"
                         "\r\nshellmatta->";
 
     shellmatta_doInit(  &inst,
@@ -439,12 +374,12 @@ TEST_CASE( "shellmatta configure disable echo" ) {
     char buffer[1024];
     char historyBuffer[1024];
     char *dummyData =   (char*)"help this is some dummy Text\r\n"
-                        "doSomething  do  Function does something  use me, please\r\n"
-                        "help         ?   Print this help text     help\r\n"
+                        "doSomething  do  Function does something\r\n"
+                        "help         ?   help [command] - print help or usage information\r\n"
                         "\r\nshellmatta->";
 
-    char *dummyData2 =  (char*)"doSomething  do  Function does something  use me, please\r\n"
-                        "help         ?   Print this help text     help\r\n"
+    char *dummyData2 =  (char*)"doSomething  do  Function does something\r\n"
+                        "help         ?   help [command] - print help or usage information\r\n"
                         "\r\nshellmatta->";
 
     shellmatta_doInit(  &inst,

+ 296 - 0
test/integrationtest/test_integration_help.cpp

@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2021 Stefan Strobel <stefan.strobel@shimatta.net>
+ *
+ * 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
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+/**
+ * @file    test_integration_help.cpp
+ * @brief   integration test implementation for the help command of the shellmatta
+ * @author  Stefan Strobel <stefan.strobel@shimatta.net>
+ */
+
+#include "test/framework/catch.hpp"
+extern "C" {
+#include "test/framework/fff.h"
+#include "shellmatta.h"
+}
+#include <string.h>
+
+FAKE_VALUE_FUNC(shellmatta_retCode_t, writeFct, const char *, uint32_t)
+FAKE_VALUE_FUNC(shellmatta_retCode_t, cmdFct1, shellmatta_handle_t, const char *, uint32_t)
+FAKE_VALUE_FUNC(shellmatta_retCode_t, cmdFct2, shellmatta_handle_t, const char *, uint32_t)
+FAKE_VALUE_FUNC(shellmatta_retCode_t, cmdFct3, shellmatta_handle_t, const char *, uint32_t)
+
+static char fakeWriteData[1024];
+static uint32_t fakeWriteLength;
+static shellmatta_retCode_t writeFct_customFake(const char* data, uint32_t length)
+{
+    while((length > 0) && (fakeWriteLength < sizeof(fakeWriteData)))
+    {
+        fakeWriteData[fakeWriteLength] = *data;
+        data ++;
+        length --;
+        fakeWriteLength ++;
+    }
+
+    return SHELLMATTA_OK;
+}
+
+/* List of fakes */
+#define FFF_FAKES_LIST(FAKE)            \
+    FAKE(writeFct)                      \
+    FAKE(cmdFct1)                       \
+    FAKE(cmdFct2)                       \
+    FAKE(cmdFct3)
+
+#define PROCESS_INPUT(input) \
+    CHECK(SHELLMATTA_OK == shellmatta_processData(handle, (char*)(input), sizeof((input)) - 1u));
+
+static shellmatta_cmd_t cmd1 = {(char*)"cmd1", (char*)"1", (char*)"cmd1 [options]", (char*)"cmd1 usage\r\n--option, -o: option", cmdFct1, NULL};
+static shellmatta_cmd_t cmd2 = {(char*)"cmd2", NULL, NULL, NULL, cmdFct2, NULL};
+static shellmatta_cmd_t cmd3 = {(char*)"cmd3", (char*)"", (char*)"", (char*)"", cmdFct3, NULL};
+
+SCENARIO("Test the help function")
+{
+    GIVEN("An initialized and empty Shellmatte instance")
+    {
+        shellmatta_instance_t inst;
+        shellmatta_handle_t handle;
+        char buffer[1024u];
+        char historyBuffer[1024u];
+
+        CHECK(SHELLMATTA_OK == shellmatta_doInit(   &inst,
+                                                    &handle,
+                                                    buffer,
+                                                    sizeof(buffer),
+                                                    historyBuffer,
+                                                    sizeof(historyBuffer),
+                                                    "shellmatta->",
+                                                    NULL,
+                                                    writeFct));
+
+        CHECK(SHELLMATTA_OK == shellmatta_addCmd(handle, &cmd1));
+        CHECK(SHELLMATTA_OK == shellmatta_addCmd(handle, &cmd2));
+        CHECK(SHELLMATTA_OK == shellmatta_addCmd(handle, &cmd3));
+
+        WHEN("The user hits help")
+        {
+            FFF_FAKES_LIST(RESET_FAKE)
+            fakeWriteLength = 0u;
+            memset(fakeWriteData, 0, sizeof(fakeWriteData));
+
+            shellmatta_write_t writeCustomFakeSeq[1] = {writeFct_customFake};
+            SET_CUSTOM_FAKE_SEQ(writeFct, writeCustomFakeSeq, 1)
+
+            PROCESS_INPUT("help\r\n")
+
+            THEN("The shellmatta prints the help text")
+            {
+                static const char * response = (char*)  "help\r\n"
+                                                        "cmd1  1  cmd1 [options]\r\n"
+                                                        "cmd2\r\n"
+                                                        "cmd3\r\n"
+                                                        "help  ?  help [command] - print help or usage information\r\n\r\n"
+                                                        "shellmatta->";
+                CHECK(writeFct_fake.call_count == 23);
+                CHECK(strlen(response) == fakeWriteLength);
+                CHECK(0 == strcmp(response, fakeWriteData));
+            }
+        }
+
+        WHEN("The user hits ?")
+        {
+            FFF_FAKES_LIST(RESET_FAKE)
+            fakeWriteLength = 0u;
+            memset(fakeWriteData, 0, sizeof(fakeWriteData));
+
+            shellmatta_write_t writeCustomFakeSeq[1] = {writeFct_customFake};
+            SET_CUSTOM_FAKE_SEQ(writeFct, writeCustomFakeSeq, 1)
+
+            PROCESS_INPUT("?\r\n")
+
+            THEN("The shellmatta prints the help text")
+            {
+                static const char * response = (char*) "?\r\n"
+                                                        "cmd1  1  cmd1 [options]\r\n"
+                                                        "cmd2\r\n"
+                                                        "cmd3\r\n"
+                                                        "help  ?  help [command] - print help or usage information\r\n\r\n"
+                                                        "shellmatta->";
+                CHECK(writeFct_fake.call_count == 20);
+                CHECK(strlen(response) == fakeWriteLength);
+                CHECK(0 == strcmp(response, fakeWriteData));
+            }
+        }
+    }
+}
+
+SCENARIO("Test if the help command prints the usage correctly")
+{
+    GIVEN("An initialized and empty Shellmatte instance")
+    {
+        shellmatta_instance_t inst;
+        shellmatta_handle_t handle;
+        char buffer[1024u];
+        char historyBuffer[1024u];
+
+        CHECK(SHELLMATTA_OK == shellmatta_doInit(   &inst,
+                                                    &handle,
+                                                    buffer,
+                                                    sizeof(buffer),
+                                                    historyBuffer,
+                                                    sizeof(historyBuffer),
+                                                    "shellmatta->",
+                                                    NULL,
+                                                    writeFct));
+
+        CHECK(SHELLMATTA_OK == shellmatta_addCmd(handle, &cmd1));
+        CHECK(SHELLMATTA_OK == shellmatta_addCmd(handle, &cmd2));
+        CHECK(SHELLMATTA_OK == shellmatta_addCmd(handle, &cmd3));
+
+        WHEN("The user requests usage information from a valid command")
+        {
+            FFF_FAKES_LIST(RESET_FAKE)
+            fakeWriteLength = 0u;
+            memset(fakeWriteData, 0, sizeof(fakeWriteData));
+
+            shellmatta_write_t writeCustomFakeSeq[1] = {writeFct_customFake};
+            SET_CUSTOM_FAKE_SEQ(writeFct, writeCustomFakeSeq, 1)
+
+            PROCESS_INPUT("help cmd1\r\n")
+
+            THEN("The shellmatta prints the help text")
+            {
+                static const char * response = (char*)  "help cmd1\r\n"
+                                                        "Help for command: cmd1 (1)\r\n\r\n"
+                                                        "cmd1 [options]\r\n\r\n"
+                                                        "Usage: \r\n"
+                                                        "cmd1 usage\r\n--option, -o: option\r\n"
+                                                        "\r\nshellmatta->";
+                CHECK(writeFct_fake.call_count == 22);
+                CHECK(strlen(response) == fakeWriteLength);
+                CHECK(0 == strcmp(response, fakeWriteData));
+            }
+        }
+
+        WHEN("The user requests usage information from a valid command using its alias")
+        {
+            FFF_FAKES_LIST(RESET_FAKE)
+            fakeWriteLength = 0u;
+            memset(fakeWriteData, 0, sizeof(fakeWriteData));
+
+            shellmatta_write_t writeCustomFakeSeq[1] = {writeFct_customFake};
+            SET_CUSTOM_FAKE_SEQ(writeFct, writeCustomFakeSeq, 1)
+
+            PROCESS_INPUT("help 1\r\n")
+
+            THEN("The shellmatta prints the help text")
+            {
+                static const char * response = (char*)  "help 1\r\n"
+                                                        "Help for command: cmd1 (1)\r\n\r\n"
+                                                        "cmd1 [options]\r\n\r\n"
+                                                        "Usage: \r\n"
+                                                        "cmd1 usage\r\n--option, -o: option\r\n"
+                                                        "\r\nshellmatta->";
+                CHECK(writeFct_fake.call_count == 19);
+                CHECK(strlen(response) == fakeWriteLength);
+                CHECK(0 == strcmp(response, fakeWriteData));
+            }
+        }
+
+        WHEN("The user requests usage information from an empty command")
+        {
+            FFF_FAKES_LIST(RESET_FAKE)
+            fakeWriteLength = 0u;
+            memset(fakeWriteData, 0, sizeof(fakeWriteData));
+
+            shellmatta_write_t writeCustomFakeSeq[1] = {writeFct_customFake};
+            SET_CUSTOM_FAKE_SEQ(writeFct, writeCustomFakeSeq, 1)
+
+            PROCESS_INPUT("help cmd2\r\n")
+
+            THEN("The shellmatta prints the help text - without alias, help and usage text")
+            {
+                static const char * response = (char*)  "help cmd2\r\n"
+                                                        "Help for command: cmd2\r\n"
+                                                        "\r\nshellmatta->";
+                CHECK(writeFct_fake.call_count == 15);
+                CHECK(strlen(response) == fakeWriteLength);
+                CHECK(0 == strcmp(response, fakeWriteData));
+            }
+        }
+
+
+        WHEN("The user requests usage information from an empty stringed command")
+        {
+            FFF_FAKES_LIST(RESET_FAKE)
+            fakeWriteLength = 0u;
+            memset(fakeWriteData, 0, sizeof(fakeWriteData));
+
+            shellmatta_write_t writeCustomFakeSeq[1] = {writeFct_customFake};
+            SET_CUSTOM_FAKE_SEQ(writeFct, writeCustomFakeSeq, 1)
+
+            PROCESS_INPUT("help cmd3\r\n")
+
+            THEN("The shellmatta prints the help text - without alias, help and usage text")
+            {
+                static const char * response = (char*)  "help cmd3\r\n"
+                                                        "Help for command: cmd3\r\n"
+                                                        "\r\nshellmatta->";
+                CHECK(writeFct_fake.call_count == 15);
+                CHECK(strlen(response) == fakeWriteLength);
+                CHECK(0 == strcmp(response, fakeWriteData));
+            }
+        }
+
+        WHEN("The user adds additional arguments to the help command")
+        {
+            FFF_FAKES_LIST(RESET_FAKE)
+            fakeWriteLength = 0u;
+            memset(fakeWriteData, 0, sizeof(fakeWriteData));
+
+            shellmatta_write_t writeCustomFakeSeq[1] = {writeFct_customFake};
+            SET_CUSTOM_FAKE_SEQ(writeFct, writeCustomFakeSeq, 1)
+
+            PROCESS_INPUT("help cmd2 foo bar meow this is nonsense\r\n")
+
+            THEN("The shellmatta ignores the superflous arguments")
+            {
+                static const char * response = (char*)  "help cmd2 foo bar meow this is nonsense\r\n"
+                                                        "Help for command: cmd2\r\n"
+                                                        "\r\nshellmatta->";
+                CHECK(writeFct_fake.call_count == 45);
+                CHECK(strlen(response) == fakeWriteLength);
+                CHECK(0 == strcmp(response, fakeWriteData));
+            }
+        }
+
+        WHEN("The user requests help of a nonexisting command")
+        {
+            FFF_FAKES_LIST(RESET_FAKE)
+            fakeWriteLength = 0u;
+            memset(fakeWriteData, 0, sizeof(fakeWriteData));
+
+            shellmatta_write_t writeCustomFakeSeq[1] = {writeFct_customFake};
+            SET_CUSTOM_FAKE_SEQ(writeFct, writeCustomFakeSeq, 1)
+
+            PROCESS_INPUT("help cmd4\r\n")
+
+            THEN("The shellmatta prints the help list")
+            {
+                static const char * response = (char*)  "help cmd4\r\n"
+                                                        "cmd1  1  cmd1 [options]\r\n"
+                                                        "cmd2\r\n"
+                                                        "cmd3\r\n"
+                                                        "help  ?  help [command] - print help or usage information\r\n\r\n"
+                                                        "shellmatta->";
+                CHECK(writeFct_fake.call_count == 28);
+                CHECK(strlen(response) == fakeWriteLength);
+                CHECK(0 == strcmp(response, fakeWriteData));
+            }
+        }
+    }
+}

+ 10 - 4
test/integrationtest/test_integration_history.cpp

@@ -43,10 +43,10 @@ FAKE_VALUE_FUNC(shellmatta_retCode_t, cmdFct4, shellmatta_handle_t, const char *
 #define PROCESS_INPUT(input) \
     CHECK(SHELLMATTA_OK == shellmatta_processData(handle, (char*)(input), sizeof((input)) - 1u));
 
-shellmatta_cmd_t cmd1 = {(char*)"cmd1", (char*)"1", NULL, NULL, cmdFct1, NULL};
-shellmatta_cmd_t cmd2 = {(char*)"cmd2", (char*)"2", NULL, NULL, cmdFct2, NULL};
-shellmatta_cmd_t cmd3 = {(char*)"cmd3", (char*)"3", NULL, NULL, cmdFct3, NULL};
-shellmatta_cmd_t cmd4 = {(char*)"cmd4", (char*)"4", NULL, NULL, cmdFct4, NULL};
+static shellmatta_cmd_t cmd1 = {(char*)"cmd1", (char*)"1", NULL, NULL, cmdFct1, NULL};
+static shellmatta_cmd_t cmd2 = {(char*)"cmd2", (char*)"2", NULL, NULL, cmdFct2, NULL};
+static shellmatta_cmd_t cmd3 = {(char*)"cmd3", (char*)"3", NULL, NULL, cmdFct3, NULL};
+static shellmatta_cmd_t cmd4 = {(char*)"cmd4", (char*)"4", NULL, NULL, cmdFct4, NULL};
 
 char *commandSequence[] =
 {
@@ -69,6 +69,8 @@ SCENARIO("Test the history buffer with a fixed sequence of commands in there")
         char buffer[1024u];
         char historyBuffer[1024u];
 
+        FFF_FAKES_LIST(RESET_FAKE)
+
         CHECK(SHELLMATTA_OK == shellmatta_doInit(   &inst,
                                                     &handle,
                                                     buffer,
@@ -249,6 +251,8 @@ SCENARIO("Test how the history buffer handles more commands than fits inside the
         char buffer[1024u];
         char historyBuffer[16u] = {0};
 
+        FFF_FAKES_LIST(RESET_FAKE)
+
         CHECK(SHELLMATTA_OK == shellmatta_doInit(   &inst,
                                                     &handle,
                                                     buffer,
@@ -355,6 +359,8 @@ SCENARIO("Test if the history buffer stores changes done during navigating")
         char buffer[1024u];
         char historyBuffer[16u] = {0};
 
+        FFF_FAKES_LIST(RESET_FAKE)
+
         CHECK(SHELLMATTA_OK == shellmatta_doInit(   &inst,
                                                     &handle,
                                                     buffer,