testCreate.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. #include "testBase.h"
  2. #define expectCreateNullUnderOom(failAfter, expr, msg) \
  3. do \
  4. { \
  5. UNITY_TEST_OOM_BEGIN((failAfter)); \
  6. RyanJson_t _node = (expr); \
  7. UNITY_TEST_OOM_END(); \
  8. if (_node) { RyanJsonDelete(_node); } \
  9. TEST_ASSERT_NULL_MESSAGE(_node, (msg)); \
  10. } while (0)
  11. static char *allocPatternString(uint32_t len, char ch)
  12. {
  13. char *buf = (char *)malloc(len + 1U);
  14. if (NULL == buf) { return NULL; }
  15. for (uint32_t i = 0; i < len; i++)
  16. {
  17. buf[i] = ch;
  18. }
  19. buf[len] = '\0';
  20. return buf;
  21. }
  22. static void testCreateEdgeCases(void)
  23. {
  24. // 测试创建空 Array
  25. RyanJson_t emptyArr = RyanJsonCreateArray();
  26. TEST_ASSERT_NOT_NULL(emptyArr);
  27. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetArraySize(emptyArr));
  28. RyanJsonDelete(emptyArr);
  29. // 测试通过辅助函数创建空 Array
  30. // RyanJsonCreateIntArray 传入 NULL 指针和 0 长度
  31. RyanJson_t nullIntArr = RyanJsonCreateIntArray(NULL, 0);
  32. // 该场景属于边界输入:只要不崩溃且行为可预测即可。
  33. // 若实现返回空 Array,则继续校验 size;
  34. // 若实现返回 NULL,也视为可接受行为。
  35. if (nullIntArr)
  36. {
  37. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetArraySize(nullIntArr));
  38. RyanJsonDelete(nullIntArr);
  39. }
  40. }
  41. static void testCreatePropertyCheck(void)
  42. {
  43. // 验证创建后的节点属性
  44. RyanJson_t node = RyanJsonCreateInt("age", 25);
  45. TEST_ASSERT_NOT_NULL(node);
  46. TEST_ASSERT_EQUAL_STRING("age", RyanJsonGetKey(node));
  47. TEST_ASSERT_TRUE(RyanJsonIsInt(node));
  48. TEST_ASSERT_EQUAL_INT(25, RyanJsonGetIntValue(node));
  49. RyanJsonDelete(node);
  50. node = RyanJsonCreateDouble("pi", 3.14159);
  51. TEST_ASSERT_NOT_NULL(node);
  52. TEST_ASSERT_TRUE(RyanJsonIsDouble(node));
  53. TEST_ASSERT_TRUE(RyanJsonCompareDouble(3.14159, RyanJsonGetDoubleValue(node)));
  54. RyanJsonDelete(node);
  55. node = RyanJsonCreateBool("active", RyanJsonTrue);
  56. TEST_ASSERT_NOT_NULL(node);
  57. TEST_ASSERT_TRUE(RyanJsonIsBool(node));
  58. TEST_ASSERT_EQUAL_INT(RyanJsonTrue, RyanJsonGetBoolValue(node));
  59. RyanJsonDelete(node);
  60. }
  61. static void testAddBoundary(void)
  62. {
  63. RyanJson_t obj = RyanJsonCreateObject();
  64. TEST_ASSERT_NOT_NULL(obj);
  65. // INT32 边界
  66. RyanJsonAddIntToObject(obj, "max", INT32_MAX);
  67. RyanJsonAddIntToObject(obj, "min", INT32_MIN);
  68. TEST_ASSERT_EQUAL_INT(INT32_MAX, RyanJsonGetIntValue(RyanJsonGetObjectToKey(obj, "max")));
  69. TEST_ASSERT_EQUAL_INT(INT32_MIN, RyanJsonGetIntValue(RyanJsonGetObjectToKey(obj, "min")));
  70. // Double 边界(仅做数值路径校验,不做位级比较)
  71. RyanJsonAddDoubleToObject(obj, "very_small", 1e-100);
  72. RyanJsonAddDoubleToObject(obj, "very_big", 1e+100);
  73. TEST_ASSERT_TRUE(RyanJsonIsDouble(RyanJsonGetObjectToKey(obj, "very_small")));
  74. TEST_ASSERT_TRUE(RyanJsonIsDouble(RyanJsonGetObjectToKey(obj, "very_big")));
  75. // 空 key 添加测试
  76. RyanJsonAddBoolToObject(obj, "", RyanJsonTrue);
  77. TEST_ASSERT_TRUE(RyanJsonGetBoolValue(RyanJsonGetObjectToKey(obj, "")));
  78. RyanJsonDelete(obj);
  79. }
  80. static void testCreateStandardComplexHierarchy(void)
  81. {
  82. RyanJson_t jsonRoot, item;
  83. // Object 生成测试
  84. jsonRoot = RyanJsonCreateObject();
  85. TEST_ASSERT_NOT_NULL_MESSAGE(jsonRoot, "创建 Object 失败");
  86. RyanJsonAddIntToObject(jsonRoot, "inter", 16);
  87. RyanJsonAddDoubleToObject(jsonRoot, "double", 16.89);
  88. RyanJsonAddStringToObject(jsonRoot, "string", "hello");
  89. RyanJsonAddBoolToObject(jsonRoot, "boolTrue", RyanJsonTrue);
  90. RyanJsonAddBoolToObject(jsonRoot, "boolFalse", RyanJsonFalse);
  91. RyanJsonAddNullToObject(jsonRoot, "null");
  92. /**
  93. * @brief Object 添加测试
  94. *
  95. */
  96. item = RyanJsonCreateObject();
  97. TEST_ASSERT_NOT_NULL_MESSAGE(item, "创建子 Object 失败");
  98. RyanJsonAddIntToObject(item, "inter", 16);
  99. RyanJsonAddDoubleToObject(item, "double", 16.89);
  100. RyanJsonAddStringToObject(item, "string", "hello");
  101. RyanJsonAddBoolToObject(item, "boolTrue", RyanJsonTrue);
  102. RyanJsonAddBoolToObject(item, "boolFalse", RyanJsonFalse);
  103. RyanJsonAddNullToObject(item, "null");
  104. RyanJsonAddItemToObject(jsonRoot, "item", item);
  105. /**
  106. * @brief Array 添加测试
  107. *
  108. */
  109. int32_t arrayInt[] = {16, 16, 16, 16, 16};
  110. RyanJsonAddItemToObject(jsonRoot, "arrayInt", RyanJsonCreateIntArray(arrayInt, sizeof(arrayInt) / sizeof(arrayInt[0])));
  111. double arrayDouble[] = {16.89, 16.89, 16.89, 16.89, 16.89};
  112. RyanJsonAddItemToObject(jsonRoot, "arrayDouble",
  113. RyanJsonCreateDoubleArray(arrayDouble, sizeof(arrayDouble) / sizeof(arrayDouble[0])));
  114. const char *arrayString[] = {"hello", "hello", "hello", "hello", "hello"};
  115. RyanJsonAddItemToObject(jsonRoot, "arrayString",
  116. RyanJsonCreateStringArray(arrayString, sizeof(arrayString) / sizeof(arrayString[0])));
  117. RyanJson_t array = RyanJsonCreateArray();
  118. TEST_ASSERT_NOT_NULL_MESSAGE(array, "创建 Array 失败");
  119. RyanJsonAddIntToArray(array, 16);
  120. RyanJsonAddDoubleToArray(array, 16.89);
  121. RyanJsonAddStringToArray(array, "hello");
  122. RyanJsonAddBoolToArray(array, RyanJsonTrue);
  123. RyanJsonAddBoolToArray(array, RyanJsonFalse);
  124. RyanJsonAddNullToArray(array);
  125. RyanJsonAddItemToObject(jsonRoot, "array", array);
  126. /**
  127. * @brief Object Array 测试
  128. *
  129. */
  130. RyanJson_t arrayItem = RyanJsonCreateArray();
  131. TEST_ASSERT_NOT_NULL_MESSAGE(arrayItem, "创建 ObjectArray 失败");
  132. item = RyanJsonCreateObject();
  133. TEST_ASSERT_NOT_NULL_MESSAGE(item, "创建 ObjectArray 项 1 失败");
  134. RyanJsonAddIntToObject(item, "inter", 16);
  135. RyanJsonAddDoubleToObject(item, "double", 16.89);
  136. RyanJsonAddStringToObject(item, "string", "hello");
  137. RyanJsonAddBoolToObject(item, "boolTrue", RyanJsonTrue);
  138. RyanJsonAddBoolToObject(item, "boolFalse", RyanJsonFalse);
  139. RyanJsonAddNullToObject(item, "null");
  140. RyanJsonAddItemToArray(arrayItem, item);
  141. item = RyanJsonCreateObject();
  142. TEST_ASSERT_NOT_NULL_MESSAGE(item, "创建 ObjectArray 项 2 失败");
  143. RyanJsonAddIntToObject(item, "inter", 16);
  144. RyanJsonAddDoubleToObject(item, "double", 16.89);
  145. RyanJsonAddStringToObject(item, "string", "hello");
  146. RyanJsonAddBoolToObject(item, "boolTrue", RyanJsonTrue);
  147. RyanJsonAddBoolToObject(item, "boolFalse", RyanJsonFalse);
  148. RyanJsonAddNullToObject(item, "null");
  149. RyanJsonAddItemToArray(arrayItem, item);
  150. RyanJsonAddItemToObject(jsonRoot, "arrayItem", arrayItem);
  151. // 最终验证根 Object 结构
  152. #if true == RyanJsonDefaultAddAtHead
  153. testCheckRootEx(jsonRoot, RyanJsonTrue);
  154. #else
  155. testCheckRootEx(jsonRoot, RyanJsonFalse);
  156. #endif
  157. RyanJsonDelete(jsonRoot);
  158. }
  159. static void testCreateHugeString(void)
  160. {
  161. // 极限大 String 创建(模拟大 Object;为控制测试耗时,先用 10KB 堆内存)
  162. uint32_t len = 1024 * 10;
  163. char *hugeStr = (char *)malloc(len + 1);
  164. TEST_ASSERT_NOT_NULL(hugeStr);
  165. memset(hugeStr, 'A', len);
  166. hugeStr[len] = '\0';
  167. RyanJson_t strJson = RyanJsonCreateString("huge", hugeStr);
  168. TEST_ASSERT_NOT_NULL(strJson);
  169. TEST_ASSERT_EQUAL_STRING(hugeStr, RyanJsonGetStringValue(strJson));
  170. RyanJsonDelete(strJson);
  171. free(hugeStr);
  172. // 特殊 Key 创建
  173. RyanJson_t nullKeyJson = RyanJsonCreateInt(NULL, 123);
  174. TEST_ASSERT_NOT_NULL(nullKeyJson); // 允许 NULL key(常见于 Array item)
  175. // 无 key 节点下,RyanJsonGetKey 可能返回值区指针。
  176. // 因此这里用 RyanJsonIsKey 作为权威判定。
  177. TEST_ASSERT_FALSE(RyanJsonIsKey(nullKeyJson));
  178. RyanJsonDelete(nullKeyJson);
  179. }
  180. static void testCreateOom(void)
  181. {
  182. UNITY_TEST_OOM_BEGIN(0);
  183. RyanJson_t obj = RyanJsonCreateObject();
  184. UNITY_TEST_OOM_END();
  185. if (obj) { RyanJsonDelete(obj); }
  186. TEST_ASSERT_NULL_MESSAGE(obj, "CreateObject OOM 应返回 NULL");
  187. }
  188. static void testCreateArgumentGuards(void)
  189. {
  190. TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateString("k", NULL), "CreateString(NULL value) 应返回 NULL");
  191. TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateIntArray(NULL, 1), "CreateIntArray(NULL,1) 应返回 NULL");
  192. TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateDoubleArray(NULL, 1), "CreateDoubleArray(NULL,1) 应返回 NULL");
  193. TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateStringArray(NULL, 1), "CreateStringArray(NULL,1) 应返回 NULL");
  194. }
  195. static void testCreateTypedArrayZeroCount(void)
  196. {
  197. int32_t intOne[1] = {1};
  198. double doubleOne[1] = {1.5};
  199. const char *strOne[1] = {"x"};
  200. RyanJson_t intArr = RyanJsonCreateIntArray(intOne, 0);
  201. RyanJson_t doubleArr = RyanJsonCreateDoubleArray(doubleOne, 0);
  202. RyanJson_t stringArr = RyanJsonCreateStringArray(strOne, 0);
  203. TEST_ASSERT_NOT_NULL(intArr);
  204. TEST_ASSERT_NOT_NULL(doubleArr);
  205. TEST_ASSERT_NOT_NULL(stringArr);
  206. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(intArr));
  207. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(doubleArr));
  208. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(stringArr));
  209. RyanJsonDelete(stringArr);
  210. RyanJsonDelete(doubleArr);
  211. RyanJsonDelete(intArr);
  212. }
  213. static void testCreateTypedArrayOomPaths(void)
  214. {
  215. int32_t ints[2] = {1, 2};
  216. double doubles[2] = {1.1, 2.2};
  217. const char *strs[2] = {"a", "b"};
  218. expectCreateNullUnderOom(1, RyanJsonCreateIntArray(ints, 2), "CreateIntArray OOM 路径应返回 NULL");
  219. expectCreateNullUnderOom(1, RyanJsonCreateDoubleArray(doubles, 2), "CreateDoubleArray OOM 路径应返回 NULL");
  220. expectCreateNullUnderOom(1, RyanJsonCreateStringArray(strs, 2), "CreateStringArray OOM 路径应返回 NULL");
  221. }
  222. static void testCreateScalarOom(void)
  223. {
  224. expectCreateNullUnderOom(0, RyanJsonCreateInt(NULL, 1), "CreateInt OOM 应返回 NULL");
  225. expectCreateNullUnderOom(0, RyanJsonCreateDouble(NULL, 1.5), "CreateDouble OOM 应返回 NULL");
  226. }
  227. static void testInsertOutOfRangeAndKeyValidation(void)
  228. {
  229. // Array:index 超出范围应追加到尾部
  230. RyanJson_t arr = RyanJsonCreateArray();
  231. TEST_ASSERT_NOT_NULL(arr);
  232. RyanJsonAddIntToArray(arr, 1);
  233. RyanJsonAddIntToArray(arr, 2);
  234. TEST_ASSERT_TRUE(RyanJsonInsert(arr, 100, RyanJsonCreateInt(NULL, 3)));
  235. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetSize(arr));
  236. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 2)));
  237. RyanJsonDelete(arr);
  238. // Object:item 无 key 应失败
  239. RyanJson_t obj = RyanJsonCreateObject();
  240. RyanJsonAddIntToObject(obj, "a", 1);
  241. RyanJson_t noKey = RyanJsonCreateInt(NULL, 2);
  242. TEST_ASSERT_FALSE_MESSAGE(RyanJsonInsert(obj, 0, noKey), "Object 插入无 key item 应失败");
  243. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(obj));
  244. // Object:重复 key 应失败
  245. #if true == RyanJsonStrictObjectKeyCheck
  246. TEST_ASSERT_FALSE_MESSAGE(RyanJsonInsert(obj, 0, RyanJsonCreateInt("a", 2)), "严格模式下 Object 插入重复 key 应失败");
  247. TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddIntToObject(obj, "a", 3), "严格模式下 AddIntToObject 重复 key 应失败");
  248. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(obj));
  249. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "a")));
  250. #else
  251. TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(obj, 0, RyanJsonCreateInt("a", 2)), "非严格模式下 Object 插入重复 key 应成功");
  252. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToObject(obj, "a", 3), "非严格模式下 AddIntToObject 重复 key 应成功");
  253. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetSize(obj));
  254. #if true == RyanJsonDefaultAddAtHead
  255. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "a")));
  256. #else
  257. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "a")));
  258. #endif
  259. #endif
  260. RyanJsonDelete(obj);
  261. }
  262. static void testInsertRejectAttachedItem(void)
  263. {
  264. RyanJson_t arr1 = RyanJsonCreateArray();
  265. RyanJson_t arr2 = RyanJsonCreateArray();
  266. RyanJson_t item = RyanJsonCreateInt(NULL, 1);
  267. TEST_ASSERT_TRUE(RyanJsonInsert(arr1, 0, item));
  268. TEST_ASSERT_FALSE_MESSAGE(RyanJsonInsert(arr2, 0, item), "已挂树的 item 不应再次插入");
  269. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(arr1));
  270. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetSize(arr2));
  271. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr1, 0)));
  272. RyanJsonDelete(arr1);
  273. RyanJsonDelete(arr2);
  274. }
  275. static void testDetachedItemApi(void)
  276. {
  277. TEST_ASSERT_FALSE(RyanJsonIsDetachedItem(NULL));
  278. RyanJson_t arr = RyanJsonCreateArray();
  279. RyanJson_t item = RyanJsonCreateInt(NULL, 123);
  280. TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(item));
  281. TEST_ASSERT_TRUE(RyanJsonInsert(arr, 0, item));
  282. TEST_ASSERT_FALSE(RyanJsonIsDetachedItem(item));
  283. RyanJson_t detached = RyanJsonDetachByIndex(arr, 0);
  284. TEST_ASSERT_EQUAL_PTR(item, detached);
  285. TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(detached));
  286. // 人工篡改到“非法游离态”:next==NULL 但 IsLast==1,应判定为非游离节点
  287. RyanJsonSetPayloadIsLastByFlag(detached, RyanJsonTrue);
  288. TEST_ASSERT_FALSE(RyanJsonIsDetachedItem(detached));
  289. // 恢复状态,避免影响后续释放
  290. RyanJsonSetPayloadIsLastByFlag(detached, RyanJsonFalse);
  291. TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(detached));
  292. RyanJsonDelete(detached);
  293. RyanJsonDelete(arr);
  294. }
  295. static void testAddLargeArrayStress(void)
  296. {
  297. // 压力测试:添加大量元素
  298. int32_t count = 2000; // 2000 个元素
  299. RyanJson_t arr = RyanJsonCreateArray();
  300. for (int32_t i = 0; i < count; i++)
  301. {
  302. RyanJsonAddIntToArray(arr, i);
  303. }
  304. TEST_ASSERT_EQUAL_INT(count, RyanJsonGetArraySize(arr));
  305. // 验证最后一个
  306. RyanJson_t last = RyanJsonGetObjectByIndex(arr, count - 1);
  307. #if true == RyanJsonDefaultAddAtHead
  308. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetIntValue(last));
  309. #else
  310. TEST_ASSERT_EQUAL_INT(count - 1, RyanJsonGetIntValue(last));
  311. #endif
  312. RyanJsonDelete(arr);
  313. // 防御性测试:向非容器添加
  314. RyanJson_t strNode = RyanJsonCreateString("k", "v");
  315. // 尝试向 String 节点添加子项,预期失败或不崩溃
  316. RyanJson_t item = RyanJsonCreateInt("sub", 1);
  317. RyanJsonBool_e res = RyanJsonInsert(strNode, 0, item);
  318. TEST_ASSERT_FALSE(res);
  319. // 该场景 item 是游离节点,Insert 失败会负责释放 item
  320. RyanJsonDelete(strNode);
  321. }
  322. static void testAddItemObjectSemantics(void)
  323. {
  324. // AddItemToObject 正常添加容器
  325. RyanJson_t obj = RyanJsonCreateObject();
  326. RyanJson_t childArr = RyanJsonCreateArray();
  327. TEST_ASSERT_NOT_NULL(obj);
  328. TEST_ASSERT_NOT_NULL(childArr);
  329. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(childArr, 1));
  330. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(childArr, 2));
  331. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(obj, "arr", childArr), "AddItemToObject(容器) 应成功");
  332. RyanJson_t arrNode = RyanJsonGetObjectByKey(obj, "arr");
  333. TEST_ASSERT_NOT_NULL(arrNode);
  334. TEST_ASSERT_TRUE(RyanJsonIsArray(arrNode));
  335. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetArraySize(arrNode));
  336. #if true == RyanJsonDefaultAddAtHead
  337. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrNode, 0)));
  338. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrNode, 1)));
  339. #else
  340. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrNode, 0)));
  341. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrNode, 1)));
  342. #endif
  343. // AddItemToObject 重复 key(容器)行为由严格模式控制
  344. RyanJson_t dupObj = RyanJsonCreateObject();
  345. TEST_ASSERT_NOT_NULL(dupObj);
  346. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(dupObj, "k", 99));
  347. #if true == RyanJsonStrictObjectKeyCheck
  348. TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToObject(obj, "arr", dupObj), "严格模式下 AddItemToObject(重复 key) 应失败");
  349. #else
  350. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(obj, "arr", dupObj), "非严格模式下 AddItemToObject(重复 key) 应成功");
  351. #endif
  352. #if true == RyanJsonStrictObjectKeyCheck
  353. arrNode = RyanJsonGetObjectByKey(obj, "arr");
  354. TEST_ASSERT_NOT_NULL(arrNode);
  355. TEST_ASSERT_TRUE(RyanJsonIsArray(arrNode));
  356. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetArraySize(arrNode));
  357. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(obj));
  358. #else
  359. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetSize(obj));
  360. RyanJson_t firstArrKeyNode = RyanJsonGetObjectByIndex(obj, 0);
  361. RyanJson_t secondArrKeyNode = RyanJsonGetObjectByIndex(obj, 1);
  362. TEST_ASSERT_NOT_NULL(firstArrKeyNode);
  363. TEST_ASSERT_NOT_NULL(secondArrKeyNode);
  364. TEST_ASSERT_TRUE(RyanJsonIsKey(firstArrKeyNode));
  365. TEST_ASSERT_TRUE(RyanJsonIsKey(secondArrKeyNode));
  366. TEST_ASSERT_EQUAL_STRING("arr", RyanJsonGetKey(firstArrKeyNode));
  367. TEST_ASSERT_EQUAL_STRING("arr", RyanJsonGetKey(secondArrKeyNode));
  368. #if true == RyanJsonDefaultAddAtHead
  369. // 头插模式:新插入的 dupObj 在前,旧 Array 在后
  370. TEST_ASSERT_TRUE(RyanJsonIsObject(firstArrKeyNode));
  371. TEST_ASSERT_TRUE(RyanJsonIsArray(secondArrKeyNode));
  372. TEST_ASSERT_EQUAL_INT(99, RyanJsonGetIntValue(RyanJsonGetObjectByKey(firstArrKeyNode, "k")));
  373. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetArraySize(secondArrKeyNode));
  374. arrNode = RyanJsonGetObjectByKey(obj, "arr");
  375. TEST_ASSERT_NOT_NULL(arrNode);
  376. TEST_ASSERT_TRUE(RyanJsonIsObject(arrNode));
  377. #else
  378. // 尾插模式:旧 Array 在前,新插入的 dupObj 在后
  379. TEST_ASSERT_TRUE(RyanJsonIsArray(firstArrKeyNode));
  380. TEST_ASSERT_TRUE(RyanJsonIsObject(secondArrKeyNode));
  381. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetArraySize(firstArrKeyNode));
  382. TEST_ASSERT_EQUAL_INT(99, RyanJsonGetIntValue(RyanJsonGetObjectByKey(secondArrKeyNode, "k")));
  383. arrNode = RyanJsonGetObjectByKey(obj, "arr");
  384. TEST_ASSERT_NOT_NULL(arrNode);
  385. TEST_ASSERT_TRUE(RyanJsonIsArray(arrNode));
  386. #endif
  387. #endif
  388. // AddItemToObject 传入标量应失败
  389. TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToObject(obj, "scalar", RyanJsonCreateInt(NULL, 7)), "AddItemToObject(标量) 应失败");
  390. TEST_ASSERT_NULL(RyanJsonGetObjectByKey(obj, "scalar"));
  391. // 非 Object 调用 AddItemToObject 应失败
  392. RyanJson_t notObj = RyanJsonCreateInt("num", 1);
  393. RyanJson_t childObj = RyanJsonCreateObject();
  394. TEST_ASSERT_NOT_NULL(notObj);
  395. TEST_ASSERT_NOT_NULL(childObj);
  396. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(childObj, "x", 1));
  397. TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToObject(notObj, "child", childObj), "非 Object 调用 AddItemToObject 应失败");
  398. TEST_ASSERT_TRUE(RyanJsonIsInt(notObj));
  399. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(notObj));
  400. RyanJsonDelete(notObj);
  401. RyanJsonDelete(obj);
  402. }
  403. static void testAddItemRejectsAttachedContainer(void)
  404. {
  405. // 复杂链路:
  406. // Parse(源文档) -> AddItemToObject/AddItemToArray(已挂树容器) -> 失败 -> 结构保持。
  407. // 目标:验证 AddItemToObject/AddItemToArray 仅接受游离容器。
  408. RyanJson_t src = RyanJsonParse("{\"arr\":[1,2],\"obj\":{\"k\":1}}");
  409. TEST_ASSERT_NOT_NULL(src);
  410. RyanJson_t attachedArr = RyanJsonGetObjectToKey(src, "arr");
  411. RyanJson_t attachedObj = RyanJsonGetObjectToKey(src, "obj");
  412. TEST_ASSERT_NOT_NULL(attachedArr);
  413. TEST_ASSERT_NOT_NULL(attachedObj);
  414. RyanJson_t dstObj = RyanJsonCreateObject();
  415. RyanJson_t dstArr = RyanJsonCreateArray();
  416. TEST_ASSERT_NOT_NULL(dstObj);
  417. TEST_ASSERT_NOT_NULL(dstArr);
  418. TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToObject(dstObj, "arr", attachedArr), "AddItemToObject(已挂树容器) 应失败");
  419. TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToArray(dstArr, attachedObj), "AddItemToArray(已挂树容器) 应失败");
  420. // 源文档结构应保持不变
  421. TEST_ASSERT_EQUAL_UINT32(2U, RyanJsonGetArraySize(RyanJsonGetObjectToKey(src, "arr")));
  422. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectToKey(src, "obj", "k")));
  423. // 目标容器应保持为空
  424. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(dstObj));
  425. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetArraySize(dstArr));
  426. RyanJsonDelete(dstArr);
  427. RyanJsonDelete(dstObj);
  428. RyanJsonDelete(src);
  429. }
  430. static void testAddItemObjectEmptyKeyRoundtrip(void)
  431. {
  432. // 复杂链路:
  433. // Parse(Array) -> AddItemToObject(空 key) -> Print/Parse -> key 与内容校验。
  434. // 目标:验证空 key 在 AddItemToObject 包装路径下可稳定保留。
  435. RyanJson_t root = RyanJsonCreateObject();
  436. TEST_ASSERT_NOT_NULL(root);
  437. RyanJson_t child = RyanJsonParse("[1,2]");
  438. TEST_ASSERT_NOT_NULL(child);
  439. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(root, "", child), "AddItemToObject(空 key) 应成功");
  440. RyanJson_t node = RyanJsonGetObjectByKey(root, "");
  441. TEST_ASSERT_NOT_NULL(node);
  442. TEST_ASSERT_TRUE(RyanJsonIsArray(node));
  443. TEST_ASSERT_EQUAL_UINT32(2U, RyanJsonGetArraySize(node));
  444. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(node, 0)));
  445. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(node, 1)));
  446. char *printed = RyanJsonPrint(root, 64, RyanJsonFalse, NULL);
  447. TEST_ASSERT_NOT_NULL(printed);
  448. RyanJson_t roundtrip = RyanJsonParse(printed);
  449. TEST_ASSERT_NOT_NULL(roundtrip);
  450. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(roundtrip, ""));
  451. RyanJson_t roundNode = RyanJsonGetObjectByKey(roundtrip, "");
  452. TEST_ASSERT_NOT_NULL(roundNode);
  453. TEST_ASSERT_TRUE(RyanJsonIsArray(roundNode));
  454. TEST_ASSERT_EQUAL_UINT32(2U, RyanJsonGetArraySize(roundNode));
  455. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(roundNode, 0)));
  456. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(roundNode, 1)));
  457. RyanJsonDelete(roundtrip);
  458. RyanJsonFree(printed);
  459. RyanJsonDelete(root);
  460. }
  461. static void testAddItemObjectLongKeyWrapRoundtrip(void)
  462. {
  463. // 复杂链路:
  464. // Parse(Object) -> AddItemToObject(长 key) -> Print/Parse -> key 与内容校验。
  465. // 目标:验证长 key + 包装路径稳定且可往返。
  466. uint32_t longLen = RyanJsonInlineStringSize + 8U;
  467. char *longKey = allocPatternString(longLen, 'k');
  468. TEST_ASSERT_NOT_NULL(longKey);
  469. RyanJson_t root = RyanJsonCreateObject();
  470. TEST_ASSERT_NOT_NULL(root);
  471. RyanJson_t child = RyanJsonParse("{\"v\":1}");
  472. TEST_ASSERT_NOT_NULL(child);
  473. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(root, longKey, child), "AddItemToObject(长 key) 应成功");
  474. RyanJson_t node = RyanJsonGetObjectByKey(root, longKey);
  475. TEST_ASSERT_NOT_NULL(node);
  476. TEST_ASSERT_TRUE(RyanJsonIsObject(node));
  477. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByKey(node, "v")));
  478. TEST_ASSERT_EQUAL_UINT32(longLen, (uint32_t)strlen(RyanJsonGetKey(node)));
  479. char *printed = RyanJsonPrint(root, 128, RyanJsonFalse, NULL);
  480. TEST_ASSERT_NOT_NULL(printed);
  481. RyanJson_t roundtrip = RyanJsonParse(printed);
  482. TEST_ASSERT_NOT_NULL(roundtrip);
  483. RyanJson_t roundNode = RyanJsonGetObjectByKey(roundtrip, longKey);
  484. TEST_ASSERT_NOT_NULL(roundNode);
  485. TEST_ASSERT_TRUE(RyanJsonIsObject(roundNode));
  486. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByKey(roundNode, "v")));
  487. RyanJsonDelete(roundtrip);
  488. RyanJsonFree(printed);
  489. RyanJsonDelete(root);
  490. free(longKey);
  491. }
  492. static void testCreateDetachedReuseAndContainerAssembleChain(void)
  493. {
  494. // 复杂链路:
  495. // Create(root/queue/map/nums) -> Insert(成功) -> 重复 Insert(失败)
  496. // -> DetachByIndex -> AddItemToObject(包装成功) -> Compare(期望文档) -> Roundtrip。
  497. // 目标:
  498. // - 验证已挂树节点重复插入会失败且不破坏结构;
  499. // - 验证游离节点在 Detach 后可被 AddItemToObject 稳定复用;
  500. // - 验证创建型链路最终语义可收敛到期望文档。
  501. #if true == RyanJsonDefaultAddAtHead
  502. const char *expectText = "{\"queue\":[],\"map\":{\"t1\":{\"name\":\"sync\",\"prio\":1}},\"nums\":[2,1]}";
  503. #else
  504. const char *expectText = "{\"queue\":[],\"map\":{\"t1\":{\"name\":\"sync\",\"prio\":1}},\"nums\":[1,2]}";
  505. #endif
  506. RyanJson_t root = RyanJsonCreateObject();
  507. RyanJson_t queue = RyanJsonCreateArray();
  508. RyanJson_t map = RyanJsonCreateObject();
  509. const int32_t numsRaw[] = {1, 2};
  510. RyanJson_t nums = RyanJsonCreateIntArray(numsRaw, (uint32_t)(sizeof(numsRaw) / sizeof(numsRaw[0])));
  511. TEST_ASSERT_NOT_NULL(root);
  512. TEST_ASSERT_NOT_NULL(queue);
  513. TEST_ASSERT_NOT_NULL(map);
  514. TEST_ASSERT_NOT_NULL(nums);
  515. TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "queue", queue));
  516. TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "map", map));
  517. TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "nums", nums));
  518. // 挂载后重新获取,避免使用旧缓存指针。
  519. queue = RyanJsonGetObjectToKey(root, "queue");
  520. map = RyanJsonGetObjectToKey(root, "map");
  521. TEST_ASSERT_NOT_NULL(queue);
  522. TEST_ASSERT_NOT_NULL(map);
  523. RyanJson_t task = RyanJsonCreateObject();
  524. TEST_ASSERT_NOT_NULL(task);
  525. TEST_ASSERT_TRUE(RyanJsonAddStringToObject(task, "name", "sync"));
  526. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(task, "prio", 1));
  527. TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(queue, 0, task), "首次插入任务节点应成功");
  528. TEST_ASSERT_FALSE_MESSAGE(RyanJsonInsert(queue, 1, task), "重复插入已挂树节点应失败");
  529. TEST_ASSERT_EQUAL_UINT32(1U, RyanJsonGetArraySize(queue));
  530. RyanJson_t detached = RyanJsonDetachByIndex(queue, 0);
  531. TEST_ASSERT_NOT_NULL_MESSAGE(detached, "从 queue 分离任务节点失败");
  532. TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(detached));
  533. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(map, "t1", detached), "将分离节点包装挂载到 map.t1 失败");
  534. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetArraySize(queue));
  535. TEST_ASSERT_TRUE(RyanJsonHasObjectToKey(root, "map", "t1", "name"));
  536. TEST_ASSERT_EQUAL_STRING("sync", RyanJsonGetStringValue(RyanJsonGetObjectToKey(root, "map", "t1", "name")));
  537. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectToKey(root, "map", "t1", "prio")));
  538. RyanJson_t expect = RyanJsonParse(expectText);
  539. TEST_ASSERT_NOT_NULL(expect);
  540. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root, expect), "Create 组装链路结果与期望文档不一致");
  541. char *printed = RyanJsonPrint(root, 128, RyanJsonFalse, NULL);
  542. TEST_ASSERT_NOT_NULL(printed);
  543. RyanJson_t roundtrip = RyanJsonParse(printed);
  544. TEST_ASSERT_NOT_NULL(roundtrip);
  545. TEST_ASSERT_TRUE(RyanJsonCompare(root, roundtrip));
  546. RyanJsonDelete(roundtrip);
  547. RyanJsonFree(printed);
  548. RyanJsonDelete(expect);
  549. RyanJsonDelete(root);
  550. }
  551. static void testCreateAddItemToArrayRejectScalarThenRecover(void)
  552. {
  553. // 复杂链路:
  554. // Create(root/arr) -> AddItemToArray(标量失败) -> AddItemToArray(容器) -> AddIntToArray
  555. // -> Compare(期望文档) -> Roundtrip。
  556. // 目标:
  557. // - 验证 AddItemToArray 仅接受容器节点;
  558. // - 验证失败后 Array 仍可继续复用;
  559. // - 验证恢复后的构建结果可稳定打印回读。
  560. RyanJson_t root = RyanJsonCreateObject();
  561. RyanJson_t arr = RyanJsonCreateArray();
  562. TEST_ASSERT_NOT_NULL(root);
  563. TEST_ASSERT_NOT_NULL(arr);
  564. TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "arr", arr));
  565. arr = RyanJsonGetObjectToKey(root, "arr");
  566. TEST_ASSERT_NOT_NULL(arr);
  567. RyanJson_t scalar = RyanJsonCreateInt(NULL, 7);
  568. TEST_ASSERT_NOT_NULL(scalar);
  569. TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToArray(arr, scalar), "AddItemToArray(标量) 应失败");
  570. TEST_ASSERT_EQUAL_UINT32_MESSAGE(0U, RyanJsonGetArraySize(arr), "失败后 Array 仍应为空");
  571. RyanJson_t obj = RyanJsonCreateObject();
  572. TEST_ASSERT_NOT_NULL(obj);
  573. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "v", 1));
  574. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToArray(arr, obj), "AddItemToArray(容器) 应成功");
  575. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 9));
  576. TEST_ASSERT_EQUAL_UINT32(2U, RyanJsonGetArraySize(arr));
  577. #if true == RyanJsonDefaultAddAtHead
  578. RyanJson_t expect = RyanJsonParse("{\"arr\":[9,{\"v\":1}]}");
  579. #else
  580. RyanJson_t expect = RyanJsonParse("{\"arr\":[{\"v\":1},9]}");
  581. #endif
  582. TEST_ASSERT_NOT_NULL(expect);
  583. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root, expect), "AddItemToArray 失败恢复后结构不符合预期");
  584. char *printed = RyanJsonPrint(root, 96, RyanJsonFalse, NULL);
  585. TEST_ASSERT_NOT_NULL(printed);
  586. RyanJson_t roundtrip = RyanJsonParse(printed);
  587. TEST_ASSERT_NOT_NULL(roundtrip);
  588. TEST_ASSERT_TRUE(RyanJsonCompare(root, roundtrip));
  589. RyanJsonDelete(roundtrip);
  590. RyanJsonFree(printed);
  591. RyanJsonDelete(expect);
  592. RyanJsonDelete(root);
  593. }
  594. static void testCreateInsertUsingAddPositionMacro(void)
  595. {
  596. // Create(Array) -> Insert(AddPosition) -> Compare(期望)。
  597. // 目标:验证 AddPosition 宏始终遵循当前默认插入策略。
  598. RyanJson_t arr = RyanJsonCreateArray();
  599. TEST_ASSERT_NOT_NULL(arr);
  600. TEST_ASSERT_TRUE(RyanJsonInsert(arr, RyanJsonAddPosition, RyanJsonCreateInt(NULL, 1)));
  601. TEST_ASSERT_TRUE(RyanJsonInsert(arr, RyanJsonAddPosition, RyanJsonCreateInt(NULL, 2)));
  602. TEST_ASSERT_TRUE(RyanJsonInsert(arr, RyanJsonAddPosition, RyanJsonCreateInt(NULL, 3)));
  603. #if true == RyanJsonDefaultAddAtHead
  604. const char *expectText = "[3,2,1]";
  605. #else
  606. const char *expectText = "[1,2,3]";
  607. #endif
  608. RyanJson_t expect = RyanJsonParse(expectText);
  609. TEST_ASSERT_NOT_NULL(expect);
  610. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(arr, expect), "AddPosition 顺序语义错误");
  611. RyanJsonDelete(expect);
  612. RyanJsonDelete(arr);
  613. }
  614. void testCreateRunner(void)
  615. {
  616. UnitySetTestFile(__FILE__);
  617. RUN_TEST(testCreateEdgeCases);
  618. RUN_TEST(testCreatePropertyCheck);
  619. RUN_TEST(testAddBoundary);
  620. RUN_TEST(testCreateStandardComplexHierarchy);
  621. RUN_TEST(testCreateHugeString);
  622. RUN_TEST(testCreateOom);
  623. RUN_TEST(testCreateArgumentGuards);
  624. RUN_TEST(testCreateTypedArrayZeroCount);
  625. RUN_TEST(testCreateTypedArrayOomPaths);
  626. RUN_TEST(testCreateScalarOom);
  627. RUN_TEST(testInsertOutOfRangeAndKeyValidation);
  628. RUN_TEST(testInsertRejectAttachedItem);
  629. RUN_TEST(testDetachedItemApi);
  630. RUN_TEST(testCreateInsertUsingAddPositionMacro);
  631. RUN_TEST(testAddLargeArrayStress);
  632. RUN_TEST(testAddItemObjectSemantics);
  633. RUN_TEST(testAddItemRejectsAttachedContainer);
  634. RUN_TEST(testAddItemObjectEmptyKeyRoundtrip);
  635. RUN_TEST(testAddItemObjectLongKeyWrapRoundtrip);
  636. RUN_TEST(testCreateDetachedReuseAndContainerAssembleChain);
  637. RUN_TEST(testCreateAddItemToArrayRejectScalarThenRecover);
  638. }