memory_checks.c 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdio.h>
  7. #include "esp_heap_caps.h"
  8. #include "unity.h"
  9. #include "memory_checks.h"
  10. static size_t before_free_8bit;
  11. static size_t before_free_32bit;
  12. static size_t test_unity_leak_level[ESP_LEAK_TYPE_MAX][ESP_COMP_LEAK_ALL] = { 0 };
  13. esp_err_t test_utils_set_leak_level(size_t leak_level, esp_type_leak_t type_of_leak, esp_comp_leak_t component)
  14. {
  15. if (type_of_leak >= ESP_LEAK_TYPE_MAX || component >= ESP_COMP_LEAK_ALL) {
  16. return ESP_ERR_INVALID_ARG;
  17. }
  18. test_unity_leak_level[type_of_leak][component] = leak_level;
  19. return ESP_OK;
  20. }
  21. size_t test_utils_get_leak_level(esp_type_leak_t type_of_leak, esp_comp_leak_t component)
  22. {
  23. size_t leak_level = 0;
  24. if (type_of_leak >= ESP_LEAK_TYPE_MAX || component > ESP_COMP_LEAK_ALL) {
  25. leak_level = 0;
  26. } else {
  27. if (component == ESP_COMP_LEAK_ALL) {
  28. for (int comp = 0; comp < ESP_COMP_LEAK_ALL; ++comp) {
  29. leak_level += test_unity_leak_level[type_of_leak][comp];
  30. }
  31. } else {
  32. leak_level = test_unity_leak_level[type_of_leak][component];
  33. }
  34. }
  35. return leak_level;
  36. }
  37. void test_utils_record_free_mem(void)
  38. {
  39. before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
  40. before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
  41. }
  42. void setup_heap_record(void)
  43. {
  44. #ifdef CONFIG_HEAP_TRACING
  45. const size_t num_heap_records = 80;
  46. static heap_trace_record_t *record_buffer;
  47. if (!record_buffer) {
  48. record_buffer = malloc(sizeof(heap_trace_record_t) * num_heap_records);
  49. assert(record_buffer);
  50. heap_trace_init_standalone(record_buffer, num_heap_records);
  51. }
  52. #endif
  53. }
  54. static void check_leak(size_t before_free,
  55. size_t after_free,
  56. const char *type,
  57. size_t warn_threshold,
  58. size_t critical_threshold)
  59. {
  60. int free_delta = (int)after_free - (int)before_free;
  61. printf("MALLOC_CAP_%s usage: Free memory delta: %d Leak threshold: -%u \n",
  62. type,
  63. free_delta,
  64. critical_threshold);
  65. if (free_delta > 0) {
  66. return; // free memory went up somehow
  67. }
  68. size_t leaked = (size_t)(free_delta * -1);
  69. if (leaked <= warn_threshold) {
  70. return;
  71. }
  72. printf("MALLOC_CAP_%s %s leak: Before %u bytes free, After %u bytes free (delta %u)\n",
  73. type,
  74. leaked <= critical_threshold ? "potential" : "critical",
  75. before_free, after_free, leaked);
  76. fflush(stdout);
  77. TEST_ASSERT_MESSAGE(leaked <= critical_threshold, "The test leaked too much memory");
  78. }
  79. void test_utils_finish_and_evaluate_leaks(size_t warn_threshold, size_t critical_threshold)
  80. {
  81. size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
  82. size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
  83. check_leak(before_free_8bit, after_free_8bit, "8BIT", warn_threshold, critical_threshold);
  84. check_leak(before_free_32bit, after_free_32bit, "32BIT", warn_threshold, critical_threshold);
  85. }