Skip to content
This repository has been archived by the owner on Dec 8, 2022. It is now read-only.

Add CLI input mode to test runner #2955

Merged
merged 15 commits into from
Jan 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,33 @@ void FreeRTOS_CLIEnterConsoleLoop( xConsoleIO_t consoleIO,
char * pOutputBuffer,
size_t outputBufferLength );


/**
* @brief Adds incoming data from console input interface (@p pConsoleInput)
* to the input command buffer (@pCommandBuffer), and if the input command is
* complete, it checks against commands registered with FreeRTOS+CLI and calls
* the matching command's handler for processing the input command.
*
* @param[in] consoleIO The console interface object for read/write operations.
* @param[in] pConsoleInput The buffer containing the data read from the console.
* @param[in] inputSize The size of the @p pConsoleInput buffer.
* @param[in, out] pCommandBuffer The buffer which represents the complete command
* entered on the console. This buffer is incrementally filled with data from
* @p pConsoleInput on each call to this function.
* @param[in] commandBufferLength The size of the @p pCommandBuffer buffer.
* @param[in, out] pCommandBufferIndex The index till where the data has been
* populated in the @p pCommandBuffer buffer.
* @param[out] pOutputBuffer This buffer is populated with the output from
* processing a command with FreeRTOS+CLI.
* @param[in] outpuBufferLength The size of the output buffer.
*/
void FreeRTOS_CLI_ProcessInputBuffer( xConsoleIO_t consoleIO,
char * pConsoleInput,
int32_t inputSize,
char * pCommandBuffer,
size_t commandBufferLength,
size_t * pCommandBufferIndex,
char * pOutputBuffer,
size_t outpuBufferLength );

#endif /* ifndef FREERTOS_CLI_CONSOLE_H */
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,7 @@ static const char * const pcNewLine = "\r\n";
static char cInputBuffer[ cmdMAX_INPUT_BUFFER_SIZE ] = "";
static char cErrorString[ cmdMAX_ERROR_SIZE ] = "";

static uint8_t ucCommandIndex = 0;

static void processInputBuffer( xConsoleIO_t consoleIO,
int32_t inputSize,
char * pCommandBuffer,
size_t commandBufferLength,
char * pOutputBuffer,
size_t outpuBufferLength );
static size_t ucCommandIndex = 0;

void FreeRTOS_CLIEnterConsoleLoop( xConsoleIO_t consoleIO,
char * pCommandBuffer,
Expand Down Expand Up @@ -86,12 +79,14 @@ void FreeRTOS_CLIEnterConsoleLoop( xConsoleIO_t consoleIO,
/* Echo back. */
consoleIO.write( cInputBuffer, bytesRead );

processInputBuffer( consoleIO,
bytesRead,
pCommandBuffer,
commandBufferLength,
pOutputBuffer,
outputBufferLength );
FreeRTOS_CLI_ProcessInputBuffer( consoleIO,
cInputBuffer,
bytesRead,
pCommandBuffer,
commandBufferLength,
&ucCommandIndex,
pOutputBuffer,
outputBufferLength );

/* Reset input buffer for next iteration. */
memset( cInputBuffer, 0x00, cmdMAX_INPUT_BUFFER_SIZE );
Expand All @@ -107,12 +102,14 @@ void FreeRTOS_CLIEnterConsoleLoop( xConsoleIO_t consoleIO,
}
}

static void processInputBuffer( xConsoleIO_t consoleIO,
int32_t inputSize,
char * pCommandBuffer,
size_t commandBufferLength,
char * pOutputBuffer,
size_t outpuBufferLength )
void FreeRTOS_CLI_ProcessInputBuffer( xConsoleIO_t consoleIO,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates some code in FreeRTOS_CLI_ProcessInputBuffer to handle the exiting the CLI loop. Can we keep code same and instead add a new command such as exit for the loop to exit gracefully.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed offline and decided that we can add a exit command support to the FreeRTOS_CLIEnterConsoleLoop function to allow the console loop to be terminated in a separate PR.

char * cInputBuffer,
int32_t inputSize,
char * pCommandBuffer,
size_t commandBufferLength,
size_t * pCommandBufferIndex,
char * pOutputBuffer,
size_t outpuBufferLength )
{
BaseType_t xReturned;
uint8_t i;
Expand All @@ -128,20 +125,20 @@ static void processInputBuffer( xConsoleIO_t consoleIO,
* passed to the command interpreter. */
if( ( cRxedChar >= ' ' ) && ( cRxedChar <= '~' ) )
{
if( ucCommandIndex < ( commandBufferLength - 1UL ) )
if( *pCommandBufferIndex < ( commandBufferLength - 1UL ) )
{
pCommandBuffer[ ucCommandIndex ] = cRxedChar;
ucCommandIndex++;
pCommandBuffer[ ucCommandIndex ] = '\0';
pCommandBuffer[ *pCommandBufferIndex ] = cRxedChar;
*pCommandBufferIndex = *pCommandBufferIndex + 1UL;
pCommandBuffer[ *pCommandBufferIndex ] = '\0';
}
}
else if( ( cRxedChar == '\b' ) || ( cRxedChar == cmdASCII_DEL ) )
{
/* Backspace was pressed. Erase the last character in the string - if any. */
if( ucCommandIndex > 0 )
if( *pCommandBufferIndex > 0 )
{
ucCommandIndex--;
pCommandBuffer[ ucCommandIndex ] = '\0';
*pCommandBufferIndex = *pCommandBufferIndex - 1UL;
pCommandBuffer[ *pCommandBufferIndex ] = '\0';
}
}
/* Was it the end of the line? */
Expand Down Expand Up @@ -178,7 +175,7 @@ static void processInputBuffer( xConsoleIO_t consoleIO,
* sent. Clear the command index to receive a new command.
* Remember the command that was just processed first in case it is
* to be processed again. */
ucCommandIndex = 0;
*pCommandBufferIndex = 0;

consoleIO.write( pcEndOfOutputMessage, strlen( pcEndOfOutputMessage ) );
}
Expand Down
13 changes: 12 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ afr_module_sources(
)
afr_module_include_dirs(
${AFR_CURRENT_MODULE}
INTERFACE "${inc_dir}"
INTERFACE
"${inc_dir}"
)
afr_module_dependencies(
${AFR_CURRENT_MODULE}
Expand All @@ -40,6 +41,16 @@ afr_module_dependencies(
AFR::common
3rdparty::unity
)

if(TARGET AFR::common_io::mcu_port)
afr_module_dependencies(
${AFR_CURRENT_MODULE}
INTERFACE
AFR::freertos_cli_plus_uart
AFR::common_io
)
endif()

if(TARGET AFR::pkcs11_implementation::mcu_port)
afr_module_dependencies(
${AFR_CURRENT_MODULE}
Expand Down
157 changes: 138 additions & 19 deletions tests/common/aws_test_runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@
/* Application version info. */
#include "aws_application_version.h"

/* Include files for UART based FreeRTOS+CLI support of test runner.
* Note: This adds a dependency on Common IO for UART communication .*/
#if defined( AWS_TEST_RUNNER_ENABLE_CLI_INPUT ) && ( AWS_TEST_RUNNER_ENABLE_CLI_INPUT == 1 )
#include <string.h>
#include "FreeRTOS_CLI.h"
#include "FreeRTOS_CLI_UART.h"
#include "iot_uart.h"
#endif

/**
* Default value of delay period before the execution of tests on device.
*/
Expand All @@ -67,7 +76,7 @@ unsigned int xHeapAfter;
* do not change the signature of it. You could, however, add or remove
* RUN_TEST_GROUP statements.
*/
static void RunTests( void )
static void RunTestSuites( void )
{
/* Tests can be disabled in aws_test_runner_config.h */

Expand Down Expand Up @@ -265,25 +274,9 @@ static void RunTests( void )
RUN_TEST_GROUP( deviceShadow_Integration );
#endif
}
/*-----------------------------------------------------------*/

void TEST_RUNNER_RunTests_task( void * pvParameters )
void RunTestsWrapper()
{
/* Disable unused parameter warning. */
( void ) pvParameters;

/* Initialize unity. */
UnityFixture.Verbose = 1;
UnityFixture.GroupFilter = 0;
UnityFixture.NameFilter = testrunnerTEST_FILTER;
UnityFixture.RepeatCount = 1;

/* Add sufficient delay before starting tests on device to allow
* device to be available as serial port connection to the host machine
* OS.
* The serial console is used by host machine to view device logs. */
vTaskDelay( pdMS_TO_TICKS( AWS_TEST_RUNNER_DELAY_MS ) );

UNITY_BEGIN();

/* Give the print buffer time to empty */
Expand All @@ -293,7 +286,7 @@ void TEST_RUNNER_RunTests_task( void * pvParameters )
xHeapBefore = xPortGetFreeHeapSize();
#endif

RunTests();
RunTestSuites();

#if ( testrunnerFULL_MEMORYLEAK_ENABLED == 1 )

Expand All @@ -313,6 +306,132 @@ void TEST_RUNNER_RunTests_task( void * pvParameters )

/* Currently disabled. Will be enabled after cleanup. */
UNITY_END();
}

/*-----------------------------------------------------------*/
#if defined( AWS_TEST_RUNNER_ENABLE_CLI_INPUT ) && ( AWS_TEST_RUNNER_ENABLE_CLI_INPUT == 1 )

/* Global flag that represents whether a "start" command is received
* on the serial console. */
static BaseType_t xReceivedCommand = pdFALSE;

/**
* @brief The command handler for the "start" command recognized by the
* serial console of the FreeRTOS test runner. On receiving the command,
* the test runner begins executing tests on the device.
*
* @return Returns pdFALSE to indicate completion of execution of tests.
*/
static BaseType_t prvRunTestsCommand( int8_t * pcWriteBuffer,
size_t xWriteBufferLen,
const int8_t * pcCommandString )
{
( void ) pcWriteBuffer;
( void ) xWriteBufferLen;
( void ) pcCommandString;

/* Set flag to indicate reception of command from serial console to start */
/* executing tests. */
xReceivedCommand = pdTRUE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An "OK" response back to the peer here will help in debugging a broken CLI connection to the actual test issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the response to acknowledge processing of command.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per offline discussion, removed the response for now as the response would be visible only at the end of the test execution. We can consider adding the response string later if there are architectural changes of running the CLI console in a different task than the test runner.


RunTestsWrapper();

return pdFALSE;
}

/* Definition of a FreeRTOS+CLI command to instruct the test runner start executing commands.
* The command takes no parameters. */
static const CLI_Command_Definition_t xStartCommand =
{
"start",
"start : Instructs test runner to start executing tests on the board.",
prvRunTestsCommand, /* The handler for the command. */
0 /* Zero number of parameters. */
};

/* Size of the buffer fot storing input command from serial console. */
#define cmdMAX_INPUT_SIZE 20

/* Size of buffer for storing output string for the serial console of test runner. */
#define cmdMAX_OUTPUT_SIZE 100

void prvTestRunnerConsole()
{
int32_t bytesRead;
int8_t serialInputChar;

static const char * const pcWelcomeMessage =
"Welcome to the Test Runner console.\r\n[Type the \"start\" command to beging executing tests]\r\n>";

/* Register the "start" command that will allow user to signal from the serial console
* about when to start execution of tests by the test runner. */
FreeRTOS_CLIRegisterCommand( &xStartCommand );

/* Print welcome message on serial console to indicate prompt for entering command. */
uartConsoleIO.write( pcWelcomeMessage, strlen( pcWelcomeMessage ) );

/* The input and output buffers are declared static to keep them off the stack. */
static int8_t pOutputBuffer[ cmdMAX_OUTPUT_SIZE ], pInputBuffer[ cmdMAX_INPUT_SIZE ], pErrorBuffer[ 30 ];
BaseType_t xErrorEncountered = pdFALSE;

while( ( xReceivedCommand == pdFALSE ) && ( xErrorEncountered == pdFALSE ) )
{
static size_t inputBufferIndex = 0;

/* Read characters to input buffer. */
bytesRead = uartConsoleIO.read( &serialInputChar, 1 );

if( bytesRead > 0 )
{
/* Echo back to the console. */
uartConsoleIO.write( &serialInputChar, bytesRead );

FreeRTOS_CLI_ProcessInputBuffer( uartConsoleIO,
&serialInputChar,
bytesRead,
pInputBuffer,
sizeof( pInputBuffer ),
&inputBufferIndex,
pOutputBuffer,
sizeof( pOutputBuffer ) );
}
else
{
snprintf( pErrorBuffer,
sizeof( pErrorBuffer ),
"Read from serial console failed. Error=%d\n",
( int ) bytesRead );
uartConsoleIO.write( pErrorBuffer, strlen( pErrorBuffer ) );

xErrorEncountered = pdTRUE;
}
}
}
#endif /* if defined( AWS_TEST_RUNNER_ENABLE_CLI_INPUT ) && ( AWS_TEST_RUNNER_ENABLE_CLI_INPUT == 1 ) */

void TEST_RUNNER_RunTests_task( void * pvParameters )
{
/* Disable unused parameter warning. */
( void ) pvParameters;

/* Initialize unity. */
UnityFixture.Verbose = 1;
UnityFixture.GroupFilter = 0;
UnityFixture.NameFilter = testrunnerTEST_FILTER;
UnityFixture.RepeatCount = 1;

#if defined( AWS_TEST_RUNNER_ENABLE_CLI_INPUT ) && ( AWS_TEST_RUNNER_ENABLE_CLI_INPUT == 1 )
prvTestRunnerConsole();
#else

/* Add sufficient delay before starting tests on device to allow
* device to be available as serial port connection to the host machine
* OS.
* The serial console is used by host machine to view device logs. */
vTaskDelay( pdMS_TO_TICKS( AWS_TEST_RUNNER_DELAY_MS ) );

RunTestsWrapper();
#endif

#ifdef CODE_COVERAGE
exit( 0 );
Expand Down
28 changes: 28 additions & 0 deletions vendors/espressif/boards/esp32/aws_tests/application_code/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
/* Test includes */
#include "aws_test_runner.h"

#include "iot_uart.h"
#include "driver/uart.h"

/* AWS library includes. */
#include "iot_system_init.h"
#include "iot_logging_task.h"
Expand Down Expand Up @@ -141,6 +144,28 @@ static void prvMiscInitialization( void );

/*-----------------------------------------------------------*/

IotUARTHandle_t xConsoleUart;

static void iot_uart_init( void )
{
IotUARTConfig_t xUartConfig;
int32_t status = IOT_UART_SUCCESS;

xConsoleUart = iot_uart_open( UART_NUM_0 );
configASSERT( xConsoleUart );

status = iot_uart_ioctl( xConsoleUart, eUartGetConfig, &xUartConfig );
configASSERT( status == IOT_UART_SUCCESS );

xUartConfig.ulBaudrate = 115200;
xUartConfig.xParity = eUartParityNone;
xUartConfig.xStopbits = eUartStopBitsOne;
xUartConfig.ucFlowControl = true;

status = iot_uart_ioctl( xConsoleUart, eUartSetConfig, &xUartConfig );
configASSERT( status == IOT_UART_SUCCESS );
}

/**
* @brief Application runtime entry point.
*/
Expand Down Expand Up @@ -198,6 +223,9 @@ int app_main( void )

static void prvMiscInitialization( void )
{
/* Initialize UART. */
iot_uart_init();

/* Initialize NVS */
esp_err_t ret = nvs_flash_init();

Expand Down
Loading