diff --git a/src/shellmatta_escape.c b/src/shellmatta_escape.c index bcb7d60..87f6a73 100644 --- a/src/shellmatta_escape.c +++ b/src/shellmatta_escape.c @@ -52,7 +52,7 @@ shellmatta_retCode_t escape_processArrowKeys(shellmatta_instance_t *inst) break; case 'B': /* arrow down */ - + /*! -# ignore the key if the history buffer points to the last entry */ if((inst->historyRead != inst->historyEnd)) { history_storeCmd(inst); diff --git a/src/shellmatta_history.c b/src/shellmatta_history.c index 0c934d4..8a6945b 100644 --- a/src/shellmatta_history.c +++ b/src/shellmatta_history.c @@ -113,21 +113,20 @@ static bool compareLastCommand(shellmatta_instance_t *inst) if(0u == i) { - i = inst->historyBufferSize; + i = (inst->historyBufferSize - 1u); } else { i --; } - if(cnt < inst->inputCount) - { - cnt ++; - } - else - { - ret = false; - } + cnt ++; + } + + /*! -# check if we are at the end of the command in the buffer - there has to be a terminating 0 */ + if(0u != inst->historyBuffer[i]) + { + ret = false; } } @@ -156,7 +155,7 @@ bool history_navigate(shellmatta_instance_t *inst, int32_t cnt) inst->historyRead ++; if(inst->historyRead >= inst->historyBufferSize) { - inst->historyRead = 0u; + inst->historyRead -= inst->historyBufferSize; } if( (inst->historyRead != inst->historyEnd) diff --git a/test/integrationtest/test_integration_history.cpp b/test/integrationtest/test_integration_history.cpp index 6a5091c..1564873 100644 --- a/test/integrationtest/test_integration_history.cpp +++ b/test/integrationtest/test_integration_history.cpp @@ -38,10 +38,10 @@ FAKE_VALUE_FUNC(shellmatta_retCode_t, cmdFct4, shellmatta_handle_t, const char * CHECK(0 == memcmp(writeFct_fake.arg0_history[(hist)], commandSequence[(idx)], strlen(commandSequence[(idx)]) - 1)); \ CHECK((strlen(commandSequence[(idx)]) - 1) == writeFct_fake.arg1_history[(hist)]); -#define UP "\x1b" "[A" -#define DOWN "\x1b" "[B" -#define PRESS_BUTTON(button) \ - CHECK(SHELLMATTA_OK == shellmatta_processData(handle, (char*)(button), 3u)); +#define BUTTON_UP "\x1b" "[A" +#define BUTTON_DOWN "\x1b" "[B" +#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}; @@ -94,7 +94,7 @@ SCENARIO("Test the history buffer with a fixed sequence of commands in there") THEN("The shellmatta prints the most recent command") { FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK(writeFct_fake.call_count == 2); CHECK(0 == memcmp(writeFct_fake.arg0_history[0], "\x1b" "[K", 3)); @@ -105,7 +105,7 @@ SCENARIO("Test the history buffer with a fixed sequence of commands in there") for(uint32_t i = CMD_SEQ_LEN - 1; i > 0; i--) { FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK(writeFct_fake.call_count == 3); @@ -122,7 +122,7 @@ SCENARIO("Test the history buffer with a fixed sequence of commands in there") { for(uint32_t i = CMD_SEQ_LEN; i > 0; i--) { - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) } AND_WHEN("The up button is pressed again") @@ -132,7 +132,7 @@ SCENARIO("Test the history buffer with a fixed sequence of commands in there") for(uint32_t i = 0u; i < 64; i++) { FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, 0u) } } @@ -145,7 +145,7 @@ SCENARIO("Test the history buffer with a fixed sequence of commands in there") for(uint32_t i = 1; i < CMD_SEQ_LEN; i++) { FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK(0 == memcmp(writeFct_fake.arg0_history[1], "\x1b" "[K", 3)); CHECK(3 == writeFct_fake.arg1_history[1]); CHECK_FOR_COMMAND(2u, i) @@ -154,87 +154,86 @@ SCENARIO("Test the history buffer with a fixed sequence of commands in there") } } - WHEN("The user pushes the up and down button alternatingly") + WHEN("The user pushes the up and down button alternately") { THEN("The output shall be updated with the correct command or not updated at all when at the end") { FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(1u, CMD_SEQ_LEN - 1u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 1u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK(writeFct_fake.call_count == 0u); FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK(writeFct_fake.call_count == 0u); FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 3u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 4u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 5u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 6u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 6u) /* back down again */ FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 5u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 4u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 3u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 1u) /* end of the buffer - shellmatta shall not update */ FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK(writeFct_fake.call_count == 0u); FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(DOWN) + PROCESS_INPUT(BUTTON_DOWN) CHECK(writeFct_fake.call_count == 0u); - /* up once mothe history buffer with a fixed sequence of commands in therere */ FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) } } @@ -248,7 +247,7 @@ SCENARIO("Test how the history buffer handles more commands than fits inside the shellmatta_instance_t inst; shellmatta_handle_t handle; char buffer[1024u]; - char historyBuffer[16u]; + char historyBuffer[16u] = {0}; CHECK(SHELLMATTA_OK == shellmatta_doInit( &inst, &handle, @@ -270,73 +269,227 @@ SCENARIO("Test how the history buffer handles more commands than fits inside the CHECK(SHELLMATTA_OK == shellmatta_processData(handle, commandSequence[i], strlen(commandSequence[i]))); } - WHEN("The user pushes the up and down button alternatingly") + WHEN("The user pushes the up and down button alternately") { THEN("The output shall be updated with the correct commands that did fit into the buffer") { FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(1u, CMD_SEQ_LEN - 1u) FFF_FAKES_LIST(RESET_FAKE) - PRESS_BUTTON(UP) + PROCESS_INPUT(BUTTON_UP) CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(DOWN) - // CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 1u) + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 3u) - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(DOWN) - // CHECK(writeFct_fake.call_count == 0u); + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 4u) - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(DOWN) - // CHECK(writeFct_fake.call_count == 0u); + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 4u) - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(UP) - // CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_DOWN) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 3u) - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(UP) - // CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 3u) + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_DOWN) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(UP) - // CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 4u) + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 3u) - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(UP) - // CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 4u) + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_DOWN) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) - // /* back down again */ - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(DOWN) - // CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 3u) + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_DOWN) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 1u) + } + } - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(DOWN) - // CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) + WHEN("A command dowes not fit into the history buffer") + { + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT("This is a very long command input\r") - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(DOWN) - // CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 1u) + THEN("The input is not stored") + { + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(1u, CMD_SEQ_LEN - 1u) - // /* end of the buffer - shellmatta shall not update */ - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(DOWN) - // CHECK(writeFct_fake.call_count == 0u); + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(DOWN) - // CHECK(writeFct_fake.call_count == 0u); + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 3u) - // /* up once mothe history buffer with a fixed sequence of commands in therere */ - // FFF_FAKES_LIST(RESET_FAKE) - // PRESS_BUTTON(UP) - // CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 4u) + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 4u) } } } -} \ No newline at end of file +} + +SCENARIO("Test if the history buffer stores changes done during navigating") +{ + GIVEN("An initialized Shellmatte instance with some commands already in the history buffer") + { + shellmatta_instance_t inst; + shellmatta_handle_t handle; + char buffer[1024u]; + char historyBuffer[16u] = {0}; + + 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)); + CHECK(SHELLMATTA_OK == shellmatta_addCmd(handle, &cmd4)); + + for(uint32_t i = 0u; i < CMD_SEQ_LEN; i++) + { + CHECK(SHELLMATTA_OK == shellmatta_processData(handle, commandSequence[i], strlen(commandSequence[i]))); + } + + WHEN("The user pushes the up and down button alternately and inputs data in between") + { + THEN("The output shall be updated with the correct commands and the input shall be stored") + { + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(1u, CMD_SEQ_LEN - 1u) + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) + + PROCESS_INPUT("\b123456") + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 3u) + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_DOWN) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 2u) + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_DOWN) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 1u) + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_DOWN) + CHECK(writeFct_fake.call_count == 3); + CHECK(0 == memcmp(writeFct_fake.arg0_history[2], "123456", 6)); + CHECK(6 == writeFct_fake.arg1_history[2]); + + PROCESS_INPUT("\r") + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 2); + CHECK(0 == memcmp(writeFct_fake.arg0_history[1], "123456", 6)); + CHECK(6 == writeFct_fake.arg1_history[1]); + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK_FOR_COMMAND(2u, CMD_SEQ_LEN - 1u) + + PROCESS_INPUT("\x03" "12345678\r") + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 2); + CHECK(0 == memcmp(writeFct_fake.arg0_history[1], "12345678", 8)); + CHECK(8 == writeFct_fake.arg1_history[1]); + + PROCESS_INPUT("\r") + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 2); + CHECK(0 == memcmp(writeFct_fake.arg0_history[1], "12345678", 8)); + CHECK(8 == writeFct_fake.arg1_history[1]); + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 3); + CHECK(0 == memcmp(writeFct_fake.arg0_history[2], "123456", 6)); + CHECK(6 == writeFct_fake.arg1_history[2]); + + /* check if the compare gets it when the new command is exactly one character longer than the stored */ + PROCESS_INPUT("\x03" "123456789\r") + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 2); + CHECK(0 == memcmp(writeFct_fake.arg0_history[1], "123456789", 9)); + CHECK(9 == writeFct_fake.arg1_history[1]); + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 3); + CHECK(0 == memcmp(writeFct_fake.arg0_history[2], "123456789", 9)); + CHECK(9 == writeFct_fake.arg1_history[2]); + + /* check if the compare gets it when the last command ist longer than the new one */ + PROCESS_INPUT("\x03" "12345678\r") + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 2); + CHECK(0 == memcmp(writeFct_fake.arg0_history[1], "12345678", 8)); + CHECK(8 == writeFct_fake.arg1_history[1]); + + + /* check what happens when there is a \0 in the buffer */ + PROCESS_INPUT("\x03" "1234" "\0" "678\r") + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 2); + CHECK(0 == memcmp(writeFct_fake.arg0_history[1], "1234", 4)); + CHECK(4 == writeFct_fake.arg1_history[1]); + + /* check what happens when there is a \0 in the buffer */ + PROCESS_INPUT("\x03" "1234" "\0" "888\r") + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 2); + CHECK(0 == memcmp(writeFct_fake.arg0_history[1], "1234", 4)); + CHECK(4 == writeFct_fake.arg1_history[1]); + + FFF_FAKES_LIST(RESET_FAKE) + PROCESS_INPUT(BUTTON_UP) + CHECK(writeFct_fake.call_count == 3); + CHECK(0 == memcmp(writeFct_fake.arg0_history[2], "888", 3)); + CHECK(3 == writeFct_fake.arg1_history[2]); + } + } + } +}