testStandardValueRoundtrip.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #include "testBase.h"
  2. static void testStandardTopLevelScalars(void)
  3. {
  4. // 标准 Json 允许顶层是任意 Json 值,而不仅是 Object/Array。
  5. RyanJson_t json = NULL;
  6. RyanJson_t roundtrip = NULL;
  7. char *printed = NULL;
  8. json = RyanJsonParse(" \n\ttrue\r ");
  9. TEST_ASSERT_NOT_NULL_MESSAGE(json, "顶层 true 解析失败");
  10. TEST_ASSERT_TRUE(RyanJsonIsBool(json));
  11. TEST_ASSERT_TRUE(RyanJsonGetBoolValue(json));
  12. printed = RyanJsonPrint(json, 32, RyanJsonFalse, NULL);
  13. TEST_ASSERT_NOT_NULL(printed);
  14. TEST_ASSERT_EQUAL_STRING("true", printed);
  15. roundtrip = RyanJsonParse(printed);
  16. TEST_ASSERT_NOT_NULL(roundtrip);
  17. TEST_ASSERT_TRUE(RyanJsonCompare(json, roundtrip));
  18. RyanJsonDelete(roundtrip);
  19. RyanJsonFree(printed);
  20. RyanJsonDelete(json);
  21. json = RyanJsonParse("false");
  22. TEST_ASSERT_NOT_NULL_MESSAGE(json, "顶层 false 解析失败");
  23. TEST_ASSERT_TRUE(RyanJsonIsBool(json));
  24. TEST_ASSERT_FALSE(RyanJsonGetBoolValue(json));
  25. printed = RyanJsonPrint(json, 32, RyanJsonFalse, NULL);
  26. TEST_ASSERT_NOT_NULL(printed);
  27. TEST_ASSERT_EQUAL_STRING("false", printed);
  28. roundtrip = RyanJsonParse(printed);
  29. TEST_ASSERT_NOT_NULL(roundtrip);
  30. TEST_ASSERT_TRUE(RyanJsonCompare(json, roundtrip));
  31. RyanJsonDelete(roundtrip);
  32. RyanJsonFree(printed);
  33. RyanJsonDelete(json);
  34. json = RyanJsonParse("null");
  35. TEST_ASSERT_NOT_NULL_MESSAGE(json, "顶层 null 解析失败");
  36. TEST_ASSERT_TRUE(RyanJsonIsNull(json));
  37. printed = RyanJsonPrint(json, 32, RyanJsonFalse, NULL);
  38. TEST_ASSERT_NOT_NULL(printed);
  39. TEST_ASSERT_EQUAL_STRING("null", printed);
  40. roundtrip = RyanJsonParse(printed);
  41. TEST_ASSERT_NOT_NULL(roundtrip);
  42. TEST_ASSERT_TRUE(RyanJsonCompare(json, roundtrip));
  43. RyanJsonDelete(roundtrip);
  44. RyanJsonFree(printed);
  45. RyanJsonDelete(json);
  46. json = RyanJsonParse("\"root string\"");
  47. TEST_ASSERT_NOT_NULL_MESSAGE(json, "顶层 String 解析失败");
  48. TEST_ASSERT_TRUE(RyanJsonIsString(json));
  49. TEST_ASSERT_EQUAL_STRING("root string", RyanJsonGetStringValue(json));
  50. printed = RyanJsonPrint(json, 64, RyanJsonFalse, NULL);
  51. TEST_ASSERT_NOT_NULL(printed);
  52. TEST_ASSERT_EQUAL_STRING("\"root string\"", printed);
  53. roundtrip = RyanJsonParse(printed);
  54. TEST_ASSERT_NOT_NULL(roundtrip);
  55. TEST_ASSERT_TRUE(RyanJsonCompare(json, roundtrip));
  56. RyanJsonDelete(roundtrip);
  57. RyanJsonFree(printed);
  58. RyanJsonDelete(json);
  59. json = RyanJsonParse("-12.5");
  60. TEST_ASSERT_NOT_NULL_MESSAGE(json, "顶层 double 解析失败");
  61. TEST_ASSERT_TRUE(RyanJsonIsDouble(json));
  62. TEST_ASSERT_TRUE(RyanJsonCompareDouble(-12.5, RyanJsonGetDoubleValue(json)));
  63. printed = RyanJsonPrint(json, 32, RyanJsonFalse, NULL);
  64. TEST_ASSERT_NOT_NULL(printed);
  65. roundtrip = RyanJsonParse(printed);
  66. TEST_ASSERT_NOT_NULL(roundtrip);
  67. TEST_ASSERT_TRUE(RyanJsonCompare(json, roundtrip));
  68. RyanJsonDelete(roundtrip);
  69. RyanJsonFree(printed);
  70. RyanJsonDelete(json);
  71. }
  72. static void testStandardStringEscapesRoundtrip(void)
  73. {
  74. // 覆盖 RFC 8259 String 基础转义字符的解码与往返。
  75. const char *jsonText = "{\"s\":\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"}";
  76. const char *expect = "\"\\/\b\f\n\r\t";
  77. RyanJson_t json = RyanJsonParse(jsonText);
  78. TEST_ASSERT_NOT_NULL_MESSAGE(json, "String 转义解析失败");
  79. RyanJson_t s = RyanJsonGetObjectToKey(json, "s");
  80. TEST_ASSERT_NOT_NULL(s);
  81. TEST_ASSERT_TRUE(RyanJsonIsString(s));
  82. TEST_ASSERT_EQUAL_STRING_MESSAGE(expect, RyanJsonGetStringValue(s), "String 转义解码结果不符合预期");
  83. char *printed = RyanJsonPrint(json, 128, RyanJsonFalse, NULL);
  84. TEST_ASSERT_NOT_NULL_MESSAGE(printed, "String 转义打印失败");
  85. RyanJson_t roundtrip = RyanJsonParse(printed);
  86. TEST_ASSERT_NOT_NULL_MESSAGE(roundtrip, "String 转义往返解析失败");
  87. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(json, roundtrip), "String 转义往返后 Compare 应相等");
  88. RyanJsonDelete(roundtrip);
  89. RyanJsonFree(printed);
  90. RyanJsonDelete(json);
  91. }
  92. static void testStandardUnicodeRoundtrip(void)
  93. {
  94. // 覆盖 BMP 转义、UTF-16 代理对与 UTF-8 直写的值语义一致性。
  95. const char *escapedText = "{\"latin\":\"\\u0041\\u00DF\\u6771\",\"pair\":\"\\uD834\\uDD1E\",\"emoji\":\"\\uD83D\\uDE03\"}";
  96. const char *utf8Text = "{\"latin\":\"A\xC3\x9F\xE6\x9D\xB1\",\"pair\":\"\xF0\x9D\x84\x9E\",\"emoji\":\"\xF0\x9F\x98\x83\"}";
  97. RyanJson_t escaped = RyanJsonParse(escapedText);
  98. RyanJson_t utf8 = RyanJsonParse(utf8Text);
  99. TEST_ASSERT_NOT_NULL_MESSAGE(escaped, "Unicode 转义文本解析失败");
  100. TEST_ASSERT_NOT_NULL_MESSAGE(utf8, "UTF-8 文本解析失败");
  101. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(escaped, utf8), "Unicode 转义与 UTF-8 文本语义应一致");
  102. TEST_ASSERT_EQUAL_STRING("A\xC3\x9F\xE6\x9D\xB1", RyanJsonGetStringValue(RyanJsonGetObjectToKey(escaped, "latin")));
  103. TEST_ASSERT_EQUAL_STRING("\xF0\x9D\x84\x9E", RyanJsonGetStringValue(RyanJsonGetObjectToKey(escaped, "pair")));
  104. TEST_ASSERT_EQUAL_STRING("\xF0\x9F\x98\x83", RyanJsonGetStringValue(RyanJsonGetObjectToKey(escaped, "emoji")));
  105. char *printed = RyanJsonPrint(escaped, 160, RyanJsonFalse, NULL);
  106. TEST_ASSERT_NOT_NULL_MESSAGE(printed, "Unicode 打印失败");
  107. RyanJson_t roundtrip = RyanJsonParse(printed);
  108. TEST_ASSERT_NOT_NULL_MESSAGE(roundtrip, "Unicode 往返解析失败");
  109. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(escaped, roundtrip), "Unicode 往返后 Compare 应相等");
  110. RyanJsonDelete(roundtrip);
  111. RyanJsonFree(printed);
  112. RyanJsonDelete(utf8);
  113. RyanJsonDelete(escaped);
  114. }
  115. static void testStandardLiteralArrayTypeMatrix(void)
  116. {
  117. // 覆盖 Array 中标准字面量与容器的类型边界,避免落回复杂 key 语义。
  118. const char *jsonText = "[null,true,false,\"true\",\"false\",\"null\",{\"k\":\"v\"},[\"x\"],0]";
  119. RyanJson_t json = RyanJsonParse(jsonText);
  120. TEST_ASSERT_NOT_NULL_MESSAGE(json, "字面量类型矩阵解析失败");
  121. TEST_ASSERT_TRUE(RyanJsonIsArray(json));
  122. TEST_ASSERT_EQUAL_UINT32(9U, RyanJsonGetArraySize(json));
  123. RyanJson_t n0 = RyanJsonGetObjectByIndex(json, 0);
  124. RyanJson_t n1 = RyanJsonGetObjectByIndex(json, 1);
  125. RyanJson_t n2 = RyanJsonGetObjectByIndex(json, 2);
  126. RyanJson_t n3 = RyanJsonGetObjectByIndex(json, 3);
  127. RyanJson_t n4 = RyanJsonGetObjectByIndex(json, 4);
  128. RyanJson_t n5 = RyanJsonGetObjectByIndex(json, 5);
  129. RyanJson_t n6 = RyanJsonGetObjectByIndex(json, 6);
  130. RyanJson_t n7 = RyanJsonGetObjectByIndex(json, 7);
  131. RyanJson_t n8 = RyanJsonGetObjectByIndex(json, 8);
  132. TEST_ASSERT_TRUE(RyanJsonIsNull(n0));
  133. TEST_ASSERT_TRUE(RyanJsonIsBool(n1));
  134. TEST_ASSERT_TRUE(RyanJsonIsBool(n2));
  135. TEST_ASSERT_TRUE(RyanJsonIsString(n3));
  136. TEST_ASSERT_TRUE(RyanJsonIsString(n4));
  137. TEST_ASSERT_TRUE(RyanJsonIsString(n5));
  138. TEST_ASSERT_TRUE(RyanJsonIsObject(n6));
  139. TEST_ASSERT_TRUE(RyanJsonIsArray(n7));
  140. TEST_ASSERT_TRUE(RyanJsonIsInt(n8));
  141. TEST_ASSERT_TRUE(RyanJsonGetBoolValue(n1));
  142. TEST_ASSERT_FALSE(RyanJsonGetBoolValue(n2));
  143. TEST_ASSERT_EQUAL_STRING("true", RyanJsonGetStringValue(n3));
  144. TEST_ASSERT_EQUAL_STRING("false", RyanJsonGetStringValue(n4));
  145. TEST_ASSERT_EQUAL_STRING("null", RyanJsonGetStringValue(n5));
  146. TEST_ASSERT_EQUAL_STRING("v", RyanJsonGetStringValue(RyanJsonGetObjectToKey(n6, "k")));
  147. TEST_ASSERT_EQUAL_STRING("x", RyanJsonGetStringValue(RyanJsonGetObjectByIndex(n7, 0)));
  148. TEST_ASSERT_EQUAL_INT(0, RyanJsonGetIntValue(n8));
  149. char *pretty = RyanJsonPrint(json, 256, RyanJsonTrue, NULL);
  150. TEST_ASSERT_NOT_NULL_MESSAGE(pretty, "字面量类型矩阵格式化打印失败");
  151. RyanJson_t roundtrip = RyanJsonParse(pretty);
  152. TEST_ASSERT_NOT_NULL_MESSAGE(roundtrip, "字面量类型矩阵格式化往返解析失败");
  153. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(json, roundtrip), "字面量类型矩阵往返 Compare 应相等");
  154. RyanJsonDelete(roundtrip);
  155. RyanJsonFree(pretty);
  156. RyanJsonDelete(json);
  157. }
  158. static void testStandardNestedWhitespaceRoundtrip(void)
  159. {
  160. // 经典嵌套结构 + 大量标准空白字符的往返语义。
  161. const char *jsonText =
  162. " { \"Image\" : { \"Width\" : 800 , \"Height\" : 600 , \"Title\" : \"View\" , "
  163. "\"Thumbnail\" : { \"Url\" : \"http://www.example.com/image/481989943\" , \"Height\" : 125 , \"Width\" : \"100\" } , "
  164. "\"Animated\" : false , \"IDs\" : [ 116 , 943 , 234 , 38793 ] } } ";
  165. RyanJson_t json = RyanJsonParse(jsonText);
  166. TEST_ASSERT_NOT_NULL_MESSAGE(json, "嵌套标准 Json 解析失败");
  167. TEST_ASSERT_EQUAL_INT(800, RyanJsonGetIntValue(RyanJsonGetObjectToKey(json, "Image", "Width")));
  168. TEST_ASSERT_EQUAL_INT(600, RyanJsonGetIntValue(RyanJsonGetObjectToKey(json, "Image", "Height")));
  169. TEST_ASSERT_EQUAL_STRING("View", RyanJsonGetStringValue(RyanJsonGetObjectToKey(json, "Image", "Title")));
  170. TEST_ASSERT_FALSE(RyanJsonGetBoolValue(RyanJsonGetObjectToKey(json, "Image", "Animated")));
  171. TEST_ASSERT_EQUAL_STRING("100", RyanJsonGetStringValue(RyanJsonGetObjectToKey(json, "Image", "Thumbnail", "Width")));
  172. TEST_ASSERT_EQUAL_UINT32(4U, RyanJsonGetArraySize(RyanJsonGetObjectToKey(json, "Image", "IDs")));
  173. char *pretty = RyanJsonPrint(json, 512, RyanJsonTrue, NULL);
  174. TEST_ASSERT_NOT_NULL_MESSAGE(pretty, "格式化打印失败");
  175. RyanJson_t roundtrip = RyanJsonParse(pretty);
  176. TEST_ASSERT_NOT_NULL_MESSAGE(roundtrip, "格式化打印后的 Json 重新解析失败");
  177. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(json, roundtrip), "嵌套标准 Json 往返后 Compare 应相等");
  178. RyanJsonDelete(roundtrip);
  179. RyanJsonFree(pretty);
  180. RyanJsonDelete(json);
  181. }
  182. static void testStandardTopLevelEmptyContainersRoundtrip(void)
  183. {
  184. RyanJson_t obj = RyanJsonParse("{}");
  185. RyanJson_t arr = RyanJsonParse("[]");
  186. TEST_ASSERT_NOT_NULL_MESSAGE(obj, "顶层空 Object 解析失败");
  187. TEST_ASSERT_NOT_NULL_MESSAGE(arr, "顶层空 Array 解析失败");
  188. TEST_ASSERT_TRUE(RyanJsonIsObject(obj));
  189. TEST_ASSERT_TRUE(RyanJsonIsArray(arr));
  190. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(obj));
  191. TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetArraySize(arr));
  192. char *objPrinted = RyanJsonPrint(obj, 16, RyanJsonFalse, NULL);
  193. char *arrPrinted = RyanJsonPrint(arr, 16, RyanJsonFalse, NULL);
  194. TEST_ASSERT_NOT_NULL(objPrinted);
  195. TEST_ASSERT_NOT_NULL(arrPrinted);
  196. TEST_ASSERT_EQUAL_STRING("{}", objPrinted);
  197. TEST_ASSERT_EQUAL_STRING("[]", arrPrinted);
  198. RyanJson_t objRoundtrip = RyanJsonParse(objPrinted);
  199. RyanJson_t arrRoundtrip = RyanJsonParse(arrPrinted);
  200. TEST_ASSERT_NOT_NULL(objRoundtrip);
  201. TEST_ASSERT_NOT_NULL(arrRoundtrip);
  202. TEST_ASSERT_TRUE(RyanJsonCompare(obj, objRoundtrip));
  203. TEST_ASSERT_TRUE(RyanJsonCompare(arr, arrRoundtrip));
  204. RyanJsonDelete(objRoundtrip);
  205. RyanJsonDelete(arrRoundtrip);
  206. RyanJsonFree(objPrinted);
  207. RyanJsonFree(arrPrinted);
  208. RyanJsonDelete(obj);
  209. RyanJsonDelete(arr);
  210. }
  211. static void testStandardUnicodeLineSeparatorInString(void)
  212. {
  213. // 覆盖 U+2028 在 String 中的值语义与往返。
  214. const char *utf8Text = "{\"s\":\"\xE2\x80\xA8\"}";
  215. const char *escapedText = "{\"s\":\"\\u2028\"}";
  216. RyanJson_t utf8 = RyanJsonParse(utf8Text);
  217. RyanJson_t escaped = RyanJsonParse(escapedText);
  218. TEST_ASSERT_NOT_NULL_MESSAGE(utf8, "UTF-8 行分隔符解析失败");
  219. TEST_ASSERT_NOT_NULL_MESSAGE(escaped, "转义行分隔符解析失败");
  220. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(utf8, escaped), "UTF-8 与转义形式应语义一致");
  221. char *printed = RyanJsonPrint(utf8, 32, RyanJsonFalse, NULL);
  222. TEST_ASSERT_NOT_NULL_MESSAGE(printed, "行分隔符打印失败");
  223. RyanJson_t roundtrip = RyanJsonParse(printed);
  224. TEST_ASSERT_NOT_NULL_MESSAGE(roundtrip, "行分隔符往返解析失败");
  225. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(utf8, roundtrip), "行分隔符往返 Compare 应相等");
  226. RyanJsonDelete(roundtrip);
  227. RyanJsonFree(printed);
  228. RyanJsonDelete(escaped);
  229. RyanJsonDelete(utf8);
  230. }
  231. static void testStandardRejectNonFiniteNumbers(void)
  232. {
  233. TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("NaN"), "标准 Json 不允许 NaN");
  234. TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("Infinity"), "标准 Json 不允许 Infinity");
  235. TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("-Infinity"), "标准 Json 不允许 -Infinity");
  236. TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"n\":NaN}"), "Object 中的 NaN 应解析失败");
  237. }
  238. void testStandardValueRoundtripRunner(void)
  239. {
  240. UnitySetTestFile(__FILE__);
  241. RUN_TEST(testStandardTopLevelScalars);
  242. RUN_TEST(testStandardStringEscapesRoundtrip);
  243. RUN_TEST(testStandardUnicodeRoundtrip);
  244. RUN_TEST(testStandardLiteralArrayTypeMatrix);
  245. RUN_TEST(testStandardNestedWhitespaceRoundtrip);
  246. RUN_TEST(testStandardTopLevelEmptyContainersRoundtrip);
  247. RUN_TEST(testStandardUnicodeLineSeparatorInString);
  248. RUN_TEST(testStandardRejectNonFiniteNumbers);
  249. }