testCompare.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. #include "testBase.h"
  2. #include <float.h>
  3. static void testCompareEdgeCases(void)
  4. {
  5. // 测试 Object 键值对顺序对比较的影响
  6. // RyanJson 的 Object 比较是无序的:键值对顺序不同也应视为相同
  7. RyanJson_t json1 = RyanJsonCreateObject();
  8. RyanJsonAddIntToObject(json1, "a", 1);
  9. RyanJsonAddIntToObject(json1, "b", 2);
  10. RyanJson_t json2 = RyanJsonCreateObject();
  11. RyanJsonAddIntToObject(json2, "b", 2);
  12. RyanJsonAddIntToObject(json2, "a", 1); // 顺序不同
  13. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(json1, json2), "顺序不同的 Object 比较应返回 True (RyanJson 是无序比较)");
  14. RyanJsonDelete(json1);
  15. RyanJsonDelete(json2);
  16. }
  17. static void testCompareObjectOrderPaths(void)
  18. {
  19. RyanJson_t left = RyanJsonCreateObject();
  20. RyanJson_t rightOrdered = RyanJsonCreateObject();
  21. RyanJson_t rightUnordered = RyanJsonCreateObject();
  22. TEST_ASSERT_NOT_NULL(left);
  23. TEST_ASSERT_NOT_NULL(rightOrdered);
  24. TEST_ASSERT_NOT_NULL(rightUnordered);
  25. // 同序构造:覆盖 Object 比较同序快路径
  26. for (int32_t i = 0; i < 64; i++)
  27. {
  28. char key[16];
  29. RyanJsonSnprintf(key, sizeof(key), "k%" PRId32, i);
  30. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(left, key, i));
  31. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightOrdered, key, i));
  32. }
  33. // 逆序构造:覆盖 Object 比较按 key 回退查找路径
  34. for (int32_t i = 63; i >= 0; i--)
  35. {
  36. char key[16];
  37. RyanJsonSnprintf(key, sizeof(key), "k%" PRId32, i);
  38. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightUnordered, key, i));
  39. }
  40. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightOrdered), "同序 Object 比较应返回 True");
  41. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightUnordered), "乱序 Object 比较应返回 True");
  42. RyanJsonDelete(left);
  43. RyanJsonDelete(rightOrdered);
  44. RyanJsonDelete(rightUnordered);
  45. }
  46. static void testCompareScalarAndTypeMatrix(void)
  47. {
  48. RyanJson_t intLeft = RyanJsonCreateInt(NULL, 10);
  49. RyanJson_t intRight = RyanJsonCreateInt(NULL, 11);
  50. RyanJson_t doubleCloseLeft = RyanJsonCreateDouble(NULL, 1.0);
  51. RyanJson_t doubleCloseRight = RyanJsonCreateDouble(NULL, 1.0 + (RyanJsonAbsTolerance / 2.0));
  52. RyanJson_t doubleFarLeft = RyanJsonCreateDouble(NULL, 1.0);
  53. RyanJson_t doubleFarRight = RyanJsonCreateDouble(NULL, 1.0 + (RyanJsonAbsTolerance * 100.0));
  54. RyanJson_t strLeft = RyanJsonCreateString(NULL, "alpha");
  55. RyanJson_t strRight = RyanJsonCreateString(NULL, "beta");
  56. RyanJson_t typeInt = RyanJsonCreateInt(NULL, 1);
  57. RyanJson_t typeDouble = RyanJsonCreateDouble(NULL, 1.0);
  58. RyanJson_t typeString = RyanJsonCreateString(NULL, "1");
  59. TEST_ASSERT_NOT_NULL(intLeft);
  60. TEST_ASSERT_NOT_NULL(intRight);
  61. TEST_ASSERT_NOT_NULL(doubleCloseLeft);
  62. TEST_ASSERT_NOT_NULL(doubleCloseRight);
  63. TEST_ASSERT_NOT_NULL(doubleFarLeft);
  64. TEST_ASSERT_NOT_NULL(doubleFarRight);
  65. TEST_ASSERT_NOT_NULL(strLeft);
  66. TEST_ASSERT_NOT_NULL(strRight);
  67. TEST_ASSERT_NOT_NULL(typeInt);
  68. TEST_ASSERT_NOT_NULL(typeDouble);
  69. TEST_ASSERT_NOT_NULL(typeString);
  70. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(intLeft, intRight), "int 值不同时 Compare 应返回 False");
  71. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(intLeft, intRight), "int 值不同时 CompareOnlyKey 应返回 True");
  72. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(doubleCloseLeft, doubleCloseRight), "double 在容差内应判等");
  73. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(doubleFarLeft, doubleFarRight), "double 超过容差应不相等");
  74. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(doubleFarLeft, doubleFarRight), "double 值不同时 CompareOnlyKey 应返回 True");
  75. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(strLeft, strRight), "string 值不同时 Compare 应返回 False");
  76. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(strLeft, strRight), "string 值不同时 CompareOnlyKey 应返回 True");
  77. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(typeInt, typeString), "类型不同时 Compare 应返回 False");
  78. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(typeInt, typeString), "类型不同时 CompareOnlyKey 应返回 False");
  79. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(typeInt, typeDouble), "int/double 即使数值相同,类型不同也应不相等");
  80. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(typeInt, typeDouble),
  81. "CompareOnlyKey 忽略 number 具体子类型,int/double 应视为相等");
  82. RyanJsonDelete(intLeft);
  83. RyanJsonDelete(intRight);
  84. RyanJsonDelete(doubleCloseLeft);
  85. RyanJsonDelete(doubleCloseRight);
  86. RyanJsonDelete(doubleFarLeft);
  87. RyanJsonDelete(doubleFarRight);
  88. RyanJsonDelete(strLeft);
  89. RyanJsonDelete(strRight);
  90. RyanJsonDelete(typeInt);
  91. RyanJsonDelete(typeDouble);
  92. RyanJsonDelete(typeString);
  93. }
  94. static void testCompareDoubleRelativeToleranceDominates(void)
  95. {
  96. // 构造一个让“相对误差”主导的场景,避免 CompareDouble 只剩绝对误差分支被覆盖。
  97. double base = (RyanJsonAbsTolerance / DBL_EPSILON) * 8.0;
  98. double epsilon = DBL_EPSILON * fabs(base);
  99. TEST_ASSERT_TRUE_MESSAGE(epsilon > RyanJsonAbsTolerance, "epsilon 应大于 absTolerance");
  100. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareDouble(base, base + (epsilon * 0.5)), "相对误差内应判等");
  101. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareDouble(base, base + (epsilon * 2.0)), "相对误差外应不等");
  102. }
  103. static void testCompareNumberSubtypeInContainers(void)
  104. {
  105. RyanJson_t left = RyanJsonParse("{\"n\":1,\"arr\":[1,2.0],\"obj\":{\"x\":3,\"y\":4.0}}");
  106. RyanJson_t right = RyanJsonParse("{\"obj\":{\"y\":4,\"x\":3.0},\"arr\":[1.0,2],\"n\":1.0}");
  107. RyanJson_t rightTypeMismatch = RyanJsonParse("{\"obj\":{\"y\":4,\"x\":\"3\"},\"arr\":[1.0,2],\"n\":1.0}");
  108. TEST_ASSERT_NOT_NULL(left);
  109. TEST_ASSERT_NOT_NULL(right);
  110. TEST_ASSERT_NOT_NULL(rightTypeMismatch);
  111. // 全量比较要求数值子类型一致;仅比较 key 时允许 Int/Double 混用
  112. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, right), "容器中 int/double 子类型不同,Compare 应返回 False");
  113. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, right),
  114. "容器中 int/double 子类型不同,但结构一致时 CompareOnlyKey 应返回 True");
  115. // 数值与 String 类型不同,即使在 CompareOnlyKey 下也必须失败
  116. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightTypeMismatch), "number/string 类型不同,Compare 应返回 False");
  117. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightTypeMismatch), "number/string 类型不同,CompareOnlyKey 也应返回 False");
  118. RyanJsonDelete(left);
  119. RyanJsonDelete(right);
  120. RyanJsonDelete(rightTypeMismatch);
  121. }
  122. static void testCompareZeroSignSemantics(void)
  123. {
  124. // -0 与 0 应视为数值相等(同为 Int 类型)
  125. RyanJson_t negZero = RyanJsonParse("-0");
  126. RyanJson_t posZero = RyanJsonParse("0");
  127. TEST_ASSERT_NOT_NULL(negZero);
  128. TEST_ASSERT_NOT_NULL(posZero);
  129. TEST_ASSERT_TRUE(RyanJsonIsInt(negZero));
  130. TEST_ASSERT_TRUE(RyanJsonIsInt(posZero));
  131. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(negZero, posZero), "-0 与 0 比较应相等");
  132. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(negZero, posZero), "-0 与 0 CompareOnlyKey 也应相等");
  133. RyanJson_t objNeg = RyanJsonParse("{\"n\":-0}");
  134. RyanJson_t objPos = RyanJsonParse("{\"n\":0}");
  135. TEST_ASSERT_NOT_NULL(objNeg);
  136. TEST_ASSERT_NOT_NULL(objPos);
  137. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(objNeg, objPos), "Object 内 -0 与 0 应相等");
  138. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(objNeg, objPos), "Object 内 -0 与 0 CompareOnlyKey 应相等");
  139. RyanJsonDelete(objPos);
  140. RyanJsonDelete(objNeg);
  141. RyanJsonDelete(posZero);
  142. RyanJsonDelete(negZero);
  143. }
  144. static void testCompareEmptyContainerAndTypeMismatch(void)
  145. {
  146. RyanJson_t emptyObjA = RyanJsonCreateObject();
  147. RyanJson_t emptyObjB = RyanJsonCreateObject();
  148. RyanJson_t emptyArrA = RyanJsonCreateArray();
  149. RyanJson_t emptyArrB = RyanJsonCreateArray();
  150. TEST_ASSERT_NOT_NULL(emptyObjA);
  151. TEST_ASSERT_NOT_NULL(emptyObjB);
  152. TEST_ASSERT_NOT_NULL(emptyArrA);
  153. TEST_ASSERT_NOT_NULL(emptyArrB);
  154. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(emptyObjA, emptyObjB), "空 Object 之间应相等");
  155. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(emptyObjA, emptyObjB), "空 Object CompareOnlyKey 应相等");
  156. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(emptyArrA, emptyArrB), "空 Array 之间应相等");
  157. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(emptyArrA, emptyArrB), "空 Array CompareOnlyKey 应相等");
  158. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(emptyObjA, emptyArrA), "Object 与 Array 类型不同应不相等");
  159. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(emptyObjA, emptyArrA), "Object 与 Array CompareOnlyKey 也应不相等");
  160. RyanJsonDelete(emptyObjA);
  161. RyanJsonDelete(emptyObjB);
  162. RyanJsonDelete(emptyArrA);
  163. RyanJsonDelete(emptyArrB);
  164. }
  165. static void testCompareArraySemantics(void)
  166. {
  167. RyanJson_t arrIntA = RyanJsonCreateArray();
  168. RyanJson_t arrIntB = RyanJsonCreateArray();
  169. RyanJson_t arrIntReverse = RyanJsonCreateArray();
  170. RyanJson_t arrMixedA = RyanJsonCreateArray();
  171. RyanJson_t arrMixedB = RyanJsonCreateArray();
  172. RyanJson_t arrShort = RyanJsonCreateArray();
  173. TEST_ASSERT_NOT_NULL(arrIntA);
  174. TEST_ASSERT_NOT_NULL(arrIntB);
  175. TEST_ASSERT_NOT_NULL(arrIntReverse);
  176. TEST_ASSERT_NOT_NULL(arrMixedA);
  177. TEST_ASSERT_NOT_NULL(arrMixedB);
  178. TEST_ASSERT_NOT_NULL(arrShort);
  179. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntA, 1));
  180. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntA, 2));
  181. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntA, 3));
  182. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntB, 1));
  183. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntB, 2));
  184. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntB, 3));
  185. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntReverse, 3));
  186. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntReverse, 2));
  187. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntReverse, 1));
  188. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrMixedA, 1));
  189. TEST_ASSERT_TRUE(RyanJsonAddStringToArray(arrMixedA, "2"));
  190. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrMixedA, 3));
  191. TEST_ASSERT_TRUE(RyanJsonAddStringToArray(arrMixedB, "1"));
  192. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrMixedB, 2));
  193. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrMixedB, 3));
  194. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrShort, 1));
  195. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrShort, 2));
  196. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(arrIntA, arrIntB), "相同 Array Compare 应返回 True");
  197. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrIntA, arrIntReverse), "Array 顺序不同 Compare 应返回 False");
  198. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(arrIntA, arrIntReverse), "Array 顺序不同但类型一致,CompareOnlyKey 应返回 True");
  199. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrMixedA, arrMixedB), "Array 元素类型顺序不同 Compare 应返回 False");
  200. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(arrMixedA, arrMixedB), "Array 元素类型顺序不同 CompareOnlyKey 应返回 False");
  201. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrIntA, arrShort), "Array 长度不同 Compare 应返回 False");
  202. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(arrIntA, arrShort), "Array 长度不同 CompareOnlyKey 应返回 False");
  203. RyanJsonDelete(arrIntA);
  204. RyanJsonDelete(arrIntB);
  205. RyanJsonDelete(arrIntReverse);
  206. RyanJsonDelete(arrMixedA);
  207. RyanJsonDelete(arrMixedB);
  208. RyanJsonDelete(arrShort);
  209. }
  210. static void testCompareNestedObjectScenarios(void)
  211. {
  212. RyanJson_t left = RyanJsonParse("{\"meta\":{\"id\":1,\"name\":\"m\"},\"list\":[1,2,3],\"flag\":true}");
  213. RyanJson_t rightOrderedDiff = RyanJsonParse("{\"flag\":true,\"list\":[1,2,3],\"meta\":{\"name\":\"m\",\"id\":1}}");
  214. RyanJson_t rightValueDiff = RyanJsonParse("{\"flag\":true,\"list\":[1,2,3],\"meta\":{\"name\":\"m\",\"id\":2}}");
  215. RyanJson_t rightMissingKey = RyanJsonParse("{\"flag\":true,\"list\":[1,2,3],\"meta\":{\"name\":\"m\",\"idx\":1}}");
  216. RyanJson_t leftSingleKey = RyanJsonParse("{\"a\":1}");
  217. RyanJson_t rightSingleKey = RyanJsonParse("{\"b\":1}");
  218. RyanJson_t leftPrefixMatch = RyanJsonParse("{\"a\":1,\"b\":2}");
  219. RyanJson_t rightPrefixMismatch = RyanJsonParse("{\"a\":1,\"c\":2}");
  220. RyanJson_t leftTailMatch = RyanJsonParse("{\"a\":1,\"b\":2,\"c\":3}");
  221. RyanJson_t rightTailMatch = RyanJsonParse("{\"b\":2,\"c\":3,\"a\":1}");
  222. RyanJson_t rightTailMismatch = RyanJsonParse("{\"c\":3,\"d\":4,\"a\":1}");
  223. TEST_ASSERT_NOT_NULL(left);
  224. TEST_ASSERT_NOT_NULL(rightOrderedDiff);
  225. TEST_ASSERT_NOT_NULL(rightValueDiff);
  226. TEST_ASSERT_NOT_NULL(rightMissingKey);
  227. TEST_ASSERT_NOT_NULL(leftSingleKey);
  228. TEST_ASSERT_NOT_NULL(rightSingleKey);
  229. TEST_ASSERT_NOT_NULL(leftPrefixMatch);
  230. TEST_ASSERT_NOT_NULL(rightPrefixMismatch);
  231. TEST_ASSERT_NOT_NULL(leftTailMatch);
  232. TEST_ASSERT_NOT_NULL(rightTailMatch);
  233. TEST_ASSERT_NOT_NULL(rightTailMismatch);
  234. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightOrderedDiff), "嵌套 Object 乱序但值一致应返回 True");
  235. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightOrderedDiff), "嵌套 Object 乱序 CompareOnlyKey 应返回 True");
  236. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightValueDiff), "嵌套 Object 值不同 Compare 应返回 False");
  237. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightValueDiff), "嵌套 Object 值不同 CompareOnlyKey 应返回 True");
  238. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightMissingKey), "嵌套 Object key 不匹配 Compare 应返回 False");
  239. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightMissingKey), "嵌套 Object key 不匹配 CompareOnlyKey 应返回 False");
  240. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(leftSingleKey, rightSingleKey), "同尺寸 Object 但 key 不同 Compare 应返回 False");
  241. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(leftSingleKey, rightSingleKey),
  242. "同尺寸 Object 但 key 不同 CompareOnlyKey 应返回 False");
  243. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(leftPrefixMatch, rightPrefixMismatch),
  244. "前缀 key 相同但后续 key 不同 Compare 应返回 False");
  245. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(leftPrefixMatch, rightPrefixMismatch),
  246. "前缀 key 相同但后续 key 不同 CompareOnlyKey 应返回 False");
  247. // 覆盖同层遍历中 rightCandidate == NULL 的回退查找成功分支
  248. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(leftTailMatch, rightTailMatch), "尾节点命中回退查找后 Compare 应返回 True");
  249. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(leftTailMatch, rightTailMatch), "尾节点命中回退查找后 CompareOnlyKey 应返回 True");
  250. // 覆盖同层遍历中 rightCandidate == NULL 的回退查找失败分支
  251. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(leftTailMatch, rightTailMismatch), "尾节点回退查找失败 Compare 应返回 False");
  252. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(leftTailMatch, rightTailMismatch),
  253. "尾节点回退查找失败 CompareOnlyKey 应返回 False");
  254. RyanJsonDelete(left);
  255. RyanJsonDelete(rightOrderedDiff);
  256. RyanJsonDelete(rightValueDiff);
  257. RyanJsonDelete(rightMissingKey);
  258. RyanJsonDelete(leftSingleKey);
  259. RyanJsonDelete(rightSingleKey);
  260. RyanJsonDelete(leftPrefixMatch);
  261. RyanJsonDelete(rightPrefixMismatch);
  262. RyanJsonDelete(leftTailMatch);
  263. RyanJsonDelete(rightTailMatch);
  264. RyanJsonDelete(rightTailMismatch);
  265. }
  266. static void testCompareArrayWithObjects(void)
  267. {
  268. RyanJson_t arrLeft = RyanJsonParse("[{\"a\":1,\"b\":2},{\"x\":3,\"y\":4}]");
  269. RyanJson_t arrObjectUnordered = RyanJsonParse("[{\"b\":2,\"a\":1},{\"y\":4,\"x\":3}]");
  270. RyanJson_t arrOrderSwapped = RyanJsonParse("[{\"y\":4,\"x\":3},{\"b\":2,\"a\":1}]");
  271. RyanJson_t arrValueDiff = RyanJsonParse("[{\"a\":9,\"b\":2},{\"x\":3,\"y\":4}]");
  272. TEST_ASSERT_NOT_NULL(arrLeft);
  273. TEST_ASSERT_NOT_NULL(arrObjectUnordered);
  274. TEST_ASSERT_NOT_NULL(arrOrderSwapped);
  275. TEST_ASSERT_NOT_NULL(arrValueDiff);
  276. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(arrLeft, arrObjectUnordered), "Array 内 Object 乱序键应比较为 True");
  277. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(arrLeft, arrObjectUnordered), "Array 内 Object 乱序键 CompareOnlyKey 应返回 True");
  278. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrLeft, arrOrderSwapped), "Array 元素顺序变化 Compare 应返回 False");
  279. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(arrLeft, arrOrderSwapped), "Array 元素顺序变化 CompareOnlyKey 应返回 False");
  280. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrLeft, arrValueDiff), "Array 内 Object 值变化 Compare 应返回 False");
  281. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(arrLeft, arrValueDiff), "Array 内 Object 值变化但键结构一致 CompareOnlyKey 应返回 True");
  282. RyanJsonDelete(arrLeft);
  283. RyanJsonDelete(arrObjectUnordered);
  284. RyanJsonDelete(arrOrderSwapped);
  285. RyanJsonDelete(arrValueDiff);
  286. }
  287. static void testCompareDeepNestAndLargeArray(void)
  288. {
  289. // 深度嵌套比较(检测栈溢出或递归限制)
  290. // 之前 200 层出现疑似内存不足或其他问题,降至 50 层验证核心逻辑
  291. int32_t depth = 50;
  292. RyanJson_t root1 = RyanJsonCreateObject();
  293. RyanJson_t root2 = RyanJsonCreateObject();
  294. RyanJson_t curr1 = root1;
  295. RyanJson_t curr2 = root2;
  296. for (int32_t i = 0; i < depth; i++)
  297. {
  298. RyanJson_t child1 = RyanJsonCreateObject();
  299. RyanJson_t child2 = RyanJsonCreateObject();
  300. TEST_ASSERT_NOT_NULL_MESSAGE(child1, "创建 child1 失败");
  301. TEST_ASSERT_NOT_NULL_MESSAGE(child2, "创建 child2 失败");
  302. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(curr1, "nest", child1), "添加到 curr1 失败");
  303. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(curr2, "nest", child2), "添加到 curr2 失败");
  304. // RyanJsonAddItemToObject 会“吞掉” child1(若其为容器),把其内容转移到新节点并释放 child1
  305. // 因此 child1 指针已失效,必须通过 key 获取新创建的节点
  306. curr1 = RyanJsonGetObjectByKey(curr1, "nest");
  307. curr2 = RyanJsonGetObjectByKey(curr2, "nest");
  308. TEST_ASSERT_NOT_NULL_MESSAGE(curr1, "获取 curr1 下一级 nest 失败");
  309. TEST_ASSERT_NOT_NULL_MESSAGE(curr2, "获取 curr2 下一级 nest 失败");
  310. }
  311. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root1, root2), "初始深度比较失败");
  312. // 修改末端
  313. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToObject(curr1, "diff", 1), "添加 diff 失败");
  314. TEST_ASSERT_EQUAL_INT_MESSAGE(1, RyanJsonGetSize(curr1), "添加 diff 后 Size 应为 1");
  315. TEST_ASSERT_EQUAL_INT_MESSAGE(0, RyanJsonGetSize(curr2), "curr2 Size 应仍为 0");
  316. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(root1, root2), "修改后深度比较应失败");
  317. RyanJsonDelete(root1);
  318. RyanJsonDelete(root2);
  319. // 大 Array 比较
  320. int32_t count = 2000;
  321. RyanJson_t arr1 = RyanJsonCreateArray();
  322. RyanJson_t arr2 = RyanJsonCreateArray();
  323. for (int32_t i = 0; i < count; i++)
  324. {
  325. RyanJsonAddIntToArray(arr1, i);
  326. RyanJsonAddIntToArray(arr2, i);
  327. }
  328. TEST_ASSERT_TRUE(RyanJsonCompare(arr1, arr2));
  329. // 修改中间一个元素
  330. RyanJsonDeleteByIndex(arr2, count / 2); // 删除中间项
  331. RyanJson_t insert = RyanJsonCreateInt("new", 99999);
  332. RyanJsonInsert(arr2, count / 2, insert);
  333. TEST_ASSERT_FALSE(RyanJsonCompare(arr1, arr2));
  334. RyanJsonDelete(arr1);
  335. RyanJsonDelete(arr2);
  336. }
  337. static void testCompareEqualityAndStructuralDiff(void)
  338. {
  339. char jsonstr[] = "{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null,\"item\":"
  340. "{\"inter\":16,\"double\":16."
  341. "89,\"string\":\"hello\","
  342. "\"boolTrue\":true,\"boolFalse\":false,\"null\":null},\"arrayInt\":[16,16,16,16,16],\"arrayDouble\":[16.89,16.89,"
  343. "16.89,16.89,16.89],"
  344. "\"arrayString\":[\"hello\",\"hello\","
  345. "\"hello\",\"hello\",\"hello\"],\"array\":[16,16.89,\"hello\",true,false,null],\"arrayItem\":[{\"inter\":16,"
  346. "\"double\":16.89,\"string\":"
  347. "\"hello\",\"boolTrue\":true,"
  348. "\"boolFalse\":false,\"null\":null},{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,"
  349. "\"boolFalse\":false,\"null\":null}]}";
  350. RyanJson_t json = RyanJsonParse(jsonstr);
  351. TEST_ASSERT_NOT_NULL_MESSAGE(json, "解析 Json 1 失败");
  352. RyanJson_t json2 = RyanJsonParse(jsonstr);
  353. TEST_ASSERT_NOT_NULL_MESSAGE(json2, "解析 Json 2 失败");
  354. // 边界情况测试
  355. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, NULL), "与 NULL 比较应返回 False");
  356. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(NULL, json2), "NULL 与 Object 比较应返回 False");
  357. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(NULL, NULL), "NULL 与 NULL 比较应返回 False");
  358. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, NULL), "仅比较 Key:与 NULL 比较应返回 False");
  359. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(NULL, json2), "仅比较 Key:NULL 与 Object 比较应返回 False");
  360. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(NULL, NULL), "仅比较 Key:NULL 与 NULL 比较应返回 False");
  361. // 完整 Object 比较
  362. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(json, json2), "两个相同内容的 Object 比较应返回 True");
  363. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(json, json), "Object 与自身比较应返回 True");
  364. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "仅比较 Key:两个相同内容的 Object 比较应返回 True");
  365. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json), "仅比较 Key:Object 与自身比较应返回 True");
  366. // 修改 Object 2 并比较
  367. // 添加 String
  368. RyanJsonDelete(json2);
  369. json2 = RyanJsonParse(jsonstr);
  370. RyanJsonAddStringToObject(json2, "test", "hello");
  371. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个字段后比较应返回 False");
  372. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个字段后仅比较 Key 应返回 False");
  373. // 添加 Int
  374. RyanJsonDelete(json2);
  375. json2 = RyanJsonParse(jsonstr);
  376. RyanJsonAddIntToObject(json2, "test", 1);
  377. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个 Int 后比较应返回 False");
  378. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个 Int 后仅比较 Key 应返回 False");
  379. // 添加 Double
  380. RyanJsonDelete(json2);
  381. json2 = RyanJsonParse(jsonstr);
  382. RyanJsonAddDoubleToObject(json2, "test", 2.0);
  383. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个 Double 后比较应返回 False");
  384. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个 Double 后仅比较 Key 应返回 False");
  385. // 添加 boolValue
  386. RyanJsonDelete(json2);
  387. json2 = RyanJsonParse(jsonstr);
  388. RyanJsonAddBoolToObject(json2, "test", RyanJsonTrue);
  389. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个 Bool 值后比较应返回 False");
  390. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个 Bool 值后仅比较 Key 应返回 False");
  391. // 添加 Null
  392. RyanJsonDelete(json2);
  393. json2 = RyanJsonParse(jsonstr);
  394. RyanJsonAddNullToObject(json2, "test");
  395. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个 Null 后比较应返回 False");
  396. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个 Null 后仅比较 Key 应返回 False");
  397. // Array 修改测试
  398. RyanJsonDelete(json2);
  399. json2 = RyanJsonParse(jsonstr);
  400. RyanJsonAddIntToArray(RyanJsonGetObjectToKey(json2, "arrayInt"), 2);
  401. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Array 长度变化后比较应返回 False");
  402. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Array 长度变化后仅比较 Key 应返回 False");
  403. RyanJsonDelete(json2);
  404. json2 = RyanJsonParse(jsonstr);
  405. RyanJsonAddDoubleToArray(RyanJsonGetObjectToKey(json2, "arrayDouble"), 2.0);
  406. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Array 长度变化(浮点)后比较应返回 False");
  407. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Array 长度变化(浮点)后仅比较 Key 应返回 False");
  408. RyanJsonDelete(json2);
  409. json2 = RyanJsonParse(jsonstr);
  410. RyanJsonAddStringToArray(RyanJsonGetObjectToKey(json2, "arrayString"), "hello");
  411. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Array 长度变化(String)后比较应返回 False");
  412. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Array 长度变化(String)后仅比较 Key 应返回 False");
  413. RyanJsonDelete(json2);
  414. json2 = RyanJsonParse(jsonstr);
  415. RyanJsonAddStringToArray(RyanJsonGetObjectToKey(json2, "arrayItem"), "hello");
  416. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Array 长度变化(项)后比较应返回 False");
  417. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Array 长度变化(项)后仅比较 Key 应返回 False");
  418. // 修改 key 名称
  419. RyanJsonDelete(json2);
  420. json2 = RyanJsonParse(jsonstr);
  421. RyanJsonChangeKey(RyanJsonGetObjectToKey(json2, "inter"), "int2");
  422. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Key 修改后比较应返回 False");
  423. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Key 修改后仅比较 Key 应返回 False");
  424. // 修改值但 key 相同
  425. RyanJsonDelete(json2);
  426. json2 = RyanJsonParse(jsonstr);
  427. RyanJsonChangeIntValue(RyanJsonGetObjectToKey(json2, "inter"), 17);
  428. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Value 修改后比较应返回 False");
  429. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Value 修改但 Key 相同,仅比较 Key 应返回 True");
  430. RyanJsonDelete(json2);
  431. json2 = RyanJsonParse(jsonstr);
  432. RyanJsonChangeDoubleValue(RyanJsonGetObjectToKey(json2, "double"), 20.89);
  433. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "浮点 Value 修改但 Key 相同,仅比较 Key 应返回 True");
  434. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "浮点 Value 修改后比较应返回 False");
  435. // 类型修改测试(从 Double 改为 int32_t)
  436. RyanJsonDelete(json2);
  437. json2 = RyanJsonParse(jsonstr);
  438. RyanJsonDeleteByKey(json2, "double");
  439. RyanJsonAddIntToObject(json2, "double", 20); // 改为 Int
  440. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "类型修改后比较应返回 False");
  441. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "类型修改但 Key 相同,仅比较 Key 应返回 True");
  442. // 修改 strValue
  443. RyanJsonDelete(json2);
  444. json2 = RyanJsonParse(jsonstr);
  445. RyanJsonChangeStringValue(RyanJsonGetObjectToKey(json2, "string"), "49");
  446. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "String Value 修改后比较应返回 False");
  447. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "String Value 修改但 Key 相同,仅比较 Key 应返回 True");
  448. // 修改 Object 1 的 boolValue
  449. RyanJsonDelete(json2);
  450. json2 = RyanJsonParse(jsonstr);
  451. RyanJsonChangeBoolValue(RyanJsonGetObjectToKey(json2, "boolTrue"), RyanJsonFalse);
  452. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Bool Value 修改后比较应返回 False");
  453. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Bool Value 修改但 Key 相同,仅比较 Key 应返回 True");
  454. // 修改嵌套 Object 的 boolValue
  455. RyanJsonDelete(json2);
  456. json2 = RyanJsonParse(jsonstr);
  457. RyanJsonChangeBoolValue(RyanJsonGetObjectToKey(json2, "item", "boolTrue"), RyanJsonFalse);
  458. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "嵌套 Bool Value 修改后比较应返回 False");
  459. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "嵌套 Bool Value 修改但结构相同,仅比较 Key 应返回 True");
  460. // 修改 Array 中的 Int
  461. RyanJsonDelete(json2);
  462. json2 = RyanJsonParse(jsonstr);
  463. RyanJsonChangeIntValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "arrayInt"), 0), 17);
  464. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Array 元素修改后比较应返回 False");
  465. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Array 元素修改但长度相同,仅比较 Key 应返回 True");
  466. // 修改 Array 中的 Double
  467. RyanJsonDelete(json2);
  468. json2 = RyanJsonParse(jsonstr);
  469. RyanJsonChangeDoubleValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "arrayDouble"), 0), 20.89);
  470. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Array 浮点元素修改后比较应返回 False");
  471. // 修改 Array 中的 String
  472. RyanJsonDelete(json2);
  473. json2 = RyanJsonParse(jsonstr);
  474. RyanJsonChangeStringValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "arrayString"), 0), "20.89");
  475. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "ArrayString 元素修改后比较应返回 False");
  476. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "ArrayString 元素修改但长度相同,仅比较 Key 应返回 True");
  477. // 修改混合 Array
  478. RyanJsonDelete(json2);
  479. json2 = RyanJsonParse(jsonstr);
  480. RyanJsonChangeIntValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "array"), 0), 17);
  481. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "混合 Array 修改后比较应返回 False");
  482. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "混合 Array 修改但长度相同,仅比较 Key 应返回 True");
  483. // 修改 Array 项中的 Object
  484. RyanJsonDelete(json2);
  485. json2 = RyanJsonParse(jsonstr);
  486. RyanJsonChangeIntValue(RyanJsonGetObjectToKey(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "arrayItem"), 0), "inter"),
  487. 17);
  488. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Array 项 Object 修改后比较应返回 False");
  489. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Array 项 Object 修改但结构相同,仅比较 Key 应返回 True");
  490. // 删除整个 key 节点
  491. RyanJsonDelete(json2);
  492. json2 = RyanJsonParse(jsonstr);
  493. RyanJsonDeleteByKey(json2, "arrayItem");
  494. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "删除 Key 后比较应返回 False");
  495. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "删除 Key 后仅比较 Key 应返回 False");
  496. // 删除 Array 索引项
  497. RyanJsonDelete(json2);
  498. json2 = RyanJsonParse(jsonstr);
  499. RyanJsonDeleteByIndex(RyanJsonGetObjectToKey(json2, "arrayInt"), 2);
  500. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "删除 Array 索引后比较应返回 False");
  501. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "删除 Array 索引后仅比较 Key 应返回 False");
  502. // 删除 Array 项中的 Object 项
  503. RyanJsonDelete(json2);
  504. json2 = RyanJsonParse(jsonstr);
  505. RyanJsonDeleteByIndex(RyanJsonGetObjectToKey(json2, "arrayItem"), 0);
  506. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "删除 ArrayObject 项后比较应返回 False");
  507. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "删除 ArrayObject 项后仅比较 Key 应返回 False");
  508. RyanJsonDelete(json);
  509. RyanJsonDelete(json2);
  510. }
  511. void testCompareRunner(void)
  512. {
  513. UnitySetTestFile(__FILE__);
  514. RUN_TEST(testCompareEdgeCases);
  515. RUN_TEST(testCompareObjectOrderPaths);
  516. RUN_TEST(testCompareScalarAndTypeMatrix);
  517. RUN_TEST(testCompareDoubleRelativeToleranceDominates);
  518. RUN_TEST(testCompareNumberSubtypeInContainers);
  519. RUN_TEST(testCompareZeroSignSemantics);
  520. RUN_TEST(testCompareEmptyContainerAndTypeMismatch);
  521. RUN_TEST(testCompareArraySemantics);
  522. RUN_TEST(testCompareNestedObjectScenarios);
  523. RUN_TEST(testCompareArrayWithObjects);
  524. RUN_TEST(testCompareDeepNestAndLargeArray);
  525. RUN_TEST(testCompareEqualityAndStructuralDiff);
  526. }
  527. static void testRootScalarStringChangeCompareRoundtrip(void)
  528. {
  529. // 复杂链路:
  530. // Parse(根 String) -> Duplicate -> ChangeStringValue -> Compare/CompareOnlyKey -> Print/Parse。
  531. // 目标:验证根节点为 String 时的修改、比较与往返稳定性。
  532. RyanJson_t root = RyanJsonParse("\"alpha\"");
  533. TEST_ASSERT_NOT_NULL(root);
  534. RyanJson_t copy = RyanJsonDuplicate(root);
  535. TEST_ASSERT_NOT_NULL(copy);
  536. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(copy, "beta"));
  537. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(root, copy), "根 String 值变化后 Compare 应返回 False");
  538. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(root, copy), "根 String 值变化后 CompareOnlyKey 应返回 True");
  539. char *printed = RyanJsonPrint(copy, 32, RyanJsonFalse, NULL);
  540. TEST_ASSERT_NOT_NULL(printed);
  541. RyanJson_t roundtrip = RyanJsonParse(printed);
  542. TEST_ASSERT_NOT_NULL(roundtrip);
  543. TEST_ASSERT_TRUE(RyanJsonCompare(copy, roundtrip));
  544. RyanJsonDelete(roundtrip);
  545. RyanJsonFree(printed);
  546. RyanJsonDelete(copy);
  547. RyanJsonDelete(root);
  548. }
  549. static void testRootScalarIntChangeCompareOnlyKey(void)
  550. {
  551. // 复杂链路:
  552. // Parse(根 Int) -> Duplicate -> ChangeIntValue -> Compare/CompareOnlyKey。
  553. // 目标:验证根节点为 Int 时 CompareOnlyKey 忽略 value 差异。
  554. RyanJson_t root = RyanJsonParse("1");
  555. TEST_ASSERT_NOT_NULL(root);
  556. RyanJson_t copy = RyanJsonDuplicate(root);
  557. TEST_ASSERT_NOT_NULL(copy);
  558. TEST_ASSERT_TRUE(RyanJsonChangeIntValue(copy, 2));
  559. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(root, copy), "根 Int 值变化后 Compare 应返回 False");
  560. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(root, copy), "根 Int 值变化后 CompareOnlyKey 应返回 True");
  561. TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(root));
  562. RyanJsonDelete(copy);
  563. RyanJsonDelete(root);
  564. }
  565. static void testRootScalarDoubleChangeCompareOnlyKey(void)
  566. {
  567. // 复杂链路:
  568. // Parse(根 Double) -> Duplicate -> ChangeDoubleValue -> Compare/CompareOnlyKey。
  569. // 目标:验证根节点为 Double 时 CompareOnlyKey 忽略 value 差异。
  570. RyanJson_t root = RyanJsonParse("1.5");
  571. TEST_ASSERT_NOT_NULL(root);
  572. RyanJson_t copy = RyanJsonDuplicate(root);
  573. TEST_ASSERT_NOT_NULL(copy);
  574. TEST_ASSERT_TRUE(RyanJsonChangeDoubleValue(copy, 2.5));
  575. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(root, copy), "根浮点值变化后 Compare 应返回 False");
  576. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(root, copy), "根浮点值变化后 CompareOnlyKey 应返回 True");
  577. RyanJsonDelete(copy);
  578. RyanJsonDelete(root);
  579. }
  580. static void testRootScalarBoolChangeCompareOnlyKey(void)
  581. {
  582. // 复杂链路:
  583. // Parse(根 Bool) -> Duplicate -> ChangeBoolValue -> Compare/CompareOnlyKey。
  584. // 目标:验证根节点为 Bool 时 CompareOnlyKey 忽略 value 差异。
  585. RyanJson_t root = RyanJsonParse("true");
  586. TEST_ASSERT_NOT_NULL(root);
  587. RyanJson_t copy = RyanJsonDuplicate(root);
  588. TEST_ASSERT_NOT_NULL(copy);
  589. TEST_ASSERT_TRUE(RyanJsonChangeBoolValue(copy, RyanJsonFalse));
  590. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(root, copy), "根 Bool 值变化后 Compare 应返回 False");
  591. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(root, copy), "根 Bool 值变化后 CompareOnlyKey 应返回 True");
  592. RyanJsonDelete(copy);
  593. RyanJsonDelete(root);
  594. }
  595. static void testRootScalarReplaceByIndexFails(void)
  596. {
  597. // 复杂链路:
  598. // Parse(根标量) -> ReplaceByIndex(失败) -> 释放 item。
  599. // 目标:验证对非容器执行 ReplaceByIndex 会失败且不会消耗 item。
  600. RyanJson_t root = RyanJsonParse("1");
  601. TEST_ASSERT_NOT_NULL(root);
  602. RyanJson_t item = RyanJsonCreateInt(NULL, 9);
  603. TEST_ASSERT_NOT_NULL(item);
  604. TEST_ASSERT_FALSE_MESSAGE(RyanJsonReplaceByIndex(root, 0, item), "根标量 ReplaceByIndex 应返回 False");
  605. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDetachedItem(item), "ReplaceByIndex 失败后 item 应保持游离");
  606. RyanJsonDelete(item);
  607. RyanJsonDelete(root);
  608. }
  609. static void testRootScalarGetSizeIsOne(void)
  610. {
  611. // 覆盖根标量的 GetSize 语义:标量节点大小应为 1。
  612. RyanJson_t root = RyanJsonParse("\"x\"");
  613. TEST_ASSERT_NOT_NULL(root);
  614. TEST_ASSERT_EQUAL_UINT32(1U, RyanJsonGetSize(root));
  615. RyanJsonDelete(root);
  616. }
  617. void testRootScalarOpsRunner(void)
  618. {
  619. UnitySetTestFile(__FILE__);
  620. RUN_TEST(testRootScalarStringChangeCompareRoundtrip);
  621. RUN_TEST(testRootScalarIntChangeCompareOnlyKey);
  622. RUN_TEST(testRootScalarDoubleChangeCompareOnlyKey);
  623. RUN_TEST(testRootScalarBoolChangeCompareOnlyKey);
  624. RUN_TEST(testRootScalarReplaceByIndexFails);
  625. RUN_TEST(testRootScalarGetSizeIsOne);
  626. }