Add unity memory extension, fake_assert, and enable -fsanitize=address (#506)

* Enable libunitymemory extension to track dynamic memory usage during unit tests
* Use UnityMemory in timers_utest.c
* Add fake_assert.h to allow mocking of configASSERT calls
* Add .editorconfig to make github show indentation correctly
* Add unity memory and fake_assert to queue_utest.c
* Add -fsanitize=address CFLAG when running unit tests
* Define mtCOVERAGE_TEST_MARKER macro to include mtCOVERAGE_TEST_MARKER lines in coverage figures
* Add additional memory check / protection CFLAGS for CMock tests
* Fix out of bounds array access in list_utest.c
* Move the fake_assert.h include to the top of FreeRTOSConfig.h
pull/511/head^2
Paul Bartell 4 years ago committed by GitHub
parent c4d8002634
commit 570ae6bb52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,8 @@
root = true
[*]
indent_style = space
indent_size = 4
[{Makefile,**.mk,Makefile.in}]
indent_style = tab

@ -255,14 +255,15 @@ FREERTOS_IGNORED_PATTERNS = [
r'.*/Makefile',
r'.*/trcConfig\.h.*',
r'.*/trcConfig\.c.*',
r'.*/trcSnapshotConfig\.h.*',
r'.*/trcSnapshotConfig\.h.*'
]
FREERTOS_IGNORED_FILES = [
'fyi-another-way-to-ignore-file.txt',
'mbedtls_config.h',
'requirements.txt',
'run-cbmc-proofs.py'
'run-cbmc-proofs.py',
'.editorconfig'
]
FREERTOS_HEADER = [

@ -12,8 +12,10 @@ include makefile.in
all: doc coverage
execs: $(UNITS) | directories
$(UNITS) : ${LIB_DIR}/libcmock.so ${LIB_DIR}/libunity.so | directories
$(UNITS) : ${LIB_DIR}/libcmock.so \
${LIB_DIR}/libunity.so \
${LIB_DIR}/libunitymemory.so \
| directories
$(MAKE) -C $@
doc: | directories
@ -52,12 +54,20 @@ $(LIB_DIR)/libunity.so : ${UNITY_SRC_DIR}/unity.c \
Makefile | directories
${CC} -o $@ -shared -fPIC $<
$(LIB_DIR)/libunitymemory.so: ${UNITY_EXTRAS_DIR}/memory/src/unity_memory.c \
${UNITY_EXTRAS_DIR}/memory/src/unity_memory.h \
${LIB_DIR}/libunity.so \
Makefile | directories
${CC} -o $@ -shared -fPIC $< ${INCLUDE_DIR}
run : $(UNITS) directories
-rm $(BUILD_DIR)/unit_test_report.txt
for f in $(BIN_DIR)/*; do \
$${f} | tee -a $(BUILD_DIR)/unit_test_report.txt ; done
$${f} | tee -a $(BUILD_DIR)/unit_test_report.txt; \
done
cd $(BUILD_DIR) && \
ruby $(UNITY_BIN_DIR)/parse_output.rb -xml $(BUILD_DIR)/unit_test_report.txt
ruby $(UNITY_BIN_DIR)/parse_output.rb -xml \
$(BUILD_DIR)/unit_test_report.txt
run_col : $(UNITS) zero_coverage | directories
for f in $(BIN_DIR)/*; do \

@ -19,16 +19,17 @@
* 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
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include "fake_assert.h"
/*-----------------------------------------------------------
* Application specific definitions.
*
@ -114,7 +115,10 @@ functions anyway. */
/* It is a good idea to define configASSERT() while developing. configASSERT()
uses the same semantics as the standard C assert() macro. */
#define configASSERT( x )
#define configASSERT( x ) \
vFakeAssert( (bool) ( x ), __FILE__, __LINE__)
#define mtCOVERAGE_TEST_MARKER() __asm volatile( "NOP" )
#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0
#if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 )

@ -0,0 +1,37 @@
/*
* FreeRTOS V202012.00
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef FAKE_ASSERT_H
#define FAKE_ASSERT_H
/* Fake assert.h */
#include <stdbool.h>
void vFakeAssert( bool x,
char * file,
int line );
#endif /* FAKE_ASSERT_H */

@ -740,7 +740,7 @@ void test_macro_listGET_ITEM_VALUE_OF_HEAD_ENTRY( void )
initialise_list_items( pxNewListItem, 2 );
pxNewListItem[ 0 ].xItemValue = 0;
pxNewListItem[ 2 ].xItemValue = 2;
pxNewListItem[ 1 ].xItemValue = 1;
vListInsert( &pxList, &pxNewListItem[ 0 ] );
vListInsert( &pxList, &pxNewListItem[ 1 ] );
@ -762,7 +762,7 @@ void test_macro_listGET_HEAD_ENTRY( void )
initialise_list_items( pxNewListItem, 2 );
pxNewListItem[ 0 ].xItemValue = 0;
pxNewListItem[ 2 ].xItemValue = 2;
pxNewListItem[ 1 ].xItemValue = 1;
vListInsert( &pxList, &pxNewListItem[ 0 ] );
vListInsert( &pxList, &pxNewListItem[ 1 ] );
@ -784,7 +784,7 @@ void test_macro_listGET_NEXT( void )
initialise_list_items( pxNewListItem, 2 );
pxNewListItem[ 0 ].xItemValue = 0;
pxNewListItem[ 2 ].xItemValue = 2;
pxNewListItem[ 1 ].xItemValue = 1;
vListInsert( &pxList, &pxNewListItem[ 0 ] );
vListInsert( &pxList, &pxNewListItem[ 1 ] );
@ -808,7 +808,7 @@ void test_macro_listGET_END_MARKER( void )
initialise_list_items( pxNewListItem, 2 );
pxNewListItem[ 0 ].xItemValue = 0;
pxNewListItem[ 2 ].xItemValue = 2;
pxNewListItem[ 1 ].xItemValue = 1;
vListInsert( &pxList, &pxNewListItem[ 0 ] );
vListInsert( &pxList, &pxNewListItem[ 1 ] );
@ -858,7 +858,7 @@ void test_macro_listGET_OWNER_OF_HEAD_ENTRY( void )
initialise_list_items( pxNewListItem, 2 );
pxNewListItem[ 0 ].xItemValue = 0;
pxNewListItem[ 2 ].xItemValue = 2;
pxNewListItem[ 1 ].xItemValue = 1;
listSET_LIST_ITEM_OWNER( &pxNewListItem[ 0 ], owner1 );
listSET_LIST_ITEM_OWNER( &pxNewListItem[ 1 ], owner2 );

@ -23,6 +23,8 @@ UNITY_DIR := $(CMOCK_DIR)/vendor/unity
UNITY_SRC_DIR := $(UNITY_DIR)/src
UNITY_INC_DIR := $(UNITY_DIR)/src
UNITY_BIN_DIR := $(UNITY_DIR)/auto
UNITY_EXTRAS_DIR := $(UNITY_DIR)/extras
UNITY_MEM_SRC_DIR := $(UNITY_EXTRAS_DIR)/memory/src
CMOCK_EXEC_DIR := $(CMOCK_DIR)/lib
@ -30,10 +32,22 @@ CMOCK_EXEC_DIR := $(CMOCK_DIR)/lib
INCLUDE_DIR := -I$(KERNEL_DIR)/include -I. -I$(UT_ROOT_DIR)/config
INCLUDE_DIR += -I$(UNITY_INC_DIR)
INCLUDE_DIR += -I$(CMOCK_SRC_DIR)
INCLUDE_DIR += -I$(UNITY_MEM_SRC_DIR)
CPPFLAGS :=
CFLAGS := $(INCLUDE_DIR) -O0 -ggdb -pthread --std=c99 -Werror -Wall
LDFLAGS := -L$(LIB_DIR) -lunity -lcmock -Wl,-rpath,$(LIB_DIR) -pthread -lgcov
CFLAGS += -fsanitize=address,undefined -fsanitize-recover=address
CFLAGS += -fstack-protector-all
CFLAGS += -Wformat -Werror=format-security -Werror=array-bounds
CFLAGS += -D_FORTIFY_SOURCE=2
LDFLAGS := -L$(LIB_DIR) -Wl,-rpath,$(LIB_DIR)
LDFLAGS += -fsanitize=address,undefined
LDFLAGS += -pthread
LDFLAGS += -lunity
LDFLAGS += -lunitymemory
LDFLAGS += -lcmock
LDFLAGS += -lgcov
export BUILD_DIR
export DOC_DIR
@ -48,4 +62,4 @@ export CMOCK_EXEC_DIR
export KERNEL_DIR
export UNITY_BIN_DIR
export LIB_DIR
export UT_ROOT_DIR

@ -8,6 +8,7 @@ PROJECT := queue
# List the dependency files you wish to mock
MOCK_FILES_FP := $(KERNEL_DIR)/include/task.h
MOCK_FILES_FP += $(KERNEL_DIR)/include/list.h
MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_assert.h
# List the options the compilation would need
CPPFLAGS += -DportUSING_MPU_WRAPPERS=0

@ -36,23 +36,24 @@
/* Test includes. */
#include "unity.h"
#include "unity_memory.h"
/* Mock includes. */
#include "mock_task.h"
#include "mock_list.h"
#include "mock_fake_assert.h"
/* ============================ GLOBAL VARIABLES =========================== */
static uint16_t usMallocFreeCalls = 0;
/* ========================== CALLBACK FUNCTIONS =========================== */
void * pvPortMalloc( size_t xSize )
{
return malloc( xSize );
return unity_malloc( xSize );
}
void vPortFree( void * pv )
{
return free( pv );
return unity_free( pv );
}
/*******************************************************************************
@ -60,15 +61,16 @@ void vPortFree( void * pv )
******************************************************************************/
void setUp( void )
{
vFakeAssert_Ignore();
/* Track calls to malloc / free */
UnityMalloc_StartTest();
}
/*! called before each testcase */
void tearDown( void )
{
TEST_ASSERT_EQUAL_INT_MESSAGE( 0, usMallocFreeCalls,
"free is not called the same number of times as malloc,"
"you might have a memory leak!!" );
usMallocFreeCalls = 0;
UnityMalloc_EndTest();
}
/*! called at the beginning of the whole suite */
@ -92,4 +94,5 @@ void test_xQueueCreate_Success( void )
QueueHandle_t xQueue = xQueueCreate( 1, 1 );
TEST_ASSERT_NOT_EQUAL( NULL, xQueue );
vQueueDelete(xQueue);
}

@ -9,6 +9,7 @@ PROJECT := timers
MOCK_FILES_FP := $(KERNEL_DIR)/include/task.h
MOCK_FILES_FP += $(KERNEL_DIR)/include/queue.h
MOCK_FILES_FP += $(KERNEL_DIR)/include/list.h
MOCK_FILES_FP += $(UT_ROOT_DIR)/config/fake_assert.h
# List the options the compilation would need
CPPFLAGS += -DconfigSUPPORT_DYNAMIC_ALLOCATION=1

@ -34,10 +34,12 @@
#include "FreeRTOSConfig.h"
#include "timers.h"
#include "unity.h"
#include "unity_memory.h"
/* Mock includes. */
#include "mock_queue.h"
#include "mock_list.h"
#include "mock_fake_assert.h"
/* ============================ GLOBAL VARIABLES =========================== */
@ -47,11 +49,11 @@ static uint16_t usMallocFreeCalls = 0;
void * pvPortMalloc( size_t xSize )
{
return malloc( xSize );
return unity_malloc( xSize );
}
void vPortFree( void * pv )
{
return free( pv );
return unity_free( pv );
}
/*******************************************************************************
@ -59,6 +61,10 @@ void vPortFree( void * pv )
******************************************************************************/
void setUp( void )
{
vFakeAssert_Ignore();
/* Track calls to malloc / free */
UnityMalloc_StartTest();
}
/*! called before each testcase */
@ -68,6 +74,8 @@ void tearDown( void )
"free is not called the same number of times as malloc,"
"you might have a memory leak!!" );
usMallocFreeCalls = 0;
UnityMalloc_EndTest();
}
/*! called at the beginning of the whole suite */
@ -81,9 +89,9 @@ int suiteTearDown( int numFailures )
return numFailures;
}
static void _xCallback_Test( TimerHandle_t xTimer )
{}
static void xCallback_Test( TimerHandle_t xTimer )
{
}
/**
* @brief xTimerCreate happy path
@ -95,17 +103,20 @@ void test_xTimerCreate_Success( void )
TimerHandle_t xTimer = NULL;
vListInitialise_Ignore();
xQueueGenericCreateStatic_IgnoreAndReturn( (QueueHandle_t)1 );
xQueueGenericCreateStatic_IgnoreAndReturn( ( QueueHandle_t ) 1 );
vQueueAddToRegistry_Ignore();
vListInitialiseItem_Ignore();
xTimer = xTimerCreate( "ut-timer",
pdMS_TO_TICKS(1000),
pdMS_TO_TICKS( 1000 ),
pdTRUE,
&ulID,
_xCallback_Test );
xCallback_Test );
TEST_ASSERT_NOT_EQUAL( NULL, xTimer );
/* HACK: Free the timer directly */
vPortFree( ( void * ) xTimer );
}
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
@ -114,10 +125,12 @@ void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
{
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
void vApplicationDaemonTaskStartupHook( void )
{}
{
}

Loading…
Cancel
Save