testCommon.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "FreeRTOS.h"
  2. #include "RyanJsonInternal.h"
  3. #include "testCommon.h"
  4. #include "tlsf.h"
  5. #if defined(RyanJsonTestPlatformQemu)
  6. #define unitTlsfPoolSize (600U * 1024U)
  7. #define unitTlsfPoolMin (512U * 1024U)
  8. #else
  9. #define unitTlsfPoolSize (1024U * 1024U)
  10. #endif
  11. typedef struct
  12. {
  13. tlsf_t tlsfHandle;
  14. void *poolBuffer;
  15. size_t poolSize;
  16. } unityTestTlsfCtx_t;
  17. static unityTestTlsfCtx_t gUnityTestTlsfCtx = {NULL, NULL, 0U};
  18. #if defined(RyanJsonTestPlatformQemu)
  19. static uint8_t gQemuTlsfPoolLogged = 0U;
  20. #endif
  21. static uint8_t gAllocSimConfigLogged = 0U;
  22. static uint8_t gAllocSimEnabled = 0U;
  23. uint64_t platformUptimeMs(void)
  24. {
  25. return testPlatformGetUptimeMs();
  26. }
  27. static size_t unityTestCalcSimulatedAllocSize(size_t requestSize)
  28. {
  29. const size_t headerSize = (size_t)RyanJsonTestAllocHeaderSize;
  30. const size_t alignSize = (size_t)RyanJsonTestAllocAlignSize;
  31. size_t allocSize = requestSize;
  32. if (0U == requestSize) { return 0U; }
  33. if (allocSize > (SIZE_MAX - headerSize)) { return 0U; }
  34. allocSize += headerSize;
  35. if (alignSize > 1U) { allocSize = RyanJsonAlign(allocSize, alignSize); }
  36. return allocSize;
  37. }
  38. void unityTestSetAllocSimulation(uint8_t isEnable)
  39. {
  40. if (0U != isEnable) { gAllocSimEnabled = 1U; }
  41. else
  42. {
  43. gAllocSimEnabled = 0U;
  44. }
  45. }
  46. uint8_t unityTestGetAllocSimulation(void)
  47. {
  48. return gAllocSimEnabled;
  49. }
  50. static bool unityTestInitTlsf(void)
  51. {
  52. if (NULL == gUnityTestTlsfCtx.poolBuffer)
  53. {
  54. size_t trySize = unitTlsfPoolSize;
  55. #if defined(RyanJsonTestPlatformQemu)
  56. while (trySize >= unitTlsfPoolMin)
  57. {
  58. gUnityTestTlsfCtx.poolBuffer = v_malloc(trySize);
  59. if (NULL != gUnityTestTlsfCtx.poolBuffer)
  60. {
  61. gUnityTestTlsfCtx.poolSize = trySize;
  62. break;
  63. }
  64. trySize /= 2U;
  65. }
  66. #else
  67. gUnityTestTlsfCtx.poolBuffer = v_malloc(trySize);
  68. if (NULL != gUnityTestTlsfCtx.poolBuffer) { gUnityTestTlsfCtx.poolSize = trySize; }
  69. #endif
  70. if ((NULL == gUnityTestTlsfCtx.poolBuffer) || (0U == gUnityTestTlsfCtx.poolSize)) { return false; }
  71. }
  72. gUnityTestTlsfCtx.tlsfHandle =
  73. tlsf_create_with_pool(gUnityTestTlsfCtx.poolBuffer, gUnityTestTlsfCtx.poolSize, gUnityTestTlsfCtx.poolSize);
  74. return (NULL != gUnityTestTlsfCtx.tlsfHandle);
  75. }
  76. void showMemoryInfo(void)
  77. {
  78. size_t total = 0U;
  79. size_t used = 0U;
  80. size_t maxUsed = 0U;
  81. if (NULL == gUnityTestTlsfCtx.tlsfHandle)
  82. {
  83. testLog("%s:%d tlsf 未初始化\r\n", __FILE__, __LINE__);
  84. return;
  85. }
  86. tlsf_memory_info(gUnityTestTlsfCtx.tlsfHandle, &total, &used, &maxUsed);
  87. testLog("%s:%d tlsf used: %lu, maxUsed: %lu, total: %lu\r\n", __FILE__, __LINE__, (unsigned long)used, (unsigned long)maxUsed,
  88. (unsigned long)total);
  89. }
  90. void logTaskStackRuntimeInfoByHandle(const char *tag, const char *taskName, TaskHandle_t taskHandle)
  91. {
  92. const char *safeTag = "<null>";
  93. const char *safeTaskName = "<null>";
  94. TaskStatus_t taskStatus = {0};
  95. UBaseType_t taskPriority = 0U;
  96. configSTACK_DEPTH_TYPE stackTotalWords = 0U;
  97. configSTACK_DEPTH_TYPE stackFreeMinWords = 0U;
  98. size_t stackUsedPeakWords = 0U;
  99. size_t stackTotalBytes = 0U;
  100. size_t stackFreeMinBytes = 0U;
  101. size_t stackUsedPeakBytes = 0U;
  102. if (NULL != tag) { safeTag = tag; }
  103. if (NULL == taskHandle)
  104. {
  105. testLog("\n[%s] 任务句柄为空,无法获取任务信息\n", safeTag);
  106. return;
  107. }
  108. vTaskGetInfo(taskHandle, &taskStatus, pdTRUE, eInvalid);
  109. if (NULL != taskName) { safeTaskName = taskName; }
  110. else if (NULL != taskStatus.pcTaskName) { safeTaskName = taskStatus.pcTaskName; }
  111. taskPriority = taskStatus.uxCurrentPriority;
  112. stackFreeMinWords = taskStatus.usStackHighWaterMark;
  113. #if (portSTACK_GROWTH < 0)
  114. if ((NULL != taskStatus.pxStackBase) && (NULL != taskStatus.pxEndOfStack) && (taskStatus.pxEndOfStack >= taskStatus.pxStackBase))
  115. {
  116. stackTotalWords = (configSTACK_DEPTH_TYPE)(taskStatus.pxEndOfStack - taskStatus.pxStackBase + 1U);
  117. }
  118. #elif (portSTACK_GROWTH > 0)
  119. if ((NULL != taskStatus.pxStackBase) && (NULL != taskStatus.pxEndOfStack) && (taskStatus.pxStackBase >= taskStatus.pxEndOfStack))
  120. {
  121. stackTotalWords = (configSTACK_DEPTH_TYPE)(taskStatus.pxStackBase - taskStatus.pxEndOfStack + 1U);
  122. }
  123. #endif
  124. if (stackTotalWords >= stackFreeMinWords) { stackUsedPeakWords = stackTotalWords - stackFreeMinWords; }
  125. stackTotalBytes = stackTotalWords * sizeof(StackType_t);
  126. stackFreeMinBytes = stackFreeMinWords * sizeof(StackType_t);
  127. stackUsedPeakBytes = stackUsedPeakWords * sizeof(StackType_t);
  128. testLog("\n[%s] 任务=%s, Tick=%lu, 优先级=%lu, 栈总量=%lu(字)/%lu字节, 已用峰值=%lu(字)/%lu字节, 栈最小剩余=%lu(字)/%lu字节\n",
  129. safeTag, safeTaskName, (unsigned long)xTaskGetTickCount(), (unsigned long)taskPriority, (unsigned long)stackTotalWords,
  130. (unsigned long)stackTotalBytes, (unsigned long)stackUsedPeakWords, (unsigned long)stackUsedPeakBytes,
  131. (unsigned long)stackFreeMinWords, (unsigned long)stackFreeMinBytes);
  132. }
  133. int32_t unityTestGetUse(void)
  134. {
  135. size_t total = 0U;
  136. size_t used = 0U;
  137. size_t maxUsed = 0U;
  138. if (NULL == gUnityTestTlsfCtx.tlsfHandle) { return 0; }
  139. tlsf_memory_info(gUnityTestTlsfCtx.tlsfHandle, &total, &used, &maxUsed);
  140. return (int32_t)used;
  141. }
  142. void *unityTestMalloc(size_t size)
  143. {
  144. size_t allocSize = 0U;
  145. if (NULL == gUnityTestTlsfCtx.tlsfHandle || 0U == size) { return NULL; }
  146. if (0U != gAllocSimEnabled) { allocSize = unityTestCalcSimulatedAllocSize(size); }
  147. else
  148. {
  149. allocSize = size;
  150. }
  151. return tlsf_malloc(gUnityTestTlsfCtx.tlsfHandle, allocSize);
  152. }
  153. void unityTestFree(void *block)
  154. {
  155. if (NULL == gUnityTestTlsfCtx.tlsfHandle || NULL == block) { return; }
  156. tlsf_free(gUnityTestTlsfCtx.tlsfHandle, block);
  157. }
  158. void *unityTestRealloc(void *block, size_t size)
  159. {
  160. size_t allocSize = 0U;
  161. if (NULL == gUnityTestTlsfCtx.tlsfHandle) { return NULL; }
  162. if (0U == size) { return tlsf_realloc(gUnityTestTlsfCtx.tlsfHandle, block, 0U); }
  163. if (0U != gAllocSimEnabled) { allocSize = unityTestCalcSimulatedAllocSize(size); }
  164. else
  165. {
  166. allocSize = size;
  167. }
  168. return tlsf_realloc(gUnityTestTlsfCtx.tlsfHandle, block, allocSize);
  169. }
  170. void ryanJsonTestSetup(void)
  171. {
  172. if (!unityTestInitTlsf())
  173. {
  174. testLog("%s:%d tlsf 初始化失败\r\n", __FILE__, __LINE__);
  175. return;
  176. }
  177. #if defined(RyanJsonTestPlatformQemu)
  178. if (0U == gQemuTlsfPoolLogged)
  179. {
  180. testLog("[QEMU][MEM] tlsfPoolSize=%lu\r\n", (unsigned long)gUnityTestTlsfCtx.poolSize);
  181. gQemuTlsfPoolLogged = 1U;
  182. }
  183. #endif
  184. if (0U == gAllocSimConfigLogged)
  185. {
  186. testLog("[MEM][SIM] header=%lu align=%lu\r\n", (unsigned long)RyanJsonTestAllocHeaderSize,
  187. (unsigned long)RyanJsonTestAllocAlignSize);
  188. gAllocSimConfigLogged = 1U;
  189. }
  190. xPortResetHeapMinimumEverFreeHeapSize();
  191. RyanJsonInitHooks(unityTestMalloc, unityTestFree, unityTestRealloc);
  192. }
  193. void ryanJsonTestTeardown(void)
  194. {
  195. gUnityTestTlsfCtx.tlsfHandle = NULL;
  196. }