memory_checks.c 3.3 KB

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