mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'refactor/test_utils_memory_check' into 'master'
memory leak detection functions now in separate file See merge request espressif/esp-idf!16011
This commit is contained in:
commit
9ee974e626
@ -4,7 +4,7 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "test_utils.h"
|
#include "memory_checks.h"
|
||||||
#include "esp_tls.h"
|
#include "esp_tls.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
@ -75,7 +75,7 @@ static void test_leak_setup(const char *file, long line)
|
|||||||
const uint8_t input_buffer[64];
|
const uint8_t input_buffer[64];
|
||||||
uint8_t output_buffer[64];
|
uint8_t output_buffer[64];
|
||||||
esp_sha(SHA2_512, input_buffer, sizeof(input_buffer), output_buffer);
|
esp_sha(SHA2_512, input_buffer, sizeof(input_buffer), output_buffer);
|
||||||
unity_reset_leak_checks();
|
test_utils_record_free_mem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,28 +1,26 @@
|
|||||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
// You may obtain a copy of the License at
|
*
|
||||||
//
|
* This test code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
*
|
||||||
//
|
* Unless required by applicable law or agreed to in writing, this
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
* CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*/
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <esp_websocket_client.h>
|
#include <esp_websocket_client.h>
|
||||||
|
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "test_utils.h"
|
#include "memory_checks.h"
|
||||||
|
|
||||||
static void test_leak_setup(const char * file, long line)
|
static void test_leak_setup(const char * file, long line)
|
||||||
{
|
{
|
||||||
printf("%s:%ld\n", file, line);
|
printf("%s:%ld\n", file, line);
|
||||||
unity_reset_leak_checks();
|
test_utils_record_free_mem();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("websocket init and deinit", "[websocket][leaks=0]")
|
TEST_CASE("websocket init and deinit", "[websocket][leaks=0]")
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
Tests for the Wi-Fi
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
*/
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*
|
||||||
|
* This test code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, this
|
||||||
|
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
* CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "esp_system.h"
|
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
@ -11,6 +19,7 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
|
#include "memory_checks.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
|
|
||||||
@ -190,7 +199,7 @@ static void start_wifi_as_softap(void)
|
|||||||
event_init();
|
event_init();
|
||||||
|
|
||||||
// can't deinit event loop, need to reset leak check
|
// can't deinit event loop, need to reset leak check
|
||||||
unity_reset_leak_checks();
|
test_utils_record_free_mem();
|
||||||
|
|
||||||
if (wifi_events == NULL) {
|
if (wifi_events == NULL) {
|
||||||
wifi_events = xEventGroupCreate();
|
wifi_events = xEventGroupCreate();
|
||||||
@ -212,7 +221,7 @@ static void start_wifi_as_sta(void)
|
|||||||
event_init();
|
event_init();
|
||||||
|
|
||||||
// can't deinit event loop, need to reset leak check
|
// can't deinit event loop, need to reset leak check
|
||||||
unity_reset_leak_checks();
|
test_utils_record_free_mem();
|
||||||
|
|
||||||
if (wifi_events == NULL) {
|
if (wifi_events == NULL) {
|
||||||
wifi_events = xEventGroupCreate();
|
wifi_events = xEventGroupCreate();
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*
|
||||||
|
* This test code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, this
|
||||||
|
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
* CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
|
#include "memory_checks.h"
|
||||||
#include "mqtt_client.h"
|
#include "mqtt_client.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "esp_ota_ops.h"
|
#include "esp_ota_ops.h"
|
||||||
@ -17,7 +30,7 @@ static void test_leak_setup(const char * file, long line)
|
|||||||
gettimeofday(&te, NULL); // get current time
|
gettimeofday(&te, NULL); // get current time
|
||||||
esp_read_mac(mac, ESP_MAC_WIFI_STA);
|
esp_read_mac(mac, ESP_MAC_WIFI_STA);
|
||||||
printf("%s:%ld: time=%ld.%lds, mac:" MACSTR "\n", file, line, te.tv_sec, te.tv_usec, MAC2STR(mac));
|
printf("%s:%ld: time=%ld.%lds, mac:" MACSTR "\n", file, line, te.tv_sec, te.tv_usec, MAC2STR(mac));
|
||||||
unity_reset_leak_checks();
|
test_utils_record_free_mem();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("mqtt init with invalid url", "[mqtt][leaks=0]")
|
TEST_CASE("mqtt init with invalid url", "[mqtt][leaks=0]")
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
// You may obtain a copy of the License at
|
*
|
||||||
|
* This test code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
*
|
||||||
//
|
* Unless required by applicable law or agreed to in writing, this
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
* CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
*/
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
@ -23,6 +21,7 @@
|
|||||||
#include "../esp_supplicant/src/esp_wifi_driver.h"
|
#include "../esp_supplicant/src/esp_wifi_driver.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
|
#include "memory_checks.h"
|
||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
|
|
||||||
#define WIFI_START_EVENT 0x00000001
|
#define WIFI_START_EVENT 0x00000001
|
||||||
@ -87,7 +86,7 @@ static void start_wifi_as_sta(void)
|
|||||||
event_init();
|
event_init();
|
||||||
|
|
||||||
// can't deinit event loop, need to reset leak check
|
// can't deinit event loop, need to reset leak check
|
||||||
unity_reset_leak_checks();
|
test_utils_record_free_mem();
|
||||||
|
|
||||||
if (wifi_event == NULL) {
|
if (wifi_event == NULL) {
|
||||||
wifi_event = xEventGroupCreate();
|
wifi_event = xEventGroupCreate();
|
||||||
|
@ -823,7 +823,6 @@ components/esp_timer/test/test_esp_timer_light_sleep.c
|
|||||||
components/esp_timer/test/test_ets_timer.c
|
components/esp_timer/test/test_ets_timer.c
|
||||||
components/esp_websocket_client/esp_websocket_client.c
|
components/esp_websocket_client/esp_websocket_client.c
|
||||||
components/esp_websocket_client/include/esp_websocket_client.h
|
components/esp_websocket_client/include/esp_websocket_client.h
|
||||||
components/esp_websocket_client/test/test_websocket_client.c
|
|
||||||
components/esp_wifi/include/esp_coexist_adapter.h
|
components/esp_wifi/include/esp_coexist_adapter.h
|
||||||
components/esp_wifi/include/esp_mesh.h
|
components/esp_wifi/include/esp_mesh.h
|
||||||
components/esp_wifi/include/esp_mesh_internal.h
|
components/esp_wifi/include/esp_mesh_internal.h
|
||||||
@ -839,7 +838,6 @@ components/esp_wifi/src/lib_printf.c
|
|||||||
components/esp_wifi/src/mesh_event.c
|
components/esp_wifi/src/mesh_event.c
|
||||||
components/esp_wifi/src/smartconfig.c
|
components/esp_wifi/src/smartconfig.c
|
||||||
components/esp_wifi/src/smartconfig_ack.c
|
components/esp_wifi/src/smartconfig_ack.c
|
||||||
components/esp_wifi/test/test_wifi.c
|
|
||||||
components/esp_wifi/test/test_wifi_init.c
|
components/esp_wifi/test/test_wifi_init.c
|
||||||
components/espcoredump/corefile/__init__.py
|
components/espcoredump/corefile/__init__.py
|
||||||
components/espcoredump/corefile/_parse_soc_header.py
|
components/espcoredump/corefile/_parse_soc_header.py
|
||||||
@ -1426,7 +1424,6 @@ components/mqtt/host_test/mocks/include/freertos/FreeRTOSConfig.h
|
|||||||
components/mqtt/host_test/mocks/include/freertos/portmacro.h
|
components/mqtt/host_test/mocks/include/freertos/portmacro.h
|
||||||
components/mqtt/host_test/mocks/include/machine/endian.h
|
components/mqtt/host_test/mocks/include/machine/endian.h
|
||||||
components/mqtt/host_test/mocks/include/sys/queue.h
|
components/mqtt/host_test/mocks/include/sys/queue.h
|
||||||
components/mqtt/test/test_mqtt.c
|
|
||||||
components/newlib/abort.c
|
components/newlib/abort.c
|
||||||
components/newlib/assert.c
|
components/newlib/assert.c
|
||||||
components/newlib/heap.c
|
components/newlib/heap.c
|
||||||
@ -2501,7 +2498,6 @@ components/wpa_supplicant/src/wps/wps_registrar.c
|
|||||||
components/wpa_supplicant/src/wps/wps_validate.c
|
components/wpa_supplicant/src/wps/wps_validate.c
|
||||||
components/wpa_supplicant/test/test_crypto.c
|
components/wpa_supplicant/test/test_crypto.c
|
||||||
components/wpa_supplicant/test/test_dpp.c
|
components/wpa_supplicant/test/test_dpp.c
|
||||||
components/wpa_supplicant/test/test_offchannel.c
|
|
||||||
components/wpa_supplicant/test/test_sae.c
|
components/wpa_supplicant/test/test_sae.c
|
||||||
components/xtensa/eri.c
|
components/xtensa/eri.c
|
||||||
components/xtensa/esp32/include/xtensa/config/core-isa.h
|
components/xtensa/esp32/include/xtensa/config/core-isa.h
|
||||||
@ -3318,13 +3314,10 @@ tools/test_mkdfu/test_mkdfu.py
|
|||||||
tools/test_mkuf2/test_mkuf2.py
|
tools/test_mkuf2/test_mkuf2.py
|
||||||
tools/unit-test-app/components/test_utils/ccomp_timer.c
|
tools/unit-test-app/components/test_utils/ccomp_timer.c
|
||||||
tools/unit-test-app/components/test_utils/include/ccomp_timer.h
|
tools/unit-test-app/components/test_utils/include/ccomp_timer.h
|
||||||
tools/unit-test-app/components/test_utils/include/test_utils.h
|
|
||||||
tools/unit-test-app/components/test_utils/private_include/ccomp_timer_impl.h
|
tools/unit-test-app/components/test_utils/private_include/ccomp_timer_impl.h
|
||||||
tools/unit-test-app/components/test_utils/test/ccomp_timer_test_api.c
|
tools/unit-test-app/components/test_utils/test/ccomp_timer_test_api.c
|
||||||
tools/unit-test-app/components/test_utils/test/ccomp_timer_test_data.c
|
tools/unit-test-app/components/test_utils/test/ccomp_timer_test_data.c
|
||||||
tools/unit-test-app/components/test_utils/test/ccomp_timer_test_inst.c
|
tools/unit-test-app/components/test_utils/test/ccomp_timer_test_inst.c
|
||||||
tools/unit-test-app/components/test_utils/test_runner.c
|
|
||||||
tools/unit-test-app/components/test_utils/test_utils.c
|
|
||||||
tools/unit-test-app/idf_ext.py
|
tools/unit-test-app/idf_ext.py
|
||||||
tools/unit-test-app/main/app_main.c
|
tools/unit-test-app/main/app_main.c
|
||||||
tools/unit-test-app/tools/CreateSectionTable.py
|
tools/unit-test-app/tools/CreateSectionTable.py
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
set(srcs "ccomp_timer.c"
|
set(srcs "ccomp_timer.c"
|
||||||
|
"memory_checks.c"
|
||||||
"test_runner.c"
|
"test_runner.c"
|
||||||
"test_utils.c")
|
"test_utils.c")
|
||||||
|
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Leak for components
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ESP_COMP_LEAK_GENERAL = 0, /**< Leak by default */
|
||||||
|
ESP_COMP_LEAK_LWIP, /**< Leak for LWIP */
|
||||||
|
ESP_COMP_LEAK_NVS, /**< Leak for NVS */
|
||||||
|
ESP_COMP_LEAK_ALL, /**< Use for getting the summary leak level */
|
||||||
|
} esp_comp_leak_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of a leak threshold
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ESP_LEAK_TYPE_WARNING = 0, /**< Warning level of leak */
|
||||||
|
ESP_LEAK_TYPE_CRITICAL, /**< Critical level of leak */
|
||||||
|
ESP_LEAK_TYPE_MAX, /**< Max number of leak levels for all components/levels */
|
||||||
|
} esp_type_leak_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adjust the 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 is why there is a default threshold for memory leaks (currently 1024 bytes).
|
||||||
|
* Within this range, the number of bytes leaked will be visually reported on the terminal, but no test failure will
|
||||||
|
* be triggered. Any memory leak above the default threshold will trigger a unit test failure.
|
||||||
|
* This function allows to adjust that memory leak threshold.
|
||||||
|
*
|
||||||
|
* @param leak_level Maximum allowed memory leak which will not trigger a unit test failure.
|
||||||
|
* @param type_of_leak There are two types of leak thresholds: critical and warning. Only the
|
||||||
|
* critical threshold will trigger a unit test failure if exceeded.
|
||||||
|
* @param component Thresholds can be set in general or for specific components. Note that this argument
|
||||||
|
* is not checked.
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success, ESP_INVALID_ARG if type_of_leak is invalid. \c component is unchecked.
|
||||||
|
*/
|
||||||
|
esp_err_t test_utils_set_leak_level(size_t leak_level, esp_type_leak_t type_of_leak, esp_comp_leak_t component);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return the memory leak thresholds for unit tests for a leak type and component.
|
||||||
|
*
|
||||||
|
* For more information, see \c test_utils_set_leak_level above.
|
||||||
|
*
|
||||||
|
* @param type_of_leak Warning or Critical
|
||||||
|
* @param component The component for which to return the leak threshold.
|
||||||
|
*/
|
||||||
|
size_t test_utils_get_leak_level(esp_type_leak_t type_of_leak, esp_comp_leak_t component);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 test_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 test_utils_record_free_mem(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Evaluate memory leak checking according to the provided thresholds.
|
||||||
|
*
|
||||||
|
* If the current memory leak level (counted from the last time calling \c test_utils_record_free_mem() ) exceeds
|
||||||
|
* \c critical_threshold, a unit test failure will be triggered. If it exceeds only the warning,
|
||||||
|
* a warning message will be issued.
|
||||||
|
*/
|
||||||
|
void test_utils_finish_and_evaluate_leaks(size_t warn_threshold, size_t critical_threshold);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper function to setup and initialize heap tracing.
|
||||||
|
*/
|
||||||
|
void setup_heap_record(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,16 +1,9 @@
|
|||||||
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Utilities for esp-idf unit tests
|
// Utilities for esp-idf unit tests
|
||||||
@ -118,18 +111,6 @@ uint64_t ref_clock_get(void);
|
|||||||
*/
|
*/
|
||||||
void test_main(void);
|
void test_main(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reset automatic leak checking which happens in unit tests.
|
|
||||||
*
|
|
||||||
* Updates recorded "before" free memory values to the free memory values
|
|
||||||
* at time of calling. Resets leak checker if tracing is enabled in
|
|
||||||
* config.
|
|
||||||
*
|
|
||||||
* This can be called if a test case does something which allocates
|
|
||||||
* memory on first use, for example.
|
|
||||||
*
|
|
||||||
* @note Use with care as this can mask real memory leak problems.
|
|
||||||
*/
|
|
||||||
void unity_reset_leak_checks(void);
|
void unity_reset_leak_checks(void);
|
||||||
|
|
||||||
|
|
||||||
@ -232,47 +213,6 @@ static inline void unity_send_signal(const char* signal_name)
|
|||||||
*/
|
*/
|
||||||
bool unity_util_convert_mac_from_string(const char* mac_str, uint8_t *mac_addr);
|
bool unity_util_convert_mac_from_string(const char* mac_str, uint8_t *mac_addr);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Leak for components
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
COMP_LEAK_GENERAL = 0, /**< Leak by default */
|
|
||||||
COMP_LEAK_LWIP, /**< Leak for LWIP */
|
|
||||||
COMP_LEAK_NVS, /**< Leak for NVS */
|
|
||||||
COMP_LEAK_ALL, /**< Use for getting the summary leak level */
|
|
||||||
} esp_comp_leak_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type of leak
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
TYPE_LEAK_WARNING = 0, /**< Warning level of leak */
|
|
||||||
TYPE_LEAK_CRITICAL, /**< Critical level of leak */
|
|
||||||
TYPE_LEAK_MAX, /**< Max number of leak levels */
|
|
||||||
} esp_type_leak_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set a leak level for the required type and component.
|
|
||||||
*
|
|
||||||
* @param[in] leak_level Level of leak
|
|
||||||
* @param[in] type Type of leak
|
|
||||||
* @param[in] component Name of component
|
|
||||||
*
|
|
||||||
* return ESP_OK: Successful.
|
|
||||||
* ESP_ERR_INVALID_ARG: Invalid argument.
|
|
||||||
*/
|
|
||||||
esp_err_t test_utils_set_leak_level(size_t leak_level, esp_type_leak_t type, esp_comp_leak_t component);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get a leak level for the required type and component.
|
|
||||||
*
|
|
||||||
* @param[in] type Type of leak.
|
|
||||||
* @param[in] component Name of component. If COMP_LEAK_ALL, then the level will be summarized for all components.
|
|
||||||
* return Leak level
|
|
||||||
*/
|
|
||||||
size_t test_utils_get_leak_level(esp_type_leak_t type, esp_comp_leak_t component);
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct test_utils_exhaust_memory_record_s *test_utils_exhaust_memory_rec;
|
typedef struct test_utils_exhaust_memory_record_s *test_utils_exhaust_memory_rec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
97
tools/unit-test-app/components/test_utils/memory_checks.c
Normal file
97
tools/unit-test-app/components/test_utils/memory_checks.c
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "memory_checks.h"
|
||||||
|
|
||||||
|
static size_t before_free_8bit;
|
||||||
|
static size_t before_free_32bit;
|
||||||
|
|
||||||
|
static size_t test_unity_leak_level[ESP_LEAK_TYPE_MAX][ESP_COMP_LEAK_ALL] = { 0 };
|
||||||
|
|
||||||
|
esp_err_t test_utils_set_leak_level(size_t leak_level, esp_type_leak_t type_of_leak, esp_comp_leak_t component)
|
||||||
|
{
|
||||||
|
if (type_of_leak >= ESP_LEAK_TYPE_MAX || component >= ESP_COMP_LEAK_ALL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
test_unity_leak_level[type_of_leak][component] = leak_level;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t test_utils_get_leak_level(esp_type_leak_t type_of_leak, esp_comp_leak_t component)
|
||||||
|
{
|
||||||
|
size_t leak_level = 0;
|
||||||
|
if (type_of_leak >= ESP_LEAK_TYPE_MAX || component > ESP_COMP_LEAK_ALL) {
|
||||||
|
leak_level = 0;
|
||||||
|
} else {
|
||||||
|
if (component == ESP_COMP_LEAK_ALL) {
|
||||||
|
for (int comp = 0; comp < ESP_COMP_LEAK_ALL; ++comp) {
|
||||||
|
leak_level += test_unity_leak_level[type_of_leak][comp];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
leak_level = test_unity_leak_level[type_of_leak][component];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return leak_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_utils_record_free_mem(void)
|
||||||
|
{
|
||||||
|
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||||
|
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_heap_record(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_HEAP_TRACING
|
||||||
|
const size_t num_heap_records = 80;
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_leak(size_t before_free,
|
||||||
|
size_t after_free,
|
||||||
|
const char *type,
|
||||||
|
size_t warn_threshold,
|
||||||
|
size_t critical_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,
|
||||||
|
critical_threshold);
|
||||||
|
|
||||||
|
if (free_delta > 0) {
|
||||||
|
return; // free memory went up somehow
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t leaked = (size_t)(free_delta * -1);
|
||||||
|
if (leaked <= warn_threshold) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("MALLOC_CAP_%s %s leak: Before %u bytes free, After %u bytes free (delta %u)\n",
|
||||||
|
type,
|
||||||
|
leaked <= critical_threshold ? "potential" : "critical",
|
||||||
|
before_free, after_free, leaked);
|
||||||
|
fflush(stdout);
|
||||||
|
TEST_ASSERT_MESSAGE(leaked <= critical_threshold, "The test leaked too much memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_utils_finish_and_evaluate_leaks(size_t warn_threshold, size_t critical_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);
|
||||||
|
check_leak(before_free_8bit, after_free_8bit, "8BIT", warn_threshold, critical_threshold);
|
||||||
|
check_leak(before_free_32bit, after_free_32bit, "32BIT", warn_threshold, critical_threshold);
|
||||||
|
}
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
@ -21,17 +13,12 @@
|
|||||||
#include "unity_test_runner.h"
|
#include "unity_test_runner.h"
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
#include "esp_newlib.h"
|
#include "esp_newlib.h"
|
||||||
|
#include "memory_checks.h"
|
||||||
|
|
||||||
#ifdef CONFIG_HEAP_TRACING
|
#ifdef CONFIG_HEAP_TRACING
|
||||||
#include "esp_heap_trace.h"
|
#include "esp_heap_trace.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static size_t before_free_8bit;
|
|
||||||
static size_t before_free_32bit;
|
|
||||||
|
|
||||||
static size_t warn_leak_threshold;
|
|
||||||
static size_t critical_leak_threshold;
|
|
||||||
|
|
||||||
static void unity_task(void *pvParameters)
|
static void unity_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
vTaskDelay(2); /* Delay a bit to let the main task be deleted */
|
vTaskDelay(2); /* Delay a bit to let the main task be deleted */
|
||||||
@ -46,28 +33,12 @@ void test_main(void)
|
|||||||
UNITY_FREERTOS_PRIORITY, NULL, UNITY_FREERTOS_CPU);
|
UNITY_FREERTOS_PRIORITY, NULL, UNITY_FREERTOS_CPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unity_reset_leak_checks(void)
|
|
||||||
{
|
|
||||||
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
|
||||||
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
|
||||||
|
|
||||||
#ifdef CONFIG_HEAP_TRACING
|
|
||||||
heap_trace_start(HEAP_TRACE_LEAKS);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setUp runs before every test */
|
/* setUp runs before every test */
|
||||||
void setUp(void)
|
void setUp(void)
|
||||||
{
|
{
|
||||||
// If heap tracing is enabled in kconfig, leak trace the test
|
// If heap tracing is enabled in kconfig, leak trace the test
|
||||||
#ifdef CONFIG_HEAP_TRACING
|
#ifdef CONFIG_HEAP_TRACING
|
||||||
const size_t num_heap_records = 80;
|
setup_heap_record();
|
||||||
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
|
#endif
|
||||||
|
|
||||||
printf("%s", ""); /* sneakily lazy-allocate the reent structure for this test task */
|
printf("%s", ""); /* sneakily lazy-allocate the reent structure for this test task */
|
||||||
@ -81,55 +52,42 @@ void setUp(void)
|
|||||||
get_test_data_partition(); /* allocate persistent partition table structures */
|
get_test_data_partition(); /* allocate persistent partition table structures */
|
||||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
unity_reset_leak_checks();
|
#ifdef CONFIG_HEAP_TRACING
|
||||||
test_utils_set_leak_level(CONFIG_UNITY_CRITICAL_LEAK_LEVEL_GENERAL, TYPE_LEAK_CRITICAL, COMP_LEAK_GENERAL);
|
heap_trace_start(HEAP_TRACE_LEAKS);
|
||||||
test_utils_set_leak_level(CONFIG_UNITY_WARN_LEAK_LEVEL_GENERAL, TYPE_LEAK_WARNING, COMP_LEAK_GENERAL);
|
#endif
|
||||||
|
test_utils_record_free_mem();
|
||||||
|
test_utils_set_leak_level(CONFIG_UNITY_CRITICAL_LEAK_LEVEL_GENERAL, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL);
|
||||||
|
test_utils_set_leak_level(CONFIG_UNITY_WARN_LEAK_LEVEL_GENERAL, ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_GENERAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_leak(size_t before_free, size_t after_free, const char *type)
|
typedef enum {
|
||||||
|
NO_LEAK_CHECK,
|
||||||
|
DEFAULT_LEAK_CHECK,
|
||||||
|
SPECIAL_LEAK_CHECK
|
||||||
|
} leak_check_type_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It is possible to specify the maximum allowed memory leak level directly in the test case
|
||||||
|
* or disable leak checking for a test case.
|
||||||
|
* This function checks if this is the case and return the appropriate return value.
|
||||||
|
* If a custom leak level has been specified, that custom threshold is written to the value pointed by threshold.
|
||||||
|
*/
|
||||||
|
static leak_check_type_t leak_check_required(size_t *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,
|
|
||||||
critical_leak_threshold);
|
|
||||||
|
|
||||||
if (free_delta > 0) {
|
|
||||||
return; // free memory went up somehow
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t leaked = (size_t)(free_delta * -1);
|
|
||||||
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_MESSAGE(leaked <= critical_leak_threshold, "The test leaked too much memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool leak_check_required(void)
|
|
||||||
{
|
|
||||||
warn_leak_threshold = test_utils_get_leak_level(TYPE_LEAK_WARNING, COMP_LEAK_ALL);
|
|
||||||
critical_leak_threshold = test_utils_get_leak_level(TYPE_LEAK_CRITICAL, COMP_LEAK_ALL);
|
|
||||||
if (Unity.CurrentDetail1 != NULL) {
|
if (Unity.CurrentDetail1 != NULL) {
|
||||||
const char *leaks = "[leaks";
|
const char *leaks = "[leaks";
|
||||||
const int len_leaks = strlen(leaks);
|
const int len_leaks = strlen(leaks);
|
||||||
const char *sub_leaks = strstr(Unity.CurrentDetail1, leaks);
|
const char *sub_leaks = strstr(Unity.CurrentDetail1, leaks);
|
||||||
if (sub_leaks != NULL) {
|
if (sub_leaks != NULL) {
|
||||||
if (sub_leaks[len_leaks] == ']') {
|
if (sub_leaks[len_leaks] == ']') {
|
||||||
return false;
|
return NO_LEAK_CHECK;
|
||||||
} else if (sub_leaks[len_leaks] == '=') {
|
} else if (sub_leaks[len_leaks] == '=') {
|
||||||
critical_leak_threshold = strtol(&sub_leaks[len_leaks + 1], NULL, 10);
|
*threshold = strtol(&sub_leaks[len_leaks + 1], NULL, 10);
|
||||||
warn_leak_threshold = critical_leak_threshold;
|
return SPECIAL_LEAK_CHECK;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return DEFAULT_LEAK_CHECK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tearDown runs after every test */
|
/* tearDown runs after every test */
|
||||||
@ -154,11 +112,23 @@ void tearDown(void)
|
|||||||
heap_trace_dump();
|
heap_trace_dump();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (leak_check_required()) {
|
size_t leak_threshold_critical = 0;
|
||||||
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
size_t leak_threshold_warning = 0;
|
||||||
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
leak_check_type_t check_type = leak_check_required(&leak_threshold_critical);
|
||||||
check_leak(before_free_8bit, after_free_8bit, "8BIT");
|
|
||||||
check_leak(before_free_32bit, after_free_32bit, "32BIT");
|
// In the "special case", only one level can be passed directly from the test case.
|
||||||
|
// Hence, we set both warning and critical leak levels to that same value here
|
||||||
|
leak_threshold_warning = leak_threshold_critical;
|
||||||
|
|
||||||
|
if (check_type == NO_LEAK_CHECK) {
|
||||||
|
// do not check
|
||||||
|
} else if (check_type == SPECIAL_LEAK_CHECK) {
|
||||||
|
test_utils_finish_and_evaluate_leaks(leak_threshold_warning, leak_threshold_critical);
|
||||||
|
} else if (check_type == DEFAULT_LEAK_CHECK) {
|
||||||
|
test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL),
|
||||||
|
test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL));
|
||||||
|
} else {
|
||||||
|
assert(false); // coding error
|
||||||
}
|
}
|
||||||
|
|
||||||
Unity.TestFile = real_testfile; // go back to the real filename
|
Unity.TestFile = real_testfile; // go back to the real filename
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
@ -20,6 +12,7 @@
|
|||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
#include "lwip/sockets.h"
|
#include "lwip/sockets.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "memory_checks.h"
|
||||||
#if !CONFIG_FREERTOS_UNICORE
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
#include "esp_ipc.h"
|
#include "esp_ipc.h"
|
||||||
#include "esp_freertos_hooks.h"
|
#include "esp_freertos_hooks.h"
|
||||||
@ -57,9 +50,9 @@ void test_case_uses_tcpip(void)
|
|||||||
printf("Note: esp_netif_init() has been called. Until next reset, TCP/IP task will periodicially allocate memory and consume CPU time.\n");
|
printf("Note: esp_netif_init() has been called. Until next reset, TCP/IP task will periodicially allocate memory and consume CPU time.\n");
|
||||||
|
|
||||||
// Reset the leak checker as LWIP allocates a lot of memory on first run
|
// Reset the leak checker as LWIP allocates a lot of memory on first run
|
||||||
unity_reset_leak_checks();
|
test_utils_record_free_mem();
|
||||||
test_utils_set_leak_level(0, TYPE_LEAK_CRITICAL, COMP_LEAK_GENERAL);
|
test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL);
|
||||||
test_utils_set_leak_level(CONFIG_UNITY_CRITICAL_LEAK_LEVEL_LWIP, TYPE_LEAK_CRITICAL, COMP_LEAK_LWIP);
|
test_utils_set_leak_level(CONFIG_UNITY_CRITICAL_LEAK_LEVEL_LWIP, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_LWIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait user to send "Enter" key or input parameter
|
// wait user to send "Enter" key or input parameter
|
||||||
@ -119,34 +112,6 @@ bool unity_util_convert_mac_from_string(const char* mac_str, uint8_t *mac_addr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t test_unity_leak_level[TYPE_LEAK_MAX][COMP_LEAK_ALL] = { 0 };
|
|
||||||
|
|
||||||
esp_err_t test_utils_set_leak_level(size_t leak_level, esp_type_leak_t type_of_leak, esp_comp_leak_t component)
|
|
||||||
{
|
|
||||||
if (type_of_leak >= TYPE_LEAK_MAX || component >= COMP_LEAK_ALL) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
test_unity_leak_level[type_of_leak][component] = leak_level;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t test_utils_get_leak_level(esp_type_leak_t type_of_leak, esp_comp_leak_t component)
|
|
||||||
{
|
|
||||||
size_t leak_level = 0;
|
|
||||||
if (type_of_leak >= TYPE_LEAK_MAX || component > COMP_LEAK_ALL) {
|
|
||||||
leak_level = 0;
|
|
||||||
} else {
|
|
||||||
if (component == COMP_LEAK_ALL) {
|
|
||||||
for (int comp = 0; comp < COMP_LEAK_ALL; ++comp) {
|
|
||||||
leak_level += test_unity_leak_level[type_of_leak][comp];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
leak_level = test_unity_leak_level[type_of_leak][component];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return leak_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define EXHAUST_MEMORY_ENTRIES 100
|
#define EXHAUST_MEMORY_ENTRIES 100
|
||||||
|
|
||||||
struct test_utils_exhaust_memory_record_s {
|
struct test_utils_exhaust_memory_record_s {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user