]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/Posix_GCC/src/code_coverage_additions.c
commit 9f316c246baafa15c542a5aea81a94f26e3d6507
[freertos] / FreeRTOS / Demo / Posix_GCC / src / code_coverage_additions.c
diff --git a/FreeRTOS/Demo/Posix_GCC/src/code_coverage_additions.c b/FreeRTOS/Demo/Posix_GCC/src/code_coverage_additions.c
new file mode 100644 (file)
index 0000000..1f43a34
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * FreeRTOS Kernel V10.3.0
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+/*
+ * Contains sundry tests to exercise code that is not touched by the standard
+ * demo tasks (which are predominantly test tasks).  Some tests are incldued
+ * here because they can only be executed when configASSERT() is not defined.
+ */
+
+#include <string.h>
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "timers.h"
+#include "event_groups.h"
+#include "semphr.h"
+#include "stream_buffer.h"
+#include "message_buffer.h"
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Try creating static objects with one of the mandatory parameters set to NULL.
+ * This can't be done in the standard demos as asserts() will get hit.
+ */
+static BaseType_t prvStaticAllocationsWithNullBuffers( void );
+
+/*
+ * Code coverage analysis is performed with tracing turned off, so this
+ * function executes the trace specific utility functions that would not
+ * otherwise be executed..
+ */
+static BaseType_t prvTraceUtils( void );
+
+/*
+ * The queue peek standard demo does not cover the case where an attempt to peek
+ * times out, so test that case.
+ */
+static BaseType_t prvPeekTimeout( void );
+
+/*
+ * Calls various interrupt safe functions designed to query the state of a
+ * queue.
+ */
+static BaseType_t prvQueueQueryFromISR( void );
+
+/*
+ * Hits a few paths in tasks state and status query functions not otherwise hit
+ * by standard demo and test files.
+ */
+static BaseType_t prvTaskQueryFunctions( void );
+
+/*
+ * None of the standard demo tasks use the task tags - exercise them here.
+ */
+static BaseType_t prvTaskTags( void );
+
+/*
+ * Exercises a few of the query functions that are not otherwise exercised in
+ * the standard demo and test functions.
+ */
+static BaseType_t prvTimerQuery( void );
+
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvStaticAllocationsWithNullBuffers( void )
+{
+uintptr_t ulReturned = 0;
+BaseType_t xReturn = pdPASS;
+UBaseType_t uxDummy = 10;
+
+       /* Don't expect to create any of the objects as a NULL parameter is always
+       passed in place of a required buffer.  Hence if all passes then none of the
+       |= will be against 0, and ulReturned will still be zero at the end of this
+       function. */
+       ulReturned |= ( uintptr_t ) xEventGroupCreateStatic( NULL );
+
+       /* Try creating a task twice, once with puxStackBuffer NULL, and once with
+       pxTaskBuffer NULL. */
+       ulReturned |= ( uintptr_t ) xTaskCreateStatic( NULL, /* Task to run, not needed as the task is not created. */
+                                                                                                 "Dummy", /* Task name. */
+                                                                                                 configMINIMAL_STACK_SIZE,
+                                                                                                 NULL,
+                                                                                                 tskIDLE_PRIORITY,
+                                                                                                 NULL,
+                                                                                                 ( StaticTask_t * ) &xReturn ); /* Dummy value just to pass a non NULL value in - won't get used. */
+
+       ulReturned |= ( uintptr_t ) xTaskCreateStatic( NULL, /* Task to run, not needed as the task is not created. */
+                                                                                                 "Dummy", /* Task name. */
+                                                                                                 configMINIMAL_STACK_SIZE,
+                                                                                                 NULL,
+                                                                                                 tskIDLE_PRIORITY,
+                                                                                                 ( StackType_t  * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
+                                                                                                 NULL );
+
+       ulReturned |= ( uintptr_t ) xQueueCreateStatic( uxDummy,
+                                                                                                  uxDummy,
+                                                                                                  ( uint8_t * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
+                                                                                                  NULL );
+
+       /* Try creating a stream buffer twice, once with pucStreamBufferStorageArea
+       set to NULL, and once with pxStaticStreamBuffer set to NULL. */
+       ulReturned |= ( uintptr_t ) xStreamBufferCreateStatic( uxDummy,
+                                                                                                                 uxDummy,
+                                                                                                                 NULL,
+                                                                                                                 ( StaticStreamBuffer_t  * ) &xReturn ); /* Dummy value just to pass a non NULL value in - won't get used. */
+
+       ulReturned |= ( uintptr_t ) xStreamBufferCreateStatic( uxDummy,
+                                                                                                                 uxDummy,
+                                                                                                                 ( uint8_t * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
+                                                                                                                 NULL );
+
+       if( ulReturned != 0 )
+       {
+               /* Something returned a non-NULL value. */
+               xReturn = pdFAIL;
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvTraceUtils( void )
+{
+EventGroupHandle_t xEventGroup;
+QueueHandle_t xQueue;
+BaseType_t xReturn = pdPASS;
+const UBaseType_t xNumber = ( UBaseType_t ) 100, xQueueLength = ( UBaseType_t ) 1;
+UBaseType_t uxValue;
+TaskHandle_t xTaskHandle;
+StreamBufferHandle_t xStreamBuffer;
+MessageBufferHandle_t xMessageBuffer;
+
+       /* Exercise the event group trace utilities. */
+       xEventGroup = xEventGroupCreate();
+
+       if( xEventGroup != NULL )
+       {
+               vEventGroupSetNumber( xEventGroup, xNumber );
+               if( uxEventGroupGetNumber( NULL ) != 0 )
+               {
+                       xReturn = pdFAIL;
+               }
+               if( uxEventGroupGetNumber( xEventGroup ) != xNumber )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               vEventGroupDelete( xEventGroup );
+       }
+       else
+       {
+               xReturn = pdFAIL;
+       }
+
+       /* Exercise the queue trace utilities. */
+       xQueue = xQueueCreate( xQueueLength, ( UBaseType_t ) sizeof( uxValue ) );
+       if( xQueue != NULL )
+       {
+               vQueueSetQueueNumber( xQueue, xNumber );
+               if( uxQueueGetQueueNumber( xQueue ) != xNumber )
+               {
+                       xReturn = pdFAIL;
+               }
+               if( ucQueueGetQueueType( xQueue ) != queueQUEUE_TYPE_BASE )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               vQueueDelete( xQueue );
+       }
+       else
+       {
+               xReturn = pdFAIL;
+       }
+
+       /* Exercise the task trace utilities.  Value of 100 is arbitrary, just want
+       to check the value that is set is also read back. */
+       uxValue = 100;
+       xTaskHandle = xTaskGetCurrentTaskHandle();
+       vTaskSetTaskNumber( xTaskHandle, uxValue );
+       if( uxTaskGetTaskNumber( xTaskHandle ) != uxValue )
+       {
+               xReturn = pdFAIL;
+       }
+       if( uxTaskGetTaskNumber( NULL ) != 0 )
+       {
+               xReturn = pdFAIL;
+       }
+
+       /* Timer trace util functions are exercised in prvTimerQuery(). */
+
+
+       /* Exercise the stream buffer utilities.  Try creating with a trigger level
+       of 0, it should then get capped to 1. */
+       xStreamBuffer = xStreamBufferCreate( sizeof( uint32_t ), 0 );
+       if( xStreamBuffer != NULL )
+       {
+               vStreamBufferSetStreamBufferNumber( xStreamBuffer, uxValue );
+               if( uxStreamBufferGetStreamBufferNumber( xStreamBuffer ) != uxValue )
+               {
+                       xReturn = pdFALSE;
+               }
+               if( ucStreamBufferGetStreamBufferType( xStreamBuffer ) != 0 )
+               {
+                       /* "Is Message Buffer" flag should have been 0. */
+                       xReturn = pdFALSE;
+               }
+
+               vStreamBufferDelete( xStreamBuffer );
+       }
+       else
+       {
+               xReturn = pdFALSE;
+       }
+
+       xMessageBuffer = xMessageBufferCreate( sizeof( uint32_t ) );
+       if( xMessageBuffer != NULL )
+       {
+               if( ucStreamBufferGetStreamBufferType( xMessageBuffer ) == 0 )
+               {
+                       /* "Is Message Buffer" flag should have been 1. */
+                       xReturn = pdFALSE;
+               }
+
+               vMessageBufferDelete( xMessageBuffer );
+       }
+       else
+       {
+               xReturn = pdFALSE;
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvPeekTimeout( void )
+{
+QueueHandle_t xHandle;
+const UBaseType_t xQueueLength = 1;
+BaseType_t xReturn = pdPASS;
+TickType_t xBlockTime = ( TickType_t ) 2;
+UBaseType_t uxReceived;
+
+       /* Create the queue just to try peeking it while it is empty. */
+       xHandle = xQueueCreate( xQueueLength, ( UBaseType_t ) sizeof( xQueueLength ) );
+
+       if( xHandle != NULL )
+       {
+               if( uxQueueMessagesWaiting( xHandle ) != 0 )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               /* Ensure peeking from the queue times out as the queue is empty. */
+               if( xQueuePeek( xHandle, &uxReceived, xBlockTime ) != pdFALSE )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               vQueueDelete( xHandle );
+       }
+       else
+       {
+               xReturn = pdFAIL;
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvQueueQueryFromISR( void )
+{
+BaseType_t xReturn = pdPASS, xValue = 1;
+const UBaseType_t xISRQueueLength = ( UBaseType_t ) 1;
+const char *pcISRQueueName = "ISRQueue";
+QueueHandle_t xISRQueue = NULL;
+
+       xISRQueue = xQueueCreate( xISRQueueLength, ( UBaseType_t ) sizeof( BaseType_t ) );
+
+       if( xISRQueue != NULL )
+       {
+               vQueueAddToRegistry( xISRQueue, pcISRQueueName );
+               if( strcmp( pcQueueGetName( xISRQueue ), pcISRQueueName ) )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               /* Expect the queue to be empty here. */
+               if(     uxQueueMessagesWaitingFromISR( xISRQueue ) != 0 )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               if( xQueueIsQueueEmptyFromISR( xISRQueue ) != pdTRUE )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               if( xQueueIsQueueFullFromISR( xISRQueue ) != pdFALSE )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               /* Now fill the queue - it only has one space. */
+               if( xQueueSendFromISR( xISRQueue, &xValue, NULL ) != pdPASS )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               /* Check it now reports as full. */
+               if(     uxQueueMessagesWaitingFromISR( xISRQueue ) != 1 )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               if( xQueueIsQueueEmptyFromISR( xISRQueue ) != pdFALSE )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               if( xQueueIsQueueFullFromISR( xISRQueue ) != pdTRUE )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               vQueueDelete( xISRQueue );
+       }
+       else
+       {
+               xReturn = pdFAIL;
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvTaskQueryFunctions( void )
+{
+static TaskStatus_t xStatus, *pxStatusArray;
+TaskHandle_t xTimerTask, xIdleTask;
+BaseType_t xReturn = pdPASS;
+UBaseType_t uxNumberOfTasks, uxReturned, ux;
+uint32_t ulTotalRunTime1, ulTotalRunTime2;
+const uint32_t ulRunTimeTollerance = ( uint32_t ) 0xfff;
+
+       /* Obtain task status with the stack high water mark and without the
+       state. */
+       vTaskGetInfo( NULL, &xStatus, pdTRUE, eRunning );
+
+       if( uxTaskGetStackHighWaterMark( NULL ) != xStatus.usStackHighWaterMark )
+       {
+               xReturn = pdFAIL;
+       }
+
+       if( uxTaskGetStackHighWaterMark2( NULL ) != ( configSTACK_DEPTH_TYPE ) xStatus.usStackHighWaterMark )
+       {
+               xReturn = pdFAIL;
+       }
+
+       /* Now obtain a task status without the high water mark but with the state,
+       which in the case of the idle task should be Read. */
+       xTimerTask = xTimerGetTimerDaemonTaskHandle();
+       vTaskSuspend( xTimerTask ); /* Should never suspend Timer task normally!. */
+       vTaskGetInfo( xTimerTask, &xStatus, pdFALSE, eInvalid );
+       if( xStatus.eCurrentState != eSuspended )
+       {
+               xReturn = pdFAIL;
+       }
+       if( xStatus.uxBasePriority != uxTaskPriorityGetFromISR( xTimerTask ) )
+       {
+               xReturn = pdFAIL;
+       }
+       if( xStatus.uxBasePriority != ( configMAX_PRIORITIES - 1 ) )
+       {
+               xReturn = pdFAIL;
+       }
+       xTaskResumeFromISR( xTimerTask );
+       vTaskGetInfo( xTimerTask, &xStatus, pdTRUE, eInvalid );
+       if( ( xStatus.eCurrentState != eReady ) && ( xStatus.eCurrentState != eBlocked ) )
+       {
+               xReturn = pdFAIL;
+       }
+       if( uxTaskGetStackHighWaterMark( xTimerTask ) != xStatus.usStackHighWaterMark )
+       {
+               xReturn = pdFAIL;
+       }
+       if( uxTaskGetStackHighWaterMark2( xTimerTask ) != ( configSTACK_DEPTH_TYPE ) xStatus.usStackHighWaterMark )
+       {
+               xReturn = pdFAIL;
+       }
+
+       /* Attempting to abort a delay in the idle task should be guaranteed to
+       fail as the idle task should never block. */
+       xIdleTask = xTaskGetIdleTaskHandle();
+       if( xTaskAbortDelay( xIdleTask ) != pdFAIL )
+       {
+               xReturn = pdFAIL;
+       }
+
+       /* Create an array of task status objects large enough to hold information
+       on the number of tasks at this time - note this may change at any time if
+       higher priority tasks are executing and creating tasks. */
+       uxNumberOfTasks = uxTaskGetNumberOfTasks();
+       pxStatusArray = ( TaskStatus_t * ) pvPortMalloc( uxNumberOfTasks * sizeof( TaskStatus_t ) );
+
+       if( pxStatusArray != NULL )
+       {
+               /* Pass part of the array into uxTaskGetSystemState() to ensure it doesn't
+               try using more space than there is available. */
+               uxReturned = uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks / ( UBaseType_t ) 2, NULL );
+               if( uxReturned != ( UBaseType_t ) 0 )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               /* Now do the same but passing in the complete array size, this is done
+               twice to check for a difference in the total run time. */
+               uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks, &ulTotalRunTime1 );
+               memset( ( void * ) pxStatusArray, 0xaa, uxNumberOfTasks * sizeof( TaskStatus_t ) );
+               uxReturned = uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks, &ulTotalRunTime2 );
+               if( ( ulTotalRunTime2 - ulTotalRunTime1 ) > ulRunTimeTollerance )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               /* Basic santity check of array contents. */
+               for( ux = 0; ux < uxReturned; ux++ )
+               {
+                       if( pxStatusArray[ ux ].eCurrentState >= ( UBaseType_t ) eInvalid )
+                       {
+                               xReturn = pdFAIL;
+                       }
+                       if( pxStatusArray[ ux ].uxCurrentPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
+                       {
+                               xReturn = pdFAIL;
+                       }
+               }
+
+               vPortFree( pxStatusArray );
+       }
+       else
+       {
+               xReturn = pdFAIL;
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvDummyTagFunction( void *pvParameter )
+{
+       return ( BaseType_t ) pvParameter;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvTaskTags( void )
+{
+BaseType_t xReturn = pdPASS, xParameter = ( BaseType_t ) 0xDEADBEEF;
+TaskHandle_t xTask;
+
+       /* First try with the handle of a different task.  Use the timer task for
+       convenience. */
+       xTask = xTimerGetTimerDaemonTaskHandle();
+
+       vTaskSetApplicationTaskTag( xTask, prvDummyTagFunction );
+       if( xTaskGetApplicationTaskTag( xTask ) != prvDummyTagFunction )
+       {
+               xReturn = pdFAIL;
+       }
+       else
+       {
+               if( xTaskCallApplicationTaskHook( xTask, ( void * ) xParameter ) != xParameter )
+               {
+                       xReturn = pdFAIL;
+               }
+               if( xTaskCallApplicationTaskHook( xTask, ( void * ) NULL ) != pdFAIL )
+               {
+                       xReturn = pdFAIL;
+               }
+       }
+
+       /* Try FromISR version too. */
+       if( xTaskGetApplicationTaskTagFromISR( xTask ) != prvDummyTagFunction )
+       {
+               xReturn = pdFAIL;
+       }
+
+       /* Now try with a NULL handle, so using this task. */
+       vTaskSetApplicationTaskTag( NULL, NULL );
+       if( xTaskGetApplicationTaskTag( NULL ) != NULL )
+       {
+               xReturn = pdFAIL;
+       }
+       if( xTaskGetApplicationTaskTagFromISR( NULL ) != NULL )
+       {
+               xReturn = pdFAIL;
+       }
+
+       vTaskSetApplicationTaskTag( NULL, prvDummyTagFunction );
+       if( xTaskGetApplicationTaskTag( NULL ) != prvDummyTagFunction )
+       {
+               xReturn = pdFAIL;
+       }
+       else
+       {
+               if( xTaskCallApplicationTaskHook( NULL, ( void * ) xParameter ) != xParameter )
+               {
+                       xReturn = pdFAIL;
+               }
+               if( xTaskCallApplicationTaskHook( NULL, ( void * ) NULL ) != pdFAIL )
+               {
+                       xReturn = pdFAIL;
+               }
+       }
+
+       /* Try FromISR version too. */
+       if( xTaskGetApplicationTaskTagFromISR( NULL ) != prvDummyTagFunction )
+       {
+               xReturn = pdFAIL;
+       }
+
+       vTaskSetApplicationTaskTag( NULL, NULL );
+       if( xTaskGetApplicationTaskTag( NULL ) != NULL )
+       {
+               xReturn = pdFAIL;
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvTimerQuery( void )
+{
+TimerHandle_t xTimer;
+BaseType_t xReturn = pdPASS;
+const char *pcTimerName = "TestTimer";
+const TickType_t xTimerPeriod = ( TickType_t ) 100;
+const UBaseType_t uxTimerNumber = ( UBaseType_t ) 55;
+
+       xTimer = xTimerCreate(  pcTimerName,
+                                                       xTimerPeriod,
+                                                       pdFALSE,
+                                                       ( void * ) xTimerPeriod,
+                                                       NULL ); /* Not actually going to start timer so NULL callback is ok. */
+
+       if( xTimer != NULL )
+       {
+               if( xTimerGetPeriod( xTimer ) != xTimerPeriod )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               if( strcmp( pcTimerGetName( xTimer ), pcTimerName ) != 0 )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               vTimerSetTimerNumber( xTimer, uxTimerNumber );
+               if( uxTimerGetTimerNumber( xTimer ) != uxTimerNumber )
+               {
+                       xReturn = pdFAIL;
+               }
+
+               xTimerDelete( xTimer, portMAX_DELAY );
+       }
+       else
+       {
+               xReturn = pdFAIL;
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xRunCodeCoverageTestAdditions( void )
+{
+BaseType_t xReturn = pdPASS;
+
+       xReturn &= prvStaticAllocationsWithNullBuffers();
+       xReturn &= prvTraceUtils();
+       xReturn &= prvPeekTimeout();
+       xReturn &= prvQueueQueryFromISR();
+       xReturn &= prvTaskQueryFunctions();
+       xReturn &= prvTaskTags();
+       xReturn &= prvTimerQuery();
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+