feature (unity): added memory leak check API, integrated it into cxx tests

This commit is contained in:
Jakob Hasse
2022-03-31 18:16:19 +08:00
parent f3e8a17285
commit 905f5c3d41
18 changed files with 203 additions and 25 deletions
+8
View File
@@ -15,7 +15,10 @@ endif()
if(CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER)
list(APPEND srcs "unity_runner.c")
# Note the following files are not compatible with the Linux target.
# On Linux, these are masked because we also don't use the IDF test runner there
list(APPEND srcs "unity_utils_freertos.c")
list(APPEND requires "freertos")
endif()
if(CONFIG_UNITY_ENABLE_FIXTURE)
@@ -23,8 +26,13 @@ if(CONFIG_UNITY_ENABLE_FIXTURE)
list(APPEND includes "unity/extras/fixture/src")
endif()
list(APPEND srcs "unity_utils_memory.c")
if(NOT "${target}" STREQUAL "linux")
list(APPEND srcs "unity_port_esp32.c")
list(APPEND srcs "port/esp/unity_utils_memory_esp.c")
else()
list(APPEND srcs "port/linux/unity_utils_memory_linux.c")
endif()
idf_component_register(SRCS "${srcs}"
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity_test_utils_memory.h"
#ifdef __cplusplus
extern "C" {
@@ -0,0 +1,80 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Adjust the allowed memory leak thresholds for unit tests.
*
* Usually, unit tests will check if memory is leaked. Some functionality used by unit tests may unavoidably
* leak memory. This function allows to adjust that memory leak threshold.
*
* @param leak_level Maximum allowed memory leak which will not trigger a unit test failure.
*/
void unity_utils_set_leak_level(size_t leak_level);
/**
* @brief Start/Restart memory leak checking.
*
* Records the current free memory values at time of calling. After the test case, it may be checked with
* \c unity_utils_finish_and_evaluate_leaks.
*
* If this function is called repeatedly, only the free memory values at the last time of calling will prevail
* as reference.
*/
void unity_utils_record_free_mem(void);
/**
* @brief Calculate leaks and check they are below against a threshold
*
* This function is for internal use, users shouldn't have a reason to call this.
*
* Calculates the leak from \c before_free and \c after_free and checks that the difference does not exceed
* \c threshold. It uses a unity assert to to the check and report in case of failure.
* A summary of the leaked data will be printed in all cases.
*/
void unity_utils_check_leak(unsigned int before_free,
unsigned int after_free,
const char *type,
unsigned int threshold);
/**
* @brief Evaluate memory leak checking according to the provided thresholds.
*
* If the current memory leak level (counted from the last time calling \c unity_utils_record_free_mem() ) exceeds
* \c threshold, a unit test failure will be triggered.
*/
void unity_utils_evaluate_leaks_direct(size_t threshold);
/**
* @brief Evaluate memory leaks.
*
* If the current memory leak level (counted from the last time calling \c unity_utils_record_free_mem() ) exceeds
* the threshold set before via \c unity_utils_set_leak_level(), a unit test failure will be triggered.
*
* @note The user MUST set the allowed leak threshold before via \c unity_utils_set_leak_level(), otherwise the
* allowed leak threshold is undefined.
*/
void unity_utils_evaluate_leaks(void);
/**
* @brief Helper function to setup and initialize heap tracing.
*
* @param num_heap_records the size of the heap record butter,
* counted in number of heap record elements (heap_trace_record_t).
* Use a default value of 80 if no special requirements need to be met.
*/
void unity_utils_setup_heap_record(size_t num_heap_records);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_heap_caps.h"
#include "unity_test_utils.h"
#ifdef CONFIG_HEAP_TRACING
#include "esp_heap_trace.h"
#endif
static size_t s_before_free_8bit;
static size_t s_before_free_32bit;
void unity_utils_record_free_mem(void)
{
s_before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
s_before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void unity_utils_setup_heap_record(size_t num_heap_records)
{
#ifdef CONFIG_HEAP_TRACING
static heap_trace_record_t *record_buffer;
if (!record_buffer) {
record_buffer = malloc(sizeof(heap_trace_record_t) * num_heap_records);
assert(record_buffer);
heap_trace_init_standalone(record_buffer, num_heap_records);
}
#endif
}
void unity_utils_evaluate_leaks_direct(size_t threshold)
{
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);
unity_utils_check_leak(s_before_free_8bit, after_free_8bit, "8BIT", threshold);
unity_utils_check_leak(s_before_free_32bit, after_free_32bit, "32BIT", threshold);
}
@@ -0,0 +1,13 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity_test_utils.h"
void unity_utils_record_free_mem(void) { }
void unity_utils_setup_heap_record(size_t num_heap_records) { }
void unity_utils_evaluate_leaks_direct(size_t threshold) { }
+46
View File
@@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "unity.h"
#include "unity_test_utils.h"
static size_t s_allowed_leak_level;
void unity_utils_set_leak_level(size_t leak_level)
{
s_allowed_leak_level = leak_level;
}
void unity_utils_check_leak(unsigned int before_free,
unsigned int after_free,
const char *type,
unsigned int threshold)
{
int free_delta = (int)after_free - (int)before_free;
printf("MALLOC_CAP_%s usage: Free memory delta: %d Leak threshold: -%u \n",
type,
free_delta,
threshold);
if (free_delta > 0) {
return; // free memory went up somehow
}
unsigned int leaked = (size_t)(free_delta * -1);
printf("MALLOC_CAP_%s %s leak: Before %u bytes free, After %u bytes free (delta %u)\n",
type,
leaked <= threshold ? "potential" : "critical",
before_free, after_free, leaked);
fflush(stdout);
TEST_ASSERT_MESSAGE(leaked <= threshold, "The test leaked too much memory");
}
void unity_utils_evaluate_leaks(void)
{
unity_utils_evaluate_leaks_direct(s_allowed_leak_level);
}