testDelete.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #include "testBase.h"
  2. static void testDeleteEdgeCases(void)
  3. {
  4. // 删除 NULL(应安全返回)
  5. RyanJsonDelete(NULL);
  6. // RyanJsonDeleteByKey 参数校验
  7. RyanJson_t obj = RyanJsonCreateObject();
  8. RyanJsonAddIntToObject(obj, "a", 1);
  9. TEST_ASSERT_FALSE_MESSAGE(RyanJsonDeleteByKey(NULL, "a"), "DeleteByKey(NULL, key) 应返回 False");
  10. TEST_ASSERT_FALSE_MESSAGE(RyanJsonDeleteByKey(obj, NULL), "DeleteByKey(obj, NULL) 应返回 False");
  11. TEST_ASSERT_FALSE_MESSAGE(RyanJsonDeleteByKey(obj, "non_existent"), "DeleteByKey(不存在的key) 应返回 False");
  12. // RyanJsonDeleteByIndex 参数校验
  13. TEST_ASSERT_FALSE_MESSAGE(RyanJsonDeleteByIndex(NULL, 0), "DeleteByIndex(NULL, 0) 应返回 False");
  14. TEST_ASSERT_FALSE_MESSAGE(RyanJsonDeleteByIndex(obj, 999), "DeleteByIndex(越界) 应返回 False");
  15. // 从非容器类型删除
  16. RyanJson_t num = RyanJsonCreateInt("num", 123);
  17. TEST_ASSERT_FALSE_MESSAGE(RyanJsonDeleteByKey(num, "a"), "从非容器 DeleteByKey 应返回 False"); // 内部 Detach 会做类型与存在性检查
  18. TEST_ASSERT_FALSE_MESSAGE(RyanJsonDeleteByIndex(num, 0), "从非容器 DeleteByIndex 应返回 False");
  19. RyanJsonDelete(obj);
  20. RyanJsonDelete(num);
  21. }
  22. static void testDeleteMassiveItemsStress(void)
  23. {
  24. // 连续删除直到空(Array)
  25. RyanJson_t arr = RyanJsonCreateArray();
  26. for (int32_t i = 0; i < 100; i++)
  27. {
  28. RyanJsonAddIntToArray(arr, i);
  29. }
  30. TEST_ASSERT_EQUAL_INT(100, RyanJsonGetSize(arr));
  31. // 从头部连续删除
  32. while (RyanJsonGetSize(arr) > 0)
  33. {
  34. TEST_ASSERT_TRUE(RyanJsonDeleteByIndex(arr, 0));
  35. }
  36. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetSize(arr));
  37. // 空 Array 删除
  38. TEST_ASSERT_FALSE(RyanJsonDeleteByIndex(arr, 0));
  39. RyanJsonDelete(arr);
  40. // 连续删除直到空(Object)
  41. RyanJson_t obj = RyanJsonCreateObject();
  42. char key[16];
  43. for (int32_t i = 0; i < 100; i++)
  44. {
  45. snprintf(key, sizeof(key), "%d", i);
  46. RyanJsonAddIntToObject(obj, key, i);
  47. }
  48. TEST_ASSERT_EQUAL_INT(100, RyanJsonGetSize(obj));
  49. // 从头部连续删除(Object 也是链表,ByIndex=0 有效)
  50. while (RyanJsonGetSize(obj) > 0)
  51. {
  52. TEST_ASSERT_TRUE(RyanJsonDeleteByIndex(obj, 0));
  53. }
  54. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetSize(obj));
  55. // Object 按 key 全量删除
  56. for (int32_t i = 0; i < 100; i++)
  57. {
  58. snprintf(key, sizeof(key), "%d", i);
  59. RyanJsonAddIntToObject(obj, key, i);
  60. }
  61. for (int32_t i = 0; i < 100; i++)
  62. {
  63. snprintf(key, sizeof(key), "%d", i);
  64. TEST_ASSERT_TRUE(RyanJsonDeleteByKey(obj, key));
  65. }
  66. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetSize(obj));
  67. // 空 Object 删除不存在的 key
  68. TEST_ASSERT_FALSE(RyanJsonDeleteByKey(obj, "any"));
  69. RyanJsonDelete(obj);
  70. }
  71. static void testDeleteSingleNodeAndReuse(void)
  72. {
  73. // Object:删除唯一节点后应保持可复用
  74. RyanJson_t obj = RyanJsonCreateObject();
  75. TEST_ASSERT_NOT_NULL(obj);
  76. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "a", 1));
  77. TEST_ASSERT_TRUE(RyanJsonDeleteByKey(obj, "a"));
  78. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetSize(obj));
  79. TEST_ASSERT_NULL(RyanJsonGetObjectValue(obj));
  80. TEST_ASSERT_FALSE(RyanJsonDeleteByKey(obj, "a"));
  81. TEST_ASSERT_TRUE(RyanJsonAddStringToObject(obj, "b", "ok"));
  82. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(obj));
  83. TEST_ASSERT_EQUAL_STRING("ok", RyanJsonGetStringValue(RyanJsonGetObjectByKey(obj, "b")));
  84. // Array:删除唯一节点后应保持可复用
  85. RyanJson_t arr = RyanJsonCreateArray();
  86. TEST_ASSERT_NOT_NULL(arr);
  87. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 9));
  88. TEST_ASSERT_TRUE(RyanJsonDeleteByIndex(arr, 0));
  89. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetSize(arr));
  90. TEST_ASSERT_NULL(RyanJsonGetObjectValue(arr));
  91. TEST_ASSERT_FALSE(RyanJsonDeleteByIndex(arr, 0));
  92. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 10));
  93. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(arr));
  94. TEST_ASSERT_EQUAL_INT(10, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 0)));
  95. RyanJsonDelete(arr);
  96. RyanJsonDelete(obj);
  97. }
  98. static void testDeleteTailAndMiddleThenAppend(void)
  99. {
  100. // Object:删除尾和中间节点后再次追加,验证链表仍可正常维护
  101. RyanJson_t obj = RyanJsonCreateObject();
  102. TEST_ASSERT_NOT_NULL(obj);
  103. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "a", 1));
  104. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "b", 2));
  105. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "c", 3));
  106. TEST_ASSERT_TRUE(RyanJsonDeleteByKey(obj, "c"));
  107. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetSize(obj));
  108. TEST_ASSERT_TRUE(RyanJsonDeleteByKey(obj, "b"));
  109. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(obj));
  110. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "d", 4));
  111. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetSize(obj));
  112. #if true == RyanJsonDefaultAddAtHead
  113. TEST_ASSERT_EQUAL_INT(4, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(obj, 0)));
  114. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(obj, 1)));
  115. #else
  116. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(obj, 0)));
  117. TEST_ASSERT_EQUAL_INT(4, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(obj, 1)));
  118. #endif
  119. // Array:同样覆盖“删尾/删中后再追加”路径
  120. RyanJson_t arr = RyanJsonCreateArray();
  121. TEST_ASSERT_NOT_NULL(arr);
  122. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 10));
  123. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 20));
  124. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 30));
  125. TEST_ASSERT_TRUE(RyanJsonDeleteByIndex(arr, 2));
  126. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetSize(arr));
  127. TEST_ASSERT_TRUE(RyanJsonDeleteByIndex(arr, 1));
  128. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(arr));
  129. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 40));
  130. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetSize(arr));
  131. #if true == RyanJsonDefaultAddAtHead
  132. TEST_ASSERT_EQUAL_INT(40, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 0)));
  133. TEST_ASSERT_EQUAL_INT(30, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 1)));
  134. #else
  135. TEST_ASSERT_EQUAL_INT(10, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 0)));
  136. TEST_ASSERT_EQUAL_INT(40, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 1)));
  137. #endif
  138. RyanJsonDelete(arr);
  139. RyanJsonDelete(obj);
  140. }
  141. static void testDeleteStandardOperations(void)
  142. {
  143. // 保持原始 jsonStr,不做修改
  144. char jsonstr[] =
  145. "{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null,\"item\":"
  146. "{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null},"
  147. "\"arrayInt\":[16,16,16,16,16],\"arrayDouble\":[16.89,16.89,16.89,16.89,16.89],"
  148. "\"arrayString\":[\"hello\",\"hello\",\"hello\",\"hello\",\"hello\"],"
  149. "\"array\":[16,16.89,\"hello\",true,false,null],"
  150. "\"arrayItem\":[{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null},"
  151. "{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null}],"
  152. "\"string2222\":\"hello\"}";
  153. RyanJson_t json = RyanJsonParse(jsonstr);
  154. TEST_ASSERT_NOT_NULL_MESSAGE(json, "解析 Json 失败");
  155. /**
  156. * @brief 删除 Object 中的节点(头、中、尾)
  157. */
  158. // 删除中间节点(Double)
  159. RyanJsonDeleteByKey(json, "double");
  160. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToKey(json, "double"), "删除中间节点 double 失败");
  161. // 删除头部节点(inter)
  162. RyanJsonDeleteByIndex(json, 0);
  163. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToKey(json, "inter"), "删除头部节点 inter 失败");
  164. // 删除尾部节点(string2222)
  165. uint32_t lastIndex = RyanJsonGetSize(json) - 1;
  166. RyanJsonDeleteByIndex(json, lastIndex);
  167. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToKey(json, "string2222"), "删除尾部节点 string2222 失败");
  168. /**
  169. * @brief 删除 Array 中的元素(arrayInt)
  170. */
  171. RyanJson_t array = RyanJsonGetObjectToKey(json, "arrayInt");
  172. TEST_ASSERT_NOT_NULL_MESSAGE(array, "获取 arrayInt 失败");
  173. // 删除 Array 首位
  174. RyanJsonDeleteByIndex(array, 0);
  175. TEST_ASSERT_EQUAL_INT_MESSAGE(4, RyanJsonGetSize(array), "删除 Array 首位后长度错误");
  176. // 删除 Array 中间元素
  177. RyanJsonDeleteByIndex(array, 1);
  178. TEST_ASSERT_EQUAL_INT_MESSAGE(3, RyanJsonGetSize(array), "删除 Array 中间元素后长度错误");
  179. // 删除 Array 尾部元素
  180. lastIndex = RyanJsonGetSize(array) - 1;
  181. RyanJsonDeleteByIndex(array, lastIndex);
  182. TEST_ASSERT_EQUAL_INT_MESSAGE(2, RyanJsonGetSize(array), "删除 Array 尾部元素后长度错误");
  183. /**
  184. * @brief 深层嵌套删除(item)
  185. */
  186. RyanJsonDeleteByKey(json, "item");
  187. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToKey(json, "item"), "删除嵌套 Object item 失败");
  188. /**
  189. * @brief Array 中 Object 元素删除(arrayItem)
  190. */
  191. RyanJson_t arrObj = RyanJsonGetObjectToKey(json, "arrayItem");
  192. TEST_ASSERT_NOT_NULL_MESSAGE(arrObj, "获取 arrayItem 失败");
  193. // 删除第一个 Object
  194. RyanJsonDeleteByIndex(arrObj, 0);
  195. TEST_ASSERT_EQUAL_INT_MESSAGE(1, RyanJsonGetSize(arrObj), "删除 Array 首个 Object 后长度错误");
  196. // 删除最后一个 Object
  197. RyanJsonDeleteByIndex(arrObj, 0);
  198. TEST_ASSERT_EQUAL_INT_MESSAGE(0, RyanJsonGetSize(arrObj), "删除 Array 最后一个 Object 后长度错误");
  199. /**
  200. * @brief 特殊类型删除(Null / Bool)
  201. */
  202. RyanJsonDeleteByKey(json, "null");
  203. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToKey(json, "null"), "删除 null 节点失败");
  204. RyanJsonDeleteByKey(json, "boolTrue");
  205. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToKey(json, "boolTrue"), "删除 boolTrue 节点失败");
  206. RyanJsonDeleteByKey(json, "boolFalse");
  207. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectToKey(json, "boolFalse"), "删除 boolFalse 节点失败");
  208. /**
  209. * @brief 异常路径覆盖(健壮性)
  210. */
  211. RyanJsonDeleteByKey(json, "non_exist"); // 删除不存在的 key
  212. RyanJsonDeleteByIndex(NULL, 0); // 在 NULL 上操作
  213. RyanJsonDelete(json);
  214. }
  215. static void testDeleteFailureAtomicityAndRebuildChain(void)
  216. {
  217. // 复杂链路:
  218. // Parse -> Delete(失败) -> Compare(snapshot) -> Delete(成功)
  219. // -> Insert/Change 重建 -> Compare(期望文档) -> Roundtrip。
  220. // 目标:
  221. // - 验证删除失败路径不会污染文档;
  222. // - 验证 Object/Array 删除后可通过插入与修改完成稳定重建;
  223. // - 验证重建后的语义可与期望文档一致。
  224. const char *source = "{\"obj\":{\"a\":1,\"b\":2},\"arr\":[1,2,3],\"meta\":{\"ok\":true}}";
  225. const char *expectText = "{\"obj\":{\"a\":1,\"c\":5},\"arr\":[1,9,3],\"meta\":{\"status\":\"done\"}}";
  226. RyanJson_t root = RyanJsonParse(source);
  227. TEST_ASSERT_NOT_NULL_MESSAGE(root, "Delete 链路样本解析失败");
  228. RyanJson_t snapshot = RyanJsonDuplicate(root);
  229. TEST_ASSERT_NOT_NULL_MESSAGE(snapshot, "Delete 链路快照构造失败");
  230. RyanJson_t obj = RyanJsonGetObjectToKey(root, "obj");
  231. RyanJson_t arr = RyanJsonGetObjectToKey(root, "arr");
  232. RyanJson_t meta = RyanJsonGetObjectToKey(root, "meta");
  233. TEST_ASSERT_NOT_NULL(obj);
  234. TEST_ASSERT_NOT_NULL(arr);
  235. TEST_ASSERT_NOT_NULL(meta);
  236. // 失败路径:删除不存在节点应失败,文档语义保持不变。
  237. TEST_ASSERT_FALSE_MESSAGE(RyanJsonDeleteByKey(obj, "missing"), "DeleteByKey(不存在 key) 应失败");
  238. TEST_ASSERT_FALSE_MESSAGE(RyanJsonDeleteByIndex(arr, 99), "DeleteByIndex(越界) 应失败");
  239. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root, snapshot), "仅发生失败删除时,文档应与 snapshot 一致");
  240. // 成功删除并重建。
  241. TEST_ASSERT_TRUE_MESSAGE(RyanJsonDeleteByKey(obj, "b"), "删除 obj.b 失败");
  242. TEST_ASSERT_TRUE_MESSAGE(RyanJsonDeleteByIndex(arr, 1), "删除 arr[1] 失败");
  243. TEST_ASSERT_TRUE_MESSAGE(RyanJsonDeleteByKey(meta, "ok"), "删除 meta.ok 失败");
  244. TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(obj, UINT32_MAX, RyanJsonCreateInt("c", 5)), "插入 obj.c 失败");
  245. TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(arr, 1, RyanJsonCreateInt(NULL, 9)), "插入 arr[1]=9 失败");
  246. TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(meta, 0, RyanJsonCreateString("status", "done")), "插入 meta.status 失败");
  247. TEST_ASSERT_TRUE(RyanJsonHasObjectToKey(obj, "a"));
  248. TEST_ASSERT_TRUE(RyanJsonHasObjectToKey(obj, "c"));
  249. TEST_ASSERT_FALSE(RyanJsonHasObjectToKey(obj, "b"));
  250. TEST_ASSERT_EQUAL_UINT32(3U, RyanJsonGetArraySize(arr));
  251. TEST_ASSERT_EQUAL_INT(9, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 1)));
  252. RyanJson_t expect = RyanJsonParse(expectText);
  253. TEST_ASSERT_NOT_NULL(expect);
  254. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root, expect), "Delete 链路重建结果与期望文档不一致");
  255. char *printed = RyanJsonPrint(root, 160, RyanJsonFalse, NULL);
  256. TEST_ASSERT_NOT_NULL(printed);
  257. RyanJson_t roundtrip = RyanJsonParse(printed);
  258. TEST_ASSERT_NOT_NULL(roundtrip);
  259. TEST_ASSERT_TRUE(RyanJsonCompare(root, roundtrip));
  260. RyanJsonDelete(roundtrip);
  261. RyanJsonFree(printed);
  262. RyanJsonDelete(expect);
  263. RyanJsonDelete(snapshot);
  264. RyanJsonDelete(root);
  265. }
  266. void testDeleteRunner(void)
  267. {
  268. UnitySetTestFile(__FILE__);
  269. RUN_TEST(testDeleteEdgeCases);
  270. RUN_TEST(testDeleteSingleNodeAndReuse);
  271. RUN_TEST(testDeleteTailAndMiddleThenAppend);
  272. RUN_TEST(testDeleteStandardOperations);
  273. RUN_TEST(testDeleteMassiveItemsStress);
  274. RUN_TEST(testDeleteFailureAtomicityAndRebuildChain);
  275. }