3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
28 * Contains sundry tests to exercise code that is not touched by the standard
29 * demo tasks (which are predominantly test tasks). Some tests are included
30 * here because they can only be executed when configASSERT() is not defined.
36 #include "event_groups.h"
38 #include "stream_buffer.h"
39 #include "message_buffer.h"
41 /*-----------------------------------------------------------*/
44 * Try creating static objects with one of the mandatory parameters set to NULL.
45 * This can't be done in the standard demos as asserts() will get hit.
47 static BaseType_t prvStaticAllocationsWithNullBuffers( void );
50 * Code coverage analysis is performed with tracing turned off, so this
51 * function executes the trace specific utility functions that would not
52 * otherwise be executed..
54 static BaseType_t prvTraceUtils( void );
57 * The queue peek standard demo does not cover the case where an attempt to peek
58 * times out, so test that case.
60 static BaseType_t prvPeekTimeout( void );
63 * Calls various interrupt safe functions designed to query the state of a
66 static BaseType_t prvQueueQueryFromISR( void );
69 * Hits a few paths in tasks state and status query functions not otherwise hit
70 * by standard demo and test files.
72 static BaseType_t prvTaskQueryFunctions( void );
75 * None of the standard demo tasks use the task tags - exercise them here.
77 static BaseType_t prvTaskTags( void );
80 * Exercises a few of the query functions that are not otherwise exercised in
81 * the standard demo and test functions.
83 static BaseType_t prvTimerQuery( void );
85 /*-----------------------------------------------------------*/
87 static BaseType_t prvStaticAllocationsWithNullBuffers( void )
89 uint32_t ulReturned = 0;
90 BaseType_t xReturn = pdPASS;
91 UBaseType_t uxDummy = 10;
93 /* Don't expect to create any of the objects as a NULL parameter is always
94 passed in place of a required buffer. Hence if all passes then none of the
95 |= will be against 0, and ulReturned will still be zero at the end of this
97 ulReturned |= ( uint32_t ) xEventGroupCreateStatic( NULL );
99 /* Try creating a task twice, once with puxStackBuffer NULL, and once with
100 pxTaskBuffer NULL. */
101 ulReturned |= ( uint32_t ) xTaskCreateStatic( NULL, /* Task to run, not needed as the task is not created. */
102 "Dummy", /* Task name. */
103 configMINIMAL_STACK_SIZE,
107 ( StaticTask_t * ) &xReturn ); /* Dummy value just to pass a non NULL value in - won't get used. */
109 ulReturned |= ( uint32_t ) xTaskCreateStatic( NULL, /* Task to run, not needed as the task is not created. */
110 "Dummy", /* Task name. */
111 configMINIMAL_STACK_SIZE,
114 ( StackType_t * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
117 ulReturned |= ( uint32_t ) xQueueCreateStatic( uxDummy,
119 ( uint8_t * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
122 /* Try creating a stream buffer twice, once with pucStreamBufferStorageArea
123 set to NULL, and once with pxStaticStreamBuffer set to NULL. */
124 ulReturned |= ( uint32_t ) xStreamBufferCreateStatic( uxDummy,
127 ( StaticStreamBuffer_t * ) &xReturn ); /* Dummy value just to pass a non NULL value in - won't get used. */
129 ulReturned |= ( uint32_t ) xStreamBufferCreateStatic( uxDummy,
131 ( uint8_t * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
134 /* Try to create a task with a stack that is too large to be allocated. */
135 if( xTaskCreate( NULL, "TooLarge", configTOTAL_HEAP_SIZE, NULL, tskIDLE_PRIORITY, NULL ) != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY )
140 if( ulReturned != 0 )
142 /* Something returned a non-NULL value. */
148 /*-----------------------------------------------------------*/
150 static BaseType_t prvTraceUtils( void )
152 EventGroupHandle_t xEventGroup;
153 QueueHandle_t xQueue;
154 BaseType_t xReturn = pdPASS;
155 const UBaseType_t xNumber = ( UBaseType_t ) 100, xQueueLength = ( UBaseType_t ) 1;
157 TaskHandle_t xTaskHandle;
158 StreamBufferHandle_t xStreamBuffer;
159 MessageBufferHandle_t xMessageBuffer;
161 /* Exercise the event group trace utilities. */
162 xEventGroup = xEventGroupCreate();
164 if( xEventGroup != NULL )
166 vEventGroupSetNumber( xEventGroup, xNumber );
167 if( uxEventGroupGetNumber( NULL ) != 0 )
171 if( uxEventGroupGetNumber( xEventGroup ) != xNumber )
176 vEventGroupDelete( xEventGroup );
183 /* Exercise the queue trace utilities. */
184 xQueue = xQueueCreate( xQueueLength, ( UBaseType_t ) sizeof( uxValue ) );
187 vQueueSetQueueNumber( xQueue, xNumber );
188 if( uxQueueGetQueueNumber( xQueue ) != xNumber )
192 if( ucQueueGetQueueType( xQueue ) != queueQUEUE_TYPE_BASE )
197 vQueueDelete( xQueue );
204 /* Exercise the task trace utilities. Value of 100 is arbitrary, just want
205 to check the value that is set is also read back. */
207 xTaskHandle = xTaskGetCurrentTaskHandle();
208 vTaskSetTaskNumber( xTaskHandle, uxValue );
209 if( uxTaskGetTaskNumber( xTaskHandle ) != uxValue )
213 if( uxTaskGetTaskNumber( NULL ) != 0 )
218 /* Timer trace util functions are exercised in prvTimerQuery(). */
221 /* Exercise the stream buffer utilities. Try creating with a trigger level
222 of 0, it should then get capped to 1. */
223 xStreamBuffer = xStreamBufferCreate( sizeof( uint32_t ), 0 );
224 if( xStreamBuffer != NULL )
226 vStreamBufferSetStreamBufferNumber( xStreamBuffer, uxValue );
227 if( uxStreamBufferGetStreamBufferNumber( xStreamBuffer ) != uxValue )
231 if( ucStreamBufferGetStreamBufferType( xStreamBuffer ) != 0 )
233 /* "Is Message Buffer" flag should have been 0. */
237 vStreamBufferDelete( xStreamBuffer );
244 xMessageBuffer = xMessageBufferCreate( sizeof( uint32_t ) );
245 if( xMessageBuffer != NULL )
247 if( ucStreamBufferGetStreamBufferType( xMessageBuffer ) == 0 )
249 /* "Is Message Buffer" flag should have been 1. */
253 vMessageBufferDelete( xMessageBuffer );
262 /*-----------------------------------------------------------*/
264 static BaseType_t prvPeekTimeout( void )
266 QueueHandle_t xHandle;
267 const UBaseType_t xQueueLength = 1;
268 BaseType_t xReturn = pdPASS;
269 TickType_t xBlockTime = ( TickType_t ) 2;
270 UBaseType_t uxReceived;
272 /* Create the queue just to try peeking it while it is empty. */
273 xHandle = xQueueCreate( xQueueLength, ( UBaseType_t ) sizeof( xQueueLength ) );
275 if( xHandle != NULL )
277 if( uxQueueMessagesWaiting( xHandle ) != 0 )
282 /* Ensure peeking from the queue times out as the queue is empty. */
283 if( xQueuePeek( xHandle, &uxReceived, xBlockTime ) != pdFALSE )
288 vQueueDelete( xHandle );
297 /*-----------------------------------------------------------*/
299 static BaseType_t prvQueueQueryFromISR( void )
301 BaseType_t xReturn = pdPASS, xValue = 1;
302 const UBaseType_t xISRQueueLength = ( UBaseType_t ) 1;
303 const char *pcISRQueueName = "ISRQueue";
304 QueueHandle_t xISRQueue = NULL;
306 xISRQueue = xQueueCreate( xISRQueueLength, ( UBaseType_t ) sizeof( BaseType_t ) );
308 if( xISRQueue != NULL )
310 vQueueAddToRegistry( xISRQueue, pcISRQueueName );
311 if( strcmp( pcQueueGetName( xISRQueue ), pcISRQueueName ) )
316 /* Expect the queue to be empty here. */
317 if( uxQueueMessagesWaitingFromISR( xISRQueue ) != 0 )
322 if( xQueueIsQueueEmptyFromISR( xISRQueue ) != pdTRUE )
327 if( xQueueIsQueueFullFromISR( xISRQueue ) != pdFALSE )
332 /* Now fill the queue - it only has one space. */
333 if( xQueueSendFromISR( xISRQueue, &xValue, NULL ) != pdPASS )
338 /* Check it now reports as full. */
339 if( uxQueueMessagesWaitingFromISR( xISRQueue ) != 1 )
344 if( xQueueIsQueueEmptyFromISR( xISRQueue ) != pdFALSE )
349 if( xQueueIsQueueFullFromISR( xISRQueue ) != pdTRUE )
354 vQueueDelete( xISRQueue );
363 /*-----------------------------------------------------------*/
365 static BaseType_t prvTaskQueryFunctions( void )
367 static TaskStatus_t xStatus, *pxStatusArray;
368 TaskHandle_t xTimerTask, xIdleTask;
369 BaseType_t xReturn = pdPASS;
370 UBaseType_t uxNumberOfTasks, uxReturned, ux;
371 uint32_t ulTotalRunTime1, ulTotalRunTime2;
372 const uint32_t ulRunTimeTollerance = ( uint32_t ) 0xfff;
374 /* Obtain task status with the stack high water mark and without the
376 vTaskGetInfo( NULL, &xStatus, pdTRUE, eRunning );
378 if( uxTaskGetStackHighWaterMark( NULL ) != xStatus.usStackHighWaterMark )
383 if( uxTaskGetStackHighWaterMark2( NULL ) != ( configSTACK_DEPTH_TYPE ) xStatus.usStackHighWaterMark )
388 /* Now obtain a task status without the high water mark but with the state,
389 which in the case of the idle task should be Read. */
390 xTimerTask = xTimerGetTimerDaemonTaskHandle();
391 vTaskSuspend( xTimerTask ); /* Should never suspend Timer task normally!. */
392 vTaskGetInfo( xTimerTask, &xStatus, pdFALSE, eInvalid );
393 if( xStatus.eCurrentState != eSuspended )
397 if( xStatus.uxBasePriority != uxTaskPriorityGetFromISR( xTimerTask ) )
401 if( xStatus.uxBasePriority != ( configMAX_PRIORITIES - 1 ) )
405 xTaskResumeFromISR( xTimerTask );
406 vTaskGetInfo( xTimerTask, &xStatus, pdTRUE, eInvalid );
407 if( ( xStatus.eCurrentState != eReady ) && ( xStatus.eCurrentState != eBlocked ) )
411 if( uxTaskGetStackHighWaterMark( xTimerTask ) != xStatus.usStackHighWaterMark )
415 if( uxTaskGetStackHighWaterMark2( xTimerTask ) != ( configSTACK_DEPTH_TYPE ) xStatus.usStackHighWaterMark )
420 /* Attempting to abort a delay in the idle task should be guaranteed to
421 fail as the idle task should never block. */
422 xIdleTask = xTaskGetIdleTaskHandle();
423 if( xTaskAbortDelay( xIdleTask ) != pdFAIL )
428 /* Create an array of task status objects large enough to hold information
429 on the number of tasks at this time - note this may change at any time if
430 higher priority tasks are executing and creating tasks. */
431 uxNumberOfTasks = uxTaskGetNumberOfTasks();
432 pxStatusArray = ( TaskStatus_t * ) pvPortMalloc( uxNumberOfTasks * sizeof( TaskStatus_t ) );
434 if( pxStatusArray != NULL )
436 /* Pass part of the array into uxTaskGetSystemState() to ensure it doesn't
437 try using more space than there is available. */
438 uxReturned = uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks / ( UBaseType_t ) 2, NULL );
439 if( uxReturned != ( UBaseType_t ) 0 )
444 /* Now do the same but passing in the complete array size, this is done
445 twice to check for a difference in the total run time. */
446 uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks, &ulTotalRunTime1 );
447 memset( ( void * ) pxStatusArray, 0xaa, uxNumberOfTasks * sizeof( TaskStatus_t ) );
448 uxReturned = uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks, &ulTotalRunTime2 );
449 if( ( ulTotalRunTime2 - ulTotalRunTime1 ) > ulRunTimeTollerance )
454 /* Basic santity check of array contents. */
455 for( ux = 0; ux < uxReturned; ux++ )
457 if( pxStatusArray[ ux ].eCurrentState >= ( UBaseType_t ) eInvalid )
461 if( pxStatusArray[ ux ].uxCurrentPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
467 vPortFree( pxStatusArray );
476 /*-----------------------------------------------------------*/
478 static BaseType_t prvDummyTagFunction( void *pvParameter )
480 return ( BaseType_t ) pvParameter;
482 /*-----------------------------------------------------------*/
484 static BaseType_t prvTaskTags( void )
486 BaseType_t xReturn = pdPASS, xParameter = ( BaseType_t ) 0xDEADBEEF;
489 /* First try with the handle of a different task. Use the timer task for
491 xTask = xTimerGetTimerDaemonTaskHandle();
493 vTaskSetApplicationTaskTag( xTask, prvDummyTagFunction );
494 if( xTaskGetApplicationTaskTag( xTask ) != prvDummyTagFunction )
500 if( xTaskCallApplicationTaskHook( xTask, ( void * ) xParameter ) != xParameter )
504 if( xTaskCallApplicationTaskHook( xTask, ( void * ) NULL ) != pdFAIL )
510 /* Try FromISR version too. */
511 if( xTaskGetApplicationTaskTagFromISR( xTask ) != prvDummyTagFunction )
516 /* Now try with a NULL handle, so using this task. */
517 vTaskSetApplicationTaskTag( NULL, NULL );
518 if( xTaskGetApplicationTaskTag( NULL ) != NULL )
522 if( xTaskGetApplicationTaskTagFromISR( NULL ) != NULL )
527 vTaskSetApplicationTaskTag( NULL, prvDummyTagFunction );
528 if( xTaskGetApplicationTaskTag( NULL ) != prvDummyTagFunction )
534 if( xTaskCallApplicationTaskHook( NULL, ( void * ) xParameter ) != xParameter )
538 if( xTaskCallApplicationTaskHook( NULL, ( void * ) NULL ) != pdFAIL )
544 /* Try FromISR version too. */
545 if( xTaskGetApplicationTaskTagFromISR( NULL ) != prvDummyTagFunction )
550 vTaskSetApplicationTaskTag( NULL, NULL );
551 if( xTaskGetApplicationTaskTag( NULL ) != NULL )
558 /*-----------------------------------------------------------*/
560 static BaseType_t prvTimerQuery( void )
562 TimerHandle_t xTimer;
563 BaseType_t xReturn = pdPASS;
564 const char *pcTimerName = "TestTimer";
565 const TickType_t xTimerPeriod = ( TickType_t ) 100;
566 const UBaseType_t uxTimerNumber = ( UBaseType_t ) 55;
568 xTimer = xTimerCreate( pcTimerName,
571 ( void * ) xTimerPeriod,
572 NULL ); /* Not actually going to start timer so NULL callback is ok. */
576 if( xTimerGetPeriod( xTimer ) != xTimerPeriod )
581 if( strcmp( pcTimerGetName( xTimer ), pcTimerName ) != 0 )
586 vTimerSetTimerNumber( xTimer, uxTimerNumber );
587 if( uxTimerGetTimerNumber( xTimer ) != uxTimerNumber )
592 xTimerDelete( xTimer, portMAX_DELAY );
601 /*-----------------------------------------------------------*/
603 BaseType_t xRunCodeCoverageTestAdditions( void )
605 BaseType_t xReturn = pdPASS;
607 xReturn &= prvStaticAllocationsWithNullBuffers();
608 xReturn &= prvTraceUtils();
609 xReturn &= prvPeekTimeout();
610 xReturn &= prvQueueQueryFromISR();
611 xReturn &= prvTaskQueryFunctions();
612 xReturn &= prvTaskTags();
613 xReturn &= prvTimerQuery();
617 /*-----------------------------------------------------------*/