testCompareDuplicateKeyBasic.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. #include "testBase.h"
  2. static void testCompareDuplicateKeyPolicyBasic(void)
  3. {
  4. // 该用例在 strict/non-strict 两种编译模式都执行:
  5. // - strict 模式:重复 key 应在解析阶段被拒绝;
  6. // - non-strict 模式:重复 key 允许存在,Compare/CompareOnlyKey 需按“同 key 出现序号”一一对齐。
  7. RyanJson_t dupLeft = RyanJsonParse("{\"a\":1,\"a\":1}");
  8. RyanJson_t diffKeyRight = RyanJsonParse("{\"a\":1,\"b\":1}");
  9. TEST_ASSERT_NOT_NULL(diffKeyRight);
  10. #if true == RyanJsonStrictObjectKeyCheck
  11. TEST_ASSERT_NULL_MESSAGE(dupLeft, "strict 模式下重复 key 应解析失败");
  12. // 控制组:普通 Object 乱序比较在 strict 模式下仍应正常。
  13. {
  14. RyanJson_t ordered = RyanJsonParse("{\"a\":1,\"b\":1}");
  15. RyanJson_t unordered = RyanJsonParse("{\"b\":1,\"a\":1}");
  16. TEST_ASSERT_NOT_NULL(ordered);
  17. TEST_ASSERT_NOT_NULL(unordered);
  18. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(ordered, unordered), "strict 模式下普通 Object 乱序 Compare 应返回 True");
  19. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(ordered, unordered),
  20. "strict 模式下普通 Object 乱序 CompareOnlyKey 应返回 True");
  21. RyanJsonDelete(ordered);
  22. RyanJsonDelete(unordered);
  23. }
  24. #else
  25. // non-strict 模式允许重复 key,本分支验证 Compare/CompareOnlyKey 不会把右侧同一节点重复匹配。
  26. RyanJson_t sameLeft = RyanJsonParse("{\"a\":1,\"a\":2}");
  27. RyanJson_t sameRight = RyanJsonParse("{\"a\":1,\"a\":2}");
  28. // 第二次出现位置的类型不一致(String vs Number)时,CompareOnlyKey 也必须失败。
  29. RyanJson_t typeLeft = RyanJsonParse("{\"a\":1,\"a\":\"2\"}");
  30. RyanJson_t typeRight = RyanJsonParse("{\"a\":1,\"a\":2}");
  31. TEST_ASSERT_NOT_NULL(dupLeft);
  32. TEST_ASSERT_NOT_NULL(sameLeft);
  33. TEST_ASSERT_NOT_NULL(sameRight);
  34. TEST_ASSERT_NOT_NULL(typeLeft);
  35. TEST_ASSERT_NOT_NULL(typeRight);
  36. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(dupLeft, diffKeyRight), "重复 key 与不同 key 混合时 Compare 应返回 False");
  37. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(dupLeft, diffKeyRight), "重复 key 与不同 key 混合时 CompareOnlyKey 应返回 False");
  38. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(sameLeft, sameRight), "重复 key 的同序号节点完全一致时 Compare 应返回 True");
  39. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(sameLeft, sameRight), "重复 key 的同序号节点完全一致时 CompareOnlyKey 应返回 True");
  40. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(typeLeft, typeRight), "重复 key 的同序号节点类型不同,Compare 应返回 False");
  41. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(typeLeft, typeRight),
  42. "重复 key 的同序号节点类型不同,CompareOnlyKey 应返回 False");
  43. RyanJsonDelete(sameLeft);
  44. RyanJsonDelete(sameRight);
  45. RyanJsonDelete(typeLeft);
  46. RyanJsonDelete(typeRight);
  47. #endif
  48. RyanJsonDelete(dupLeft);
  49. RyanJsonDelete(diffKeyRight);
  50. }
  51. static void testCompareDuplicateKeyCountAndOrder(void)
  52. {
  53. RyanJson_t left = RyanJsonParse("{\"a\":1,\"a\":2,\"a\":3}");
  54. RyanJson_t rightCountMismatch = RyanJsonParse("{\"a\":1,\"a\":2,\"b\":3}");
  55. RyanJson_t rightOrderSwapped = RyanJsonParse("{\"a\":3,\"a\":2,\"a\":1}");
  56. RyanJson_t rightSame = RyanJsonParse("{\"a\":1,\"a\":2,\"a\":3}");
  57. RyanJson_t rightTypeChanged = RyanJsonParse("{\"a\":1,\"a\":\"2\",\"a\":3}");
  58. #if true == RyanJsonStrictObjectKeyCheck
  59. TEST_ASSERT_NULL_MESSAGE(left, "strict 模式下重复 key 应解析失败");
  60. TEST_ASSERT_NULL_MESSAGE(rightCountMismatch, "strict 模式下重复 key 应解析失败");
  61. TEST_ASSERT_NULL_MESSAGE(rightOrderSwapped, "strict 模式下重复 key 应解析失败");
  62. TEST_ASSERT_NULL_MESSAGE(rightSame, "strict 模式下重复 key 应解析失败");
  63. TEST_ASSERT_NULL_MESSAGE(rightTypeChanged, "strict 模式下重复 key 应解析失败");
  64. // 控制组:无重复 key 时,key 不一致应判 False。
  65. {
  66. RyanJson_t normalLeft = RyanJsonParse("{\"a\":1,\"b\":2,\"c\":3}");
  67. RyanJson_t normalRight = RyanJsonParse("{\"a\":1,\"b\":2,\"x\":3}");
  68. TEST_ASSERT_NOT_NULL(normalLeft);
  69. TEST_ASSERT_NOT_NULL(normalRight);
  70. TEST_ASSERT_FALSE(RyanJsonCompare(normalLeft, normalRight));
  71. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(normalLeft, normalRight));
  72. RyanJsonDelete(normalLeft);
  73. RyanJsonDelete(normalRight);
  74. }
  75. #else
  76. TEST_ASSERT_NOT_NULL(left);
  77. TEST_ASSERT_NOT_NULL(rightCountMismatch);
  78. TEST_ASSERT_NOT_NULL(rightOrderSwapped);
  79. TEST_ASSERT_NOT_NULL(rightSame);
  80. TEST_ASSERT_NOT_NULL(rightTypeChanged);
  81. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightCountMismatch), "重复 key 个数不一致时 Compare 应返回 False");
  82. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightCountMismatch), "重复 key 个数不一致时 CompareOnlyKey 应返回 False");
  83. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightOrderSwapped), "重复 key 同序号值不同,Compare 应返回 False");
  84. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightOrderSwapped), "重复 key 同序号类型一致,CompareOnlyKey 应返回 True");
  85. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightSame), "重复 key 完全一致时 Compare 应返回 True");
  86. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightSame), "重复 key 完全一致时 CompareOnlyKey 应返回 True");
  87. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightTypeChanged), "重复 key 同序号类型变化,Compare 应返回 False");
  88. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightTypeChanged), "重复 key 同序号类型变化,CompareOnlyKey 应返回 False");
  89. #endif
  90. RyanJsonDelete(left);
  91. RyanJsonDelete(rightCountMismatch);
  92. RyanJsonDelete(rightOrderSwapped);
  93. RyanJsonDelete(rightSame);
  94. RyanJsonDelete(rightTypeChanged);
  95. }
  96. static void testCompareDuplicateKeyNestedObject(void)
  97. {
  98. RyanJson_t left = RyanJsonParse("{\"outer\":{\"k\":1,\"k\":2},\"stable\":1}");
  99. RyanJson_t rightSame = RyanJsonParse("{\"stable\":1,\"outer\":{\"k\":1,\"k\":2}}");
  100. RyanJson_t rightKeyMismatch = RyanJsonParse("{\"stable\":1,\"outer\":{\"k\":1,\"x\":2}}");
  101. RyanJson_t rightTypeMismatch = RyanJsonParse("{\"stable\":1,\"outer\":{\"k\":1,\"k\":\"2\"}}");
  102. RyanJson_t rightValueMismatch = RyanJsonParse("{\"stable\":1,\"outer\":{\"k\":1,\"k\":9}}");
  103. #if true == RyanJsonStrictObjectKeyCheck
  104. TEST_ASSERT_NULL_MESSAGE(left, "strict 模式下嵌套重复 key 应解析失败");
  105. TEST_ASSERT_NULL_MESSAGE(rightSame, "strict 模式下嵌套重复 key 应解析失败");
  106. TEST_ASSERT_NULL_MESSAGE(rightTypeMismatch, "strict 模式下嵌套重复 key 应解析失败");
  107. TEST_ASSERT_NULL_MESSAGE(rightValueMismatch, "strict 模式下嵌套重复 key 应解析失败");
  108. TEST_ASSERT_NOT_NULL(rightKeyMismatch);
  109. // 控制组:无重复 key 的嵌套 Object 可以正常比较。
  110. {
  111. RyanJson_t normalLeft = RyanJsonParse("{\"outer\":{\"k\":1,\"m\":2},\"stable\":1}");
  112. TEST_ASSERT_NOT_NULL(normalLeft);
  113. TEST_ASSERT_FALSE(RyanJsonCompare(normalLeft, rightKeyMismatch));
  114. TEST_ASSERT_FALSE(RyanJsonCompareOnlyKey(normalLeft, rightKeyMismatch));
  115. RyanJsonDelete(normalLeft);
  116. }
  117. #else
  118. TEST_ASSERT_NOT_NULL(left);
  119. TEST_ASSERT_NOT_NULL(rightSame);
  120. TEST_ASSERT_NOT_NULL(rightKeyMismatch);
  121. TEST_ASSERT_NOT_NULL(rightTypeMismatch);
  122. TEST_ASSERT_NOT_NULL(rightValueMismatch);
  123. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightSame), "嵌套重复 key 完全一致时 Compare 应返回 True");
  124. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightSame), "嵌套重复 key 完全一致时 CompareOnlyKey 应返回 True");
  125. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightKeyMismatch), "嵌套重复 key 与普通 key 混合时 Compare 应返回 False");
  126. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightKeyMismatch),
  127. "嵌套重复 key 与普通 key 混合时 CompareOnlyKey 应返回 False");
  128. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightTypeMismatch), "嵌套重复 key 同序号类型变化,Compare 应返回 False");
  129. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightTypeMismatch),
  130. "嵌套重复 key 同序号类型变化,CompareOnlyKey 应返回 False");
  131. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightValueMismatch), "嵌套重复 key 同序号值变化,Compare 应返回 False");
  132. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightValueMismatch),
  133. "嵌套重复 key 同序号类型一致时 CompareOnlyKey 应返回 True");
  134. #endif
  135. RyanJsonDelete(left);
  136. RyanJsonDelete(rightSame);
  137. RyanJsonDelete(rightKeyMismatch);
  138. RyanJsonDelete(rightTypeMismatch);
  139. RyanJsonDelete(rightValueMismatch);
  140. }
  141. static void testCompareDuplicateKeyArrayObject(void)
  142. {
  143. RyanJson_t left = RyanJsonParse("[{\"a\":1,\"a\":2},{\"b\":1}]");
  144. RyanJson_t rightSame = RyanJsonParse("[{\"a\":1,\"a\":2},{\"b\":1}]");
  145. RyanJson_t rightArraySwap = RyanJsonParse("[{\"b\":1},{\"a\":1,\"a\":2}]");
  146. RyanJson_t rightInnerMismatch = RyanJsonParse("[{\"a\":1,\"b\":2},{\"b\":1}]");
  147. RyanJson_t rightInnerValueDiff = RyanJsonParse("[{\"a\":9,\"a\":8},{\"b\":1}]");
  148. #if true == RyanJsonStrictObjectKeyCheck
  149. TEST_ASSERT_NULL_MESSAGE(left, "strict 模式下 Array 元素中的重复 key 应解析失败");
  150. TEST_ASSERT_NULL_MESSAGE(rightSame, "strict 模式下 Array 元素中的重复 key 应解析失败");
  151. TEST_ASSERT_NULL_MESSAGE(rightArraySwap, "strict 模式下 Array 元素中的重复 key 应解析失败");
  152. TEST_ASSERT_NULL_MESSAGE(rightInnerValueDiff, "strict 模式下 Array 元素中的重复 key 应解析失败");
  153. TEST_ASSERT_NOT_NULL(rightInnerMismatch);
  154. // 控制组:无重复 key 的 Array 中 Object 语义正常。
  155. {
  156. RyanJson_t normalLeft = RyanJsonParse("[{\"a\":1,\"b\":2},{\"b\":1}]");
  157. TEST_ASSERT_NOT_NULL(normalLeft);
  158. TEST_ASSERT_TRUE(RyanJsonCompare(normalLeft, rightInnerMismatch));
  159. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(normalLeft, rightInnerMismatch));
  160. RyanJsonDelete(normalLeft);
  161. }
  162. #else
  163. TEST_ASSERT_NOT_NULL(left);
  164. TEST_ASSERT_NOT_NULL(rightSame);
  165. TEST_ASSERT_NOT_NULL(rightArraySwap);
  166. TEST_ASSERT_NOT_NULL(rightInnerMismatch);
  167. TEST_ASSERT_NOT_NULL(rightInnerValueDiff);
  168. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightSame), "Array 内重复 key Object 完全一致时 Compare 应返回 True");
  169. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightSame), "Array 内重复 key Object 完全一致时 CompareOnlyKey 应返回 True");
  170. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightArraySwap), "Array 顺序改变后 Compare 应返回 False");
  171. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightArraySwap), "Array 顺序改变后 CompareOnlyKey 应返回 False");
  172. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightInnerMismatch), "Array 内重复 key 与普通 key 混合时 Compare 应返回 False");
  173. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightInnerMismatch),
  174. "Array 内重复 key 与普通 key 混合时 CompareOnlyKey 应返回 False");
  175. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightInnerValueDiff), "Array 内重复 key 同序号值变化,Compare 应返回 False");
  176. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightInnerValueDiff),
  177. "Array 内重复 key 同序号类型一致时 CompareOnlyKey 应返回 True");
  178. #endif
  179. RyanJsonDelete(left);
  180. RyanJsonDelete(rightSame);
  181. RyanJsonDelete(rightArraySwap);
  182. RyanJsonDelete(rightInnerMismatch);
  183. RyanJsonDelete(rightInnerValueDiff);
  184. }
  185. static void testCompareDuplicateKeyDeepOccurrenceAlign(void)
  186. {
  187. RyanJson_t left = RyanJsonParse("{\"a\":{\"v\":1},\"a\":{\"v\":2}}");
  188. RyanJson_t rightSame = RyanJsonParse("{\"a\":{\"v\":1},\"a\":{\"v\":2}}");
  189. RyanJson_t rightSwap = RyanJsonParse("{\"a\":{\"v\":2},\"a\":{\"v\":1}}");
  190. RyanJson_t rightTypeChanged = RyanJsonParse("{\"a\":{\"v\":1},\"a\":{\"v\":\"2\"}}");
  191. #if true == RyanJsonStrictObjectKeyCheck
  192. TEST_ASSERT_NULL_MESSAGE(left, "strict 模式下深层重复 key 应解析失败");
  193. TEST_ASSERT_NULL_MESSAGE(rightSame, "strict 模式下深层重复 key 应解析失败");
  194. TEST_ASSERT_NULL_MESSAGE(rightSwap, "strict 模式下深层重复 key 应解析失败");
  195. TEST_ASSERT_NULL_MESSAGE(rightTypeChanged, "strict 模式下深层重复 key 应解析失败");
  196. // 控制组:无重复 key 的深层 Object 比较应正常。
  197. {
  198. RyanJson_t normalLeft = RyanJsonParse("{\"a1\":{\"v\":1},\"a2\":{\"v\":2}}");
  199. RyanJson_t normalRight = RyanJsonParse("{\"a2\":{\"v\":2},\"a1\":{\"v\":1}}");
  200. TEST_ASSERT_NOT_NULL(normalLeft);
  201. TEST_ASSERT_NOT_NULL(normalRight);
  202. TEST_ASSERT_TRUE(RyanJsonCompare(normalLeft, normalRight));
  203. TEST_ASSERT_TRUE(RyanJsonCompareOnlyKey(normalLeft, normalRight));
  204. RyanJsonDelete(normalLeft);
  205. RyanJsonDelete(normalRight);
  206. }
  207. #else
  208. TEST_ASSERT_NOT_NULL(left);
  209. TEST_ASSERT_NOT_NULL(rightSame);
  210. TEST_ASSERT_NOT_NULL(rightSwap);
  211. TEST_ASSERT_NOT_NULL(rightTypeChanged);
  212. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(left, rightSame), "深层重复 key 同序号完全一致时 Compare 应返回 True");
  213. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightSame), "深层重复 key 同序号完全一致时 CompareOnlyKey 应返回 True");
  214. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightSwap), "深层重复 key 同序号值错位时 Compare 应返回 False");
  215. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareOnlyKey(left, rightSwap), "深层重复 key 同序号类型一致时 CompareOnlyKey 应返回 True");
  216. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompare(left, rightTypeChanged), "深层重复 key 同序号类型变化时 Compare 应返回 False");
  217. TEST_ASSERT_FALSE_MESSAGE(RyanJsonCompareOnlyKey(left, rightTypeChanged),
  218. "深层重复 key 同序号类型变化时 CompareOnlyKey 应返回 False");
  219. #endif
  220. RyanJsonDelete(left);
  221. RyanJsonDelete(rightSame);
  222. RyanJsonDelete(rightSwap);
  223. RyanJsonDelete(rightTypeChanged);
  224. }
  225. void testCompareDuplicateKeyRunner(void)
  226. {
  227. UnitySetTestFile(__FILE__);
  228. RUN_TEST(testCompareDuplicateKeyPolicyBasic);
  229. RUN_TEST(testCompareDuplicateKeyCountAndOrder);
  230. RUN_TEST(testCompareDuplicateKeyNestedObject);
  231. RUN_TEST(testCompareDuplicateKeyArrayObject);
  232. RUN_TEST(testCompareDuplicateKeyDeepOccurrenceAlign);
  233. }