testDeepRecursion.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. #define _GNU_SOURCE
  2. #include "testBase.h"
  3. #include "FreeRTOS.h"
  4. #include "task.h"
  5. // 使用轻量 xorshift 保持生成过程可复现且开销更低
  6. static uint32_t gDeepRandState = 0x9E3779B9U;
  7. typedef enum
  8. {
  9. deepJsonModeMixed = 0,
  10. deepJsonModeObjectOnly = 1,
  11. deepJsonModeArrayOnly = 2
  12. } deepJsonMode_e;
  13. static deepJsonMode_e gDeepJsonMode = deepJsonModeMixed;
  14. static int32_t gDeepJsonDepth = 10000;
  15. static const size_t gDeepStackThreadWords = 512;
  16. static const char *deepJsonModeName(deepJsonMode_e mode)
  17. {
  18. if (deepJsonModeObjectOnly == mode) { return "object-only"; }
  19. if (deepJsonModeArrayOnly == mode) { return "array-only"; }
  20. return "mixed";
  21. }
  22. // 辅助:生成 0 到 max-1 的随机数
  23. static inline uint32_t randomRange(uint32_t max)
  24. {
  25. if (0U == max) { return 0U; }
  26. gDeepRandState ^= gDeepRandState << 13;
  27. gDeepRandState ^= gDeepRandState >> 17;
  28. gDeepRandState ^= gDeepRandState << 5;
  29. return gDeepRandState % max;
  30. }
  31. /**
  32. * @brief 生成深度嵌套的 Json 字符串
  33. *
  34. * @param depth 目标深度
  35. * @param outSize 输出生成的字符串长度
  36. * @return char* 动态分配的字符串,需要调用者 free
  37. */
  38. static char *generateDeepJson(int32_t depth, size_t *outSize, deepJsonMode_e mode)
  39. {
  40. /**
  41. * @brief 生成缓冲区预估策略
  42. *
  43. * 每层结构平均约 4 字节,再叠加少量噪声负载与位图开销,使用 `depth * 6 + 1024`
  44. * 可在控制内存占用的同时,显著降低深层 Json 生成过程中的扩容/越界风险。
  45. */
  46. size_t bufCap = depth * 6 + 1024;
  47. char *jsonStr = (char *)malloc(bufCap);
  48. // 使用位图替代类型栈,减少辅助空间占用
  49. // bit=1 表示对象层,bit=0 表示数组层
  50. uint8_t *typeBitset = (uint8_t *)calloc((depth + 7) / 8, 1);
  51. if (!jsonStr || !typeBitset)
  52. {
  53. if (jsonStr) { free(jsonStr); }
  54. if (typeBitset) { free(typeBitset); }
  55. return NULL;
  56. }
  57. char *ptr = jsonStr;
  58. for (int32_t i = 0; i < depth; i++)
  59. {
  60. // 随机决定当前层类型:对象或数组
  61. bool isObject = false;
  62. if (deepJsonModeObjectOnly == mode) { isObject = true; }
  63. else if (deepJsonModeArrayOnly == mode) { isObject = false; }
  64. else
  65. {
  66. isObject = randomRange(2);
  67. }
  68. // 记录类型到位图
  69. if (isObject) { typeBitset[i / 8] |= (1 << (i % 8)); }
  70. if (isObject)
  71. {
  72. *ptr++ = '{';
  73. // 稀疏噪声注入:仅 5% 概率插入额外字段,兼顾覆盖率与内存占用
  74. if (deepJsonModeMixed == mode && randomRange(100) < 5)
  75. {
  76. // 随机生成短 key,避免与核心 key "n" 冲突
  77. char key = (char)('a' + randomRange(13)); // a-m
  78. int32_t type = (int32_t)randomRange(4);
  79. // 生成简短负载
  80. if (type == 0)
  81. {
  82. ptr += sprintf(ptr, "\"%c\":%d,", key, randomRange(9)); // int32_t
  83. }
  84. else if (type == 1)
  85. {
  86. ptr += sprintf(ptr, "\"%c\":true,", key); // bool
  87. }
  88. else if (type == 2)
  89. {
  90. ptr += sprintf(ptr, "\"%c\":null,", key); // null
  91. }
  92. else
  93. {
  94. ptr += sprintf(ptr, "\"%c\":\"s\",", key); // string
  95. }
  96. }
  97. // 核心嵌套 key:"n"(next)
  98. memcpy(ptr, "\"n\":", 4);
  99. ptr += 4;
  100. }
  101. else // 数组层
  102. {
  103. *ptr++ = '[';
  104. // 稀疏噪声注入
  105. if (deepJsonModeMixed == mode && randomRange(100) < 5)
  106. {
  107. int32_t type = (int32_t)randomRange(4);
  108. if (type == 0) { ptr += sprintf(ptr, "%d,", randomRange(9)); }
  109. else if (type == 1) { memcpy(ptr, "false,", 6); }
  110. else if (type == 2) { memcpy(ptr, "null,", 5); }
  111. else
  112. {
  113. memcpy(ptr, "\"v\",", 4);
  114. }
  115. }
  116. }
  117. // 简单的越界保护
  118. if ((size_t)(ptr - jsonStr) >= bufCap - 128)
  119. {
  120. testLog("警告:Json 生成缓冲区在深度 %d 处接近耗尽\n", i);
  121. break;
  122. }
  123. }
  124. // 最内层终点
  125. memcpy(ptr, "\"end\"", 5);
  126. ptr += 5;
  127. // 回溯闭合:倒序读取位图并补齐 ] / }
  128. for (int32_t i = depth - 1; i >= 0; i--)
  129. {
  130. int32_t isObject = (typeBitset[i / 8] >> (i % 8)) & 1;
  131. if (isObject) { *ptr++ = '}'; }
  132. else
  133. {
  134. *ptr++ = ']';
  135. }
  136. }
  137. *ptr = '\0';
  138. if (outSize) { *outSize = (size_t)(ptr - jsonStr); }
  139. free(typeBitset); // 释放位图
  140. return jsonStr;
  141. }
  142. /**
  143. * @brief 深度递归与栈占用压力测试
  144. *
  145. * 在 16KB 栈环境中验证 Parse、Print、Duplicate、Delete 等核心路径是否以迭代方式工作,
  146. * 并在深层嵌套数据下避免栈溢出风险。
  147. */
  148. static void deepStackTask(void)
  149. {
  150. const int32_t depth = gDeepJsonDepth;
  151. const deepJsonMode_e mode = gDeepJsonMode;
  152. size_t jsonLen = 0;
  153. const char *modeName = deepJsonModeName(mode);
  154. gDeepRandState = 0x9E3779B9U ^ (uint32_t)depth ^ (((uint32_t)mode + 1U) << 24);
  155. testLog("正在生成深度 %d 的测试 Json(mode=%s)...\n", depth, modeName);
  156. char *jsonStr = generateDeepJson(depth, &jsonLen, mode);
  157. TEST_ASSERT_NOT_NULL(jsonStr);
  158. // 执行 Minify(压缩,迭代路径验证)
  159. testLog("正在运行 Minify...\n");
  160. RyanJsonMinify(jsonStr, (int32_t)jsonLen);
  161. // 执行 Parse(解析,迭代路径验证)
  162. testLog("正在运行 Parse,深度 %d ...\n", depth);
  163. RyanJson_t json = RyanJsonParse(jsonStr);
  164. TEST_ASSERT_NOT_NULL_MESSAGE(json, "深层嵌套解析失败 (返回了 NULL)");
  165. free(jsonStr);
  166. // 执行 Duplicate(复制,迭代路径验证)
  167. testLog("正在运行 Duplicate...\n");
  168. RyanJson_t dup = RyanJsonDuplicate(json);
  169. TEST_ASSERT_NOT_NULL_MESSAGE(dup, "深层嵌套复制失败 (返回了 NULL)");
  170. // 执行 Compare(比较,迭代路径验证)
  171. testLog("正在运行 Compare...\n");
  172. RyanJsonBool_e eq = RyanJsonCompare(json, dup);
  173. TEST_ASSERT_TRUE_MESSAGE(eq, "深层嵌套比较失败 (结果不相等)");
  174. RyanJsonDelete(dup);
  175. // 执行 Print(打印,迭代路径验证)
  176. testLog("正在运行 Print (无格式化)...\n");
  177. uint32_t len = 0;
  178. char *text = RyanJsonPrint(json, 1024, RyanJsonFalse, &len);
  179. TEST_ASSERT_NOT_NULL_MESSAGE(text, "深层嵌套打印失败 (返回了 NULL)");
  180. TEST_ASSERT_TRUE_MESSAGE(len == jsonLen, "打印输出长度异常");
  181. RyanJsonFree(text);
  182. // 格式化打印
  183. // 占用堆太大,不够用
  184. // printf("正在运行 Print (格式化)...\n");
  185. // text = RyanJsonPrint(json, 1024, RyanJsonTrue, &len);
  186. // TEST_ASSERT_NOT_NULL_MESSAGE(text, "深层嵌套格式化打印失败");
  187. // RyanJsonFree(text);
  188. // GetSize(统计节点数量,迭代路径验证)
  189. testLog("正在运行 GetSize...\n");
  190. uint32_t size = RyanJsonGetSize(json);
  191. TEST_ASSERT_TRUE(size > 0);
  192. // 深层遍历与修改测试
  193. testLog("正在运行深度遍历...\n");
  194. RyanJson_t current = json;
  195. RyanJson_t parent = NULL;
  196. int32_t actualDepth = 0;
  197. // 逐层向下遍历到最深节点
  198. while (current)
  199. {
  200. if (RyanJsonIsObject(current))
  201. {
  202. parent = current;
  203. current = RyanJsonGetObjectByKey(current, "n");
  204. }
  205. else if (RyanJsonIsArray(current))
  206. {
  207. // 对于本测试生成的结构,下一个层级(或负载)总是数组最后一个元素。
  208. // 旧逻辑只查找 Object/Array,末层为 "end"(String/Number)时会少算 1 层。
  209. RyanJson_t child = RyanJsonGetObjectValue(current);
  210. if (child)
  211. {
  212. while (RyanJsonGetNext(child))
  213. {
  214. child = RyanJsonGetNext(child);
  215. }
  216. // child 此时为最后一个节点(容器或负载)
  217. parent = current;
  218. current = child;
  219. }
  220. else
  221. {
  222. // 生成器理论上不会产出空数组,这里保留防御性分支
  223. current = NULL;
  224. }
  225. }
  226. else
  227. {
  228. break; // 已到达负载节点
  229. }
  230. if (current) { actualDepth++; }
  231. }
  232. testLog("实际遍历深度: %d (预期 %d)\n", actualDepth, depth);
  233. TEST_ASSERT_TRUE_MESSAGE(actualDepth == depth, "遍历深度严重偏离预期");
  234. TEST_ASSERT_NOT_NULL(parent);
  235. // 深层插入
  236. testLog("正在运行深层插入...\n");
  237. RyanJsonBool_e insertOk = RyanJsonFalse;
  238. if (RyanJsonIsObject(parent)) { insertOk = RyanJsonAddStringToObject(parent, "inserted_key", "val"); }
  239. else if (RyanJsonIsArray(parent))
  240. {
  241. RyanJson_t newItem = RyanJsonCreateString(NULL, "val");
  242. insertOk = RyanJsonInsert(parent, 0, newItem);
  243. if (RyanJsonFalse == insertOk) { RyanJsonDelete(newItem); }
  244. }
  245. TEST_ASSERT_TRUE_MESSAGE(insertOk, "Deep Insert 失败");
  246. // 深层替换
  247. testLog("正在运行深层替换...\n");
  248. RyanJson_t replaceItem = RyanJsonCreateInt("replaced", 999);
  249. if (RyanJsonIsObject(parent))
  250. {
  251. // RyanJsonReplaceByKey 会替换 key 为 "inserted_key" 的节点
  252. if (RyanJsonFalse == RyanJsonReplaceByKey(parent, "inserted_key", replaceItem))
  253. {
  254. RyanJsonDelete(replaceItem);
  255. replaceItem = NULL;
  256. }
  257. }
  258. else if (RyanJsonIsArray(parent))
  259. {
  260. if (RyanJsonFalse == RyanJsonReplaceByIndex(parent, 0, replaceItem))
  261. {
  262. RyanJsonDelete(replaceItem);
  263. replaceItem = NULL;
  264. }
  265. }
  266. else
  267. {
  268. RyanJsonDelete(replaceItem);
  269. replaceItem = NULL;
  270. }
  271. // 深层分离
  272. testLog("正在运行深层分离...\n");
  273. RyanJson_t detached = NULL;
  274. if (RyanJsonIsObject(parent)) { detached = RyanJsonDetachByKey(parent, "inserted_key"); }
  275. else if (RyanJsonIsArray(parent)) { detached = RyanJsonDetachByIndex(parent, 0); }
  276. if (detached) { RyanJsonDelete(detached); }
  277. else
  278. {
  279. testLog("警告:Detach 返回了 NULL。\n");
  280. }
  281. // 删除整棵 Json 树
  282. testLog("正在运行 Delete Json...\n");
  283. RyanJsonDelete(json);
  284. }
  285. typedef struct
  286. {
  287. int32_t depth;
  288. deepJsonMode_e mode;
  289. uint8_t isTestProtectPassed;
  290. } deepStressThreadCtx_t;
  291. static void deepStressThreadTask(void *arg)
  292. {
  293. deepStressThreadCtx_t *threadCtx = (deepStressThreadCtx_t *)arg;
  294. const char *modeName = "mixed";
  295. TaskHandle_t currentTask = NULL;
  296. char taskName[64] = {0};
  297. if (NULL == threadCtx) { return; }
  298. threadCtx->isTestProtectPassed = 0U;
  299. gDeepJsonDepth = threadCtx->depth;
  300. gDeepJsonMode = threadCtx->mode;
  301. if (TEST_PROTECT())
  302. {
  303. deepStackTask();
  304. threadCtx->isTestProtectPassed = 1U;
  305. }
  306. modeName = deepJsonModeName(threadCtx->mode);
  307. testLog("[deep] 用例参数: 模式=%s, 深度=%ld\n", modeName, (long)threadCtx->depth);
  308. (void)snprintf(taskName, sizeof(taskName), "deep-%s", modeName);
  309. currentTask = xTaskGetCurrentTaskHandle();
  310. logTaskStackRuntimeInfoByHandle("deep", taskName, currentTask);
  311. }
  312. static void runDeepStackUsageStressCase(int32_t depth, deepJsonMode_e mode)
  313. {
  314. int32_t runRet = 0;
  315. deepStressThreadCtx_t threadCtx = {0};
  316. threadCtx.depth = depth;
  317. threadCtx.mode = mode;
  318. runRet = testPlatformRunThreadWithStackSize(deepStressThreadTask, &threadCtx, gDeepStackThreadWords);
  319. TEST_ASSERT_EQUAL_INT_MESSAGE(0, runRet, "deep 测试线程启动失败");
  320. TEST_ASSERT_TRUE_MESSAGE(0U != threadCtx.isTestProtectPassed, "deep 测试线程执行失败");
  321. }
  322. static void testDeepStackUsageStress(void)
  323. {
  324. runDeepStackUsageStressCase(10000, deepJsonModeMixed);
  325. }
  326. static void testDeepStackUsageObjectOnlyStress(void)
  327. {
  328. runDeepStackUsageStressCase(10000, deepJsonModeObjectOnly);
  329. }
  330. static void testDeepStackUsageArrayOnlyStress(void)
  331. {
  332. runDeepStackUsageStressCase(10000, deepJsonModeArrayOnly);
  333. }
  334. void testDeepRecursionRunner(void)
  335. {
  336. UnitySetTestFile(__FILE__);
  337. RUN_TEST(testDeepStackUsageStress);
  338. RUN_TEST(testDeepStackUsageObjectOnlyStress);
  339. RUN_TEST(testDeepStackUsageArrayOnlyStress);
  340. }