testStabilityLinkedListBasic.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. #include "testBase.h"
  2. static void testListStabilityArrayDetachHeadAppend(void)
  3. {
  4. // 复杂链路:
  5. // Parse(Array) -> DetachByIndex(head) -> Insert(tail) -> 遍历链表校验。
  6. // 目标:验证 Array 节点线索化链表在头删尾插后仍稳定。
  7. RyanJson_t arr = RyanJsonParse("[1,2,3]");
  8. TEST_ASSERT_NOT_NULL(arr);
  9. RyanJson_t detached = RyanJsonDetachByIndex(arr, 0);
  10. TEST_ASSERT_NOT_NULL(detached);
  11. TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(detached));
  12. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(detached), "游离 Array 节点 next 应返回 NULL");
  13. TEST_ASSERT_NULL_MESSAGE(RyanJsonInternalGetParent(detached), "游离 Array 节点 parent 应为 NULL");
  14. TEST_ASSERT_TRUE(RyanJsonInsert(arr, 99, detached));
  15. TEST_ASSERT_EQUAL_UINT32(3U, RyanJsonGetArraySize(arr));
  16. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 0)));
  17. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 1)));
  18. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 2)));
  19. TEST_ASSERT_EQUAL_PTR_MESSAGE(arr, RyanJsonInternalGetParent(detached), "回插后的 Array 节点 parent 应重新绑定");
  20. TEST_ASSERT_EQUAL_PTR_MESSAGE(detached, RyanJsonGetObjectByIndex(arr, 2), "尾插后的 Array 末元素应为回插节点");
  21. uint32_t size = RyanJsonGetArraySize(arr);
  22. uint32_t count = 0;
  23. RyanJson_t node = RyanJsonGetObjectValue(arr);
  24. RyanJson_t last = NULL;
  25. while (node)
  26. {
  27. count++;
  28. if (count > size + 1U) { TEST_FAIL_MESSAGE("Array 链表疑似形成环"); }
  29. last = node;
  30. node = RyanJsonGetNext(node);
  31. }
  32. TEST_ASSERT_EQUAL_UINT32(size, count);
  33. TEST_ASSERT_NOT_NULL(last);
  34. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(last), "Array 尾节点 GetNext 应返回 NULL");
  35. RyanJsonDelete(arr);
  36. }
  37. static void testListStabilityObjectReplaceLastThenTraverse(void)
  38. {
  39. // 复杂链路:
  40. // Parse(Object) -> ReplaceByKey(尾节点) -> 遍历链表校验。
  41. // 目标:验证 Object 尾节点替换后链表依旧稳定。
  42. RyanJson_t obj = RyanJsonParse("{\"a\":1,\"b\":2,\"c\":3}");
  43. TEST_ASSERT_NOT_NULL(obj);
  44. TEST_ASSERT_TRUE(RyanJsonReplaceByKey(obj, "c", RyanJsonCreateInt("c", 9)));
  45. TEST_ASSERT_EQUAL_INT(9, RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "c")));
  46. uint32_t size = RyanJsonGetSize(obj);
  47. uint32_t count = 0;
  48. RyanJson_t node = RyanJsonGetObjectValue(obj);
  49. RyanJson_t last = NULL;
  50. while (node)
  51. {
  52. count++;
  53. if (count > size + 1U) { TEST_FAIL_MESSAGE("Object 链表疑似形成环"); }
  54. last = node;
  55. node = RyanJsonGetNext(node);
  56. }
  57. TEST_ASSERT_EQUAL_UINT32(size, count);
  58. TEST_ASSERT_NOT_NULL(last);
  59. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(last), "Object 尾节点 GetNext 应返回 NULL");
  60. RyanJsonDelete(obj);
  61. }
  62. static void testListStabilityObjectDetachReinsertAtHead(void)
  63. {
  64. // 复杂链路:
  65. // Parse(Object) -> DetachByKey(middle) -> Insert(head) -> 遍历链表校验。
  66. // 目标:验证 Object 中间节点迁移后链表稳定。
  67. RyanJson_t obj = RyanJsonParse("{\"a\":1,\"b\":2,\"c\":3}");
  68. TEST_ASSERT_NOT_NULL(obj);
  69. RyanJson_t moved = RyanJsonDetachByKey(obj, "b");
  70. TEST_ASSERT_NOT_NULL(moved);
  71. TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(moved));
  72. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(moved), "游离 Object 节点 next 应返回 NULL");
  73. TEST_ASSERT_NULL_MESSAGE(RyanJsonInternalGetParent(moved), "游离 Object 节点 parent 应为 NULL");
  74. TEST_ASSERT_TRUE(RyanJsonInsert(obj, 0, moved));
  75. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(obj, "a"));
  76. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(obj, "b"));
  77. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(obj, "c"));
  78. TEST_ASSERT_EQUAL_UINT32(3U, RyanJsonGetSize(obj));
  79. TEST_ASSERT_EQUAL_PTR_MESSAGE(obj, RyanJsonInternalGetParent(moved), "回插后的 Object 节点 parent 应重新绑定");
  80. uint32_t size = RyanJsonGetSize(obj);
  81. uint32_t count = 0;
  82. RyanJson_t node = RyanJsonGetObjectValue(obj);
  83. RyanJson_t last = NULL;
  84. while (node)
  85. {
  86. count++;
  87. if (count > size + 1U) { TEST_FAIL_MESSAGE("Object 链表疑似形成环"); }
  88. last = node;
  89. node = RyanJsonGetNext(node);
  90. }
  91. TEST_ASSERT_EQUAL_UINT32(size, count);
  92. TEST_ASSERT_NOT_NULL(last);
  93. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(last), "Object 尾节点 GetNext 应返回 NULL");
  94. RyanJsonDelete(obj);
  95. }
  96. static void testListStabilityArrayReplaceMiddleRebindsChain(void)
  97. {
  98. // 复杂链路:
  99. // Parse(Array) -> ReplaceByIndex(middle) -> sibling/parent 校验。
  100. // 目标:验证 public Replace 会把新节点重新接入正确链路,而不是仅修改值。
  101. RyanJson_t arr = RyanJsonParse("[1,2,3]");
  102. TEST_ASSERT_NOT_NULL(arr);
  103. RyanJson_t replacement = RyanJsonCreateInt(NULL, 9);
  104. TEST_ASSERT_NOT_NULL(replacement);
  105. TEST_ASSERT_TRUE(RyanJsonReplaceByIndex(arr, 1, replacement));
  106. RyanJson_t head = RyanJsonGetObjectByIndex(arr, 0);
  107. RyanJson_t middle = RyanJsonGetObjectByIndex(arr, 1);
  108. RyanJson_t tail = RyanJsonGetObjectByIndex(arr, 2);
  109. TEST_ASSERT_NOT_NULL(head);
  110. TEST_ASSERT_NOT_NULL(middle);
  111. TEST_ASSERT_NOT_NULL(tail);
  112. TEST_ASSERT_EQUAL_PTR_MESSAGE(replacement, middle, "Replace 后中间节点应为 replacement");
  113. TEST_ASSERT_EQUAL_PTR_MESSAGE(middle, RyanJsonGetNext(head), "Replace 后 head.next 应指向新节点");
  114. TEST_ASSERT_EQUAL_PTR_MESSAGE(tail, RyanJsonGetNext(middle), "Replace 后新节点 next 应连接尾节点");
  115. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(tail), "Replace 后尾节点 next 应返回 NULL");
  116. TEST_ASSERT_EQUAL_PTR_MESSAGE(arr, RyanJsonInternalGetParent(middle), "Replace 后新节点 parent 应为 Array");
  117. RyanJsonDelete(arr);
  118. }
  119. static void testListStabilityDetachAllThenRebuild(void)
  120. {
  121. // 复杂链路:
  122. // Parse(Object) -> DetachByKey(全部) -> Insert(重建) -> 遍历链表校验。
  123. // 目标:验证 Object 被清空后重建仍保持链表稳定。
  124. RyanJson_t obj = RyanJsonParse("{\"a\":1,\"b\":2,\"c\":3}");
  125. TEST_ASSERT_NOT_NULL(obj);
  126. RyanJson_t a = RyanJsonDetachByKey(obj, "a");
  127. RyanJson_t b = RyanJsonDetachByKey(obj, "b");
  128. RyanJson_t c = RyanJsonDetachByKey(obj, "c");
  129. TEST_ASSERT_NOT_NULL(a);
  130. TEST_ASSERT_NOT_NULL(b);
  131. TEST_ASSERT_NOT_NULL(c);
  132. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(obj));
  133. TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(a));
  134. TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(b));
  135. TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(c));
  136. TEST_ASSERT_TRUE(RyanJsonInsert(obj, 0, c));
  137. TEST_ASSERT_TRUE(RyanJsonInsert(obj, 0, b));
  138. TEST_ASSERT_TRUE(RyanJsonInsert(obj, 0, a));
  139. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(obj, "a"));
  140. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(obj, "b"));
  141. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(obj, "c"));
  142. TEST_ASSERT_EQUAL_UINT32(3U, RyanJsonGetSize(obj));
  143. uint32_t size = RyanJsonGetSize(obj);
  144. uint32_t count = 0;
  145. RyanJson_t node = RyanJsonGetObjectValue(obj);
  146. RyanJson_t last = NULL;
  147. while (node)
  148. {
  149. count++;
  150. if (count > size + 1U) { TEST_FAIL_MESSAGE("Object 链表疑似形成环"); }
  151. last = node;
  152. node = RyanJsonGetNext(node);
  153. }
  154. TEST_ASSERT_EQUAL_UINT32(size, count);
  155. TEST_ASSERT_NOT_NULL(last);
  156. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(last), "Object 尾节点 GetNext 应返回 NULL");
  157. RyanJsonDelete(obj);
  158. }
  159. static void testListStabilityArrayMoveBetweenParents(void)
  160. {
  161. // 复杂链路:
  162. // Parse(root) -> DetachByIndex(arrA) -> Insert(arrB) -> 遍历链表校验。
  163. // 目标:验证 Array 元素跨父节点迁移后链表稳定。
  164. RyanJson_t root = RyanJsonParse("{\"a\":[1,2],\"b\":[3,4]}");
  165. TEST_ASSERT_NOT_NULL(root);
  166. RyanJson_t arrA = RyanJsonGetObjectToKey(root, "a");
  167. RyanJson_t arrB = RyanJsonGetObjectToKey(root, "b");
  168. TEST_ASSERT_NOT_NULL(arrA);
  169. TEST_ASSERT_NOT_NULL(arrB);
  170. RyanJson_t moved = RyanJsonDetachByIndex(arrA, 1);
  171. TEST_ASSERT_NOT_NULL(moved);
  172. TEST_ASSERT_TRUE(RyanJsonInsert(arrB, 0, moved));
  173. TEST_ASSERT_EQUAL_UINT32(1U, RyanJsonGetArraySize(arrA));
  174. TEST_ASSERT_EQUAL_UINT32(3U, RyanJsonGetArraySize(arrB));
  175. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrA, 0)));
  176. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrB, 0)));
  177. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrB, 1)));
  178. TEST_ASSERT_EQUAL_INT(4, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrB, 2)));
  179. // arrA 链表校验
  180. {
  181. uint32_t size = RyanJsonGetArraySize(arrA);
  182. uint32_t count = 0;
  183. RyanJson_t node = RyanJsonGetObjectValue(arrA);
  184. RyanJson_t last = NULL;
  185. while (node)
  186. {
  187. count++;
  188. if (count > size + 1U) { TEST_FAIL_MESSAGE("arrA 链表疑似形成环"); }
  189. last = node;
  190. node = RyanJsonGetNext(node);
  191. }
  192. TEST_ASSERT_EQUAL_UINT32(size, count);
  193. TEST_ASSERT_NOT_NULL(last);
  194. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(last), "arrA 尾节点 GetNext 应返回 NULL");
  195. }
  196. // arrB 链表校验
  197. {
  198. uint32_t size = RyanJsonGetArraySize(arrB);
  199. uint32_t count = 0;
  200. RyanJson_t node = RyanJsonGetObjectValue(arrB);
  201. RyanJson_t last = NULL;
  202. while (node)
  203. {
  204. count++;
  205. if (count > size + 1U) { TEST_FAIL_MESSAGE("arrB 链表疑似形成环"); }
  206. last = node;
  207. node = RyanJsonGetNext(node);
  208. }
  209. TEST_ASSERT_EQUAL_UINT32(size, count);
  210. TEST_ASSERT_NOT_NULL(last);
  211. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(last), "arrB 尾节点 GetNext 应返回 NULL");
  212. }
  213. RyanJsonDelete(root);
  214. }
  215. static void testListStabilityWrappedContainerChildTraversal(void)
  216. {
  217. // 复杂链路:
  218. // Create(child) -> AddItemToObject(包装) -> 子链表遍历校验。
  219. // 目标:验证包装后的子容器链表稳定。
  220. RyanJson_t root = RyanJsonCreateObject();
  221. RyanJson_t child = RyanJsonCreateObject();
  222. TEST_ASSERT_NOT_NULL(root);
  223. TEST_ASSERT_NOT_NULL(child);
  224. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(child, "x", 1));
  225. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(child, "y", 2));
  226. TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "wrap", child));
  227. RyanJson_t wrap = RyanJsonGetObjectToKey(root, "wrap");
  228. TEST_ASSERT_NOT_NULL(wrap);
  229. TEST_ASSERT_TRUE(RyanJsonIsObject(wrap));
  230. TEST_ASSERT_EQUAL_UINT32(2U, RyanJsonGetSize(wrap));
  231. uint32_t size = RyanJsonGetSize(wrap);
  232. uint32_t count = 0;
  233. RyanJson_t node = RyanJsonGetObjectValue(wrap);
  234. RyanJson_t last = NULL;
  235. while (node)
  236. {
  237. count++;
  238. if (count > size + 1U) { TEST_FAIL_MESSAGE("包装子链表疑似形成环"); }
  239. last = node;
  240. node = RyanJsonGetNext(node);
  241. }
  242. TEST_ASSERT_EQUAL_UINT32(size, count);
  243. TEST_ASSERT_NOT_NULL(last);
  244. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetNext(last), "包装子链表尾节点 GetNext 应返回 NULL");
  245. RyanJsonDelete(root);
  246. }
  247. static void testListStabilityDuplicateAfterChurn(void)
  248. {
  249. // 复杂链路:
  250. // Parse -> DetachByIndex -> AddItemToObject(包装) -> ReplaceByKey -> Duplicate -> Compare。
  251. // 目标:验证变更后链表仍可被 Duplicate 正确复制。
  252. RyanJson_t root = RyanJsonParse("{\"arr\":[{\"v\":1},{\"v\":2}],\"obj\":{\"a\":1}}");
  253. TEST_ASSERT_NOT_NULL(root);
  254. RyanJson_t arr = RyanJsonGetObjectToKey(root, "arr");
  255. RyanJson_t moved = RyanJsonDetachByIndex(arr, 0);
  256. TEST_ASSERT_NOT_NULL(moved);
  257. TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "moved", moved));
  258. TEST_ASSERT_TRUE(RyanJsonReplaceByKey(root, "obj", RyanJsonCreateString("obj", "flat")));
  259. RyanJson_t dup = RyanJsonDuplicate(root);
  260. TEST_ASSERT_NOT_NULL(dup);
  261. TEST_ASSERT_TRUE(RyanJsonCompare(root, dup));
  262. RyanJsonDelete(dup);
  263. RyanJsonDelete(root);
  264. }
  265. static void testListStabilityPrintAfterChurn(void)
  266. {
  267. // 复杂链路:
  268. // Parse -> DetachByKey -> AddItemToObject -> Insert(Array) -> Print/Parse -> Compare。
  269. // 目标:验证多次结构变更后打印链路稳定。
  270. RyanJson_t root = RyanJsonParse("{\"a\":[1,2],\"b\":{\"x\":1}}");
  271. TEST_ASSERT_NOT_NULL(root);
  272. // 直接迁移容器节点,避免 AddItemToObject 处理标量失败
  273. RyanJson_t moved = RyanJsonDetachByKey(root, "b");
  274. TEST_ASSERT_NOT_NULL(moved);
  275. TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "moved", moved));
  276. RyanJson_t arr = RyanJsonGetObjectToKey(root, "a");
  277. TEST_ASSERT_TRUE(RyanJsonInsert(arr, 1, RyanJsonCreateInt(NULL, 9)));
  278. char *printed = RyanJsonPrint(root, 128, RyanJsonFalse, NULL);
  279. TEST_ASSERT_NOT_NULL(printed);
  280. RyanJson_t roundtrip = RyanJsonParse(printed);
  281. TEST_ASSERT_NOT_NULL(roundtrip);
  282. TEST_ASSERT_TRUE(RyanJsonCompare(root, roundtrip));
  283. RyanJsonDelete(roundtrip);
  284. RyanJsonFree(printed);
  285. RyanJsonDelete(root);
  286. }
  287. void testStabilityLinkedListBasicRunner(void)
  288. {
  289. UnitySetTestFile(__FILE__);
  290. RUN_TEST(testListStabilityArrayDetachHeadAppend);
  291. RUN_TEST(testListStabilityObjectReplaceLastThenTraverse);
  292. RUN_TEST(testListStabilityObjectDetachReinsertAtHead);
  293. RUN_TEST(testListStabilityArrayReplaceMiddleRebindsChain);
  294. RUN_TEST(testListStabilityDetachAllThenRebuild);
  295. RUN_TEST(testListStabilityArrayMoveBetweenParents);
  296. RUN_TEST(testListStabilityWrappedContainerChildTraversal);
  297. RUN_TEST(testListStabilityDuplicateAfterChurn);
  298. RUN_TEST(testListStabilityPrintAfterChurn);
  299. }