testRobust.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. #include "testBase.h"
  2. static int32_t gFailAfter = -1;
  3. static int32_t gAllocCount = 0;
  4. static void *failingMalloc(size_t size)
  5. {
  6. if (gFailAfter >= 0 && gAllocCount++ >= gFailAfter) { return NULL; }
  7. return unityTestMalloc(size);
  8. }
  9. static void *failingRealloc(void *block, size_t size)
  10. {
  11. if (gFailAfter >= 0 && gAllocCount++ >= gFailAfter) { return NULL; }
  12. return unityTestRealloc(block, size);
  13. }
  14. static void setFailAfter(int32_t n)
  15. {
  16. gFailAfter = n;
  17. gAllocCount = 0;
  18. RyanJsonInitHooks(failingMalloc, unityTestFree, failingRealloc);
  19. }
  20. static void setFailAfterNoRealloc(int32_t n)
  21. {
  22. gFailAfter = n;
  23. gAllocCount = 0;
  24. RyanJsonInitHooks(failingMalloc, unityTestFree, NULL);
  25. }
  26. static void restoreHooks(void)
  27. {
  28. RyanJsonInitHooks(unityTestMalloc, unityTestFree, unityTestRealloc);
  29. gFailAfter = -1;
  30. gAllocCount = 0;
  31. }
  32. static void assertMinifyEq(char *buffer, int32_t textLen, const char *expected)
  33. {
  34. uint32_t len = RyanJsonMinify(buffer, textLen);
  35. TEST_ASSERT_EQUAL_STRING(expected, buffer);
  36. TEST_ASSERT_EQUAL_UINT32((uint32_t)strlen(expected), len);
  37. }
  38. #define expectCreateNullUnderOom(failAfter, expr, msg) \
  39. do \
  40. { \
  41. setFailAfter((failAfter)); \
  42. RyanJson_t _node = (expr); \
  43. restoreHooks(); \
  44. if (_node) { RyanJsonDelete(_node); } \
  45. TEST_ASSERT_NULL_MESSAGE(_node, (msg)); \
  46. } while (0)
  47. static void testParseOptionsTerminator(void)
  48. {
  49. const char *end = NULL;
  50. // 允许尾部内容:requireNullTerminator = false
  51. const char *text = " {\"a\":1} trailing";
  52. RyanJson_t json = RyanJsonParseOptions(text, (uint32_t)strlen(text), RyanJsonFalse, &end);
  53. TEST_ASSERT_NOT_NULL_MESSAGE(json, "ParseOptions(允许尾部) 失败");
  54. TEST_ASSERT_NOT_NULL_MESSAGE(end, "parseEndPtr 不应为 NULL");
  55. TEST_ASSERT_EQUAL_STRING_MESSAGE(" trailing", end, "parseEndPtr 位置错误");
  56. RyanJsonDelete(json);
  57. // 禁止尾部内容:requireNullTerminator = true
  58. json = RyanJsonParseOptions(text, (uint32_t)strlen(text), RyanJsonTrue, NULL);
  59. TEST_ASSERT_NULL_MESSAGE(json, "ParseOptions(强制结尾) 应失败");
  60. // 仅包含空白尾部:应成功,parseEndPtr 应指向末尾
  61. text = "{\"a\":1} \t\r\n";
  62. json = RyanJsonParseOptions(text, (uint32_t)strlen(text), RyanJsonTrue, &end);
  63. TEST_ASSERT_NOT_NULL_MESSAGE(json, "ParseOptions(空白尾部) 失败");
  64. TEST_ASSERT_NOT_NULL(end);
  65. TEST_ASSERT_EQUAL_CHAR('\0', *end);
  66. RyanJsonDelete(json);
  67. // 限长解析:仅解析前半段
  68. const char *concat = "{\"a\":1}{\"b\":2}";
  69. uint32_t firstLen = (uint32_t)strlen("{\"a\":1}");
  70. end = NULL;
  71. json = RyanJsonParseOptions(concat, firstLen, RyanJsonTrue, &end);
  72. TEST_ASSERT_NOT_NULL_MESSAGE(json, "ParseOptions(限长解析) 失败");
  73. TEST_ASSERT_NOT_NULL(end);
  74. TEST_ASSERT_EQUAL_STRING_MESSAGE("{\"b\":2}", end, "size-limited parseEndPtr 错误");
  75. RyanJsonDelete(json);
  76. }
  77. static void testMinifyComplexEscapesAndComments(void)
  78. {
  79. // 注释应被剔除,但字符串里的注释片段必须保留
  80. char buf[] = " { \"url\" : \"http://x//y\" , /* block */ \"path\" : \"C:\\\\tmp\\\\/*file*/\" , // line\n \"ok\" : true } ";
  81. assertMinifyEq(buf, (int32_t)strlen(buf), "{\"url\":\"http://x//y\",\"path\":\"C:\\\\tmp\\\\/*file*/\",\"ok\":true}");
  82. // 转义引号与字符串内 // 也应保持原样
  83. char buf2[] = "{\"msg\":\"he said: \\\"/*no*/\\\" //keep\" , \"v\" : 1} ";
  84. assertMinifyEq(buf2, (int32_t)strlen(buf2), "{\"msg\":\"he said: \\\"/*no*/\\\" //keep\",\"v\":1}");
  85. }
  86. static void testMinifyNoTerminatorOverflow(void)
  87. {
  88. // textLen 不包含额外 '\0' 空间时,不应越界写终止符
  89. uint8_t rawBuf[8] = {'{', '\"', 'a', '\"', ':', '1', '}', '#'};
  90. uint32_t len = RyanJsonMinify((char *)rawBuf, 7);
  91. TEST_ASSERT_EQUAL_UINT32(7, len);
  92. TEST_ASSERT_EQUAL_UINT8('#', rawBuf[7]);
  93. TEST_ASSERT_EQUAL_UINT8('{', rawBuf[0]);
  94. TEST_ASSERT_EQUAL_UINT8('\"', rawBuf[1]);
  95. TEST_ASSERT_EQUAL_UINT8('a', rawBuf[2]);
  96. TEST_ASSERT_EQUAL_UINT8('\"', rawBuf[3]);
  97. TEST_ASSERT_EQUAL_UINT8(':', rawBuf[4]);
  98. TEST_ASSERT_EQUAL_UINT8('1', rawBuf[5]);
  99. TEST_ASSERT_EQUAL_UINT8('}', rawBuf[6]);
  100. }
  101. static void testMinifyCommentBoundaryCases(void)
  102. {
  103. // 行注释直到输入结束(无换行)
  104. char lineTail[] = "{\"a\":1}//tail";
  105. assertMinifyEq(lineTail, (int32_t)strlen(lineTail), "{\"a\":1}");
  106. // 块注释未闭合:应安全走到 end,不越界
  107. char blockTail[] = "{\"a\":1}/*tail";
  108. assertMinifyEq(blockTail, (int32_t)strlen(blockTail), "{\"a\":1}");
  109. // 末尾孤立 '/' 不是注释起始,应保留
  110. char loneSlash[] = "{\"a\":1}/";
  111. assertMinifyEq(loneSlash, (int32_t)strlen(loneSlash), "{\"a\":1}/");
  112. // 字符串内末尾反斜杠且 textLen 截断,覆盖 text + 1 < end 为 false 的路径
  113. char rawTruncated[3] = {'\"', 'a', '\\'};
  114. uint32_t len = RyanJsonMinify(rawTruncated, 3);
  115. TEST_ASSERT_EQUAL_UINT32(3U, len);
  116. TEST_ASSERT_EQUAL_UINT8('\"', (uint8_t)rawTruncated[0]);
  117. TEST_ASSERT_EQUAL_UINT8('a', (uint8_t)rawTruncated[1]);
  118. TEST_ASSERT_EQUAL_UINT8('\\', (uint8_t)rawTruncated[2]);
  119. }
  120. static void testMinifyWhitespaceAndNonCommentSlashPaths(void)
  121. {
  122. char tabLeading[] = "\t{\"a\":1}";
  123. assertMinifyEq(tabLeading, (int32_t)strlen(tabLeading), "{\"a\":1}");
  124. char crLeading[] = "\r{\"b\":2}";
  125. assertMinifyEq(crLeading, (int32_t)strlen(crLeading), "{\"b\":2}");
  126. // "/x" 不是注释,应完整保留
  127. char slashNonComment[] = "/x";
  128. assertMinifyEq(slashNonComment, (int32_t)strlen(slashNonComment), "/x");
  129. // 块注释内出现 '*' 但后续不是 '/',应继续扫描直到真正闭合
  130. char blockWithStar[] = "/*a*b*/{\"k\":1}";
  131. assertMinifyEq(blockWithStar, (int32_t)strlen(blockWithStar), "{\"k\":1}");
  132. // 未闭合块注释且最后一个字符是 '*'
  133. char blockEndWithStar[] = "/*abc*";
  134. assertMinifyEq(blockEndWithStar, (int32_t)strlen(blockEndWithStar), "");
  135. }
  136. static void testParseAllocatedKeyCleanupOnValueError(void)
  137. {
  138. const char *bad = "{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\":}";
  139. RyanJson_t json = RyanJsonParse(bad);
  140. TEST_ASSERT_NULL_MESSAGE(json, "长 key 后 value 非法时应解析失败");
  141. }
  142. static void testPrintPreallocatedArgGuards(void)
  143. {
  144. RyanJson_t obj = RyanJsonCreateObject();
  145. TEST_ASSERT_NOT_NULL(obj);
  146. RyanJsonAddStringToObject(obj, "k", "v");
  147. char buf[16] = {0};
  148. TEST_ASSERT_NULL(RyanJsonPrintPreallocated(NULL, buf, sizeof(buf), RyanJsonFalse, NULL));
  149. TEST_ASSERT_NULL(RyanJsonPrintPreallocated(obj, NULL, sizeof(buf), RyanJsonFalse, NULL));
  150. TEST_ASSERT_NULL(RyanJsonPrintPreallocated(obj, buf, 0, RyanJsonFalse, NULL));
  151. uint32_t len = 0;
  152. char *out = RyanJsonPrintPreallocated(obj, buf, sizeof(buf), RyanJsonFalse, &len);
  153. TEST_ASSERT_NOT_NULL(out);
  154. TEST_ASSERT_EQUAL_STRING("{\"k\":\"v\"}", out);
  155. TEST_ASSERT_EQUAL_UINT32((uint32_t)strlen(out), len);
  156. RyanJsonDelete(obj);
  157. }
  158. static void testInitHooksAndCreateApiGuards(void)
  159. {
  160. TEST_ASSERT_FALSE_MESSAGE(RyanJsonInitHooks(NULL, unityTestFree, unityTestRealloc), "InitHooks(NULL malloc) 应失败");
  161. TEST_ASSERT_FALSE_MESSAGE(RyanJsonInitHooks(unityTestMalloc, NULL, unityTestRealloc), "InitHooks(NULL free) 应失败");
  162. TEST_ASSERT_TRUE_MESSAGE(RyanJsonInitHooks(unityTestMalloc, unityTestFree, unityTestRealloc), "恢复默认 hooks 应成功");
  163. TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateString("k", NULL), "CreateString(NULL value) 应返回 NULL");
  164. TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateIntArray(NULL, 1), "CreateIntArray(NULL,1) 应返回 NULL");
  165. TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateDoubleArray(NULL, 1), "CreateDoubleArray(NULL,1) 应返回 NULL");
  166. TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateStringArray(NULL, 1), "CreateStringArray(NULL,1) 应返回 NULL");
  167. }
  168. static void testNumberBoundaries(void)
  169. {
  170. RyanJson_t json = RyanJsonParse("{\"i\":2147483647,\"i2\":-2147483648,\"i3\":2147483648,\"n\":-0}");
  171. TEST_ASSERT_NOT_NULL(json);
  172. RyanJson_t i = RyanJsonGetObjectToKey(json, "i");
  173. RyanJson_t i2 = RyanJsonGetObjectToKey(json, "i2");
  174. RyanJson_t i3 = RyanJsonGetObjectToKey(json, "i3");
  175. RyanJson_t n = RyanJsonGetObjectToKey(json, "n");
  176. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsInt(i), "2147483647 应解析为 int32_t");
  177. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsInt(i2), "-2147483648 应解析为 int32_t");
  178. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDouble(i3), "2147483648 应解析为 double");
  179. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsInt(n), "-0 应解析为 int32_t");
  180. TEST_ASSERT_EQUAL_INT_MESSAGE(0, RyanJsonGetIntValue(n), "-0 值错误");
  181. RyanJsonDelete(json);
  182. }
  183. static void testVarargsPathTypeMismatchAndNullInput(void)
  184. {
  185. RyanJson_t root = RyanJsonCreateObject();
  186. TEST_ASSERT_NOT_NULL(root);
  187. RyanJson_t arr = RyanJsonCreateArray();
  188. TEST_ASSERT_NOT_NULL(arr);
  189. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 7));
  190. RyanJsonAddItemToObject(root, "arr", arr);
  191. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(root, "n", 42));
  192. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToKey(NULL, "a"), "NULL 根节点应返回 NULL");
  193. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToIndex(NULL, 0), "NULL 根节点应返回 NULL");
  194. // 根节点是 object,也支持按索引获取直接子节点
  195. TEST_ASSERT_NOT_NULL_MESSAGE(RyanJsonGetObjectToIndex(root, 0), "object 根节点按 index=0 获取应成功");
  196. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToIndex(root, 100), "object 根节点 index 越界应返回 NULL");
  197. // 标量节点继续向下取 key/index 都应失败
  198. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToKey(root, "n", "x"), "标量节点不应继续按 key 深入");
  199. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToIndex(arr, 0, 0), "标量节点不应继续按 index 深入");
  200. TEST_ASSERT_FALSE(RyanJsonHasObjectToKey(root, "n", "x"));
  201. TEST_ASSERT_FALSE(RyanJsonHasObjectToIndex(arr, 0, 0));
  202. // 首层查找失败路径(不进入可变参数迭代)
  203. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectByKeys(root, "missing", NULL), "首层 key 缺失应返回 NULL");
  204. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectByIndexs(arr, 1, UINT32_MAX), "首层 index 越界应返回 NULL");
  205. RyanJsonDelete(root);
  206. }
  207. static void testDuplicateKeyDetach(void)
  208. {
  209. RyanJson_t obj = RyanJsonCreateObject();
  210. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "dup", 1));
  211. #if true == RyanJsonStrictObjectKeyCheck
  212. TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddIntToObject(obj, "dup", 2), "严格模式下对象不应允许重复 key");
  213. #else
  214. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToObject(obj, "dup", 2), "非严格模式下对象应允许重复 key");
  215. #endif
  216. RyanJson_t only = RyanJsonGetObjectByKey(obj, "dup");
  217. TEST_ASSERT_NOT_NULL(only);
  218. #if true == RyanJsonDefaultAddAtHead && false == RyanJsonStrictObjectKeyCheck
  219. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(only));
  220. #else
  221. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(only));
  222. #endif
  223. RyanJson_t detached = RyanJsonDetachByKey(obj, "dup");
  224. TEST_ASSERT_NOT_NULL(detached);
  225. #if true == RyanJsonDefaultAddAtHead && false == RyanJsonStrictObjectKeyCheck
  226. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(detached));
  227. #else
  228. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(detached));
  229. #endif
  230. RyanJsonDelete(detached);
  231. #if true == RyanJsonStrictObjectKeyCheck
  232. TEST_ASSERT_NULL(RyanJsonGetObjectByKey(obj, "dup"));
  233. #else
  234. RyanJson_t second = RyanJsonGetObjectByKey(obj, "dup");
  235. TEST_ASSERT_NOT_NULL(second);
  236. #if true == RyanJsonDefaultAddAtHead
  237. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(second));
  238. #else
  239. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(second));
  240. #endif
  241. RyanJson_t detached2 = RyanJsonDetachByKey(obj, "dup");
  242. TEST_ASSERT_NOT_NULL(detached2);
  243. #if true == RyanJsonDefaultAddAtHead
  244. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(detached2));
  245. #else
  246. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(detached2));
  247. #endif
  248. RyanJsonDelete(detached2);
  249. TEST_ASSERT_NULL(RyanJsonGetObjectByKey(obj, "dup"));
  250. #endif
  251. RyanJsonDelete(obj);
  252. }
  253. static void testInsertOutOfRangeAndKeyValidation(void)
  254. {
  255. // Array:index 超出范围应追加到尾部
  256. RyanJson_t arr = RyanJsonCreateArray();
  257. RyanJsonAddIntToArray(arr, 1);
  258. RyanJsonAddIntToArray(arr, 2);
  259. TEST_ASSERT_TRUE(RyanJsonInsert(arr, 100, RyanJsonCreateInt(NULL, 3)));
  260. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetSize(arr));
  261. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 2)));
  262. RyanJsonDelete(arr);
  263. // Object:item 无 key 应失败
  264. RyanJson_t obj = RyanJsonCreateObject();
  265. RyanJsonAddIntToObject(obj, "a", 1);
  266. RyanJson_t noKey = RyanJsonCreateInt(NULL, 2);
  267. TEST_ASSERT_FALSE_MESSAGE(RyanJsonInsert(obj, 0, noKey), "Object 插入无 key item 应失败");
  268. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(obj));
  269. RyanJsonDelete(obj);
  270. }
  271. static void testGetSizeNullAndContainer(void)
  272. {
  273. TEST_ASSERT_EQUAL_UINT32_MESSAGE(0, RyanJsonGetSize(NULL), "NULL GetSize 应返回 0");
  274. RyanJson_t num = RyanJsonParse("1");
  275. TEST_ASSERT_NOT_NULL(num);
  276. TEST_ASSERT_EQUAL_INT_MESSAGE(1, RyanJsonGetSize(num), "标量 GetSize 应返回 1");
  277. RyanJsonDelete(num);
  278. RyanJson_t obj = RyanJsonCreateObject();
  279. TEST_ASSERT_NOT_NULL(obj);
  280. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "a", 1));
  281. TEST_ASSERT_TRUE(RyanJsonAddItemToObject(obj, "b", RyanJsonCreateObject()));
  282. TEST_ASSERT_EQUAL_UINT32_MESSAGE(2, RyanJsonGetSize(obj), "对象 GetSize 应返回直接子节点数量");
  283. TEST_ASSERT_EQUAL_UINT32_MESSAGE(0, RyanJsonGetSize(RyanJsonGetObjectToKey(obj, "b")), "空对象 GetSize 应为 0");
  284. RyanJsonDelete(obj);
  285. RyanJson_t arr = RyanJsonCreateArray();
  286. TEST_ASSERT_NOT_NULL(arr);
  287. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 1));
  288. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 2));
  289. TEST_ASSERT_EQUAL_UINT32_MESSAGE(2, RyanJsonGetSize(arr), "数组 GetSize 应返回元素数量");
  290. RyanJsonDelete(arr);
  291. }
  292. static void testInternalUtilsBranchCoverage(void)
  293. {
  294. const char *same = "same";
  295. TEST_ASSERT_TRUE(RyanJsonInternalStrEq(same, same));
  296. TEST_ASSERT_FALSE(RyanJsonInternalStrEq("abc", "abd"));
  297. TEST_ASSERT_EQUAL_UINT8(4, RyanJsonInternalDecodeKeyLenField(3));
  298. TEST_ASSERT_EQUAL_UINT8(2, RyanJsonInternalDecodeKeyLenField(2));
  299. TEST_ASSERT_EQUAL_UINT8(1, RyanJsonInternalCalcLenBytes(UINT8_MAX));
  300. TEST_ASSERT_EQUAL_UINT8(2, RyanJsonInternalCalcLenBytes((uint32_t)UINT8_MAX + 1U));
  301. TEST_ASSERT_EQUAL_UINT8(3, RyanJsonInternalCalcLenBytes((uint32_t)UINT16_MAX + 1U));
  302. RyanJson_t arr = RyanJsonCreateArray();
  303. TEST_ASSERT_NOT_NULL(arr);
  304. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 7));
  305. RyanJson_t v = RyanJsonGetObjectByIndexs(arr, 0, UINT32_MAX);
  306. TEST_ASSERT_NOT_NULL(v);
  307. TEST_ASSERT_EQUAL_INT(7, RyanJsonGetIntValue(v));
  308. RyanJsonDelete(arr);
  309. }
  310. static void testTypedArrayCreationZeroCount(void)
  311. {
  312. int32_t intOne[1] = {1};
  313. double doubleOne[1] = {1.5};
  314. const char *strOne[1] = {"x"};
  315. RyanJson_t iArr = RyanJsonCreateIntArray(intOne, 0);
  316. RyanJson_t dArr = RyanJsonCreateDoubleArray(doubleOne, 0);
  317. RyanJson_t sArr = RyanJsonCreateStringArray(strOne, 0);
  318. TEST_ASSERT_NOT_NULL(iArr);
  319. TEST_ASSERT_NOT_NULL(dArr);
  320. TEST_ASSERT_NOT_NULL(sArr);
  321. TEST_ASSERT_EQUAL_UINT32(0, RyanJsonGetSize(iArr));
  322. TEST_ASSERT_EQUAL_UINT32(0, RyanJsonGetSize(dArr));
  323. TEST_ASSERT_EQUAL_UINT32(0, RyanJsonGetSize(sArr));
  324. RyanJsonDelete(iArr);
  325. RyanJsonDelete(dArr);
  326. RyanJsonDelete(sArr);
  327. }
  328. static void testTypedArrayCreationOomPaths(void)
  329. {
  330. int32_t ints[2] = {1, 2};
  331. double doubles[2] = {1.1, 2.2};
  332. const char *strs[2] = {"a", "b"};
  333. expectCreateNullUnderOom(1, RyanJsonCreateIntArray(ints, 2), "CreateIntArray OOM 路径应返回 NULL");
  334. expectCreateNullUnderOom(1, RyanJsonCreateDoubleArray(doubles, 2), "CreateDoubleArray OOM 路径应返回 NULL");
  335. expectCreateNullUnderOom(1, RyanJsonCreateStringArray(strs, 2), "CreateStringArray OOM 路径应返回 NULL");
  336. }
  337. static void testCreateScalarOomAndTypeGuards(void)
  338. {
  339. // CreateInt/CreateDouble 失败分支
  340. expectCreateNullUnderOom(0, RyanJsonCreateInt(NULL, 1), "CreateInt OOM 应返回 NULL");
  341. expectCreateNullUnderOom(0, RyanJsonCreateDouble(NULL, 1.5), "CreateDouble OOM 应返回 NULL");
  342. // 类型判定与 GetObjectByKey 空参分支
  343. RyanJson_t nullNode = RyanJsonCreateNull(NULL);
  344. RyanJson_t intNode = RyanJsonCreateInt(NULL, 7);
  345. TEST_ASSERT_NOT_NULL(nullNode);
  346. TEST_ASSERT_NOT_NULL(intNode);
  347. TEST_ASSERT_TRUE(RyanJsonIsNull(nullNode));
  348. TEST_ASSERT_FALSE(RyanJsonIsNull(intNode));
  349. TEST_ASSERT_FALSE(RyanJsonIsNull(NULL));
  350. RyanJson_t obj = RyanJsonCreateObject();
  351. TEST_ASSERT_NOT_NULL(obj);
  352. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "a", 1));
  353. TEST_ASSERT_NULL(RyanJsonGetObjectByKey(obj, NULL));
  354. TEST_ASSERT_NULL(RyanJsonGetObjectByKey(NULL, "a"));
  355. RyanJsonDelete(obj);
  356. RyanJsonDelete(nullNode);
  357. RyanJsonDelete(intNode);
  358. }
  359. static void testPrintExpandFallbackWithoutRealloc(void)
  360. {
  361. char longValue[600] = {0};
  362. memset(longValue, 'x', sizeof(longValue) - 1U);
  363. RyanJson_t obj = RyanJsonCreateObject();
  364. TEST_ASSERT_NOT_NULL(obj);
  365. TEST_ASSERT_TRUE(RyanJsonAddStringToObject(obj, "k", longValue));
  366. // PrintWithStyle 至少会分配 RyanJsonPrintfPreAlloSize;长字符串可稳定触发扩容
  367. // 先成功分配初始缓冲,再在扩容时失败,覆盖 jsonRealloc=NULL 的 fallback 路径
  368. setFailAfterNoRealloc(1);
  369. char *printed = RyanJsonPrint(obj, RyanJsonPrintfPreAlloSize, RyanJsonFalse, NULL);
  370. restoreHooks();
  371. if (printed) { RyanJsonFree(printed); }
  372. TEST_ASSERT_NULL_MESSAGE(printed, "Print 扩容 fallback(malloc) 失败应返回 NULL");
  373. RyanJsonDelete(obj);
  374. }
  375. static void testDuplicateEmptyContainerAndOomPaths(void)
  376. {
  377. RyanJson_t root = RyanJsonCreateObject();
  378. TEST_ASSERT_NOT_NULL(root);
  379. RyanJson_t emptyObj = RyanJsonCreateObject();
  380. TEST_ASSERT_NOT_NULL(emptyObj);
  381. TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "e", emptyObj));
  382. RyanJson_t dup = RyanJsonDuplicate(root);
  383. TEST_ASSERT_NOT_NULL_MESSAGE(dup, "Duplicate(含空容器) 应成功");
  384. RyanJson_t dupE = RyanJsonGetObjectToKey(dup, "e");
  385. TEST_ASSERT_NOT_NULL(dupE);
  386. TEST_ASSERT_TRUE(RyanJsonIsObject(dupE));
  387. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(dupE));
  388. RyanJsonDelete(dup);
  389. RyanJsonDelete(root);
  390. root = RyanJsonCreateObject();
  391. TEST_ASSERT_NOT_NULL(root);
  392. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(root, "a", 1));
  393. // 根节点复制成功,首个子节点复制失败,覆盖 Duplicate error__ 路径
  394. expectCreateNullUnderOom(1, RyanJsonDuplicate(root), "Duplicate OOM 路径应返回 NULL");
  395. RyanJsonDelete(root);
  396. }
  397. static void testOomCreateParsePrint(void)
  398. {
  399. // 创建对象:首次分配失败
  400. setFailAfter(0);
  401. RyanJson_t obj = RyanJsonCreateObject();
  402. restoreHooks();
  403. if (obj) { RyanJsonDelete(obj); }
  404. TEST_ASSERT_NULL_MESSAGE(obj, "CreateObject OOM 应返回 NULL");
  405. // 解析流程:中途分配失败(长 key 触发 key buffer 分配)
  406. const char *longKeyJson =
  407. "{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\":1}";
  408. setFailAfter(1); // root 成功,key buffer 失败
  409. RyanJson_t json = RyanJsonParse(longKeyJson);
  410. restoreHooks();
  411. if (json) { RyanJsonDelete(json); }
  412. TEST_ASSERT_NULL_MESSAGE(json, "Parse OOM 应返回 NULL");
  413. // 打印流程:分配打印缓冲失败
  414. obj = RyanJsonCreateObject();
  415. RyanJsonAddIntToObject(obj, "a", 1);
  416. setFailAfter(0);
  417. char *printed = RyanJsonPrint(obj, 32, RyanJsonFalse, NULL);
  418. restoreHooks();
  419. TEST_ASSERT_NULL_MESSAGE(printed, "Print OOM 应返回 NULL");
  420. RyanJsonDelete(obj);
  421. }
  422. void testRobustRunner(void)
  423. {
  424. UnitySetTestFile(__FILE__);
  425. RUN_TEST(testParseOptionsTerminator);
  426. RUN_TEST(testMinifyComplexEscapesAndComments);
  427. RUN_TEST(testMinifyNoTerminatorOverflow);
  428. RUN_TEST(testMinifyCommentBoundaryCases);
  429. RUN_TEST(testMinifyWhitespaceAndNonCommentSlashPaths);
  430. RUN_TEST(testParseAllocatedKeyCleanupOnValueError);
  431. RUN_TEST(testPrintPreallocatedArgGuards);
  432. RUN_TEST(testInitHooksAndCreateApiGuards);
  433. RUN_TEST(testNumberBoundaries);
  434. RUN_TEST(testVarargsPathTypeMismatchAndNullInput);
  435. RUN_TEST(testDuplicateKeyDetach);
  436. RUN_TEST(testInsertOutOfRangeAndKeyValidation);
  437. RUN_TEST(testGetSizeNullAndContainer);
  438. RUN_TEST(testInternalUtilsBranchCoverage);
  439. RUN_TEST(testTypedArrayCreationZeroCount);
  440. RUN_TEST(testTypedArrayCreationOomPaths);
  441. RUN_TEST(testCreateScalarOomAndTypeGuards);
  442. RUN_TEST(testPrintExpandFallbackWithoutRealloc);
  443. RUN_TEST(testDuplicateEmptyContainerAndOomPaths);
  444. RUN_TEST(testOomCreateParsePrint);
  445. }