testStress.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #include "testBase.h"
  2. /**
  3. * @brief 压力与边界测试
  4. *
  5. * @note 验证 RyanJson 处理大数据量(长 String、大 Array)的能力。
  6. */
  7. static void testStressLongString(void)
  8. {
  9. // 测试超长 String (10KB)
  10. const int32_t longStrLen = 10 * 1024;
  11. char *longStrVal = (char *)malloc(longStrLen + 1);
  12. TEST_ASSERT_NOT_NULL(longStrVal);
  13. memset(longStrVal, 'A', longStrLen);
  14. longStrVal[longStrLen] = '\0';
  15. RyanJson_t jsonStr = RyanJsonCreateString("longStr", longStrVal);
  16. TEST_ASSERT_NOT_NULL(jsonStr);
  17. TEST_ASSERT_EQUAL_STRING_MESSAGE(longStrVal, RyanJsonGetStringValue(jsonStr), "超长 String 读取不匹配");
  18. RyanJsonDelete(jsonStr);
  19. free(longStrVal);
  20. }
  21. static void testStressLargeArray(void)
  22. {
  23. // 测试大 Array (1000 个 Int)
  24. const uint32_t arraySize = 1000;
  25. RyanJson_t array = RyanJsonCreateArray();
  26. TEST_ASSERT_NOT_NULL(array);
  27. for (uint32_t i = 0; i < arraySize; i++)
  28. {
  29. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToArray(array, (int32_t)i), "向大 Array 添加 Int 失败");
  30. }
  31. TEST_ASSERT_EQUAL_UINT32_MESSAGE(arraySize, (uint32_t)RyanJsonGetArraySize(array), "大 Array 长度错误");
  32. // 校验最后一个元素
  33. RyanJson_t lastItem = RyanJsonGetObjectByIndex(array, (int32_t)(arraySize - 1U));
  34. #if true == RyanJsonDefaultAddAtHead
  35. TEST_ASSERT_EQUAL_INT32_MESSAGE(0, RyanJsonGetIntValue(lastItem), "大 Array 末尾元素错误");
  36. #else
  37. TEST_ASSERT_EQUAL_INT32_MESSAGE((int32_t)(arraySize - 1U), RyanJsonGetIntValue(lastItem), "大 Array 末尾元素错误");
  38. #endif
  39. RyanJsonDelete(array);
  40. }
  41. static void testStressPrint(void)
  42. {
  43. // 序列化压力测试 (无格式)
  44. const uint32_t arraySize = 1000;
  45. RyanJson_t array = RyanJsonCreateArray();
  46. TEST_ASSERT_NOT_NULL(array);
  47. for (uint32_t i = 0; i < arraySize; i++)
  48. {
  49. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToArray(array, (int32_t)i), "向大 Array 添加 Int 失败");
  50. }
  51. char *printed = RyanJsonPrint(array, 8192, RyanJsonFalse, NULL);
  52. TEST_ASSERT_NOT_NULL_MESSAGE(printed, "大 Array 序列化失败");
  53. RyanJsonFree(printed);
  54. RyanJsonDelete(array);
  55. }
  56. static void testStressLargeArrayRoundtrip(void)
  57. {
  58. const uint32_t arraySize = 2048;
  59. RyanJson_t array = RyanJsonCreateArray();
  60. TEST_ASSERT_NOT_NULL(array);
  61. for (uint32_t i = 0; i < arraySize; i++)
  62. {
  63. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToArray(array, (int32_t)i), "向大 Array 添加 Int 失败");
  64. }
  65. // 关键位置抽样检查,避免仅检查尾节点导致漏检
  66. const uint32_t sampleIndex[] = {0U, 1U, 2U, 127U, 1023U, 1536U, 2047U};
  67. for (uint32_t i = 0; i < sizeof(sampleIndex) / sizeof(sampleIndex[0]); i++)
  68. {
  69. uint32_t idx = sampleIndex[i];
  70. RyanJson_t item = RyanJsonGetObjectByIndex(array, (int32_t)idx);
  71. TEST_ASSERT_NOT_NULL_MESSAGE(item, "大 Array 抽样索引越界");
  72. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsInt(item), "大 Array 抽样元素类型错误");
  73. #if true == RyanJsonDefaultAddAtHead
  74. TEST_ASSERT_EQUAL_INT32_MESSAGE((int32_t)(arraySize - 1U - idx), RyanJsonGetIntValue(item), "大 Array 抽样元素值错误");
  75. #else
  76. TEST_ASSERT_EQUAL_INT32_MESSAGE((int32_t)idx, RyanJsonGetIntValue(item), "大 Array 抽样元素值错误");
  77. #endif
  78. }
  79. uint32_t printLen = 0;
  80. char *printed = RyanJsonPrint(array, 0, RyanJsonFalse, &printLen);
  81. TEST_ASSERT_NOT_NULL_MESSAGE(printed, "大 Array 往返测试:序列化失败");
  82. TEST_ASSERT_TRUE_MESSAGE(printLen > arraySize, "大 Array 序列化长度异常");
  83. RyanJson_t parsed = RyanJsonParse(printed);
  84. TEST_ASSERT_NOT_NULL_MESSAGE(parsed, "大 Array 往返测试:反序列化失败");
  85. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(array, parsed), "大 Array 往返测试:前后 Compare 不一致");
  86. RyanJsonDelete(parsed);
  87. RyanJsonFree(printed);
  88. RyanJsonDelete(array);
  89. }
  90. static void testStressLargeStringArrayPreallocated(void)
  91. {
  92. const uint32_t arraySize = 1200;
  93. RyanJson_t array = RyanJsonCreateArray();
  94. TEST_ASSERT_NOT_NULL(array);
  95. for (uint32_t i = 0; i < arraySize; i++)
  96. {
  97. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddStringToArray(array, "v"), "向 String 大 Array 添加元素失败");
  98. }
  99. uint32_t expectLen = 0;
  100. char *expect = RyanJsonPrint(array, 0, RyanJsonFalse, &expectLen);
  101. TEST_ASSERT_NOT_NULL_MESSAGE(expect, "String 大 Array 序列化失败");
  102. char *buf = (char *)malloc((size_t)expectLen + 1U);
  103. TEST_ASSERT_NOT_NULL(buf);
  104. char *out = RyanJsonPrintPreallocated(array, buf, expectLen + 1U, RyanJsonFalse, NULL);
  105. TEST_ASSERT_NOT_NULL_MESSAGE(out, "String 大 Array 预分配刚好够用应成功");
  106. TEST_ASSERT_EQUAL_STRING_MESSAGE(expect, out, "String 大 Array 预分配输出不一致");
  107. RyanJson_t parsed = RyanJsonParse(out);
  108. TEST_ASSERT_NOT_NULL_MESSAGE(parsed, "String 大 Array 预分配结果解析失败");
  109. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(array, parsed), "String 大 Array 预分配结果前后 Compare 不一致");
  110. RyanJsonDelete(parsed);
  111. free(buf);
  112. RyanJsonFree(expect);
  113. RyanJsonDelete(array);
  114. }
  115. static void testStressLargeStringArrayPreallocatedNoTerminator(void)
  116. {
  117. const uint32_t arraySize = 800;
  118. RyanJson_t array = RyanJsonCreateArray();
  119. TEST_ASSERT_NOT_NULL(array);
  120. for (uint32_t i = 0; i < arraySize; i++)
  121. {
  122. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddStringToArray(array, "value"), "向 String 大 Array 添加元素失败");
  123. }
  124. uint32_t expectLen = 0;
  125. char *expect = RyanJsonPrint(array, 0, RyanJsonFalse, &expectLen);
  126. TEST_ASSERT_NOT_NULL(expect);
  127. char *buf = (char *)malloc((size_t)expectLen);
  128. TEST_ASSERT_NOT_NULL(buf);
  129. // 少 1 字节 '\0' 空间,预分配打印应失败
  130. char *out = RyanJsonPrintPreallocated(array, buf, expectLen, RyanJsonFalse, NULL);
  131. TEST_ASSERT_NULL_MESSAGE(out, "预分配缺少 '\\0' 空间应失败");
  132. free(buf);
  133. RyanJsonFree(expect);
  134. RyanJsonDelete(array);
  135. }
  136. static void testStressPrintOomLargeArray(void)
  137. {
  138. RyanJson_t array = RyanJsonCreateArray();
  139. TEST_ASSERT_NOT_NULL(array);
  140. for (int32_t i = 0; i < 2000; i++)
  141. {
  142. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToArray(array, i), "向大 Array 添加 Int 失败");
  143. }
  144. // 首次分配失败
  145. UNITY_TEST_OOM_BEGIN(0);
  146. char *printed = RyanJsonPrint(array, 0, RyanJsonFalse, NULL);
  147. UNITY_TEST_OOM_END();
  148. if (printed) { RyanJsonFree(printed); }
  149. TEST_ASSERT_NULL_MESSAGE(printed, "Print OOM(首次分配失败) 应返回 NULL");
  150. // 首次分配成功,扩容失败
  151. UNITY_TEST_OOM_BEGIN(1);
  152. printed = RyanJsonPrint(array, 1, RyanJsonFalse, NULL);
  153. UNITY_TEST_OOM_END();
  154. if (printed) { RyanJsonFree(printed); }
  155. TEST_ASSERT_NULL_MESSAGE(printed, "Print OOM(扩容失败) 应返回 NULL");
  156. RyanJsonDelete(array);
  157. }
  158. static void testStressLargeObjectKeyLookup(void)
  159. {
  160. const uint32_t keyCount = 1500;
  161. RyanJson_t obj = RyanJsonCreateObject();
  162. TEST_ASSERT_NOT_NULL(obj);
  163. for (uint32_t i = 0; i < keyCount; i++)
  164. {
  165. char key[24];
  166. RyanJsonSnprintf(key, sizeof(key), "k%04u", (unsigned)i);
  167. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToObject(obj, key, (int32_t)i), "大 Object 添加 key 失败");
  168. }
  169. TEST_ASSERT_EQUAL_UINT32_MESSAGE(keyCount, (uint32_t)RyanJsonGetSize(obj), "大 Object 大小错误");
  170. // 热点索引查找:头/中/尾
  171. const uint32_t lookupIndex[] = {0U, keyCount / 2U, keyCount - 1U};
  172. for (uint32_t i = 0; i < sizeof(lookupIndex) / sizeof(lookupIndex[0]); i++)
  173. {
  174. char key[24];
  175. uint32_t idx = lookupIndex[i];
  176. RyanJsonSnprintf(key, sizeof(key), "k%04u", (unsigned)idx);
  177. RyanJson_t item = RyanJsonGetObjectByKey(obj, key);
  178. TEST_ASSERT_NOT_NULL_MESSAGE(item, "大 Object key 查找失败");
  179. TEST_ASSERT_EQUAL_INT32_MESSAGE((int32_t)idx, RyanJsonGetIntValue(item), "大 Object key 查找值错误");
  180. }
  181. // 替换中间节点并验证
  182. {
  183. char midKey[24];
  184. uint32_t mid = keyCount / 2U;
  185. RyanJsonSnprintf(midKey, sizeof(midKey), "k%04u", (unsigned)mid);
  186. RyanJson_t replaceItem = RyanJsonCreateInt(midKey, -12345);
  187. TEST_ASSERT_NOT_NULL(replaceItem);
  188. TEST_ASSERT_TRUE_MESSAGE(RyanJsonReplaceByKey(obj, midKey, replaceItem), "大 Object 中间节点替换失败");
  189. TEST_ASSERT_EQUAL_INT32_MESSAGE(-12345, RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, midKey)),
  190. "大 Object 中间节点替换值错误");
  191. }
  192. uint32_t len = 0;
  193. char *printed = RyanJsonPrint(obj, 0, RyanJsonFalse, &len);
  194. TEST_ASSERT_NOT_NULL_MESSAGE(printed, "大 Object 序列化失败");
  195. TEST_ASSERT_TRUE_MESSAGE(len > keyCount * 6U, "大 Object 序列化长度异常");
  196. RyanJson_t roundtrip = RyanJsonParse(printed);
  197. TEST_ASSERT_NOT_NULL_MESSAGE(roundtrip, "大 Object 往返测试:解析失败");
  198. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(obj, roundtrip), "大 Object 往返测试:前后 Compare 不一致");
  199. RyanJsonDelete(roundtrip);
  200. RyanJsonFree(printed);
  201. RyanJsonDelete(obj);
  202. }
  203. void testStressRunner(void)
  204. {
  205. UnitySetTestFile(__FILE__);
  206. RUN_TEST(testStressLongString);
  207. RUN_TEST(testStressLargeArray);
  208. RUN_TEST(testStressPrint);
  209. RUN_TEST(testStressLargeArrayRoundtrip);
  210. RUN_TEST(testStressLargeStringArrayPreallocated);
  211. RUN_TEST(testStressLargeStringArrayPreallocatedNoTerminator);
  212. RUN_TEST(testStressPrintOomLargeArray);
  213. RUN_TEST(testStressLargeObjectKeyLookup);
  214. }