]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Posix_GCC/src/code_coverage_additions.c
commit 9f316c246baafa15c542a5aea81a94f26e3d6507
[freertos] / FreeRTOS / Demo / Posix_GCC / src / code_coverage_additions.c
1 /*
2  * FreeRTOS Kernel V10.3.0
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
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:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
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.
21  *
22  * http://www.FreeRTOS.org
23  * http://aws.amazon.com/freertos
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /*
29  * Contains sundry tests to exercise code that is not touched by the standard
30  * demo tasks (which are predominantly test tasks).  Some tests are incldued
31  * here because they can only be executed when configASSERT() is not defined.
32  */
33
34 #include <string.h>
35
36 #include "FreeRTOS.h"
37 #include "task.h"
38 #include "timers.h"
39 #include "event_groups.h"
40 #include "semphr.h"
41 #include "stream_buffer.h"
42 #include "message_buffer.h"
43
44 /*-----------------------------------------------------------*/
45
46 /*
47  * Try creating static objects with one of the mandatory parameters set to NULL.
48  * This can't be done in the standard demos as asserts() will get hit.
49  */
50 static BaseType_t prvStaticAllocationsWithNullBuffers( void );
51
52 /*
53  * Code coverage analysis is performed with tracing turned off, so this
54  * function executes the trace specific utility functions that would not
55  * otherwise be executed..
56  */
57 static BaseType_t prvTraceUtils( void );
58
59 /*
60  * The queue peek standard demo does not cover the case where an attempt to peek
61  * times out, so test that case.
62  */
63 static BaseType_t prvPeekTimeout( void );
64
65 /*
66  * Calls various interrupt safe functions designed to query the state of a
67  * queue.
68  */
69 static BaseType_t prvQueueQueryFromISR( void );
70
71 /*
72  * Hits a few paths in tasks state and status query functions not otherwise hit
73  * by standard demo and test files.
74  */
75 static BaseType_t prvTaskQueryFunctions( void );
76
77 /*
78  * None of the standard demo tasks use the task tags - exercise them here.
79  */
80 static BaseType_t prvTaskTags( void );
81
82 /*
83  * Exercises a few of the query functions that are not otherwise exercised in
84  * the standard demo and test functions.
85  */
86 static BaseType_t prvTimerQuery( void );
87
88 /*-----------------------------------------------------------*/
89
90 static BaseType_t prvStaticAllocationsWithNullBuffers( void )
91 {
92 uintptr_t ulReturned = 0;
93 BaseType_t xReturn = pdPASS;
94 UBaseType_t uxDummy = 10;
95
96         /* Don't expect to create any of the objects as a NULL parameter is always
97         passed in place of a required buffer.  Hence if all passes then none of the
98         |= will be against 0, and ulReturned will still be zero at the end of this
99         function. */
100         ulReturned |= ( uintptr_t ) xEventGroupCreateStatic( NULL );
101
102         /* Try creating a task twice, once with puxStackBuffer NULL, and once with
103         pxTaskBuffer NULL. */
104         ulReturned |= ( uintptr_t ) xTaskCreateStatic( NULL, /* Task to run, not needed as the task is not created. */
105                                                                                                   "Dummy", /* Task name. */
106                                                                                                   configMINIMAL_STACK_SIZE,
107                                                                                                   NULL,
108                                                                                                   tskIDLE_PRIORITY,
109                                                                                                   NULL,
110                                                                                                   ( StaticTask_t * ) &xReturn ); /* Dummy value just to pass a non NULL value in - won't get used. */
111
112         ulReturned |= ( uintptr_t ) xTaskCreateStatic( NULL, /* Task to run, not needed as the task is not created. */
113                                                                                                   "Dummy", /* Task name. */
114                                                                                                   configMINIMAL_STACK_SIZE,
115                                                                                                   NULL,
116                                                                                                   tskIDLE_PRIORITY,
117                                                                                                   ( StackType_t  * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
118                                                                                                   NULL );
119
120         ulReturned |= ( uintptr_t ) xQueueCreateStatic( uxDummy,
121                                                                                                    uxDummy,
122                                                                                                    ( uint8_t * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
123                                                                                                    NULL );
124
125         /* Try creating a stream buffer twice, once with pucStreamBufferStorageArea
126         set to NULL, and once with pxStaticStreamBuffer set to NULL. */
127         ulReturned |= ( uintptr_t ) xStreamBufferCreateStatic( uxDummy,
128                                                                                                                   uxDummy,
129                                                                                                                   NULL,
130                                                                                                                   ( StaticStreamBuffer_t  * ) &xReturn ); /* Dummy value just to pass a non NULL value in - won't get used. */
131
132         ulReturned |= ( uintptr_t ) xStreamBufferCreateStatic( uxDummy,
133                                                                                                                   uxDummy,
134                                                                                                                   ( uint8_t * ) &xReturn, /* Dummy value just to pass a non NULL value in - won't get used. */
135                                                                                                                   NULL );
136
137         if( ulReturned != 0 )
138         {
139                 /* Something returned a non-NULL value. */
140                 xReturn = pdFAIL;
141         }
142
143         return xReturn;
144 }
145 /*-----------------------------------------------------------*/
146
147 static BaseType_t prvTraceUtils( void )
148 {
149 EventGroupHandle_t xEventGroup;
150 QueueHandle_t xQueue;
151 BaseType_t xReturn = pdPASS;
152 const UBaseType_t xNumber = ( UBaseType_t ) 100, xQueueLength = ( UBaseType_t ) 1;
153 UBaseType_t uxValue;
154 TaskHandle_t xTaskHandle;
155 StreamBufferHandle_t xStreamBuffer;
156 MessageBufferHandle_t xMessageBuffer;
157
158         /* Exercise the event group trace utilities. */
159         xEventGroup = xEventGroupCreate();
160
161         if( xEventGroup != NULL )
162         {
163                 vEventGroupSetNumber( xEventGroup, xNumber );
164                 if( uxEventGroupGetNumber( NULL ) != 0 )
165                 {
166                         xReturn = pdFAIL;
167                 }
168                 if( uxEventGroupGetNumber( xEventGroup ) != xNumber )
169                 {
170                         xReturn = pdFAIL;
171                 }
172
173                 vEventGroupDelete( xEventGroup );
174         }
175         else
176         {
177                 xReturn = pdFAIL;
178         }
179
180         /* Exercise the queue trace utilities. */
181         xQueue = xQueueCreate( xQueueLength, ( UBaseType_t ) sizeof( uxValue ) );
182         if( xQueue != NULL )
183         {
184                 vQueueSetQueueNumber( xQueue, xNumber );
185                 if( uxQueueGetQueueNumber( xQueue ) != xNumber )
186                 {
187                         xReturn = pdFAIL;
188                 }
189                 if( ucQueueGetQueueType( xQueue ) != queueQUEUE_TYPE_BASE )
190                 {
191                         xReturn = pdFAIL;
192                 }
193
194                 vQueueDelete( xQueue );
195         }
196         else
197         {
198                 xReturn = pdFAIL;
199         }
200
201         /* Exercise the task trace utilities.  Value of 100 is arbitrary, just want
202         to check the value that is set is also read back. */
203         uxValue = 100;
204         xTaskHandle = xTaskGetCurrentTaskHandle();
205         vTaskSetTaskNumber( xTaskHandle, uxValue );
206         if( uxTaskGetTaskNumber( xTaskHandle ) != uxValue )
207         {
208                 xReturn = pdFAIL;
209         }
210         if( uxTaskGetTaskNumber( NULL ) != 0 )
211         {
212                 xReturn = pdFAIL;
213         }
214
215         /* Timer trace util functions are exercised in prvTimerQuery(). */
216
217
218         /* Exercise the stream buffer utilities.  Try creating with a trigger level
219         of 0, it should then get capped to 1. */
220         xStreamBuffer = xStreamBufferCreate( sizeof( uint32_t ), 0 );
221         if( xStreamBuffer != NULL )
222         {
223                 vStreamBufferSetStreamBufferNumber( xStreamBuffer, uxValue );
224                 if( uxStreamBufferGetStreamBufferNumber( xStreamBuffer ) != uxValue )
225                 {
226                         xReturn = pdFALSE;
227                 }
228                 if( ucStreamBufferGetStreamBufferType( xStreamBuffer ) != 0 )
229                 {
230                         /* "Is Message Buffer" flag should have been 0. */
231                         xReturn = pdFALSE;
232                 }
233
234                 vStreamBufferDelete( xStreamBuffer );
235         }
236         else
237         {
238                 xReturn = pdFALSE;
239         }
240
241         xMessageBuffer = xMessageBufferCreate( sizeof( uint32_t ) );
242         if( xMessageBuffer != NULL )
243         {
244                 if( ucStreamBufferGetStreamBufferType( xMessageBuffer ) == 0 )
245                 {
246                         /* "Is Message Buffer" flag should have been 1. */
247                         xReturn = pdFALSE;
248                 }
249
250                 vMessageBufferDelete( xMessageBuffer );
251         }
252         else
253         {
254                 xReturn = pdFALSE;
255         }
256
257         return xReturn;
258 }
259 /*-----------------------------------------------------------*/
260
261 static BaseType_t prvPeekTimeout( void )
262 {
263 QueueHandle_t xHandle;
264 const UBaseType_t xQueueLength = 1;
265 BaseType_t xReturn = pdPASS;
266 TickType_t xBlockTime = ( TickType_t ) 2;
267 UBaseType_t uxReceived;
268
269         /* Create the queue just to try peeking it while it is empty. */
270         xHandle = xQueueCreate( xQueueLength, ( UBaseType_t ) sizeof( xQueueLength ) );
271
272         if( xHandle != NULL )
273         {
274                 if( uxQueueMessagesWaiting( xHandle ) != 0 )
275                 {
276                         xReturn = pdFAIL;
277                 }
278
279                 /* Ensure peeking from the queue times out as the queue is empty. */
280                 if( xQueuePeek( xHandle, &uxReceived, xBlockTime ) != pdFALSE )
281                 {
282                         xReturn = pdFAIL;
283                 }
284
285                 vQueueDelete( xHandle );
286         }
287         else
288         {
289                 xReturn = pdFAIL;
290         }
291
292         return xReturn;
293 }
294 /*-----------------------------------------------------------*/
295
296 static BaseType_t prvQueueQueryFromISR( void )
297 {
298 BaseType_t xReturn = pdPASS, xValue = 1;
299 const UBaseType_t xISRQueueLength = ( UBaseType_t ) 1;
300 const char *pcISRQueueName = "ISRQueue";
301 QueueHandle_t xISRQueue = NULL;
302
303         xISRQueue = xQueueCreate( xISRQueueLength, ( UBaseType_t ) sizeof( BaseType_t ) );
304
305         if( xISRQueue != NULL )
306         {
307                 vQueueAddToRegistry( xISRQueue, pcISRQueueName );
308                 if( strcmp( pcQueueGetName( xISRQueue ), pcISRQueueName ) )
309                 {
310                         xReturn = pdFAIL;
311                 }
312
313                 /* Expect the queue to be empty here. */
314                 if(     uxQueueMessagesWaitingFromISR( xISRQueue ) != 0 )
315                 {
316                         xReturn = pdFAIL;
317                 }
318
319                 if( xQueueIsQueueEmptyFromISR( xISRQueue ) != pdTRUE )
320                 {
321                         xReturn = pdFAIL;
322                 }
323
324                 if( xQueueIsQueueFullFromISR( xISRQueue ) != pdFALSE )
325                 {
326                         xReturn = pdFAIL;
327                 }
328
329                 /* Now fill the queue - it only has one space. */
330                 if( xQueueSendFromISR( xISRQueue, &xValue, NULL ) != pdPASS )
331                 {
332                         xReturn = pdFAIL;
333                 }
334
335                 /* Check it now reports as full. */
336                 if(     uxQueueMessagesWaitingFromISR( xISRQueue ) != 1 )
337                 {
338                         xReturn = pdFAIL;
339                 }
340
341                 if( xQueueIsQueueEmptyFromISR( xISRQueue ) != pdFALSE )
342                 {
343                         xReturn = pdFAIL;
344                 }
345
346                 if( xQueueIsQueueFullFromISR( xISRQueue ) != pdTRUE )
347                 {
348                         xReturn = pdFAIL;
349                 }
350
351                 vQueueDelete( xISRQueue );
352         }
353         else
354         {
355                 xReturn = pdFAIL;
356         }
357
358         return xReturn;
359 }
360 /*-----------------------------------------------------------*/
361
362 static BaseType_t prvTaskQueryFunctions( void )
363 {
364 static TaskStatus_t xStatus, *pxStatusArray;
365 TaskHandle_t xTimerTask, xIdleTask;
366 BaseType_t xReturn = pdPASS;
367 UBaseType_t uxNumberOfTasks, uxReturned, ux;
368 uint32_t ulTotalRunTime1, ulTotalRunTime2;
369 const uint32_t ulRunTimeTollerance = ( uint32_t ) 0xfff;
370
371         /* Obtain task status with the stack high water mark and without the
372         state. */
373         vTaskGetInfo( NULL, &xStatus, pdTRUE, eRunning );
374
375         if( uxTaskGetStackHighWaterMark( NULL ) != xStatus.usStackHighWaterMark )
376         {
377                 xReturn = pdFAIL;
378         }
379
380         if( uxTaskGetStackHighWaterMark2( NULL ) != ( configSTACK_DEPTH_TYPE ) xStatus.usStackHighWaterMark )
381         {
382                 xReturn = pdFAIL;
383         }
384
385         /* Now obtain a task status without the high water mark but with the state,
386         which in the case of the idle task should be Read. */
387         xTimerTask = xTimerGetTimerDaemonTaskHandle();
388         vTaskSuspend( xTimerTask ); /* Should never suspend Timer task normally!. */
389         vTaskGetInfo( xTimerTask, &xStatus, pdFALSE, eInvalid );
390         if( xStatus.eCurrentState != eSuspended )
391         {
392                 xReturn = pdFAIL;
393         }
394         if( xStatus.uxBasePriority != uxTaskPriorityGetFromISR( xTimerTask ) )
395         {
396                 xReturn = pdFAIL;
397         }
398         if( xStatus.uxBasePriority != ( configMAX_PRIORITIES - 1 ) )
399         {
400                 xReturn = pdFAIL;
401         }
402         xTaskResumeFromISR( xTimerTask );
403         vTaskGetInfo( xTimerTask, &xStatus, pdTRUE, eInvalid );
404         if( ( xStatus.eCurrentState != eReady ) && ( xStatus.eCurrentState != eBlocked ) )
405         {
406                 xReturn = pdFAIL;
407         }
408         if( uxTaskGetStackHighWaterMark( xTimerTask ) != xStatus.usStackHighWaterMark )
409         {
410                 xReturn = pdFAIL;
411         }
412         if( uxTaskGetStackHighWaterMark2( xTimerTask ) != ( configSTACK_DEPTH_TYPE ) xStatus.usStackHighWaterMark )
413         {
414                 xReturn = pdFAIL;
415         }
416
417         /* Attempting to abort a delay in the idle task should be guaranteed to
418         fail as the idle task should never block. */
419         xIdleTask = xTaskGetIdleTaskHandle();
420         if( xTaskAbortDelay( xIdleTask ) != pdFAIL )
421         {
422                 xReturn = pdFAIL;
423         }
424
425         /* Create an array of task status objects large enough to hold information
426         on the number of tasks at this time - note this may change at any time if
427         higher priority tasks are executing and creating tasks. */
428         uxNumberOfTasks = uxTaskGetNumberOfTasks();
429         pxStatusArray = ( TaskStatus_t * ) pvPortMalloc( uxNumberOfTasks * sizeof( TaskStatus_t ) );
430
431         if( pxStatusArray != NULL )
432         {
433                 /* Pass part of the array into uxTaskGetSystemState() to ensure it doesn't
434                 try using more space than there is available. */
435                 uxReturned = uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks / ( UBaseType_t ) 2, NULL );
436                 if( uxReturned != ( UBaseType_t ) 0 )
437                 {
438                         xReturn = pdFAIL;
439                 }
440
441                 /* Now do the same but passing in the complete array size, this is done
442                 twice to check for a difference in the total run time. */
443                 uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks, &ulTotalRunTime1 );
444                 memset( ( void * ) pxStatusArray, 0xaa, uxNumberOfTasks * sizeof( TaskStatus_t ) );
445                 uxReturned = uxTaskGetSystemState( pxStatusArray, uxNumberOfTasks, &ulTotalRunTime2 );
446                 if( ( ulTotalRunTime2 - ulTotalRunTime1 ) > ulRunTimeTollerance )
447                 {
448                         xReturn = pdFAIL;
449                 }
450
451                 /* Basic santity check of array contents. */
452                 for( ux = 0; ux < uxReturned; ux++ )
453                 {
454                         if( pxStatusArray[ ux ].eCurrentState >= ( UBaseType_t ) eInvalid )
455                         {
456                                 xReturn = pdFAIL;
457                         }
458                         if( pxStatusArray[ ux ].uxCurrentPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
459                         {
460                                 xReturn = pdFAIL;
461                         }
462                 }
463
464                 vPortFree( pxStatusArray );
465         }
466         else
467         {
468                 xReturn = pdFAIL;
469         }
470
471         return xReturn;
472 }
473 /*-----------------------------------------------------------*/
474
475 static BaseType_t prvDummyTagFunction( void *pvParameter )
476 {
477         return ( BaseType_t ) pvParameter;
478 }
479 /*-----------------------------------------------------------*/
480
481 static BaseType_t prvTaskTags( void )
482 {
483 BaseType_t xReturn = pdPASS, xParameter = ( BaseType_t ) 0xDEADBEEF;
484 TaskHandle_t xTask;
485
486         /* First try with the handle of a different task.  Use the timer task for
487         convenience. */
488         xTask = xTimerGetTimerDaemonTaskHandle();
489
490         vTaskSetApplicationTaskTag( xTask, prvDummyTagFunction );
491         if( xTaskGetApplicationTaskTag( xTask ) != prvDummyTagFunction )
492         {
493                 xReturn = pdFAIL;
494         }
495         else
496         {
497                 if( xTaskCallApplicationTaskHook( xTask, ( void * ) xParameter ) != xParameter )
498                 {
499                         xReturn = pdFAIL;
500                 }
501                 if( xTaskCallApplicationTaskHook( xTask, ( void * ) NULL ) != pdFAIL )
502                 {
503                         xReturn = pdFAIL;
504                 }
505         }
506
507         /* Try FromISR version too. */
508         if( xTaskGetApplicationTaskTagFromISR( xTask ) != prvDummyTagFunction )
509         {
510                 xReturn = pdFAIL;
511         }
512
513         /* Now try with a NULL handle, so using this task. */
514         vTaskSetApplicationTaskTag( NULL, NULL );
515         if( xTaskGetApplicationTaskTag( NULL ) != NULL )
516         {
517                 xReturn = pdFAIL;
518         }
519         if( xTaskGetApplicationTaskTagFromISR( NULL ) != NULL )
520         {
521                 xReturn = pdFAIL;
522         }
523
524         vTaskSetApplicationTaskTag( NULL, prvDummyTagFunction );
525         if( xTaskGetApplicationTaskTag( NULL ) != prvDummyTagFunction )
526         {
527                 xReturn = pdFAIL;
528         }
529         else
530         {
531                 if( xTaskCallApplicationTaskHook( NULL, ( void * ) xParameter ) != xParameter )
532                 {
533                         xReturn = pdFAIL;
534                 }
535                 if( xTaskCallApplicationTaskHook( NULL, ( void * ) NULL ) != pdFAIL )
536                 {
537                         xReturn = pdFAIL;
538                 }
539         }
540
541         /* Try FromISR version too. */
542         if( xTaskGetApplicationTaskTagFromISR( NULL ) != prvDummyTagFunction )
543         {
544                 xReturn = pdFAIL;
545         }
546
547         vTaskSetApplicationTaskTag( NULL, NULL );
548         if( xTaskGetApplicationTaskTag( NULL ) != NULL )
549         {
550                 xReturn = pdFAIL;
551         }
552
553         return xReturn;
554 }
555 /*-----------------------------------------------------------*/
556
557 static BaseType_t prvTimerQuery( void )
558 {
559 TimerHandle_t xTimer;
560 BaseType_t xReturn = pdPASS;
561 const char *pcTimerName = "TestTimer";
562 const TickType_t xTimerPeriod = ( TickType_t ) 100;
563 const UBaseType_t uxTimerNumber = ( UBaseType_t ) 55;
564
565         xTimer = xTimerCreate(  pcTimerName,
566                                                         xTimerPeriod,
567                                                         pdFALSE,
568                                                         ( void * ) xTimerPeriod,
569                                                         NULL ); /* Not actually going to start timer so NULL callback is ok. */
570
571         if( xTimer != NULL )
572         {
573                 if( xTimerGetPeriod( xTimer ) != xTimerPeriod )
574                 {
575                         xReturn = pdFAIL;
576                 }
577
578                 if( strcmp( pcTimerGetName( xTimer ), pcTimerName ) != 0 )
579                 {
580                         xReturn = pdFAIL;
581                 }
582
583                 vTimerSetTimerNumber( xTimer, uxTimerNumber );
584                 if( uxTimerGetTimerNumber( xTimer ) != uxTimerNumber )
585                 {
586                         xReturn = pdFAIL;
587                 }
588
589                 xTimerDelete( xTimer, portMAX_DELAY );
590         }
591         else
592         {
593                 xReturn = pdFAIL;
594         }
595
596         return xReturn;
597 }
598 /*-----------------------------------------------------------*/
599
600 BaseType_t xRunCodeCoverageTestAdditions( void )
601 {
602 BaseType_t xReturn = pdPASS;
603
604         xReturn &= prvStaticAllocationsWithNullBuffers();
605         xReturn &= prvTraceUtils();
606         xReturn &= prvPeekTimeout();
607         xReturn &= prvQueueQueryFromISR();
608         xReturn &= prvTaskQueryFunctions();
609         xReturn &= prvTaskTags();
610         xReturn &= prvTimerQuery();
611
612         return xReturn;
613 }
614 /*-----------------------------------------------------------*/
615