testEqualityString.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include "testBase.h"
  2. /**
  3. * @brief 简单字符串样例(X-macro)
  4. */
  5. #define SimpleStringList \
  6. X("") \
  7. X("hello") \
  8. X("world") \
  9. X("test") \
  10. X("RyanJson") \
  11. X("123") \
  12. X("0") \
  13. X("-1") \
  14. X("3.14") \
  15. X("1e10") \
  16. X("hello world") \
  17. X("path/to/file") \
  18. X("abcdefghijklmnopqrstuvwxyz") \
  19. X("ABCDEFGHIJKLMNOPQRSTUVWXYZ") \
  20. X("0123456789") \
  21. X("The quick brown fox jumps over the lazy dog") \
  22. X(" ") \
  23. X(" ") \
  24. X(" leading") \
  25. X("trailing ") \
  26. X(" both ") \
  27. X("true") \
  28. X("false") \
  29. X("null") \
  30. X("@#$%^&*()") \
  31. X("!@#$%") \
  32. X("a=b&c=d") \
  33. X("user@example.com") \
  34. X("中文测试") \
  35. X("日本語テスト") \
  36. X("한국어테스트") \
  37. X("混合Mixed混合") \
  38. X("Привет мир") \
  39. X("مرحبا بالعالم") \
  40. X("שלום עולם")
  41. static const char *SimpleStringValueTable[] = {
  42. #define X(a) a,
  43. SimpleStringList
  44. #undef X
  45. };
  46. static const char *SimpleStringJsonTable[] = {
  47. #define X(a) "{\"str\":\"" a "\"}",
  48. SimpleStringList
  49. #undef X
  50. };
  51. /**
  52. * @brief 转义字符串样例(Json 文本与期望值分离)
  53. */
  54. typedef struct
  55. {
  56. const char *json; // Json 字符串(带转义)
  57. const char *expected; // 期望的 C strValue
  58. } EscapeTestCase;
  59. static const EscapeTestCase EscapeTestCases[] = {
  60. // 制表符
  61. {"{\"str\":\"hello\\tworld\"}", "hello\tworld"},
  62. {"{\"str\":\"tab\\there\"}", "tab\there"},
  63. // 换行符
  64. {"{\"str\":\"hello\\nworld\"}", "hello\nworld"},
  65. {"{\"str\":\"line1\\nline2\\nline3\"}", "line1\nline2\nline3"},
  66. // 回车符
  67. {"{\"str\":\"hello\\rworld\"}", "hello\rworld"},
  68. // 引号转义
  69. {"{\"str\":\"quote\\\"inside\"}", "quote\"inside"},
  70. {"{\"str\":\"say \\\"hello\\\"\"}", "say \"hello\""},
  71. // 反斜杠转义
  72. {"{\"str\":\"backslash\\\\here\"}", "backslash\\here"},
  73. {"{\"str\":\"C:\\\\Windows\\\\System32\"}", "C:\\Windows\\System32"},
  74. {"{\"str\":\"path\\\\to\\\\file\"}", "path\\to\\file"},
  75. // 斜杠(可选转义)
  76. {"{\"str\":\"a\\/b\"}", "a/b"},
  77. // 退格符
  78. {"{\"str\":\"back\\bspace\"}", "back\bspace"},
  79. // 换页符
  80. {"{\"str\":\"form\\ffeed\"}", "form\ffeed"},
  81. // 组合转义
  82. {"{\"str\":\"line1\\nline2\\ttab\"}", "line1\nline2\ttab"},
  83. {"{\"str\":\"\\\"quoted\\\" and \\\\escaped\\\\\"}", "\"quoted\" and \\escaped\\"},
  84. // Unicode转义
  85. {"{\"str\":\"\\u0048\\u0065\\u006C\\u006C\\u006F\"}", "Hello"},
  86. {"{\"str\":\"\\u4E2D\\u6587\"}", "中文"},
  87. {"{\"str\":\"euro: \\u20AC\"}", "euro: €"},
  88. {"{\"str\":\"smile: \\u263A\"}", "smile: ☺"},
  89. };
  90. /**
  91. * @brief 字符串类型边界与类型一致性测试
  92. */
  93. void testEqualityStringEdgeCases(void)
  94. {
  95. // NULL 输入
  96. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsString(NULL), "RyanJsonIsString(NULL) 应返回 false");
  97. // 类型混淆测试
  98. RyanJson_t num = RyanJsonCreateInt("num", 123);
  99. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsString(num), "RyanJsonIsString(Int) 应返回 false");
  100. RyanJsonDelete(num);
  101. RyanJson_t dbl = RyanJsonCreateDouble("dbl", 1.23);
  102. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsString(dbl), "RyanJsonIsString(Double) 应返回 false");
  103. RyanJsonDelete(dbl);
  104. RyanJson_t boolNode = RyanJsonCreateBool("bool", RyanJsonTrue);
  105. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsString(boolNode), "RyanJsonIsString(Bool) 应返回 false");
  106. RyanJsonDelete(boolNode);
  107. RyanJson_t obj = RyanJsonCreateObject();
  108. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsString(obj), "RyanJsonIsString(Object) 应返回 false");
  109. RyanJsonDelete(obj);
  110. RyanJson_t arr = RyanJsonCreateArray();
  111. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsString(arr), "RyanJsonIsString(Array) 应返回 false");
  112. RyanJsonDelete(arr);
  113. RyanJson_t nullNode = RyanJsonCreateNull("null");
  114. TEST_ASSERT_FALSE_MESSAGE(RyanJsonIsString(nullNode), "RyanJsonIsString(Null) 应返回 false");
  115. RyanJsonDelete(nullNode);
  116. }
  117. /**
  118. * @brief 简单字符串解析与往返测试
  119. */
  120. static void testEqualityStringSimple(void)
  121. {
  122. for (uint32_t i = 0; i < sizeof(SimpleStringValueTable) / sizeof(SimpleStringValueTable[0]); i++)
  123. {
  124. const char *jsonStrInput = SimpleStringJsonTable[i];
  125. RyanJson_t jsonRoot = RyanJsonParse(jsonStrInput);
  126. TEST_ASSERT_NOT_NULL_MESSAGE(jsonRoot, "简单字符串解析失败");
  127. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsString(RyanJsonGetObjectToKey(jsonRoot, "str")), "字段 'str' 不是字符串类型");
  128. const char *strValue = RyanJsonGetStringValue(RyanJsonGetObjectToKey(jsonRoot, "str"));
  129. TEST_ASSERT_EQUAL_STRING_MESSAGE(SimpleStringValueTable[i], strValue, jsonStrInput);
  130. // 往返测试
  131. char *serializedStr = RyanJsonPrint(jsonRoot, 128, RyanJsonFalse, NULL);
  132. RyanJsonDelete(jsonRoot);
  133. RyanJson_t roundtripJson = RyanJsonParse(serializedStr);
  134. RyanJsonFree(serializedStr);
  135. TEST_ASSERT_NOT_NULL_MESSAGE(roundtripJson, "简单字符串往返测试:重新解析失败");
  136. const char *roundtripValue = RyanJsonGetStringValue(RyanJsonGetObjectToKey(roundtripJson, "str"));
  137. TEST_ASSERT_EQUAL_STRING_MESSAGE(SimpleStringValueTable[i], roundtripValue, "简单字符串往返测试不匹配");
  138. RyanJsonDelete(roundtripJson);
  139. }
  140. }
  141. /**
  142. * @brief 转义字符串解析与往返测试
  143. */
  144. static void testEqualityStringEscape(void)
  145. {
  146. for (uint32_t i = 0; i < sizeof(EscapeTestCases) / sizeof(EscapeTestCases[0]); i++)
  147. {
  148. const EscapeTestCase *tc = &EscapeTestCases[i];
  149. RyanJson_t jsonRoot = RyanJsonParse(tc->json);
  150. TEST_ASSERT_NOT_NULL_MESSAGE(jsonRoot, tc->json);
  151. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsString(RyanJsonGetObjectToKey(jsonRoot, "str")), "转义字段 'str' 类型错误");
  152. const char *strValue = RyanJsonGetStringValue(RyanJsonGetObjectToKey(jsonRoot, "str"));
  153. TEST_ASSERT_EQUAL_STRING_MESSAGE(tc->expected, strValue, tc->json);
  154. // 往返测试
  155. char *serializedStr = RyanJsonPrint(jsonRoot, 128, RyanJsonFalse, NULL);
  156. RyanJsonDelete(jsonRoot);
  157. RyanJson_t roundtripJson = RyanJsonParse(serializedStr);
  158. RyanJsonFree(serializedStr);
  159. TEST_ASSERT_NOT_NULL_MESSAGE(roundtripJson, "转义字符串往返测试:重新解析失败");
  160. const char *roundtripValue = RyanJsonGetStringValue(RyanJsonGetObjectToKey(roundtripJson, "str"));
  161. TEST_ASSERT_EQUAL_STRING_MESSAGE(tc->expected, roundtripValue, "转义字符串往返测试不匹配");
  162. RyanJsonDelete(roundtripJson);
  163. }
  164. }
  165. void testEqualityStringRunner(void)
  166. {
  167. UnitySetTestFile(__FILE__);
  168. RUN_TEST(testEqualityStringEdgeCases);
  169. RUN_TEST(testEqualityStringSimple);
  170. RUN_TEST(testEqualityStringEscape);
  171. }