testCompareDuplicateKeyAdvanced.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. #include "testBase.h"
  2. static void testCompareDuplicateKeyInterleavedWithUnique(void)
  3. {
  4. // 该用例覆盖“重复 key 与唯一 key 交错”场景:
  5. // - 非严格模式:验证重复 key 的出现序号匹配不会被交错 key 干扰;
  6. // - 严格模式:重复 key 解析应失败,并使用无重复 key 控制组验证普通语义。
  7. RyanJson_t left = RyanJsonParse("{\"a\":1,\"b\":2,\"a\":3,\"c\":4}");
  8. RyanJson_t rightSame = RyanJsonParse("{\"c\":4,\"a\":1,\"b\":2,\"a\":3}");
  9. RyanJson_t rightDupSwapped = RyanJsonParse("{\"c\":4,\"a\":3,\"b\":2,\"a\":1}");
  10. RyanJson_t rightMissingUnique = RyanJsonParse("{\"c\":4,\"a\":1,\"a\":3,\"d\":2}");
  11. RyanJson_t rightTypeMismatch = RyanJsonParse("{\"c\":4,\"a\":1,\"b\":2,\"a\":\"3\"}");
  12. #if true == RyanJsonStrictObjectKeyCheck
  13. TEST_ASSERT_NULL_MESSAGE(left, "strict 模式下重复 key 应解析失败");
  14. TEST_ASSERT_NULL_MESSAGE(rightSame, "strict 模式下重复 key 应解析失败");
  15. TEST_ASSERT_NULL_MESSAGE(rightDupSwapped, "strict 模式下重复 key 应解析失败");
  16. TEST_ASSERT_NULL_MESSAGE(rightMissingUnique, "strict 模式下重复 key 应解析失败");
  17. TEST_ASSERT_NULL_MESSAGE(rightTypeMismatch, "strict 模式下重复 key 应解析失败");
  18. // 控制组:无重复 key 时,Object 乱序应相等,key 不同应不等。
  19. {
  20. RyanJson_t normalLeft = RyanJsonParse("{\"a\":1,\"b\":2,\"c\":3,\"d\":4}");
  21. RyanJson_t normalRight = RyanJsonParse("{\"d\":4,\"c\":3,\"b\":2,\"a\":1}");
  22. RyanJson_t normalMismatch = RyanJsonParse("{\"d\":4,\"x\":3,\"b\":2,\"a\":1}");
  23. TEST_ASSERT_NOT_NULL(normalLeft);
  24. TEST_ASSERT_NOT_NULL(normalRight);
  25. TEST_ASSERT_NOT_NULL(normalMismatch);
  26. TEST_ASSERT_TRUE(RyanJsonCompare(normalLeft, normalRight));
  27. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(normalLeft, normalRight));
  28. TEST_ASSERT_FALSE(RyanJsonCompare(normalLeft, normalMismatch));
  29. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(normalLeft, normalMismatch));
  30. RyanJsonDelete(normalLeft);
  31. RyanJsonDelete(normalRight);
  32. RyanJsonDelete(normalMismatch);
  33. }
  34. #else
  35. TEST_ASSERT_NOT_NULL(left);
  36. TEST_ASSERT_NOT_NULL(rightSame);
  37. TEST_ASSERT_NOT_NULL(rightDupSwapped);
  38. TEST_ASSERT_NOT_NULL(rightMissingUnique);
  39. TEST_ASSERT_NOT_NULL(rightTypeMismatch);
  40. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightSame), "交错场景下重复 key 同序号一致时 Compare 应返回 True");
  41. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightSame), "交错场景下重复 key 同序号一致时 CompareOnlyKey 应返回 True");
  42. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightDupSwapped), "交错场景下重复 key 同序号值错位时 Compare 应返回 False");
  43. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightDupSwapped),
  44. "交错场景下重复 key 同序号类型一致时 CompareOnlyKey 应返回 True");
  45. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightMissingUnique), "交错场景下唯一 key 不一致时 Compare 应返回 False");
  46. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightMissingUnique),
  47. "交错场景下唯一 key 不一致时 CompareOnlyKey 应返回 False");
  48. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightTypeMismatch), "交错场景下重复 key 同序号类型变化时 Compare 应返回 False");
  49. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightTypeMismatch),
  50. "交错场景下重复 key 同序号类型变化时 CompareOnlyKey 应返回 False");
  51. #endif
  52. RyanJsonDelete(left);
  53. RyanJsonDelete(rightSame);
  54. RyanJsonDelete(rightDupSwapped);
  55. RyanJsonDelete(rightMissingUnique);
  56. RyanJsonDelete(rightTypeMismatch);
  57. }
  58. static void testCompareDuplicateKeyMutationCountMismatchAndRecover(void)
  59. {
  60. // 该用例覆盖“重复 key 在变更后计数不一致”的检测与恢复路径。
  61. RyanJson_t left = RyanJsonParse("{\"a\":1,\"a\":2,\"b\":3}");
  62. RyanJson_t right = RyanJsonParse("{\"a\":1,\"a\":2,\"b\":3}");
  63. #if true == RyanJsonStrictObjectKeyCheck
  64. TEST_ASSERT_NULL_MESSAGE(left, "strict 模式下重复 key 应解析失败");
  65. TEST_ASSERT_NULL_MESSAGE(right, "strict 模式下重复 key 应解析失败");
  66. // 控制组:无重复 key 的变更链路应保持 CompareOnlyKey 语义正确。
  67. {
  68. RyanJson_t normalLeft = RyanJsonParse("{\"a\":1,\"b\":2}");
  69. RyanJson_t normalRight = RyanJsonDuplicate(normalLeft);
  70. TEST_ASSERT_NOT_NULL(normalLeft);
  71. TEST_ASSERT_NOT_NULL(normalRight);
  72. RyanJson_t removed = RyanJsonDetachByKey(normalRight, "a");
  73. TEST_ASSERT_NOT_NULL(removed);
  74. RyanJsonDelete(removed);
  75. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(normalRight, "c", 3));
  76. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(normalLeft, normalRight));
  77. TEST_ASSERT_FALSE(RyanJsonCompare(normalLeft, normalRight));
  78. RyanJsonDelete(normalLeft);
  79. RyanJsonDelete(normalRight);
  80. }
  81. #else
  82. TEST_ASSERT_NOT_NULL(left);
  83. TEST_ASSERT_NOT_NULL(right);
  84. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, right), "初始重复 key 结构一致时 CompareOnlyKey 应返回 True");
  85. // 移除一个 a,再补一个 b -> key 计数变化,应判不等。
  86. RyanJson_t removedA = RyanJsonDetachByKey(right, "a");
  87. TEST_ASSERT_NOT_NULL(removedA);
  88. RyanJsonDelete(removedA);
  89. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(right, "b", 4));
  90. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, right), "重复 key 计数不一致时 CompareOnlyKey 应返回 False");
  91. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, right), "重复 key 计数不一致时 Compare 应返回 False");
  92. // 恢复:移除一个 b,再补一个 a -> key 计数对齐,应恢复 CompareOnlyKey。
  93. RyanJson_t removedB = RyanJsonDetachByKey(right, "b");
  94. TEST_ASSERT_NOT_NULL(removedB);
  95. RyanJsonDelete(removedB);
  96. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(right, "a", 9));
  97. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, right), "重复 key 计数恢复后 CompareOnlyKey 应返回 True");
  98. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, right), "值变化后 Compare 应返回 False");
  99. #endif
  100. RyanJsonDelete(left);
  101. RyanJsonDelete(right);
  102. }
  103. static void testCompareDuplicateKeyChangeKeyCreatesMismatch(void)
  104. {
  105. // 该用例验证 ChangeKey 在非严格模式下制造重复 key 后 CompareOnlyKey 的行为。
  106. RyanJson_t left = RyanJsonParse("{\"a\":1,\"a\":2,\"b\":3}");
  107. RyanJson_t right = RyanJsonParse("{\"a\":1,\"a\":2,\"b\":3}");
  108. #if true == RyanJsonStrictObjectKeyCheck
  109. TEST_ASSERT_NULL_MESSAGE(left, "strict 模式下重复 key 应解析失败");
  110. TEST_ASSERT_NULL_MESSAGE(right, "strict 模式下重复 key 应解析失败");
  111. // 控制组:strict 模式下 ChangeKey 不允许制造重复 key。
  112. {
  113. RyanJson_t normal = RyanJsonParse("{\"a\":1,\"b\":2}");
  114. TEST_ASSERT_NOT_NULL(normal);
  115. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeKey(RyanJsonGetObjectToKey(normal, "a"), "b"),
  116. "strict 模式下 ChangeKey 制造重复 key 应失败");
  117. RyanJson_t expect = RyanJsonParse("{\"a\":1,\"b\":2}");
  118. TEST_ASSERT_NOT_NULL(expect);
  119. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(normal, expect));
  120. RyanJsonDelete(expect);
  121. RyanJsonDelete(normal);
  122. }
  123. #else
  124. TEST_ASSERT_NOT_NULL(left);
  125. TEST_ASSERT_NOT_NULL(right);
  126. TEST_ASSERT_TRUE_MESSAGE(RyanJsonChangeKey(RyanJsonGetObjectToKey(right, "a"), "b"), "非严格模式下 ChangeKey 制造重复 key 应成功");
  127. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, right), "重复 key 计数变化后 CompareOnlyKey 应返回 False");
  128. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, right), "重复 key 计数变化后 Compare 应返回 False");
  129. #endif
  130. RyanJsonDelete(left);
  131. RyanJsonDelete(right);
  132. }
  133. static void testCompareDuplicateKeyNestedMutationIsolation(void)
  134. {
  135. // 该用例覆盖“嵌套重复 key 变更”对 CompareOnlyKey 的影响。
  136. RyanJson_t left = RyanJsonParse("{\"outer\":{\"a\":1,\"a\":2},\"keep\":1}");
  137. RyanJson_t right = RyanJsonParse("{\"outer\":{\"a\":1,\"a\":2},\"keep\":1}");
  138. #if true == RyanJsonStrictObjectKeyCheck
  139. TEST_ASSERT_NULL_MESSAGE(left, "strict 模式下嵌套重复 key 应解析失败");
  140. TEST_ASSERT_NULL_MESSAGE(right, "strict 模式下嵌套重复 key 应解析失败");
  141. // 控制组:无重复 key 的嵌套 Object 变更应被 CompareOnlyKey 捕获。
  142. {
  143. RyanJson_t normalLeft = RyanJsonParse("{\"outer\":{\"a\":1,\"b\":2},\"keep\":1}");
  144. RyanJson_t normalRight = RyanJsonDuplicate(normalLeft);
  145. TEST_ASSERT_NOT_NULL(normalLeft);
  146. TEST_ASSERT_NOT_NULL(normalRight);
  147. RyanJson_t outer = RyanJsonGetObjectToKey(normalRight, "outer");
  148. RyanJson_t removed = RyanJsonDetachByKey(outer, "a");
  149. TEST_ASSERT_NOT_NULL(removed);
  150. RyanJsonDelete(removed);
  151. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(outer, "c", 3));
  152. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(normalLeft, normalRight));
  153. TEST_ASSERT_FALSE(RyanJsonCompare(normalLeft, normalRight));
  154. RyanJsonDelete(normalLeft);
  155. RyanJsonDelete(normalRight);
  156. }
  157. #else
  158. TEST_ASSERT_NOT_NULL(left);
  159. TEST_ASSERT_NOT_NULL(right);
  160. RyanJson_t outerRight = RyanJsonGetObjectToKey(right, "outer");
  161. TEST_ASSERT_NOT_NULL(outerRight);
  162. // 移除一个 a,再补 b -> 嵌套 key 计数变化,应判不等。
  163. RyanJson_t removedA = RyanJsonDetachByKey(outerRight, "a");
  164. TEST_ASSERT_NOT_NULL(removedA);
  165. RyanJsonDelete(removedA);
  166. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(outerRight, "b", 3));
  167. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, right), "嵌套重复 key 计数不一致时 CompareOnlyKey 应返回 False");
  168. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, right), "嵌套重复 key 计数不一致时 Compare 应返回 False");
  169. // 恢复:移除一个 b,再补一个 a -> key 计数对齐,应恢复 CompareOnlyKey。
  170. RyanJson_t removedB = RyanJsonDetachByKey(outerRight, "b");
  171. TEST_ASSERT_NOT_NULL(removedB);
  172. RyanJsonDelete(removedB);
  173. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(outerRight, "a", 9));
  174. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, right), "嵌套重复 key 计数恢复后 CompareOnlyKey 应返回 True");
  175. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, right), "值变化后 Compare 应返回 False");
  176. #endif
  177. RyanJsonDelete(left);
  178. RyanJsonDelete(right);
  179. }
  180. static void testCompareDuplicateKeyCreatedByApi(void)
  181. {
  182. // 该用例验证通过 API 构造重复 key 后的 Compare/CompareOnlyKey 行为。
  183. #if true == RyanJsonStrictObjectKeyCheck
  184. {
  185. RyanJson_t strictObj = RyanJsonCreateObject();
  186. TEST_ASSERT_NOT_NULL(strictObj);
  187. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(strictObj, "a", 1));
  188. TEST_ASSERT_FALSE(RyanJsonAddIntToObject(strictObj, "a", 2));
  189. RyanJsonDelete(strictObj);
  190. }
  191. #else
  192. RyanJson_t left = RyanJsonCreateObject();
  193. RyanJson_t right = RyanJsonCreateObject();
  194. RyanJson_t rightTypeMismatch = RyanJsonCreateObject();
  195. TEST_ASSERT_NOT_NULL(left);
  196. TEST_ASSERT_NOT_NULL(right);
  197. TEST_ASSERT_NOT_NULL(rightTypeMismatch);
  198. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(left, "a", 1));
  199. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(left, "a", 2));
  200. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(right, "a", 1));
  201. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(right, "a", 2));
  202. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightTypeMismatch, "a", 1));
  203. TEST_ASSERT_TRUE(RyanJsonAddStringToObject(rightTypeMismatch, "a", "2"));
  204. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, right), "API 构造的重复 key 完全一致时 Compare 应返回 True");
  205. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, right), "API 构造的重复 key 完全一致时 CompareOnlyKey 应返回 True");
  206. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightTypeMismatch), "API 构造的重复 key 同序号类型变化,Compare 应返回 False");
  207. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightTypeMismatch),
  208. "API 构造的重复 key 同序号类型变化,CompareOnlyKey 应返回 False");
  209. RyanJsonDelete(left);
  210. RyanJsonDelete(right);
  211. RyanJsonDelete(rightTypeMismatch);
  212. #endif
  213. }
  214. static void testCompareDuplicateKeyReplaceByKeyFirstOccurrence(void)
  215. {
  216. // 该用例验证 ReplaceByKey 在重复 key 下仅替换首个命中。
  217. #if true == RyanJsonStrictObjectKeyCheck
  218. RyanJson_t strict = RyanJsonParse("{\"a\":1,\"a\":2}");
  219. TEST_ASSERT_NULL_MESSAGE(strict, "strict 模式下重复 key 应解析失败");
  220. #else
  221. RyanJson_t base = RyanJsonParse("{\"a\":1,\"a\":2}");
  222. RyanJson_t changed = RyanJsonDuplicate(base);
  223. TEST_ASSERT_NOT_NULL(base);
  224. TEST_ASSERT_NOT_NULL(changed);
  225. TEST_ASSERT_TRUE(RyanJsonReplaceByKey(changed, "a", RyanJsonCreateInt("a", 9)));
  226. RyanJson_t expect = RyanJsonParse("{\"a\":9,\"a\":2}");
  227. TEST_ASSERT_NOT_NULL(expect);
  228. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(changed, expect), "ReplaceByKey 应仅替换首个命中节点");
  229. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(changed, expect), "ReplaceByKey 不应改变 key/type 结构");
  230. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(base, changed), "值变化后 Compare 应返回 False");
  231. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(base, changed), "仅值变化时 CompareOnlyKey 应返回 True");
  232. RyanJsonDelete(expect);
  233. RyanJsonDelete(changed);
  234. RyanJsonDelete(base);
  235. #endif
  236. }
  237. static void testCompareDuplicateKeyContainerIsolation(void)
  238. {
  239. // 该用例验证“不同 Object 容器”的重复 key 计数不应互相抵消。
  240. #if true == RyanJsonStrictObjectKeyCheck
  241. RyanJson_t strict = RyanJsonParse("{\"obj\":{\"a\":1,\"a\":2}}");
  242. TEST_ASSERT_NULL_MESSAGE(strict, "strict 模式下重复 key 应解析失败");
  243. #else
  244. RyanJson_t left = RyanJsonParse("{\"obj\":{\"a\":1,\"a\":2},\"other\":{\"a\":1}}");
  245. RyanJson_t right = RyanJsonParse("{\"obj\":{\"a\":1,\"a\":2},\"other\":{\"a\":1,\"a\":2}}");
  246. TEST_ASSERT_NOT_NULL(left);
  247. TEST_ASSERT_NOT_NULL(right);
  248. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, right), "不同容器的重复 key 计数不一致时 CompareOnlyKey 应返回 False");
  249. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, right), "不同容器的重复 key 计数不一致时 Compare 应返回 False");
  250. RyanJsonDelete(left);
  251. RyanJsonDelete(right);
  252. #endif
  253. }
  254. static void testCompareDuplicateKeyEscapedAndEmptyKey(void)
  255. {
  256. // 该用例验证两类容易遗漏的重复 key:
  257. // - 空 key("")重复;
  258. // - 转义后等价 key("a" 与 "\u0061")重复。
  259. RyanJson_t left = RyanJsonParse("{\"\":1,\"\":2,\"a\":3,\"\\u0061\":4}");
  260. RyanJson_t rightSame = RyanJsonParse("{\"a\":3,\"\\u0061\":4,\"\":1,\"\":2}");
  261. RyanJson_t rightValueSwap = RyanJsonParse("{\"\\u0061\":4,\"a\":3,\"\":1,\"\":2}");
  262. RyanJson_t rightTypeMismatch = RyanJsonParse("{\"a\":3,\"\\u0061\":\"4\",\"\":1,\"\":2}");
  263. RyanJson_t rightCountMismatch = RyanJsonParse("{\"a\":3,\"\":1,\"\":2}");
  264. #if true == RyanJsonStrictObjectKeyCheck
  265. TEST_ASSERT_NULL_MESSAGE(left, "strict 模式下空 key 重复应解析失败");
  266. TEST_ASSERT_NULL_MESSAGE(rightSame, "strict 模式下空 key/转义重复应解析失败");
  267. TEST_ASSERT_NULL_MESSAGE(rightValueSwap, "strict 模式下空 key/转义重复应解析失败");
  268. TEST_ASSERT_NULL_MESSAGE(rightTypeMismatch, "strict 模式下空 key/转义重复应解析失败");
  269. TEST_ASSERT_NULL_MESSAGE(rightCountMismatch, "strict 模式下空 key 重复应解析失败");
  270. // 控制组:转义 key 与普通 key 但不重复时,乱序比较应成立。
  271. {
  272. RyanJson_t normalLeft = RyanJsonParse("{\"\":1,\"a\":3,\"\\u0062\":4}");
  273. RyanJson_t normalRight = RyanJsonParse("{\"\\u0062\":4,\"a\":3,\"\":1}");
  274. RyanJson_t normalMismatch = RyanJsonParse("{\"\\u0063\":4,\"a\":3,\"\":1}");
  275. TEST_ASSERT_NOT_NULL(normalLeft);
  276. TEST_ASSERT_NOT_NULL(normalRight);
  277. TEST_ASSERT_NOT_NULL(normalMismatch);
  278. TEST_ASSERT_TRUE(RyanJsonCompare(normalLeft, normalRight));
  279. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(normalLeft, normalRight));
  280. TEST_ASSERT_FALSE(RyanJsonCompare(normalLeft, normalMismatch));
  281. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(normalLeft, normalMismatch));
  282. RyanJsonDelete(normalLeft);
  283. RyanJsonDelete(normalRight);
  284. RyanJsonDelete(normalMismatch);
  285. }
  286. #else
  287. TEST_ASSERT_NOT_NULL(left);
  288. TEST_ASSERT_NOT_NULL(rightSame);
  289. TEST_ASSERT_NOT_NULL(rightValueSwap);
  290. TEST_ASSERT_NOT_NULL(rightTypeMismatch);
  291. TEST_ASSERT_NOT_NULL(rightCountMismatch);
  292. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightSame), "空 key 与转义重复 key 同序号一致时 Compare 应返回 True");
  293. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightSame), "空 key 与转义重复 key 同序号一致时 CompareOnlyKey 应返回 True");
  294. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightValueSwap), "转义重复 key 同序号值错位时 Compare 应返回 False");
  295. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightValueSwap), "转义重复 key 同序号类型一致时 CompareOnlyKey 应返回 True");
  296. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightTypeMismatch), "转义重复 key 同序号类型变化时 Compare 应返回 False");
  297. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightTypeMismatch),
  298. "转义重复 key 同序号类型变化时 CompareOnlyKey 应返回 False");
  299. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightCountMismatch), "空 key/转义重复 key 个数不一致时 Compare 应返回 False");
  300. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightCountMismatch),
  301. "空 key/转义重复 key 个数不一致时 CompareOnlyKey 应返回 False");
  302. #endif
  303. RyanJsonDelete(left);
  304. RyanJsonDelete(rightSame);
  305. RyanJsonDelete(rightValueSwap);
  306. RyanJsonDelete(rightTypeMismatch);
  307. RyanJsonDelete(rightCountMismatch);
  308. }
  309. static void testCompareDuplicateKeySymmetry(void)
  310. {
  311. // 该用例验证比较运算的对称性:
  312. // 对任意 A/B,Compare(A,B) 与 Compare(B,A) 结果应一致,
  313. // CompareOnlyKey 同理。
  314. RyanJson_t trueLeft = RyanJsonParse("{\"k\":1,\"k\":2,\"x\":3}");
  315. RyanJson_t trueRight = RyanJsonParse("{\"x\":3,\"k\":1,\"k\":2}");
  316. RyanJson_t falseTypeLeft = RyanJsonParse("{\"k\":1,\"k\":2,\"x\":3}");
  317. RyanJson_t falseTypeRight = RyanJsonParse("{\"x\":3,\"k\":1,\"k\":\"2\"}");
  318. RyanJson_t falseKeyLeft = RyanJsonParse("{\"k\":1,\"k\":2}");
  319. RyanJson_t falseKeyRight = RyanJsonParse("{\"k\":1,\"x\":2}");
  320. #if true == RyanJsonStrictObjectKeyCheck
  321. TEST_ASSERT_NULL_MESSAGE(trueLeft, "strict 模式下重复 key 应解析失败");
  322. TEST_ASSERT_NULL_MESSAGE(trueRight, "strict 模式下重复 key 应解析失败");
  323. TEST_ASSERT_NULL_MESSAGE(falseTypeLeft, "strict 模式下重复 key 应解析失败");
  324. TEST_ASSERT_NULL_MESSAGE(falseTypeRight, "strict 模式下重复 key 应解析失败");
  325. TEST_ASSERT_NULL_MESSAGE(falseKeyLeft, "strict 模式下重复 key 应解析失败");
  326. TEST_ASSERT_NOT_NULL(falseKeyRight);
  327. // 控制组:无重复 key 的对称性。
  328. {
  329. RyanJson_t normalLeft = RyanJsonParse("{\"a\":1,\"b\":2}");
  330. RyanJson_t normalRight = RyanJsonParse("{\"b\":2,\"a\":1}");
  331. RyanJson_t normalMismatch = RyanJsonParse("{\"a\":1,\"c\":2}");
  332. TEST_ASSERT_NOT_NULL(normalLeft);
  333. TEST_ASSERT_NOT_NULL(normalRight);
  334. TEST_ASSERT_NOT_NULL(normalMismatch);
  335. TEST_ASSERT_TRUE(RyanJsonCompare(normalLeft, normalRight));
  336. TEST_ASSERT_TRUE(RyanJsonCompare(normalRight, normalLeft));
  337. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(normalLeft, normalRight));
  338. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(normalRight, normalLeft));
  339. TEST_ASSERT_FALSE(RyanJsonCompare(normalLeft, normalMismatch));
  340. TEST_ASSERT_FALSE(RyanJsonCompare(normalMismatch, normalLeft));
  341. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(normalLeft, normalMismatch));
  342. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(normalMismatch, normalLeft));
  343. RyanJsonDelete(normalLeft);
  344. RyanJsonDelete(normalRight);
  345. RyanJsonDelete(normalMismatch);
  346. }
  347. #else
  348. TEST_ASSERT_NOT_NULL(trueLeft);
  349. TEST_ASSERT_NOT_NULL(trueRight);
  350. TEST_ASSERT_NOT_NULL(falseTypeLeft);
  351. TEST_ASSERT_NOT_NULL(falseTypeRight);
  352. TEST_ASSERT_NOT_NULL(falseKeyLeft);
  353. TEST_ASSERT_NOT_NULL(falseKeyRight);
  354. TEST_ASSERT_TRUE(RyanJsonCompare(trueLeft, trueRight));
  355. TEST_ASSERT_TRUE(RyanJsonCompare(trueRight, trueLeft));
  356. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(trueLeft, trueRight));
  357. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(trueRight, trueLeft));
  358. TEST_ASSERT_FALSE(RyanJsonCompare(falseTypeLeft, falseTypeRight));
  359. TEST_ASSERT_FALSE(RyanJsonCompare(falseTypeRight, falseTypeLeft));
  360. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(falseTypeLeft, falseTypeRight));
  361. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(falseTypeRight, falseTypeLeft));
  362. TEST_ASSERT_FALSE(RyanJsonCompare(falseKeyLeft, falseKeyRight));
  363. TEST_ASSERT_FALSE(RyanJsonCompare(falseKeyRight, falseKeyLeft));
  364. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(falseKeyLeft, falseKeyRight));
  365. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(falseKeyRight, falseKeyLeft));
  366. #endif
  367. RyanJsonDelete(trueLeft);
  368. RyanJsonDelete(trueRight);
  369. RyanJsonDelete(falseTypeLeft);
  370. RyanJsonDelete(falseTypeRight);
  371. RyanJsonDelete(falseKeyLeft);
  372. RyanJsonDelete(falseKeyRight);
  373. }
  374. static void testCompareDuplicateKeyHighCardinality(void)
  375. {
  376. // 该用例覆盖大量元素时的重复 key 对齐路径。
  377. // 为控制内存占用,只使用 256 个节点,避免测试本身成为内存压力源。
  378. const uint32_t repeatCount = 256U;
  379. #if true == RyanJsonStrictObjectKeyCheck
  380. // strict 模式控制组:重复 key 从第二次起必须拒绝。
  381. {
  382. RyanJson_t strictObj = RyanJsonCreateObject();
  383. TEST_ASSERT_NOT_NULL(strictObj);
  384. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(strictObj, "dup", 1));
  385. TEST_ASSERT_FALSE(RyanJsonAddIntToObject(strictObj, "dup", 2));
  386. RyanJsonDelete(strictObj);
  387. }
  388. // strict 模式下用大规模“唯一 key”Object 验证普通比较路径稳定性。
  389. {
  390. RyanJson_t left = RyanJsonCreateObject();
  391. RyanJson_t rightSame = RyanJsonCreateObject();
  392. RyanJson_t rightValueMismatch = RyanJsonCreateObject();
  393. TEST_ASSERT_NOT_NULL(left);
  394. TEST_ASSERT_NOT_NULL(rightSame);
  395. TEST_ASSERT_NOT_NULL(rightValueMismatch);
  396. for (uint32_t i = 0; i < repeatCount; i++)
  397. {
  398. char key[32];
  399. RyanJsonSnprintf(key, sizeof(key), "k%" PRIu32, i);
  400. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(left, key, (int32_t)i));
  401. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightSame, key, (int32_t)i));
  402. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightValueMismatch, key, (int32_t)(i == 177U ? (i + 1U) : i)));
  403. }
  404. TEST_ASSERT_TRUE(RyanJsonCompare(left, rightSame));
  405. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(left, rightSame));
  406. TEST_ASSERT_FALSE(RyanJsonCompare(left, rightValueMismatch));
  407. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(left, rightValueMismatch));
  408. RyanJsonDelete(left);
  409. RyanJsonDelete(rightSame);
  410. RyanJsonDelete(rightValueMismatch);
  411. }
  412. #else
  413. RyanJson_t left = RyanJsonCreateObject();
  414. RyanJson_t rightSame = RyanJsonCreateObject();
  415. RyanJson_t rightValueMismatch = RyanJsonCreateObject();
  416. RyanJson_t rightTypeMismatch = RyanJsonCreateObject();
  417. TEST_ASSERT_NOT_NULL(left);
  418. TEST_ASSERT_NOT_NULL(rightSame);
  419. TEST_ASSERT_NOT_NULL(rightValueMismatch);
  420. TEST_ASSERT_NOT_NULL(rightTypeMismatch);
  421. for (uint32_t i = 0; i < repeatCount; i++)
  422. {
  423. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(left, "dup", (int32_t)i));
  424. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightSame, "dup", (int32_t)i));
  425. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightValueMismatch, "dup", (int32_t)(i == 177U ? (i + 1U) : i)));
  426. // 在固定序号注入 Number/String 类型差异,验证 CompareOnlyKey 的类型判定不被大数据量掩盖。
  427. if (i == 177U) { TEST_ASSERT_TRUE(RyanJsonAddStringToObject(rightTypeMismatch, "dup", "177")); }
  428. else
  429. {
  430. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(rightTypeMismatch, "dup", (int32_t)i));
  431. }
  432. }
  433. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightSame), "大量重复 key 同序号完全一致时 Compare 应返回 True");
  434. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightSame), "大量重复 key 同序号完全一致时 CompareOnlyKey 应返回 True");
  435. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightValueMismatch), "大量重复 key 存在同序号值差异时 Compare 应返回 False");
  436. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightValueMismatch),
  437. "大量重复 key 仅值不同且类型一致时 CompareOnlyKey 应返回 True");
  438. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightTypeMismatch), "大量重复 key 存在同序号类型差异时 Compare 应返回 False");
  439. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightTypeMismatch),
  440. "大量重复 key 存在同序号类型差异时 CompareOnlyKey 应返回 False");
  441. RyanJsonDelete(left);
  442. RyanJsonDelete(rightSame);
  443. RyanJsonDelete(rightValueMismatch);
  444. RyanJsonDelete(rightTypeMismatch);
  445. #endif
  446. }
  447. static void testCompareDuplicateKeyStreamParseMutationChain(void)
  448. {
  449. // 复杂链路:
  450. // ParseOptions(文档1) -> ParseOptions(文档2) -> Compare/CompareOnlyKey
  451. // -> ReplaceByKey(失败) -> CompareOnlyKey 再校验 -> Detach/Add 修复结构 -> Compare。
  452. // 目标:
  453. // - 覆盖“流式多文档 + 重复 key 比较”的真实调用链;
  454. // - 验证失败 API 不会污染 CompareOnlyKey 的结构判断;
  455. // - 验证结构修复后 Compare/CompareOnlyKey 可恢复一致。
  456. const char *dupStream = "{\"a\":1,\"a\":2,\"c\":3}{\"a\":1,\"b\":2,\"c\":3}";
  457. const uint32_t dupLen = (uint32_t)strlen(dupStream);
  458. const char *dupEnd = NULL;
  459. RyanJson_t first = RyanJsonParseOptions(dupStream, dupLen, RyanJsonFalse, &dupEnd);
  460. // strict 模式下,文档1 含重复 key,会在解析阶段失败。
  461. // 这里走一条无重复 key 的控制链路,保证该用例在两种模式都可执行。
  462. if (NULL == first)
  463. {
  464. const char *strictStream = "{\"a\":1,\"c\":3}{\"a\":1,\"b\":2,\"c\":3}";
  465. const uint32_t strictLen = (uint32_t)strlen(strictStream);
  466. const char *strictEnd = NULL;
  467. RyanJson_t strictFirst = RyanJsonParseOptions(strictStream, strictLen, RyanJsonFalse, &strictEnd);
  468. TEST_ASSERT_NOT_NULL_MESSAGE(strictFirst, "strict 控制链路文档1 解析应成功");
  469. TEST_ASSERT_NOT_NULL(strictEnd);
  470. uint32_t strictRemain = (uint32_t)(strictLen - (uint32_t)(strictEnd - strictStream));
  471. RyanJson_t strictSecond = RyanJsonParseOptions(strictEnd, strictRemain, RyanJsonTrue, NULL);
  472. TEST_ASSERT_NOT_NULL_MESSAGE(strictSecond, "strict 控制链路文档2 解析应成功");
  473. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(strictFirst, strictSecond),
  474. "strict 控制链路初始 key 集不一致,应返回 False");
  475. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToObject(strictFirst, "b", 2), "strict 控制链路补齐 key=b 失败");
  476. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(strictFirst, strictSecond), "strict 控制链路补齐后 Compare 应返回 True");
  477. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(strictFirst, strictSecond),
  478. "strict 控制链路补齐后 CompareOnlyKey 应返回 True");
  479. RyanJsonDelete(strictSecond);
  480. RyanJsonDelete(strictFirst);
  481. return;
  482. }
  483. TEST_ASSERT_NOT_NULL(dupEnd);
  484. TEST_ASSERT_EQUAL_CHAR('{', *dupEnd);
  485. uint32_t dupRemain = (uint32_t)(dupLen - (uint32_t)(dupEnd - dupStream));
  486. RyanJson_t second = RyanJsonParseOptions(dupEnd, dupRemain, RyanJsonTrue, NULL);
  487. TEST_ASSERT_NOT_NULL_MESSAGE(second, "文档2 解析应成功");
  488. // 初始时:文档1 为 a,a,c;文档2 为 a,b,c。应明显不等。
  489. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(first, second), "重复 key 文档与唯一 key 文档初始 Compare 应返回 False");
  490. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(first, second), "重复 key 文档与唯一 key 文档初始 CompareOnlyKey 应返回 False");
  491. RyanJson_t sameShape = RyanJsonParse("{\"c\":30,\"a\":10,\"a\":20}");
  492. RyanJson_t keyMismatch = RyanJsonParse("{\"c\":30,\"a\":10,\"b\":20}");
  493. TEST_ASSERT_NOT_NULL(sameShape);
  494. TEST_ASSERT_NOT_NULL(keyMismatch);
  495. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(first, sameShape), "同 key 同序号类型一致时 CompareOnlyKey 应返回 True");
  496. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(first, keyMismatch), "重复 key 与不同 key 混合时 CompareOnlyKey 应返回 False");
  497. // 失败路径:不存在 key 的替换失败,结构语义不应被破坏。
  498. RyanJson_t failCandidate = RyanJsonCreateInt("missing", 7);
  499. TEST_ASSERT_NOT_NULL(failCandidate);
  500. TEST_ASSERT_FALSE_MESSAGE(RyanJsonReplaceByKey(first, "missing", failCandidate), "ReplaceByKey(不存在 key) 应失败");
  501. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDetachedItem(failCandidate), "失败后 failCandidate 应保持 detached");
  502. RyanJsonDelete(failCandidate);
  503. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(first, sameShape), "失败路径后 CompareOnlyKey 语义不应变化");
  504. // 修复结构:删除第二个 a,再补 b,使其与文档2 结构和值都对齐。
  505. RyanJson_t removedDup = RyanJsonDetachByIndex(first, 1);
  506. TEST_ASSERT_NOT_NULL_MESSAGE(removedDup, "分离第二个重复 key 节点失败");
  507. RyanJsonDelete(removedDup);
  508. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToObject(first, "b", 2), "补齐 key=b 失败");
  509. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(first, second), "结构修复后 CompareOnlyKey 应返回 True");
  510. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(first, second), "结构和值修复后 Compare 应返回 True");
  511. char *printed = RyanJsonPrint(first, 128, RyanJsonFalse, NULL);
  512. TEST_ASSERT_NOT_NULL(printed);
  513. RyanJson_t roundtrip = RyanJsonParse(printed);
  514. TEST_ASSERT_NOT_NULL(roundtrip);
  515. TEST_ASSERT_TRUE(RyanJsonCompare(first, roundtrip));
  516. RyanJsonDelete(roundtrip);
  517. RyanJsonFree(printed);
  518. RyanJsonDelete(keyMismatch);
  519. RyanJsonDelete(sameShape);
  520. RyanJsonDelete(second);
  521. RyanJsonDelete(first);
  522. }
  523. void testCompareDuplicateKeyAdvancedRunner(void)
  524. {
  525. UnitySetTestFile(__FILE__);
  526. RUN_TEST(testCompareDuplicateKeyInterleavedWithUnique);
  527. RUN_TEST(testCompareDuplicateKeyMutationCountMismatchAndRecover);
  528. RUN_TEST(testCompareDuplicateKeyChangeKeyCreatesMismatch);
  529. RUN_TEST(testCompareDuplicateKeyNestedMutationIsolation);
  530. RUN_TEST(testCompareDuplicateKeyCreatedByApi);
  531. RUN_TEST(testCompareDuplicateKeyReplaceByKeyFirstOccurrence);
  532. RUN_TEST(testCompareDuplicateKeyContainerIsolation);
  533. RUN_TEST(testCompareDuplicateKeyEscapedAndEmptyKey);
  534. RUN_TEST(testCompareDuplicateKeySymmetry);
  535. RUN_TEST(testCompareDuplicateKeyHighCardinality);
  536. RUN_TEST(testCompareDuplicateKeyStreamParseMutationChain);
  537. }