testCompare.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. #include "testBase.h"
  2. static void testCompareEdgeCases(void)
  3. {
  4. // 测试对象键值对顺序对比较的影响
  5. // RyanJson 的对象比较是无序的:键值对顺序不同也应视为相同
  6. RyanJson_t json1 = RyanJsonCreateObject();
  7. RyanJsonAddIntToObject(json1, "a", 1);
  8. RyanJsonAddIntToObject(json1, "b", 2);
  9. RyanJson_t json2 = RyanJsonCreateObject();
  10. RyanJsonAddIntToObject(json2, "b", 2);
  11. RyanJsonAddIntToObject(json2, "a", 1); // 顺序不同
  12. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(json1, json2), "顺序不同的对象比较应返回 True (RyanJson 是无序比较)");
  13. RyanJsonDelete(json1);
  14. RyanJsonDelete(json2);
  15. }
  16. static void testCompareObjectOrderPaths(void)
  17. {
  18. RyanJson_t left = RyanJsonCreateObject();
  19. RyanJson_t rightOrdered = RyanJsonCreateObject();
  20. RyanJson_t rightUnordered = RyanJsonCreateObject();
  21. TEST_ASSERT_NOT_NULL(left);
  22. TEST_ASSERT_NOT_NULL(rightOrdered);
  23. TEST_ASSERT_NOT_NULL(rightUnordered);
  24. // 同序构造:覆盖对象比较同序快路径
  25. for (int32_t i = 0; i < 64; i++)
  26. {
  27. char key[16];
  28. RyanJsonSnprintf(key, sizeof(key), "k%" PRId32, i);
  29. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(left, key, i));
  30. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightOrdered, key, i));
  31. }
  32. // 逆序构造:覆盖对象比较按 key 回退查找路径
  33. for (int32_t i = 63; i >= 0; i--)
  34. {
  35. char key[16];
  36. RyanJsonSnprintf(key, sizeof(key), "k%" PRId32, i);
  37. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightUnordered, key, i));
  38. }
  39. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightOrdered), "同序对象比较应返回 True");
  40. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightUnordered), "乱序对象比较应返回 True");
  41. RyanJsonDelete(left);
  42. RyanJsonDelete(rightOrdered);
  43. RyanJsonDelete(rightUnordered);
  44. }
  45. static void testCompareScalarAndTypeMatrix(void)
  46. {
  47. RyanJson_t intLeft = RyanJsonCreateInt(NULL, 10);
  48. RyanJson_t intRight = RyanJsonCreateInt(NULL, 11);
  49. RyanJson_t doubleCloseLeft = RyanJsonCreateDouble(NULL, 1.0);
  50. RyanJson_t doubleCloseRight = RyanJsonCreateDouble(NULL, 1.0 + (RyanJsonAbsTolerance / 2.0));
  51. RyanJson_t doubleFarLeft = RyanJsonCreateDouble(NULL, 1.0);
  52. RyanJson_t doubleFarRight = RyanJsonCreateDouble(NULL, 1.0 + (RyanJsonAbsTolerance * 100.0));
  53. RyanJson_t strLeft = RyanJsonCreateString(NULL, "alpha");
  54. RyanJson_t strRight = RyanJsonCreateString(NULL, "beta");
  55. RyanJson_t typeInt = RyanJsonCreateInt(NULL, 1);
  56. RyanJson_t typeDouble = RyanJsonCreateDouble(NULL, 1.0);
  57. RyanJson_t typeString = RyanJsonCreateString(NULL, "1");
  58. TEST_ASSERT_NOT_NULL(intLeft);
  59. TEST_ASSERT_NOT_NULL(intRight);
  60. TEST_ASSERT_NOT_NULL(doubleCloseLeft);
  61. TEST_ASSERT_NOT_NULL(doubleCloseRight);
  62. TEST_ASSERT_NOT_NULL(doubleFarLeft);
  63. TEST_ASSERT_NOT_NULL(doubleFarRight);
  64. TEST_ASSERT_NOT_NULL(strLeft);
  65. TEST_ASSERT_NOT_NULL(strRight);
  66. TEST_ASSERT_NOT_NULL(typeInt);
  67. TEST_ASSERT_NOT_NULL(typeDouble);
  68. TEST_ASSERT_NOT_NULL(typeString);
  69. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(intLeft, intRight), "int 值不同时 Compare 应返回 False");
  70. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(intLeft, intRight), "int 值不同时 CompareOnlyKey 应返回 True");
  71. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(doubleCloseLeft, doubleCloseRight), "double 在容差内应判等");
  72. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(doubleFarLeft, doubleFarRight), "double 超过容差应不相等");
  73. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(doubleFarLeft, doubleFarRight), "double 值不同时 CompareOnlyKey 应返回 True");
  74. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(strLeft, strRight), "string 值不同时 Compare 应返回 False");
  75. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(strLeft, strRight), "string 值不同时 CompareOnlyKey 应返回 True");
  76. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(typeInt, typeString), "类型不同时 Compare 应返回 False");
  77. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(typeInt, typeString), "类型不同时 CompareOnlyKey 应返回 False");
  78. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(typeInt, typeDouble), "int/double 即使数值相同,类型不同也应不相等");
  79. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(typeInt, typeDouble),
  80. "CompareOnlyKey 忽略 number 具体子类型,int/double 应视为相等");
  81. RyanJsonDelete(intLeft);
  82. RyanJsonDelete(intRight);
  83. RyanJsonDelete(doubleCloseLeft);
  84. RyanJsonDelete(doubleCloseRight);
  85. RyanJsonDelete(doubleFarLeft);
  86. RyanJsonDelete(doubleFarRight);
  87. RyanJsonDelete(strLeft);
  88. RyanJsonDelete(strRight);
  89. RyanJsonDelete(typeInt);
  90. RyanJsonDelete(typeDouble);
  91. RyanJsonDelete(typeString);
  92. }
  93. static void testCompareNumberSubtypeInContainers(void)
  94. {
  95. RyanJson_t left = RyanJsonParse("{\"n\":1,\"arr\":[1,2.0],\"obj\":{\"x\":3,\"y\":4.0}}");
  96. RyanJson_t right = RyanJsonParse("{\"obj\":{\"y\":4,\"x\":3.0},\"arr\":[1.0,2],\"n\":1.0}");
  97. RyanJson_t rightTypeMismatch = RyanJsonParse("{\"obj\":{\"y\":4,\"x\":\"3\"},\"arr\":[1.0,2],\"n\":1.0}");
  98. TEST_ASSERT_NOT_NULL(left);
  99. TEST_ASSERT_NOT_NULL(right);
  100. TEST_ASSERT_NOT_NULL(rightTypeMismatch);
  101. // 全量比较要求数值子类型一致;仅比较 key 时允许 int/double 混用
  102. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, right), "容器中 int/double 子类型不同,Compare 应返回 False");
  103. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, right),
  104. "容器中 int/double 子类型不同,但结构一致时 CompareOnlyKey 应返回 True");
  105. // 数值与字符串类型不同,即使在 CompareOnlyKey 下也必须失败
  106. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightTypeMismatch), "number/string 类型不同,Compare 应返回 False");
  107. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightTypeMismatch), "number/string 类型不同,CompareOnlyKey 也应返回 False");
  108. RyanJsonDelete(left);
  109. RyanJsonDelete(right);
  110. RyanJsonDelete(rightTypeMismatch);
  111. }
  112. static void testCompareEmptyContainerAndTypeMismatch(void)
  113. {
  114. RyanJson_t emptyObjA = RyanJsonCreateObject();
  115. RyanJson_t emptyObjB = RyanJsonCreateObject();
  116. RyanJson_t emptyArrA = RyanJsonCreateArray();
  117. RyanJson_t emptyArrB = RyanJsonCreateArray();
  118. TEST_ASSERT_NOT_NULL(emptyObjA);
  119. TEST_ASSERT_NOT_NULL(emptyObjB);
  120. TEST_ASSERT_NOT_NULL(emptyArrA);
  121. TEST_ASSERT_NOT_NULL(emptyArrB);
  122. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(emptyObjA, emptyObjB), "空对象之间应相等");
  123. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(emptyObjA, emptyObjB), "空对象 CompareOnlyKey 应相等");
  124. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(emptyArrA, emptyArrB), "空数组之间应相等");
  125. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(emptyArrA, emptyArrB), "空数组 CompareOnlyKey 应相等");
  126. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(emptyObjA, emptyArrA), "对象与数组类型不同应不相等");
  127. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(emptyObjA, emptyArrA), "对象与数组 CompareOnlyKey 也应不相等");
  128. RyanJsonDelete(emptyObjA);
  129. RyanJsonDelete(emptyObjB);
  130. RyanJsonDelete(emptyArrA);
  131. RyanJsonDelete(emptyArrB);
  132. }
  133. static void testCompareArraySemantics(void)
  134. {
  135. RyanJson_t arrIntA = RyanJsonCreateArray();
  136. RyanJson_t arrIntB = RyanJsonCreateArray();
  137. RyanJson_t arrIntReverse = RyanJsonCreateArray();
  138. RyanJson_t arrMixedA = RyanJsonCreateArray();
  139. RyanJson_t arrMixedB = RyanJsonCreateArray();
  140. RyanJson_t arrShort = RyanJsonCreateArray();
  141. TEST_ASSERT_NOT_NULL(arrIntA);
  142. TEST_ASSERT_NOT_NULL(arrIntB);
  143. TEST_ASSERT_NOT_NULL(arrIntReverse);
  144. TEST_ASSERT_NOT_NULL(arrMixedA);
  145. TEST_ASSERT_NOT_NULL(arrMixedB);
  146. TEST_ASSERT_NOT_NULL(arrShort);
  147. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntA, 1));
  148. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntA, 2));
  149. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntA, 3));
  150. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntB, 1));
  151. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntB, 2));
  152. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntB, 3));
  153. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntReverse, 3));
  154. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntReverse, 2));
  155. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrIntReverse, 1));
  156. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrMixedA, 1));
  157. TEST_ASSERT_TRUE(RyanJsonAddStringToArray(arrMixedA, "2"));
  158. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrMixedA, 3));
  159. TEST_ASSERT_TRUE(RyanJsonAddStringToArray(arrMixedB, "1"));
  160. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrMixedB, 2));
  161. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrMixedB, 3));
  162. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrShort, 1));
  163. TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arrShort, 2));
  164. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(arrIntA, arrIntB), "相同数组 Compare 应返回 True");
  165. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrIntA, arrIntReverse), "数组顺序不同 Compare 应返回 False");
  166. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(arrIntA, arrIntReverse), "数组顺序不同但类型一致,CompareOnlyKey 应返回 True");
  167. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrMixedA, arrMixedB), "数组元素类型顺序不同 Compare 应返回 False");
  168. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(arrMixedA, arrMixedB), "数组元素类型顺序不同 CompareOnlyKey 应返回 False");
  169. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrIntA, arrShort), "数组长度不同 Compare 应返回 False");
  170. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(arrIntA, arrShort), "数组长度不同 CompareOnlyKey 应返回 False");
  171. RyanJsonDelete(arrIntA);
  172. RyanJsonDelete(arrIntB);
  173. RyanJsonDelete(arrIntReverse);
  174. RyanJsonDelete(arrMixedA);
  175. RyanJsonDelete(arrMixedB);
  176. RyanJsonDelete(arrShort);
  177. }
  178. static void testCompareNestedObjectScenarios(void)
  179. {
  180. RyanJson_t left = RyanJsonParse("{\"meta\":{\"id\":1,\"name\":\"m\"},\"list\":[1,2,3],\"flag\":true}");
  181. RyanJson_t rightOrderedDiff = RyanJsonParse("{\"flag\":true,\"list\":[1,2,3],\"meta\":{\"name\":\"m\",\"id\":1}}");
  182. RyanJson_t rightValueDiff = RyanJsonParse("{\"flag\":true,\"list\":[1,2,3],\"meta\":{\"name\":\"m\",\"id\":2}}");
  183. RyanJson_t rightMissingKey = RyanJsonParse("{\"flag\":true,\"list\":[1,2,3],\"meta\":{\"name\":\"m\",\"idx\":1}}");
  184. RyanJson_t leftSingleKey = RyanJsonParse("{\"a\":1}");
  185. RyanJson_t rightSingleKey = RyanJsonParse("{\"b\":1}");
  186. RyanJson_t leftPrefixMatch = RyanJsonParse("{\"a\":1,\"b\":2}");
  187. RyanJson_t rightPrefixMismatch = RyanJsonParse("{\"a\":1,\"c\":2}");
  188. RyanJson_t leftTailMatch = RyanJsonParse("{\"a\":1,\"b\":2,\"c\":3}");
  189. RyanJson_t rightTailMatch = RyanJsonParse("{\"b\":2,\"c\":3,\"a\":1}");
  190. RyanJson_t rightTailMismatch = RyanJsonParse("{\"c\":3,\"d\":4,\"a\":1}");
  191. TEST_ASSERT_NOT_NULL(left);
  192. TEST_ASSERT_NOT_NULL(rightOrderedDiff);
  193. TEST_ASSERT_NOT_NULL(rightValueDiff);
  194. TEST_ASSERT_NOT_NULL(rightMissingKey);
  195. TEST_ASSERT_NOT_NULL(leftSingleKey);
  196. TEST_ASSERT_NOT_NULL(rightSingleKey);
  197. TEST_ASSERT_NOT_NULL(leftPrefixMatch);
  198. TEST_ASSERT_NOT_NULL(rightPrefixMismatch);
  199. TEST_ASSERT_NOT_NULL(leftTailMatch);
  200. TEST_ASSERT_NOT_NULL(rightTailMatch);
  201. TEST_ASSERT_NOT_NULL(rightTailMismatch);
  202. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightOrderedDiff), "嵌套对象乱序但值一致应返回 True");
  203. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightOrderedDiff), "嵌套对象乱序 CompareOnlyKey 应返回 True");
  204. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightValueDiff), "嵌套对象值不同 Compare 应返回 False");
  205. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightValueDiff), "嵌套对象值不同 CompareOnlyKey 应返回 True");
  206. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightMissingKey), "嵌套对象 key 不匹配 Compare 应返回 False");
  207. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightMissingKey), "嵌套对象 key 不匹配 CompareOnlyKey 应返回 False");
  208. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(leftSingleKey, rightSingleKey), "同尺寸对象但 key 不同 Compare 应返回 False");
  209. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(leftSingleKey, rightSingleKey),
  210. "同尺寸对象但 key 不同 CompareOnlyKey 应返回 False");
  211. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(leftPrefixMatch, rightPrefixMismatch),
  212. "前缀 key 相同但后续 key 不同 Compare 应返回 False");
  213. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(leftPrefixMatch, rightPrefixMismatch),
  214. "前缀 key 相同但后续 key 不同 CompareOnlyKey 应返回 False");
  215. // 覆盖同层遍历中 rightCandidate == NULL 的回退查找成功分支
  216. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(leftTailMatch, rightTailMatch), "尾节点命中回退查找后 Compare 应返回 True");
  217. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(leftTailMatch, rightTailMatch), "尾节点命中回退查找后 CompareOnlyKey 应返回 True");
  218. // 覆盖同层遍历中 rightCandidate == NULL 的回退查找失败分支
  219. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(leftTailMatch, rightTailMismatch), "尾节点回退查找失败 Compare 应返回 False");
  220. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(leftTailMatch, rightTailMismatch),
  221. "尾节点回退查找失败 CompareOnlyKey 应返回 False");
  222. RyanJsonDelete(left);
  223. RyanJsonDelete(rightOrderedDiff);
  224. RyanJsonDelete(rightValueDiff);
  225. RyanJsonDelete(rightMissingKey);
  226. RyanJsonDelete(leftSingleKey);
  227. RyanJsonDelete(rightSingleKey);
  228. RyanJsonDelete(leftPrefixMatch);
  229. RyanJsonDelete(rightPrefixMismatch);
  230. RyanJsonDelete(leftTailMatch);
  231. RyanJsonDelete(rightTailMatch);
  232. RyanJsonDelete(rightTailMismatch);
  233. }
  234. static void testCompareArrayWithObjects(void)
  235. {
  236. RyanJson_t arrLeft = RyanJsonParse("[{\"a\":1,\"b\":2},{\"x\":3,\"y\":4}]");
  237. RyanJson_t arrObjectUnordered = RyanJsonParse("[{\"b\":2,\"a\":1},{\"y\":4,\"x\":3}]");
  238. RyanJson_t arrOrderSwapped = RyanJsonParse("[{\"y\":4,\"x\":3},{\"b\":2,\"a\":1}]");
  239. RyanJson_t arrValueDiff = RyanJsonParse("[{\"a\":9,\"b\":2},{\"x\":3,\"y\":4}]");
  240. TEST_ASSERT_NOT_NULL(arrLeft);
  241. TEST_ASSERT_NOT_NULL(arrObjectUnordered);
  242. TEST_ASSERT_NOT_NULL(arrOrderSwapped);
  243. TEST_ASSERT_NOT_NULL(arrValueDiff);
  244. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(arrLeft, arrObjectUnordered), "数组内对象乱序键应比较为 True");
  245. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(arrLeft, arrObjectUnordered), "数组内对象乱序键 CompareOnlyKey 应返回 True");
  246. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrLeft, arrOrderSwapped), "数组元素顺序变化 Compare 应返回 False");
  247. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(arrLeft, arrOrderSwapped), "数组元素顺序变化 CompareOnlyKey 应返回 False");
  248. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(arrLeft, arrValueDiff), "数组内对象值变化 Compare 应返回 False");
  249. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(arrLeft, arrValueDiff), "数组内对象值变化但键结构一致 CompareOnlyKey 应返回 True");
  250. RyanJsonDelete(arrLeft);
  251. RyanJsonDelete(arrObjectUnordered);
  252. RyanJsonDelete(arrOrderSwapped);
  253. RyanJsonDelete(arrValueDiff);
  254. }
  255. static void testCompareDeepNestAndLargeArray(void)
  256. {
  257. // 深度嵌套比较(检测栈溢出或递归限制)
  258. // 之前 200 层出现疑似内存不足或其他问题,降至 50 层验证核心逻辑
  259. int32_t depth = 50;
  260. RyanJson_t root1 = RyanJsonCreateObject();
  261. RyanJson_t root2 = RyanJsonCreateObject();
  262. RyanJson_t curr1 = root1;
  263. RyanJson_t curr2 = root2;
  264. for (int32_t i = 0; i < depth; i++)
  265. {
  266. RyanJson_t child1 = RyanJsonCreateObject();
  267. RyanJson_t child2 = RyanJsonCreateObject();
  268. TEST_ASSERT_NOT_NULL_MESSAGE(child1, "创建 child1 失败");
  269. TEST_ASSERT_NOT_NULL_MESSAGE(child2, "创建 child2 失败");
  270. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(curr1, "nest", child1), "添加到 curr1 失败");
  271. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(curr2, "nest", child2), "添加到 curr2 失败");
  272. // RyanJsonAddItemToObject 会“吞掉” child1(若其为容器),把其内容转移到新节点并释放 child1
  273. // 因此 child1 指针已失效,必须通过 key 获取新创建的节点
  274. curr1 = RyanJsonGetObjectByKey(curr1, "nest");
  275. curr2 = RyanJsonGetObjectByKey(curr2, "nest");
  276. TEST_ASSERT_NOT_NULL_MESSAGE(curr1, "获取 curr1 下一级 nest 失败");
  277. TEST_ASSERT_NOT_NULL_MESSAGE(curr2, "获取 curr2 下一级 nest 失败");
  278. }
  279. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root1, root2), "初始深度比较失败");
  280. // 修改末端
  281. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToObject(curr1, "diff", 1), "添加 diff 失败");
  282. TEST_ASSERT_EQUAL_INT_MESSAGE(1, RyanJsonGetSize(curr1), "添加 diff 后 Size 应为 1");
  283. TEST_ASSERT_EQUAL_INT_MESSAGE(0, RyanJsonGetSize(curr2), "curr2 Size 应仍为 0");
  284. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(root1, root2), "修改后深度比较应失败");
  285. RyanJsonDelete(root1);
  286. RyanJsonDelete(root2);
  287. // 大数组比较
  288. int32_t count = 2000;
  289. RyanJson_t arr1 = RyanJsonCreateArray();
  290. RyanJson_t arr2 = RyanJsonCreateArray();
  291. for (int32_t i = 0; i < count; i++)
  292. {
  293. RyanJsonAddIntToArray(arr1, i);
  294. RyanJsonAddIntToArray(arr2, i);
  295. }
  296. TEST_ASSERT_TRUE(RyanJsonCompare(arr1, arr2));
  297. // 修改中间一个元素
  298. RyanJsonDeleteByIndex(arr2, count / 2); // 删除中间项
  299. RyanJson_t insert = RyanJsonCreateInt("new", 99999);
  300. RyanJsonInsert(arr2, count / 2, insert);
  301. TEST_ASSERT_FALSE(RyanJsonCompare(arr1, arr2));
  302. RyanJsonDelete(arr1);
  303. RyanJsonDelete(arr2);
  304. }
  305. static void testCompareEqualityAndStructuralDiff(void)
  306. {
  307. char jsonstr[] = "{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null,\"item\":"
  308. "{\"inter\":16,\"double\":16."
  309. "89,\"string\":\"hello\","
  310. "\"boolTrue\":true,\"boolFalse\":false,\"null\":null},\"arrayInt\":[16,16,16,16,16],\"arrayDouble\":[16.89,16.89,"
  311. "16.89,16.89,16.89],"
  312. "\"arrayString\":[\"hello\",\"hello\","
  313. "\"hello\",\"hello\",\"hello\"],\"array\":[16,16.89,\"hello\",true,false,null],\"arrayItem\":[{\"inter\":16,"
  314. "\"double\":16.89,\"string\":"
  315. "\"hello\",\"boolTrue\":true,"
  316. "\"boolFalse\":false,\"null\":null},{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,"
  317. "\"boolFalse\":false,\"null\":null}]}";
  318. RyanJson_t json = RyanJsonParse(jsonstr);
  319. TEST_ASSERT_NOT_NULL_MESSAGE(json, "解析 Json 1 失败");
  320. RyanJson_t json2 = RyanJsonParse(jsonstr);
  321. TEST_ASSERT_NOT_NULL_MESSAGE(json2, "解析 Json 2 失败");
  322. // 边界情况测试
  323. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, NULL), "与 NULL 比较应返回 False");
  324. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(NULL, json2), "NULL 与对象比较应返回 False");
  325. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(NULL, NULL), "NULL 与 NULL 比较应返回 False");
  326. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, NULL), "仅比较 Key:与 NULL 比较应返回 False");
  327. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(NULL, json2), "仅比较 Key:NULL 与对象比较应返回 False");
  328. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(NULL, NULL), "仅比较 Key:NULL 与 NULL 比较应返回 False");
  329. // 完整对象比较
  330. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(json, json2), "两个相同内容的对象比较应返回 True");
  331. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(json, json), "对象与自身比较应返回 True");
  332. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "仅比较 Key:两个相同内容的对象比较应返回 True");
  333. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json), "仅比较 Key:对象与自身比较应返回 True");
  334. // 修改对象 2 并比较
  335. // 添加字符串
  336. RyanJsonDelete(json2);
  337. json2 = RyanJsonParse(jsonstr);
  338. RyanJsonAddStringToObject(json2, "test", "hello");
  339. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个字段后比较应返回 False");
  340. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个字段后仅比较 Key 应返回 False");
  341. // 添加整数
  342. RyanJsonDelete(json2);
  343. json2 = RyanJsonParse(jsonstr);
  344. RyanJsonAddIntToObject(json2, "test", 1);
  345. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个整数后比较应返回 False");
  346. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个整数后仅比较 Key 应返回 False");
  347. // 添加浮点数
  348. RyanJsonDelete(json2);
  349. json2 = RyanJsonParse(jsonstr);
  350. RyanJsonAddDoubleToObject(json2, "test", 2.0);
  351. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个浮点数后比较应返回 False");
  352. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个浮点数后仅比较 Key 应返回 False");
  353. // 添加 boolValue
  354. RyanJsonDelete(json2);
  355. json2 = RyanJsonParse(jsonstr);
  356. RyanJsonAddBoolToObject(json2, "test", RyanJsonTrue);
  357. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个布尔值后比较应返回 False");
  358. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个布尔值后仅比较 Key 应返回 False");
  359. // 添加 null
  360. RyanJsonDelete(json2);
  361. json2 = RyanJsonParse(jsonstr);
  362. RyanJsonAddNullToObject(json2, "test");
  363. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "多出一个 Null 后比较应返回 False");
  364. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "多出一个 Null 后仅比较 Key 应返回 False");
  365. // 数组修改测试
  366. RyanJsonDelete(json2);
  367. json2 = RyanJsonParse(jsonstr);
  368. RyanJsonAddIntToArray(RyanJsonGetObjectToKey(json2, "arrayInt"), 2);
  369. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "数组长度变化后比较应返回 False");
  370. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "数组长度变化后仅比较 Key 应返回 False");
  371. RyanJsonDelete(json2);
  372. json2 = RyanJsonParse(jsonstr);
  373. RyanJsonAddDoubleToArray(RyanJsonGetObjectToKey(json2, "arrayDouble"), 2.0);
  374. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "数组长度变化(浮点)后比较应返回 False");
  375. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "数组长度变化(浮点)后仅比较 Key 应返回 False");
  376. RyanJsonDelete(json2);
  377. json2 = RyanJsonParse(jsonstr);
  378. RyanJsonAddStringToArray(RyanJsonGetObjectToKey(json2, "arrayString"), "hello");
  379. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "数组长度变化(字符串)后比较应返回 False");
  380. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "数组长度变化(字符串)后仅比较 Key 应返回 False");
  381. RyanJsonDelete(json2);
  382. json2 = RyanJsonParse(jsonstr);
  383. RyanJsonAddStringToArray(RyanJsonGetObjectToKey(json2, "arrayItem"), "hello");
  384. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "数组长度变化(项)后比较应返回 False");
  385. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "数组长度变化(项)后仅比较 Key 应返回 False");
  386. // 修改 key 名称
  387. RyanJsonDelete(json2);
  388. json2 = RyanJsonParse(jsonstr);
  389. RyanJsonChangeKey(RyanJsonGetObjectToKey(json2, "inter"), "int2");
  390. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Key 修改后比较应返回 False");
  391. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Key 修改后仅比较 Key 应返回 False");
  392. // 修改值但 key 相同
  393. RyanJsonDelete(json2);
  394. json2 = RyanJsonParse(jsonstr);
  395. RyanJsonChangeIntValue(RyanJsonGetObjectToKey(json2, "inter"), 17);
  396. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "Value 修改后比较应返回 False");
  397. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "Value 修改但 Key 相同,仅比较 Key 应返回 True");
  398. RyanJsonDelete(json2);
  399. json2 = RyanJsonParse(jsonstr);
  400. RyanJsonChangeDoubleValue(RyanJsonGetObjectToKey(json2, "double"), 20.89);
  401. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "浮点 Value 修改但 Key 相同,仅比较 Key 应返回 True");
  402. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "浮点 Value 修改后比较应返回 False");
  403. // 类型修改测试(从 double 改为 int32_t)
  404. RyanJsonDelete(json2);
  405. json2 = RyanJsonParse(jsonstr);
  406. RyanJsonDeleteByKey(json2, "double");
  407. RyanJsonAddIntToObject(json2, "double", 20); // 改为 int
  408. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "类型修改后比较应返回 False");
  409. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "类型修改但 Key 相同,仅比较 Key 应返回 True");
  410. // 修改 strValue
  411. RyanJsonDelete(json2);
  412. json2 = RyanJsonParse(jsonstr);
  413. RyanJsonChangeStringValue(RyanJsonGetObjectToKey(json2, "string"), "49");
  414. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "字符串 Value 修改后比较应返回 False");
  415. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "字符串 Value 修改但 Key 相同,仅比较 Key 应返回 True");
  416. // 修改对象 1 的 boolValue
  417. RyanJsonDelete(json2);
  418. json2 = RyanJsonParse(jsonstr);
  419. RyanJsonChangeBoolValue(RyanJsonGetObjectToKey(json2, "boolTrue"), RyanJsonFalse);
  420. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "布尔 Value 修改后比较应返回 False");
  421. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "布尔 Value 修改但 Key 相同,仅比较 Key 应返回 True");
  422. // 修改嵌套对象的 boolValue
  423. RyanJsonDelete(json2);
  424. json2 = RyanJsonParse(jsonstr);
  425. RyanJsonChangeBoolValue(RyanJsonGetObjectToKey(json2, "item", "boolTrue"), RyanJsonFalse);
  426. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "嵌套布尔 Value 修改后比较应返回 False");
  427. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "嵌套布尔 Value 修改但结构相同,仅比较 Key 应返回 True");
  428. // 修改数组中的整数
  429. RyanJsonDelete(json2);
  430. json2 = RyanJsonParse(jsonstr);
  431. RyanJsonChangeIntValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "arrayInt"), 0), 17);
  432. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "数组元素修改后比较应返回 False");
  433. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "数组元素修改但长度相同,仅比较 Key 应返回 True");
  434. // 修改数组中的浮点数
  435. RyanJsonDelete(json2);
  436. json2 = RyanJsonParse(jsonstr);
  437. RyanJsonChangeDoubleValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "arrayDouble"), 0), 20.89);
  438. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "数组浮点元素修改后比较应返回 False");
  439. // 修改数组中的字符串
  440. RyanJsonDelete(json2);
  441. json2 = RyanJsonParse(jsonstr);
  442. RyanJsonChangeStringValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "arrayString"), 0), "20.89");
  443. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "数组字符串元素修改后比较应返回 False");
  444. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "数组字符串元素修改但长度相同,仅比较 Key 应返回 True");
  445. // 修改混合数组
  446. RyanJsonDelete(json2);
  447. json2 = RyanJsonParse(jsonstr);
  448. RyanJsonChangeIntValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "array"), 0), 17);
  449. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "混合数组修改后比较应返回 False");
  450. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "混合数组修改但长度相同,仅比较 Key 应返回 True");
  451. // 修改数组项中的对象
  452. RyanJsonDelete(json2);
  453. json2 = RyanJsonParse(jsonstr);
  454. RyanJsonChangeIntValue(RyanJsonGetObjectToKey(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(json2, "arrayItem"), 0), "inter"),
  455. 17);
  456. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "数组项对象修改后比较应返回 False");
  457. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "数组项对象修改但结构相同,仅比较 Key 应返回 True");
  458. // 删除整个 key 节点
  459. RyanJsonDelete(json2);
  460. json2 = RyanJsonParse(jsonstr);
  461. RyanJsonDeleteByKey(json2, "arrayItem");
  462. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "删除 Key 后比较应返回 False");
  463. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "删除 Key 后仅比较 Key 应返回 False");
  464. // 删除数组索引项
  465. RyanJsonDelete(json2);
  466. json2 = RyanJsonParse(jsonstr);
  467. RyanJsonDeleteByIndex(RyanJsonGetObjectToKey(json2, "arrayInt"), 2);
  468. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "删除数组索引后比较应返回 False");
  469. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "删除数组索引后仅比较 Key 应返回 False");
  470. // 删除数组项中的对象项
  471. RyanJsonDelete(json2);
  472. json2 = RyanJsonParse(jsonstr);
  473. RyanJsonDeleteByIndex(RyanJsonGetObjectToKey(json2, "arrayItem"), 0);
  474. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(json, json2), "删除数组对象项后比较应返回 False");
  475. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(json, json2), "删除数组对象项后仅比较 Key 应返回 False");
  476. RyanJsonDelete(json);
  477. RyanJsonDelete(json2);
  478. }
  479. void testCompareRunner(void)
  480. {
  481. UnitySetTestFile(__FILE__);
  482. RUN_TEST(testCompareEdgeCases);
  483. RUN_TEST(testCompareObjectOrderPaths);
  484. RUN_TEST(testCompareScalarAndTypeMatrix);
  485. RUN_TEST(testCompareNumberSubtypeInContainers);
  486. RUN_TEST(testCompareEmptyContainerAndTypeMismatch);
  487. RUN_TEST(testCompareArraySemantics);
  488. RUN_TEST(testCompareNestedObjectScenarios);
  489. RUN_TEST(testCompareArrayWithObjects);
  490. RUN_TEST(testCompareDeepNestAndLargeArray);
  491. RUN_TEST(testCompareEqualityAndStructuralDiff);
  492. }