Преглед на файлове

fix #47 now calling a continued command even without new input data
added integration tests

prozessorkern преди 4 години
родител
ревизия
c74e37b846
променени са 7 файла, в които са добавени 396 реда и са изтрити 15 реда
  1. 1 0
      api/shellmatta.h
  2. 1 0
      makefile
  3. 42 11
      src/shellmatta.c
  4. 12 3
      src/shellmatta_opt.c
  5. 3 1
      src/shellmatta_opt.h
  6. 53 0
      test/integrationtest/test_integration_busy.cpp
  7. 284 0
      test/integrationtest/test_integration_continue.cpp

+ 1 - 0
api/shellmatta.h

@@ -77,6 +77,7 @@ typedef struct
  */
 typedef struct
 {
+    uint32_t    argStart;   /**< start of the arguments of the command  */
     uint32_t    offset;     /**< current offset of the option parser    */
     uint32_t    nextOffset; /**< offset of the next hunk                */
     uint32_t    len;        /**< length of the current hunk             */

+ 1 - 0
makefile

@@ -42,6 +42,7 @@ INTEGRATIONTEST_SOURCES :=  test/integrationtest/test_main.cpp
                             test/integrationtest/test_integration.cpp           \
                             test/integrationtest/test_integration_opt.cpp       \
                             test/integrationtest/test_integration_optLong.cpp   \
+							test/integrationtest/test_integration_continue.cpp  \
                             test/integrationtest/test_integration_busy.cpp
 
 UNITTEST_CPPOBJ  := $(patsubst %.cpp,$(OBJ_DIR)%.o,$(UNITTEST_SOURCES))

+ 42 - 11
src/shellmatta.c

@@ -101,6 +101,7 @@ shellmatta_retCode_t shellmatta_doInit(
         inst->continuousCmd         = NULL;
         inst->busyCmd               = NULL;
         inst->cmdListIsConst        = false;
+        shellmatta_opt_init(inst, 0u);
 
         /** -# copy the help command structure to this instance */
         memcpy(&(inst->helpCmd), &helpCmd, sizeof(shellmatta_cmd_t));
@@ -158,6 +159,7 @@ shellmatta_retCode_t shellmatta_resetShell( shellmatta_handle_t handle, bool pri
         inst->hereStartIdx          = 0u;
         inst->hereDelimiterIdx      = 0u;
         inst->hereLength            = 0u;
+        shellmatta_opt_init(inst, 0u);
 
         if(true == printPrompt)
         {
@@ -385,20 +387,44 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
         if(NULL != inst->busyCmd)
         {
             /** -# just call the function until it is not busy anymore */
-            cmdRet = inst->busyCmd->cmdFct(handle, inst->buffer, inst->inputCount);
+            (void)shellmatta_opt_reInit(inst);
+            ret = inst->busyCmd->cmdFct(handle, inst->buffer, inst->inputCount);
 
-            if(SHELLMATTA_BUSY != cmdRet)
+            if(SHELLMATTA_BUSY == ret)
             {
-                utils_terminateInput(inst);
+                /** -# do nothing - still busy */
             }
-            else if(SHELLMATTA_CONTINUE == cmdRet)
+            else if(SHELLMATTA_CONTINUE == ret)
             {
                 inst->continuousCmd = inst->busyCmd;
                 inst->busyCmd       = NULL;
             }
             else
             {
-                ret = cmdRet;
+                utils_terminateInput(inst);
+            }
+        }
+        /** -# call continuous function even if there is no data */
+        else if((0u == size) && (NULL != inst->continuousCmd))
+        {
+            /** -# just call the function without any new data */
+            inst->stdinLength               = 0u;
+            inst->buffer[inst->stdinIdx]    = '\0';
+            (void)shellmatta_opt_reInit(inst);
+            ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
+
+            if(SHELLMATTA_CONTINUE == ret)
+            {
+                /** -# do nothing just continue */
+            }
+            else if(SHELLMATTA_BUSY == ret)
+            {
+                inst->busyCmd       = inst->continuousCmd;
+                inst->continuousCmd = NULL;
+            }
+            else
+            {
+                utils_terminateInput(inst);
             }
         }
 
@@ -409,21 +435,25 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
             if(NULL != inst->continuousCmd)
             {
                 /** -# copy data and call command function */
-                inst->buffer[inst->stdinIdx]    = data[inst->byteCounter];
-                inst->stdinLength               = 1u;
-                cmdRet = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
+                inst->buffer[inst->stdinIdx]        = data[inst->byteCounter];
+                inst->buffer[inst->stdinIdx + 1u]   = '\0';
+                inst->stdinLength                   = 1u;
+                (void)shellmatta_opt_reInit(inst);
+                ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
                 
                 /** -# check if continuous mode is canceled or interrupted by busy mode */
-                if(SHELLMATTA_BUSY == cmdRet)
+                if(SHELLMATTA_BUSY == ret)
                 {
                     inst->busyCmd 	= inst->continuousCmd;
                     inst->continuousCmd = NULL;
                 }
                 else if(('\x03' == data[inst->byteCounter]))
                 {
+                    /** -# cancel continue session */
                     utils_terminateInput(inst);
+                    ret = SHELLMATTA_OK;
                 }
-                else if(SHELLMATTA_CONTINUE == cmdRet)
+                else if(SHELLMATTA_CONTINUE == ret)
                 {
                     /** -# do nothing - continue */
                 }
@@ -589,6 +619,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
                                     inst->stdinIdx      = inst->inputCount + 1u;
                                     inst->stdinLength   = 0u;
                                     inst->continuousCmd = cmd;
+                                    ret                 = cmdRet;
                                     break;
                                 
                                 case SHELLMATTA_BUSY:
@@ -668,7 +699,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t     handle,
             }
         }
 
-        /*! -# initialize the byte buffer if processing of the input is finished */
+        /** -# initialize the byte buffer if processing of the input is finished */
         if(ret != SHELLMATTA_BUSY)
         {
             inst->byteCounter = 0u;

+ 12 - 3
src/shellmatta_opt.c

@@ -410,12 +410,21 @@ shellmatta_retCode_t shellmatta_opt_long(   shellmatta_handle_t         handle,
  * @param[in, out]  inst        pointer to a shellmatta instance
  * @param[in]       argStart    start offset of the arguments (after command name/alias)
  */
-shellmatta_retCode_t shellmatta_opt_init(shellmatta_instance_t *inst, uint32_t argStart)
+void shellmatta_opt_init(shellmatta_instance_t *inst, uint32_t argStart)
 {
     /** -# initialize all relevant option parser variables */
-    inst->optionParser.nextOffset = argStart;
+    inst->optionParser.argStart     = argStart;
+    inst->optionParser.nextOffset   = argStart;
+}
 
-    return SHELLMATTA_OK;
+/**
+ * @brief           re-initializes the option parser instance using the data from the last init
+ * @param[in, out]  inst        pointer to a shellmatta instance
+ */
+void shellmatta_opt_reInit(shellmatta_instance_t *inst)
+{
+    /** -# initialize all relevant option parser variables */
+    inst->optionParser.nextOffset = inst->optionParser.argStart;
 }
 
 /**

+ 3 - 1
src/shellmatta_opt.h

@@ -34,9 +34,11 @@ shellmatta_retCode_t shellmatta_opt_long(   shellmatta_handle_t         handle,
                                             char                        **argument,
                                             uint32_t                    *argLen);
 
-shellmatta_retCode_t shellmatta_opt_init(   shellmatta_instance_t   *inst,
+void shellmatta_opt_init(                   shellmatta_instance_t   *inst,
                                             uint32_t argStart);
 
+void shellmatta_opt_reInit(                 shellmatta_instance_t   *inst);
+
 #endif
 
 /** @} */

+ 53 - 0
test/integrationtest/test_integration_busy.cpp

@@ -23,6 +23,7 @@ static char write_data[1024];
 static uint32_t write_length;
 static uint32_t busyCallCnt;
 static uint32_t notBusyCallCnt;
+static bool suspendBusy;
 
 static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
 {
@@ -67,6 +68,11 @@ static shellmatta_retCode_t busyCmdFct(shellmatta_handle_t handle, const char *a
         ret = SHELLMATTA_OK;
     }
 
+    if(true == suspendBusy)
+    {
+        ret = SHELLMATTA_CONTINUE;
+    }
+
     return ret;
 }
 shellmatta_cmd_t busyCmd = {(char*)"busy", (char*)"b", NULL, NULL, busyCmdFct, NULL};
@@ -111,6 +117,7 @@ TEST_CASE( "shellmatta busy 1" ) {
     write_callCnt = 0u;
     memset(write_data, 0, sizeof(write_data));
     write_length = 0u;
+    suspendBusy = false;
 
     shellmatta_addCmd(handle, &busyCmd);
     shellmatta_addCmd(handle, &notBusyCmd);
@@ -128,3 +135,49 @@ TEST_CASE( "shellmatta busy 1" ) {
     CHECK( write_length == strlen(dummyData));
     REQUIRE( strcmp(dummyData, write_data) == 0);
 }
+
+TEST_CASE( "shellmatta busy suspend with continuous mode" ) {
+
+    shellmatta_retCode_t ret;
+    shellmatta_instance_t inst;
+    shellmatta_handle_t handle;
+    char buffer[1024];
+    char historyBuffer[1024];
+    char *dummyData =   (char*) "busy and some arguments\r\n";
+
+    shellmatta_doInit(  &inst,
+                        &handle,
+                        buffer,
+                        sizeof(buffer),
+                        historyBuffer,
+                        sizeof(historyBuffer),
+                        "shellmatta->",
+                        NULL,
+                        writeFct);
+
+    busyCallCnt = 0u;
+    notBusyCallCnt = 0u;
+    write_callCnt = 0u;
+    memset(write_data, 0, sizeof(write_data));
+    write_length = 0u;
+    suspendBusy = false;
+
+    shellmatta_addCmd(handle, &busyCmd);
+    shellmatta_addCmd(handle, &notBusyCmd);
+
+    do
+    {
+        ret = shellmatta_processData(handle, (char*)"busy and some arguments\r123", 27u);
+
+        suspendBusy = true;
+
+    } while (SHELLMATTA_BUSY == ret);
+
+    ret = shellmatta_processData(handle, (char*)"", 0u);
+
+    CHECK( SHELLMATTA_CONTINUE == ret);
+    CHECK( 6u  == busyCallCnt);
+    CHECK( 0u   == notBusyCallCnt );
+    CHECK( write_length == strlen(dummyData));
+    REQUIRE( strcmp(dummyData, write_data) == 0);
+}

+ 284 - 0
test/integrationtest/test_integration_continue.cpp

@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2019 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_busy.cpp
+ * @brief   integration test implementation for the cmd busy function
+ * @author  Stefan Strobel <stefan.strobel@shimatta.net>
+ */
+
+#include "test/framework/catch.hpp"
+extern "C" {
+#include "shellmatta.h"
+}
+#include <string.h>
+
+static uint32_t write_callCnt = 0u;
+static char write_data[1024];
+static uint32_t write_length;
+static uint32_t contCallCnt;
+static uint32_t busyCallCnt;
+
+static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
+{
+    write_callCnt ++;
+    while((length > 0) && (write_length < sizeof(write_data)))
+    {
+        write_data[write_length] = *data;
+        data ++;
+        length --;
+        write_length ++;
+    }
+
+    return SHELLMATTA_OK;
+}
+
+static shellmatta_retCode_t continueCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
+{
+    (void)      handle;
+    (void)      arguments;
+    (void)      length;
+    shellmatta_retCode_t ret        = SHELLMATTA_CONTINUE;
+    char *stdinData;
+    uint32_t stdinLength = 0u;
+
+    shellmatta_read(handle, &stdinData, &stdinLength);
+    if(NULL == stdinData)
+    {
+        stdinData = (char *)"";
+    }
+    
+    shellmatta_printf(handle, "arguments: %s length: %u\r\n", stdinData, stdinLength);
+
+    /** change to busy mode when k is pressed */
+    if('k' == stdinData[0])
+    {
+        ret = SHELLMATTA_BUSY;
+        busyCallCnt ++;
+    }
+
+    if(busyCallCnt > 1u)
+    {
+        ret = SHELLMATTA_CONTINUE;
+    }
+
+    if(contCallCnt >= 9u)
+    {
+        ret = SHELLMATTA_OK;
+    }
+
+    /* -# the arguments shall stay the same on every call - data is transferred per stdin */
+    CHECK(length == 28u);
+    CHECK(strcmp(arguments, "continue some arguments meow") == 0);
+
+    contCallCnt ++;
+
+    return ret;
+}
+shellmatta_cmd_t continueCmd = {(char*)"continue", (char*)"c", NULL, NULL, continueCmdFct, NULL};
+
+
+TEST_CASE( "shellmatta continue 1" ) {
+
+    shellmatta_retCode_t ret;
+    shellmatta_instance_t inst;
+    shellmatta_handle_t handle;
+    char buffer[1024];
+    char historyBuffer[1024];
+    char *dummyData =   (char*) "continue some arguments meow\r\n"
+                                "arguments:  length: 0\r\n"
+                                "arguments:  length: 0\r\n"
+                                "arguments: a length: 1\r\n"
+                                "arguments: b length: 1\r\n"
+                                "arguments: c length: 1\r\n"
+                                "arguments: 8 length: 1\r\n"
+                                "arguments: 7 length: 1\r\n"
+                                "arguments: 6 length: 1\r\n"
+                                "arguments: 5 length: 1\r\n"
+                                "arguments:  length: 0\r\n"
+                                "\r\n"
+                                "shellmatta->\r\n"
+                                "shellmatta->";
+
+    shellmatta_doInit(  &inst,
+                        &handle,
+                        buffer,
+                        sizeof(buffer),
+                        historyBuffer,
+                        sizeof(historyBuffer),
+                        "shellmatta->",
+                        NULL,
+                        writeFct);
+
+    contCallCnt = 0u;
+    busyCallCnt = 0u;
+    write_callCnt = 0u;
+    memset(write_data, 0, sizeof(write_data));
+    write_length = 0u;
+
+    shellmatta_addCmd(handle, &continueCmd);
+
+    ret = shellmatta_processData(handle, (char*)"continue some arguments meow\r", 29);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    /** -# call without any argument */
+    ret = shellmatta_processData(handle, NULL, 0);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    /** -# pass some argument */
+    ret = shellmatta_processData(handle, (char*)"abc", 3);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    ret = shellmatta_processData(handle, (char*)"8765", 4);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    /** -# call without any argument */
+    ret = shellmatta_processData(handle, NULL, 0);
+    CHECK(SHELLMATTA_OK == ret);
+
+    /** -# continue session should be over */
+    ret = shellmatta_processData(handle, (char*)"\r", 1);
+    CHECK(SHELLMATTA_OK == ret);
+
+    CHECK( 0u  == busyCallCnt);
+    CHECK( 10u  == contCallCnt);
+    CHECK( write_length == strlen(dummyData));
+    REQUIRE( strcmp(dummyData, write_data) == 0);
+}
+
+TEST_CASE( "shellmatta continue cancel" ) {
+
+    shellmatta_retCode_t ret;
+    shellmatta_instance_t inst;
+    shellmatta_handle_t handle;
+    char buffer[1024];
+    char historyBuffer[1024];
+    char *dummyData =   (char*) "continue some arguments meow\r\n"
+                                "arguments:  length: 0\r\n"
+                                "arguments:  length: 0\r\n"
+                                "arguments: a length: 1\r\n"
+                                "arguments: b length: 1\r\n"
+                                "arguments: \x03 length: 1\r\n"
+                                "\r\n"
+                                "shellmatta->\r\n"
+                                "shellmatta->";
+
+    shellmatta_doInit(  &inst,
+                        &handle,
+                        buffer,
+                        sizeof(buffer),
+                        historyBuffer,
+                        sizeof(historyBuffer),
+                        "shellmatta->",
+                        NULL,
+                        writeFct);
+
+    contCallCnt = 0u;
+    busyCallCnt = 0u;
+    write_callCnt = 0u;
+    memset(write_data, 0, sizeof(write_data));
+    write_length = 0u;
+
+    shellmatta_addCmd(handle, &continueCmd);
+
+    ret = shellmatta_processData(handle, (char*)"continue some arguments meow\r", 29);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    /** -# call without any argument */
+    ret = shellmatta_processData(handle, NULL, 0);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    /** -# pass some argument */
+    ret = shellmatta_processData(handle, (char*)"ab", 2);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    ret = shellmatta_processData(handle, (char*)"\x03", 1);
+    CHECK(SHELLMATTA_OK == ret);
+
+    /** -# continue session should be over */
+    ret = shellmatta_processData(handle, (char*)"\r", 1);
+    CHECK(SHELLMATTA_OK == ret);
+
+    CHECK( 0u  == busyCallCnt);
+    CHECK( 5u  == contCallCnt);
+    CHECK( write_length == strlen(dummyData));
+    REQUIRE( strcmp(dummyData, write_data) == 0);
+}
+
+TEST_CASE( "shellmatta continue suspend with busy mode" ) {
+
+    shellmatta_retCode_t ret;
+    shellmatta_instance_t inst;
+    shellmatta_handle_t handle;
+    char buffer[1024];
+    char historyBuffer[1024];
+    char *dummyData =   (char*) "continue some arguments meow\r\n"
+                                "arguments:  length: 0\r\n"
+                                "arguments:  length: 0\r\n"
+                                "arguments: a length: 1\r\n"
+                                "arguments: b length: 1\r\n"
+                                "arguments: k length: 1\r\n"
+                                "arguments: k length: 1\r\n"
+                                "arguments:  length: 0\r\n"
+                                "arguments: a length: 1\r\n"
+                                "arguments: b length: 1\r\n"
+                                "arguments: c length: 1\r\n"
+                                "\r\n"
+                                "shellmatta->\r\n"
+                                "shellmatta->";
+
+    shellmatta_doInit(  &inst,
+                        &handle,
+                        buffer,
+                        sizeof(buffer),
+                        historyBuffer,
+                        sizeof(historyBuffer),
+                        "shellmatta->",
+                        NULL,
+                        writeFct);
+
+    contCallCnt = 0u;
+    busyCallCnt = 0u;
+    write_callCnt = 0u;
+    memset(write_data, 0, sizeof(write_data));
+    write_length = 0u;
+
+    shellmatta_addCmd(handle, &continueCmd);
+
+    ret = shellmatta_processData(handle, (char*)"continue some arguments meow\r", 29);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    /** -# call without any argument */
+    ret = shellmatta_processData(handle, NULL, 0);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    /** -# pass some argument */
+    ret = shellmatta_processData(handle, (char*)"ab", 2);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    ret = shellmatta_processData(handle, (char*)"k", 1);
+    CHECK(SHELLMATTA_BUSY == ret);
+
+    ret = shellmatta_processData(handle, (char*)"k", 1);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    ret = shellmatta_processData(handle, (char*)"", 0);
+    CHECK(SHELLMATTA_CONTINUE == ret);
+
+    ret = shellmatta_processData(handle, (char*)"abc", 3);
+    CHECK(SHELLMATTA_OK == ret);
+
+    /** -# continue session should be over */
+    ret = shellmatta_processData(handle, (char*)"\r", 1);
+    CHECK(SHELLMATTA_OK == ret);
+
+    CHECK( 10u  == contCallCnt);
+    CHECK( 2u  == busyCallCnt);
+    CHECK( write_length == strlen(dummyData));
+    REQUIRE( strcmp(dummyData, write_data) == 0);
+}