Merge branch 'feature/#20-heredoc' of shimatta/shellmatta into develop

This commit is contained in:
shimatta 2020-02-03 20:29:37 +01:00 committed by Gogs
commit 017c3c050e
20 changed files with 20451 additions and 42 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
output
output

View File

@ -91,6 +91,7 @@ typedef struct
char *buffer; /**< input buffer */
uint32_t bufferSize; /**< size of the input buffer */
uint32_t inputCount; /**< offset of the current write operation */
uint32_t lastNewlineIdx; /**< index of the lest newline */
uint32_t cursor; /**< offset where the cursor is at */
char *historyBuffer; /**< buffer to store the last commands */
uint32_t historyBufferSize; /**< size of the history buffer */
@ -100,7 +101,10 @@ typedef struct
bool historyReadUp; /**< flag to show the last history dir */
uint32_t tabCounter; /**< counts the tabulator key presses */
uint32_t escapeCounter; /**< counts the characters of an escape seq */
char escapeChars[4]; /**< buffer to save the escape characters */
char escapeChars[4u]; /**< buffer to save the escape characters */
uint32_t hereStartIdx; /**< heredoc start of "<<" */
uint32_t hereDelimiterIdx; /**< heredoc delimiter index in input */
uint32_t hereLength; /**< length of the heredoc delimiter */
bool echoEnabled; /**< if true the input is printed */
bool dirty; /**< dirty flag to show changes */
const char *prompt; /**< prompt is printed after every command */

121
example/main.c Normal file
View File

@ -0,0 +1,121 @@
/*
* main.c
*
* Created on: Jun 10, 2019
* Author: stefan
*/
#include "shellmatta.h"
#include <stdint.h>
#include <stdio.h>
#include <ncurses.h>
#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
static bool exitRequest = false;
int f;
shellmatta_handle_t handle;
void set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf ("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
printf ("error %d setting term attributes", errno);
}
static shellmatta_retCode_t doSomething(shellmatta_handle_t handle, const char *arguments, uint32_t length)
{
shellmatta_printf(handle, "%s - length: %u", arguments, length);
return SHELLMATTA_OK;
}
shellmatta_cmd_t doSomethingCmd = {"doSomething", "do", "Function does something", "use me, please", doSomething, NULL};
static shellmatta_retCode_t doSome(shellmatta_handle_t handle, const char *arguments, uint32_t length)
{
shellmatta_write(handle, "blubb\r\n", 7u);
return SHELLMATTA_OK;
}
shellmatta_cmd_t doSomeCmd = {"adoSome2", "adof2", "Function does something", "use me, please", doSome, NULL};
static shellmatta_retCode_t quit(shellmatta_handle_t handle, const char *arguments, uint32_t length)
{
exitRequest = true;
return SHELLMATTA_OK;
}
shellmatta_cmd_t quitCommand = {"quit", "q", "Function quits the shell", "", quit, NULL};
shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
write(f, data, length);
return SHELLMATTA_OK;
}
int main(void)
{
static char buffer[1024];
static char historyBuffer[4096];
static shellmatta_instance_t instance;
f = open("/dev/pts/3", O_RDWR | O_SYNC);
if (f < 0)
{
printf("failure %d\n", errno);
return f;
}
set_blocking (f, 1);
shellmatta_doInit( &instance,
&handle,
buffer,
sizeof(buffer),
historyBuffer,
sizeof(historyBuffer),
"shellmatta->",
NULL,
writeFct);
shellmatta_addCmd(handle, &doSomethingCmd);
shellmatta_addCmd(handle, &doSomeCmd);
shellmatta_addCmd(handle, &quitCommand);
while(exitRequest == false)
{
char c;
int res = 0;
res = read (f, &c, 1);
fprintf(stdout, "0x%02x \n", c);
fflush(stdout);
shellmatta_processData(handle, &c, res);
}
close(f);
return 0;
}

135
makefile Normal file
View File

@ -0,0 +1,135 @@
#
# 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/.
#
OBJ_DIR := output/
CC := gcc
CPP := g++
LN := ln
SOURCES := src/shellmatta.c \
src/shellmatta_autocomplete.c \
src/shellmatta_history.c \
src/shellmatta_utils.c \
src/shellmatta_escape.c
INCLUDES := api .
UNITTEST_SOURCES := test/unittest/test_main.cpp \
test/unittest/shellmatta_utils/test_utils_writeEcho.cpp \
test/unittest/shellmatta_utils/test_utils_shellItoa.cpp \
test/unittest/shellmatta_utils/test_utils_saveCursorPos.cpp \
test/unittest/shellmatta_utils/test_utils_restoreCursorPos.cpp \
test/unittest/shellmatta_utils/test_utils_eraseLine.cpp \
test/unittest/shellmatta_utils/test_utils_rewindCursor.cpp \
test/unittest/shellmatta_utils/test_utils_forwardCursor.cpp \
test/unittest/shellmatta_utils/test_utils_clearInput.cpp \
test/unittest/shellmatta_utils/test_utils_insertChars.cpp
INTEGRATIONTEST_SOURCES := test/integrationtest/test_main.cpp \
test/integrationtest/test_integration.cpp
UNITTEST_CPPOBJ := $(patsubst %.cpp,$(OBJ_DIR)%.o,$(UNITTEST_SOURCES))
INTEGRATIONTEST_CPPOBJ := $(patsubst %.cpp,$(OBJ_DIR)%.o,$(INTEGRATIONTEST_SOURCES))
CFLAGS := $(INCLUDES:%=-I%) -g
TESTFLAGS := $(INCLUDES:%=-I%) -g -fprofile-arcs -ftest-coverage
TESTLFLAGS := -fprofile-arcs -Wl,--allow-multiple-definition
DEPEND = -MT $@ -MF "$(@:%.o=%.d)" -MG -MM
COBJ := $(patsubst %.c,$(OBJ_DIR)%.o,$(SOURCES))
EXAMPLE_SOURCES := example/main.c
EXAMPLE_COBJ := $(patsubst %.c,$(OBJ_DIR)%.o,$(EXAMPLE_SOURCES))
EXAMPLE_TARGET := $(OBJ_DIR)example/example
UNITTEST_TARGET := $(OBJ_DIR)test/unittest/unittest
INTEGRATIONTEST_TARGET := $(OBJ_DIR)test/integrationtest/integrationtest
OBJ := $(COBJ) $(EXAMPLE_COBJ) $(UNITTEST_CPPOBJ) $(INTEGRATIONTEST_CPPOBJ)
DEPS := $(OBJ:%.o=%.d)
export
help:
@echo Shellmatta help
@echo -------------------------
@echo test - run all tests
@echo example - build example
@echo -------------------------
test: unittest integrationtest
unittest: $(UNITTEST_TARGET)
- @mkdir -p output/test/unittest/report
@echo running test:
-$(UNITTEST_TARGET)
#gcov -o output/test $(TEST_CPPOBJ) -r
gcovr --html-details --output $(OBJ_DIR)test/unittest/report/report.html output/test/unittest -f src -f api
#-rm *.gcov
integrationtest: $(INTEGRATIONTEST_TARGET)
- @mkdir -p output/test/integrationtest/report
@echo running test:
-$(INTEGRATIONTEST_TARGET)
#gcov -o output/test $(TEST_CPPOBJ) -r
gcovr --html-details --output $(OBJ_DIR)test/integrationtest/report/report.html output/test/integrationtest -f src -f api
#-rm *.gcov
example: $(EXAMPLE_TARGET)
@echo building example
doc:
- @mkdir -p output/doc/html
- @mkdir -p output/doc/latex
doxygen settings/doxygen/doxyfile
clean:
- rm -rf $(OBJ_DIR)
$(EXAMPLE_TARGET): $(COBJ) $(EXAMPLE_COBJ)
- @mkdir -p $(@D)
$(CC) $(LFLAGS) $(LIB_PATH) -o $@ $^ $(LIBS)
$(UNITTEST_TARGET): $(UNITTEST_CPPOBJ)
- @mkdir -p $(@D)
$(CPP) $(TESTLFLAGS) $(LIB_PATH) -o $@ $^ $(LIBS)
$(INTEGRATIONTEST_TARGET): $(INTEGRATIONTEST_CPPOBJ) $(COBJ)
- @mkdir -p $(@D)
$(CPP) $(TESTLFLAGS) $(LIB_PATH) -o $@ $^ $(LIBS)
$(TARGET): $(OBJ)
- @mkdir -p $(@D)
$(CC) $(LFLAGS) $(LIB_PATH) -o $@ $^ $(LIBS)
$(COBJ):
- @mkdir -p $(@D)
@$(CC) -c $(CFLAGS) $(DEPEND) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
$(CC) -c $(CFLAGS) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
$(EXAMPLE_COBJ):
- @mkdir -p $(@D)
@$(CC) -c $(CFLAGS) $(DEPEND) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
$(CC) -c $(CFLAGS) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
$(UNITTEST_CPPOBJ) $(INTEGRATIONTEST_CPPOBJ):
- @mkdir -p $(@D)
@$(CPP) -c $(TESTFLAGS) $(DEPEND) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.cpp))
$(CPP) -c $(TESTFLAGS) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.cpp))
%.o: %.cpp
- @mkdir -p $(@D)
@$(CPP) -c $(CFLAGS) $(DEPEND) -o $@ $(subst $(OBJ_DIR), ,$(@:%.o=%.c))
$(CPP) -c $(CFLAGS) -o $@ $<
-include $(DEPS)

2536
settings/doxygen/doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -74,6 +74,7 @@ shellmatta_retCode_t shellmatta_doInit(
inst->buffer = buffer;
inst->bufferSize = bufferSize;
inst->inputCount = 0u;
inst->lastNewlineIdx = 0u;
inst->cursor = 0u;
inst->historyBuffer = historyBuffer;
inst->historyBufferSize = historyBufferSize;
@ -87,6 +88,9 @@ shellmatta_retCode_t shellmatta_doInit(
inst->dirty = false;
inst->tabCounter = 0u;
inst->escapeCounter = 0u;
inst->hereStartIdx = 0u;
inst->hereDelimiterIdx = 0u;
inst->hereLength = 0u;
inst->mode = SHELLMATTA_MODE_INSERT;
inst->cmdList = &helpCmd;
inst->cmdListIsConst = false;
@ -194,6 +198,12 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
shellmatta_cmd_t *cmd;
uint8_t cmdExecuted = 0u;
uint32_t cmdLen;
char *tempString;
char *argumentString;
uint32_t argumentLength;
uint32_t byteCounter;
uint32_t idx;
shellmatta_retCode_t ret = SHELLMATTA_OK;
shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
@ -202,7 +212,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
&& (SHELLMATTA_MAGIC == inst->magic))
{
/** -# process byte wise */
for (uint32_t i = 0u; i < size; i++)
for (byteCounter = 0u; byteCounter < size; byteCounter++)
{
/** -# handle escape sequences */
if(inst->escapeCounter != 0u)
@ -218,19 +228,115 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
/** -# handle return as start of processing the command */
else if ('\r' == *data)
{
cmd = inst->cmdList;
inst->buffer[inst->inputCount] = 0u;
if(0u == inst->hereLength)
{
/**
* \dot
* digraph heredocParser {
* start -> wait [ label="<< in first line - store delimiter" ];
* wait -> wait [ label="delimiter not detected" ];
* wait -> end [ label="delimiter found - remove all heredoc stuff and send the input to the command" ];
* }
* \enddot */
/** -# check for heredoc */
tempString = strstr(inst->buffer, "<<");
if(NULL != tempString)
{
/*' -# check if length of heredoc delimiter is valid */
if(inst->inputCount > ((uint32_t)(tempString - inst->buffer) + 2u))
{
inst->hereStartIdx = (uint32_t)(tempString - inst->buffer);
inst->hereDelimiterIdx = inst->hereStartIdx + 2u;
while((inst->hereDelimiterIdx < inst->inputCount)
&& ( ('\0' == inst->buffer[inst->hereDelimiterIdx])
|| (' ' == inst->buffer[inst->hereDelimiterIdx])))
{
inst->hereDelimiterIdx ++;
}
inst->hereLength = inst->inputCount - inst->hereDelimiterIdx;
inst->dirty = true;
utils_insertChars(inst, data, 1);
inst->lastNewlineIdx = inst->inputCount;
}
else
{
inst->hereLength = 0u;
/** -# store the current command and reset the history buffer */
inst->dirty = true;
history_storeCmd(inst);
history_reset(inst);
}
}
else
{
argumentString = inst->buffer;
argumentLength = inst->inputCount;
/** -# store the current command and reset the history buffer */
inst->dirty = true;
history_storeCmd(inst);
history_reset(inst);
}
}
else
{
tempString = &inst->buffer[inst->lastNewlineIdx];
cmdLen = inst->inputCount - inst->lastNewlineIdx;
/** -# skip newline characters before comparison */
while(('\n' == *tempString) || ('\r' == *tempString))
{
tempString ++;
cmdLen --;
}
if( (inst->hereLength == cmdLen)
&& (0 == strncmp( &inst->buffer[inst->hereDelimiterIdx],
tempString,
inst->hereLength)))
{
argumentLength = inst->lastNewlineIdx;
/** -# store the current command and reset the history buffer */
inst->dirty = true;
history_storeCmd(inst);
history_reset(inst);
/* TODO it is difficult to store the complete command in the history buffer if it is restructured before...
* So this should be an extra function that can be called after parsing the command and before calling the command funktion */
for(idx = 1u; idx <= inst->hereStartIdx; idx++)
{
inst->buffer[inst->hereDelimiterIdx + inst->hereLength - idx] = inst->buffer[inst->hereStartIdx - idx];
}
argumentString = &(inst->buffer[inst->hereDelimiterIdx + inst->hereLength - inst->hereStartIdx]);
argumentLength = inst->lastNewlineIdx - ((inst->hereDelimiterIdx + inst->hereLength) - inst->hereStartIdx);
inst->hereLength = 0u;
}
else
{
inst->lastNewlineIdx = inst->inputCount;
utils_insertChars(inst, data, 1);
}
}
if(0u == inst->hereLength)
{
cmd = inst->cmdList;
argumentString[argumentLength] = 0u;
/** -# determine the cmd len (chars until first space or \0 is found */
cmdLen = 0u;
while( (cmdLen < inst->inputCount)
&& (' ' != inst->buffer[cmdLen])
&& ('\0' != inst->buffer[cmdLen]))
while( (cmdLen < argumentLength)
&& (' ' != argumentString[cmdLen])
&& ('\r' != argumentString[cmdLen])
&& ('\n' != argumentString[cmdLen])
&& ('\0' != argumentString[cmdLen]))
{
cmdLen ++;
}
@ -239,11 +345,11 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
while (NULL != cmd)
{
/** -# compare command string and length */
if ( ((0 == strncmp( inst->buffer,
if ( ((0 == strncmp( argumentString,
cmd->cmd,
cmdLen))
&& (cmdLen == strlen(cmd->cmd)))
|| ((0 == strncmp( inst->buffer,
|| ((0 == strncmp( argumentString,
cmd->cmdAlias,
cmdLen))
&& (cmdLen == strlen(cmd->cmdAlias))))
@ -251,7 +357,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
inst->write("\r\n", 2u);
cmdExecuted = 1u;
cmd->cmdFct(inst, inst->buffer, inst->inputCount);
cmd->cmdFct(inst, argumentString, argumentLength);
cmd = NULL;
}
else
@ -262,13 +368,14 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
if ((cmdExecuted == 0u) && (inst->inputCount > 0))
{
inst->buffer[inst->inputCount] = '\0';
inst->write("\r\nCommand: ", 11u);
inst->write(inst->buffer, inst->inputCount);
inst->write(argumentString, argumentLength);
inst->write(" not found", 10u);
}
utils_terminateInput(inst);
}
}
/** -# check for tabulator key - auto complete */
else if('\t' == *data)
{

View File

@ -336,6 +336,8 @@ shellmatta_cmd_t helpCmd = {"help", "h", "Print this help text", "help", helpCmd
void utils_terminateInput(shellmatta_instance_t *inst)
{
inst->inputCount = 0u;
inst->lastNewlineIdx = 0u;
inst->hereLength = 0u;
inst->cursor = 0u;
inst->write("\r\n", 2u);
inst->write(inst->prompt, strlen(inst->prompt));

16865
test/framework/catch.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,122 @@
#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 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 doSomething(shellmatta_handle_t handle, const char *arguments, uint32_t length)
{
return SHELLMATTA_OK;
}
shellmatta_cmd_t doSomethingCmd = {"doSomething", "do", "Function does something", "use me, please", doSomething, NULL};
TEST_CASE( "shellmatta empty function" ) {
shellmatta_instance_t inst;
shellmatta_handle_t handle;
char buffer[1024];
char historyBuffer[1024];
char *dummyData = "\r\nshellmatta->";
shellmatta_doInit( &inst,
&handle,
buffer,
sizeof(buffer),
historyBuffer,
sizeof(historyBuffer),
"shellmatta->",
NULL,
writeFct);
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
shellmatta_processData(handle, "\r", 1);
CHECK( write_length == 14u);
REQUIRE( strcmp(dummyData, write_data) == 0);
}
TEST_CASE( "shellmatta help function" ) {
shellmatta_instance_t inst;
shellmatta_handle_t handle;
char buffer[1024];
char historyBuffer[1024];
char *dummyData = "h\r\n"
"doSomething do Function does something use me, please\r\n"
"help h 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, &doSomethingCmd);
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
shellmatta_processData(handle, "h\r", 2);
CHECK( write_length == 123u);
CHECK( strcmp(dummyData, write_data) == 0);
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
dummyData = "h 564 321 56 465 46\r\n"
"doSomething do Function does something use me, please\r\n"
"help h Print this help text help\r\n"
"\r\nshellmatta->";
shellmatta_processData(handle, "h 564 321 56 465 46\r", 20);
CHECK( write_length == 141u);
CHECK( strcmp(dummyData, write_data) == 0);
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
dummyData = "hr\r\n"
"Command: hr not found"
"\r\nshellmatta->";
shellmatta_processData(handle, "hr\r", 3);
CHECK( write_length == 39u);
REQUIRE( strcmp(dummyData, write_data) == 0);
}

View File

@ -0,0 +1,7 @@
// 010-TestCase.cpp
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include "test/framework/catch.hpp"

View File

@ -0,0 +1,26 @@
#include "test/framework/catch.hpp"
#include "src/shellmatta_utils.c"
#include <string.h>
shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
return SHELLMATTA_OK;
}
TEST_CASE( "shellmatta_clearInput normal call" ) {
shellmatta_instance_t inst;
char buffer[20];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.write = writeFct;
utils_clearInput(&inst);
CHECK( inst.cursor == 0);
REQUIRE( inst.inputCount == 0);
}

View File

@ -0,0 +1,41 @@
#include "test/framework/catch.hpp"
#include "src/shellmatta_utils.c"
#include <string.h>
static uint32_t write_callCnt = 0u;
static char write_data[10];
static uint32_t write_length;
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
write_callCnt ++;
strncpy(write_data, data, length);
write_length = length;
return SHELLMATTA_OK;
}
TEST_CASE( "shellmatta_utils_eraseLine" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_eraseLine(&inst);
CHECK( write_callCnt == 1u);
CHECK( write_length == 3u);
REQUIRE( strncmp("\e[K", write_data, 3u) == 0);
}

View File

@ -0,0 +1,117 @@
#include "test/framework/catch.hpp"
#include "src/shellmatta_utils.c"
#include <string.h>
static uint32_t write_callCnt = 0u;
static char write_data[10];
static uint32_t write_length;
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
write_callCnt ++;
strncpy(write_data, data, length);
write_length = length;
return SHELLMATTA_OK;
}
TEST_CASE( "shellmatta_utils_forwardCursor normal" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 20;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_forwardCursor(&inst, 5u);
CHECK( write_callCnt == 1u);
CHECK( write_length == 4u);
REQUIRE( strncmp("\e[5C", write_data, 4u) == 0);
}
TEST_CASE( "shellmatta_utils_forwardCursor normal echo off" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 20;
inst.echoEnabled = false;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_forwardCursor(&inst, 5u);
CHECK( write_callCnt == 0u);
CHECK( write_length == 0u);
REQUIRE( strncmp("\0\0\0\0", write_data, 4u) == 0);
}
TEST_CASE( "shellmatta_utils_forwardCursor forward by 12 with cursor at 5 and input count at 10" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 5;
inst.inputCount = 10;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_forwardCursor(&inst, 12u);
CHECK( write_callCnt == 1u);
CHECK( write_length == 4u);
REQUIRE( strncmp("\e[5C", write_data, 4u) == 0);
}
TEST_CASE( "shellmatta_utils_forwardCursor forward by 0" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_forwardCursor(&inst, 0u);
CHECK( write_callCnt == 0u);
CHECK( write_length == 0u);
REQUIRE( strncmp("\0\0\0\0\0", write_data, 4u) == 0);
}

View File

@ -0,0 +1,27 @@
#include "test/framework/catch.hpp"
#include "src/shellmatta_utils.c"
#include <string.h>
shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
return SHELLMATTA_OK;
}
TEST_CASE( "shellmatta_insertChars normal call" ) {
shellmatta_instance_t inst;
char buffer[20];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 8;
inst.inputCount = 10;
inst.write = writeFct;
utils_insertChars(&inst, "blksdflsd kfjlk", 4);
CHECK( inst.cursor == 12);
REQUIRE( inst.inputCount == 14);
}

View File

@ -0,0 +1,41 @@
#include "test/framework/catch.hpp"
#include "src/shellmatta_utils.c"
#include <string.h>
static uint32_t write_callCnt = 0u;
static char write_data[10];
static uint32_t write_length;
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
write_callCnt ++;
strncpy(write_data, data, length);
write_length = length;
return SHELLMATTA_OK;
}
TEST_CASE( "shellmatta_utils_restoreCursorPos" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_restoreCursorPos(&inst);
CHECK( write_callCnt == 1u);
CHECK( write_length == 3u);
REQUIRE( strncmp("\e[u", write_data, 3u) == 0);
}

View File

@ -0,0 +1,92 @@
#include "test/framework/catch.hpp"
#include "src/shellmatta_utils.c"
#include <string.h>
static uint32_t write_callCnt = 0u;
static char write_data[10];
static uint32_t write_length;
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
write_callCnt ++;
strncpy(write_data, data, length);
write_length = length;
return SHELLMATTA_OK;
}
TEST_CASE( "shellmatta_utils_rewindCursor normal" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_rewindCursor(&inst, 5u);
CHECK( write_callCnt == 1u);
CHECK( write_length == 4u);
REQUIRE( strncmp("\e[5D", write_data, 4u) == 0);
}
TEST_CASE( "shellmatta_utils_rewindCursor rewind by 12 with cursor at 10" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_rewindCursor(&inst, 12u);
CHECK( write_callCnt == 1u);
CHECK( write_length == 5u);
REQUIRE( strncmp("\e[10D", write_data, 5u) == 0);
}
TEST_CASE( "shellmatta_utils_rewindCursor rewind by 0" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_rewindCursor(&inst, 0u);
CHECK( write_callCnt == 0u);
CHECK( write_length == 0u);
REQUIRE( strncmp("\0\0\0\0\0", write_data, 4u) == 0);
}

View File

@ -0,0 +1,41 @@
#include "test/framework/catch.hpp"
#include "src/shellmatta_utils.c"
#include <string.h>
static uint32_t write_callCnt = 0u;
static char write_data[10];
static uint32_t write_length;
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
write_callCnt ++;
strncpy(write_data, data, length);
write_length = length;
return SHELLMATTA_OK;
}
TEST_CASE( "shellmatta_utils_saveCursorPos" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
utils_saveCursorPos(&inst);
CHECK( write_callCnt == 1u);
CHECK( write_length == 3u);
REQUIRE( strncmp("\e[s", write_data, 3u) == 0);
}

View File

@ -0,0 +1,52 @@
#include "test/framework/catch.hpp"
#include "src/shellmatta_utils.c"
#include <string.h>
TEST_CASE( "shellmatta_utils.c - itoa - 123456 base 10" ) {
char buffer[64];
memset(buffer, 0, sizeof(buffer));
CHECK( utils_shellItoa(123456, buffer, 10) == 6 );
REQUIRE( strcmp(buffer, "123456") == 0);
}
TEST_CASE( "shellmatta_utils.c - itoa - 0x0ABBCCDD base 16") {
char buffer[64];
memset(buffer, 0, sizeof(buffer));
CHECK( utils_shellItoa(0x0ABBCCDD, buffer, 16) == 7 );
REQUIRE( strcmp(buffer, "ABBCCDD") == 0);
}
TEST_CASE( "shellmatta_utils.c - itoa - -574236 base 10") {
char buffer[64];
memset(buffer, 0, sizeof(buffer));
CHECK( utils_shellItoa(-574236, buffer, 10) == 7 );
REQUIRE( strcmp(buffer, "-574236") == 0);
}
TEST_CASE( "shellmatta_utils.c - itoa - 0x80000000 base 2") {
char buffer[64];
memset(buffer, 0, sizeof(buffer));
CHECK( utils_shellItoa(0x80000000, buffer, 2) == 33 );
REQUIRE( strcmp(buffer, "-10000000000000000000000000000000") == 0);
}
TEST_CASE( "shellmatta_utils.c - itoa - 0x7FFFFFFF base 2") {
char buffer[64];
memset(buffer, 0, sizeof(buffer));
CHECK( utils_shellItoa(0x7FFFFFFF, buffer, 2) == 31 );
REQUIRE( strcmp(buffer, "1111111111111111111111111111111") == 0);
}
TEST_CASE( "shellmatta_utils.c - itoa - 0x7FFFFFFF base 1 - wrong base") {
char buffer[64];
memset(buffer, 0, sizeof(buffer));
CHECK( utils_shellItoa(0x7FFFFFFF, buffer, 1) == 0 );
REQUIRE( strcmp(buffer, "\0") == 0);
}
TEST_CASE( "shellmatta_utils.c - itoa - 0x7FFFFFFF base 17 - wrong base") {
char buffer[64];
memset(buffer, 0, sizeof(buffer));
CHECK( utils_shellItoa(0x7FFFFFFF, buffer, 17) == 0 );
REQUIRE( strcmp(buffer, "\0") == 0);
}

View File

@ -0,0 +1,65 @@
#include "test/framework/catch.hpp"
#include "src/shellmatta_utils.c"
#include <string.h>
static uint32_t write_callCnt = 0u;
static const char *write_data;
static uint32_t write_length;
static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
write_callCnt ++;
write_data = data;
write_length = length;
return SHELLMATTA_OK;
}
TEST_CASE( "shellmatta_writeEcho echo enabled" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.echoEnabled = true;
inst.write = writeFct;
write_callCnt = 0u;
write_data = 0u;
write_length = 0u;
utils_writeEcho(&inst, (char*)&dummyData, sizeof(dummyData));
CHECK( write_callCnt == 1u );
CHECK( write_data == (char*)&dummyData );
REQUIRE( write_length == sizeof(dummyData));
}
TEST_CASE( "shellmatta_writeEcho echo disabled" ) {
shellmatta_instance_t inst;
char buffer[20];
char dummyData[29];
inst.buffer = buffer;
inst.bufferSize = 20;
inst.cursor = 10;
inst.inputCount = 10;
inst.echoEnabled = false;
inst.write = writeFct;
write_callCnt = 0u;
write_data = 0u;
write_length = 0u;
utils_writeEcho(&inst, (char*)&dummyData, sizeof(dummyData));
CHECK( write_callCnt == 0u );
CHECK( write_data == (char*)0u );
REQUIRE( write_length == 0u );
}

View File

@ -0,0 +1,7 @@
// 010-TestCase.cpp
// Let Catch provide main():
#define CATCH_CONFIG_MAIN
#include "test/framework/catch.hpp"