From 5222428dde58ec6d3357a389f1abe17fa91a76d5 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 10 May 2017 17:19:00 +1000 Subject: [PATCH] unit tests: Check heap integrity after each test, check for obvious leaks --- components/heap/include/esp_heap_alloc_caps.h | 2 +- .../components/unity/unity_platform.c | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/components/heap/include/esp_heap_alloc_caps.h b/components/heap/include/esp_heap_alloc_caps.h index 5338d279c3..f92e92e352 100644 --- a/components/heap/include/esp_heap_alloc_caps.h +++ b/components/heap/include/esp_heap_alloc_caps.h @@ -27,7 +27,7 @@ void *pvPortMallocCaps(size_t xWantedSize, uint32_t caps) asm("heap_caps_malloc" /* Please use heap_caps_get_minimum_free_heap_size() instead of this function */ size_t xPortGetMinimumEverFreeHeapSizeCaps( uint32_t caps ) asm("heap_caps_get_minimum_free_heap_size") __attribute__((deprecated)); -/* Please use heap_caps_get_free_heap_size() instead of this function */ +/* Please use heap_caps_get_free_size() instead of this function */ size_t xPortGetFreeHeapSizeCaps( uint32_t caps ) asm("heap_caps_get_free_heap_size") __attribute__((deprecated)); #ifdef __cplusplus diff --git a/tools/unit-test-app/components/unity/unity_platform.c b/tools/unit-test-app/components/unity/unity_platform.c index 9ee114fc67..ef985f2711 100644 --- a/tools/unit-test-app/components/unity/unity_platform.c +++ b/tools/unit-test-app/components/unity/unity_platform.c @@ -9,6 +9,7 @@ #include "freertos/task.h" #include "esp_log.h" #include "soc/cpu.h" +#include "esp_heap_caps.h" #define unity_printf ets_printf @@ -19,6 +20,63 @@ static struct test_desc_t* s_unity_tests_last = NULL; // Inverse of the filter static bool s_invert = false; + +static size_t before_free_8bit; +static size_t before_free_32bit; + +/* Each unit test is allowed to "leak" this many bytes. + + TODO: Make this value editable by the test. + + Will always need to be some value here, as fragmentation can reduce free space even when no leak is occuring. +*/ +const size_t WARN_LEAK_THRESHOLD = 256; +const size_t CRITICAL_LEAK_THRESHOLD = 4096; + +/* setUp runs before every test */ +void setUp(void) +{ + printf("%s", ""); /* sneakily lazy-allocate the reent structure for this test task */ + + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + if (before_free <= after_free) { + return; + } + size_t leaked = before_free - after_free; + if (leaked < WARN_LEAK_THRESHOLD) { + return; + } + + printf("MALLOC_CAP_%s %s leak: Before %u bytes free, After %u bytes free (delta %u)\n", + type, + leaked < CRITICAL_LEAK_THRESHOLD ? "potential" : "critical", + before_free, after_free, leaked); + fflush(stdout); + TEST_ASSERT(leaked < CRITICAL_LEAK_THRESHOLD); /* fail the test if it leaks too much */ +} + +/* tearDown runs after every test */ +void tearDown(void) +{ + /* some FreeRTOS stuff is cleaned up by idle task */ + vTaskDelay(5); + + /* check if unit test has caused heap corruption in any heap */ + TEST_ASSERT( heap_caps_check_integrity(MALLOC_CAP_INVALID, true) ); + + /* check for leaks */ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); +} + void unity_putc(int c) { if (c == '\n') -- 2.40.0