testKeyNumericLike.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "testBase.h"
  2. static void testNumericLikeKeyLookupKeepsLiteralSpellings(void)
  3. {
  4. // 覆盖“看起来像 Number”的 key 仍按字面文本存取,不做归一化。
  5. struct
  6. {
  7. const char *key;
  8. int32_t value;
  9. } cases[] = {{"0", 1}, {"00", 2}, {"01", 3}, {"1e2", 4}, {"1E2", 5}, {"00123", 6}, {"9007199254740993", 7},
  10. {"Infinity", 8}, {"NaN", 9}, {"0x1", 10}, {"2-3", 11}};
  11. const char *jsonText = "{\"0\":1,\"00\":2,\"01\":3,\"1e2\":4,\"1E2\":5,\"00123\":6,\"9007199254740993\":7,\"Infinity\":8,\"NaN\":9,"
  12. "\"0x1\":10,\"2-3\":11}";
  13. RyanJson_t root = RyanJsonParse(jsonText);
  14. TEST_ASSERT_NOT_NULL_MESSAGE(root, "numeric-like key 样本解析失败");
  15. TEST_ASSERT_EQUAL_UINT32((uint32_t)(sizeof(cases) / sizeof(cases[0])), RyanJsonGetSize(root));
  16. for (uint32_t i = 0; i < (uint32_t)(sizeof(cases) / sizeof(cases[0])); i++)
  17. {
  18. RyanJson_t byKey = RyanJsonGetObjectByKey(root, cases[i].key);
  19. RyanJson_t byIndex = RyanJsonGetObjectByIndex(root, i);
  20. TEST_ASSERT_NOT_NULL_MESSAGE(byKey, "字面 key 查询失败");
  21. TEST_ASSERT_NOT_NULL_MESSAGE(byIndex, "按索引读取 numeric-like key 失败");
  22. TEST_ASSERT_EQUAL_INT(cases[i].value, RyanJsonGetIntValue(byKey));
  23. TEST_ASSERT_EQUAL_STRING(cases[i].key, RyanJsonGetKey(byIndex));
  24. }
  25. TEST_ASSERT_FALSE(RyanJsonHasObjectByKey(root, "123"));
  26. TEST_ASSERT_FALSE(RyanJsonHasObjectByKey(root, "100"));
  27. TEST_ASSERT_FALSE(RyanJsonHasObjectByKey(root, "-Infinity"));
  28. RyanJsonDelete(root);
  29. }
  30. static void testNumericLikeKeyNestedPathUsesExactSegments(void)
  31. {
  32. // 覆盖多段 numeric-like key 路径:每一段都必须按原始拼写命中。
  33. const char *jsonText =
  34. "{\"00123\":{\"123\":{\"1e2\":3},\"9007199254740993\":{\"1E2\":4}},\"Infinity\":{\"NaN\":5,\"-Infinity\":6}}";
  35. RyanJson_t root = RyanJsonParse(jsonText);
  36. TEST_ASSERT_NOT_NULL_MESSAGE(root, "nested numeric-like key 样本解析失败");
  37. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetIntValue(RyanJsonGetObjectByKeys(root, "00123", "123", "1e2", NULL)));
  38. TEST_ASSERT_EQUAL_INT(4, RyanJsonGetIntValue(RyanJsonGetObjectByKeys(root, "00123", "9007199254740993", "1E2", NULL)));
  39. TEST_ASSERT_EQUAL_INT(5, RyanJsonGetIntValue(RyanJsonGetObjectByKeys(root, "Infinity", "NaN", NULL)));
  40. TEST_ASSERT_EQUAL_INT(6, RyanJsonGetIntValue(RyanJsonGetObjectByKeys(root, "Infinity", "-Infinity", NULL)));
  41. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectByKeys(root, "00123", "123", "1E2", NULL), "大小写不同的指数 key 不应混淆");
  42. TEST_ASSERT_NULL_MESSAGE(RyanJsonGetObjectByKeys(root, "00123", "00123", "1e2", NULL), "带前导零的 key 不应被归一化到无前导零版本");
  43. RyanJsonDelete(root);
  44. }
  45. static void testNumericLikeKeyHasApisTreatSimilarSpellingsAsDifferentKeys(void)
  46. {
  47. // 覆盖 HasObjectByKey/HasObjectToKey 对相似 numeric-like key 的区分语义。
  48. RyanJson_t root = RyanJsonParse("{\"00123\":{\"000\":1},\"123\":{\"000\":2},\"1e2\":{\"1E2\":3},\"1E2\":{\"1e2\":4}}");
  49. TEST_ASSERT_NOT_NULL_MESSAGE(root, "Has API numeric-like key 样本解析失败");
  50. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(root, "00123"));
  51. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(root, "123"));
  52. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(root, "1e2"));
  53. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(root, "1E2"));
  54. TEST_ASSERT_FALSE(RyanJsonHasObjectByKey(root, "000123"));
  55. TEST_ASSERT_FALSE(RyanJsonHasObjectByKey(root, "100"));
  56. TEST_ASSERT_TRUE(RyanJsonHasObjectToKey(root, "00123", "000"));
  57. TEST_ASSERT_TRUE(RyanJsonHasObjectToKey(root, "123", "000"));
  58. TEST_ASSERT_TRUE(RyanJsonHasObjectToKey(root, "1e2", "1E2"));
  59. TEST_ASSERT_TRUE(RyanJsonHasObjectToKey(root, "1E2", "1e2"));
  60. TEST_ASSERT_FALSE(RyanJsonHasObjectToKey(root, "00123", "001"));
  61. TEST_ASSERT_FALSE(RyanJsonHasObjectToKey(root, "1e2", "1e2"));
  62. RyanJsonDelete(root);
  63. }
  64. static void testNumericLikeKeyChangeKeyRetainsTextualIdentityAfterRoundtrip(void)
  65. {
  66. // 复杂链路:ChangeKey(leading-zero -> big-integer-like) -> Print -> Parse。
  67. // 目标:验证 key 改名后仍按文本保真,不会被数值化。
  68. RyanJson_t root = RyanJsonParse("{\"00123\":7,\"keep\":17}");
  69. TEST_ASSERT_NOT_NULL_MESSAGE(root, "ChangeKey numeric-like 样本解析失败");
  70. RyanJson_t node = RyanJsonGetObjectByKey(root, "00123");
  71. TEST_ASSERT_NOT_NULL(node);
  72. TEST_ASSERT_TRUE(RyanJsonChangeKey(node, "9007199254740993"));
  73. TEST_ASSERT_FALSE(RyanJsonHasObjectByKey(root, "00123"));
  74. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(root, "9007199254740993"));
  75. TEST_ASSERT_EQUAL_INT(7, RyanJsonGetIntValue(RyanJsonGetObjectByKey(root, "9007199254740993")));
  76. TEST_ASSERT_EQUAL_INT(17, RyanJsonGetIntValue(RyanJsonGetObjectByKey(root, "keep")));
  77. char *printed = RyanJsonPrint(root, 160, RyanJsonFalse, NULL);
  78. TEST_ASSERT_NOT_NULL(printed);
  79. RyanJson_t roundtrip = RyanJsonParse(printed);
  80. TEST_ASSERT_NOT_NULL(roundtrip);
  81. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(roundtrip, "9007199254740993"));
  82. TEST_ASSERT_FALSE(RyanJsonHasObjectByKey(roundtrip, "00123"));
  83. TEST_ASSERT_TRUE(RyanJsonCompare(root, roundtrip));
  84. RyanJsonDelete(roundtrip);
  85. RyanJsonFree(printed);
  86. RyanJsonDelete(root);
  87. }
  88. static void testNumericLikeKeyDeleteDetachReplaceMatchExactLiteralOnly(void)
  89. {
  90. // 覆盖 Delete/Detach/Replace 对 numeric-like key 的精确匹配语义。
  91. RyanJson_t root = RyanJsonParse("{\"1e2\":1,\"1E2\":2,\"0x1\":3,\"Infinity\":4,\"NaN\":5}");
  92. TEST_ASSERT_NOT_NULL_MESSAGE(root, "numeric-like ops 样本解析失败");
  93. TEST_ASSERT_TRUE(RyanJsonDeleteByKey(root, "1e2"));
  94. TEST_ASSERT_FALSE(RyanJsonHasObjectByKey(root, "1e2"));
  95. TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByKey(root, "1E2")));
  96. RyanJson_t detached = RyanJsonDetachByKey(root, "0x1");
  97. TEST_ASSERT_NOT_NULL(detached);
  98. TEST_ASSERT_EQUAL_INT(3, RyanJsonGetIntValue(detached));
  99. TEST_ASSERT_FALSE(RyanJsonHasObjectByKey(root, "0x1"));
  100. TEST_ASSERT_EQUAL_INT(4, RyanJsonGetIntValue(RyanJsonGetObjectByKey(root, "Infinity")));
  101. TEST_ASSERT_TRUE(RyanJsonReplaceByKey(root, "Infinity", RyanJsonCreateInt("Infinity", 40)));
  102. TEST_ASSERT_EQUAL_INT(40, RyanJsonGetIntValue(RyanJsonGetObjectByKey(root, "Infinity")));
  103. TEST_ASSERT_EQUAL_INT(5, RyanJsonGetIntValue(RyanJsonGetObjectByKey(root, "NaN")));
  104. TEST_ASSERT_EQUAL_UINT32(3U, RyanJsonGetSize(root));
  105. RyanJsonDelete(detached);
  106. RyanJsonDelete(root);
  107. }
  108. void testKeyNumericLikeRunner(void)
  109. {
  110. UnitySetTestFile(__FILE__);
  111. RUN_TEST(testNumericLikeKeyLookupKeepsLiteralSpellings);
  112. RUN_TEST(testNumericLikeKeyNestedPathUsesExactSegments);
  113. RUN_TEST(testNumericLikeKeyHasApisTreatSimilarSpellingsAsDifferentKeys);
  114. RUN_TEST(testNumericLikeKeyChangeKeyRetainsTextualIdentityAfterRoundtrip);
  115. RUN_TEST(testNumericLikeKeyDeleteDetachReplaceMatchExactLiteralOnly);
  116. }