testEdgeStringBoundary.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #include "testBase.h"
  2. static char *allocPatternString(uint32_t len, char ch)
  3. {
  4. char *buf = (char *)malloc(len + 1U);
  5. if (NULL == buf) { return NULL; }
  6. for (uint32_t i = 0; i < len; i++)
  7. {
  8. buf[i] = ch;
  9. }
  10. buf[len] = '\0';
  11. return buf;
  12. }
  13. static char *allocJsonStringWithContent(const char *content)
  14. {
  15. size_t len = strlen(content);
  16. char *json = (char *)malloc(len + 3U);
  17. TEST_ASSERT_NOT_NULL(json);
  18. json[0] = '"';
  19. if (len) { memcpy(json + 1, content, len); }
  20. json[len + 1] = '"';
  21. json[len + 2] = '\0';
  22. return json;
  23. }
  24. static char *allocEscapedUnicodeRepeat(uint32_t count)
  25. {
  26. const char *unit = "\\u0061";
  27. const size_t unitLen = 6U;
  28. size_t total = unitLen * (size_t)count;
  29. char *buf = (char *)malloc(total + 1U);
  30. TEST_ASSERT_NOT_NULL(buf);
  31. for (uint32_t i = 0; i < count; i++)
  32. {
  33. memcpy(buf + ((size_t)i * unitLen), unit, unitLen);
  34. }
  35. buf[total] = '\0';
  36. return buf;
  37. }
  38. static void assertStringNodeMode(RyanJson_t node, const char *expect, uint32_t expectLen, RyanJsonBool_e expectPtrMode)
  39. {
  40. TEST_ASSERT_NOT_NULL(node);
  41. TEST_ASSERT_TRUE(RyanJsonIsString(node));
  42. TEST_ASSERT_EQUAL_UINT32(expectLen, (uint32_t)strlen(RyanJsonGetStringValue(node)));
  43. TEST_ASSERT_EQUAL_MEMORY(expect, RyanJsonGetStringValue(node), expectLen);
  44. TEST_ASSERT_EQUAL_UINT8((uint8_t)expectPtrMode, (uint8_t)RyanJsonGetPayloadStrIsPtrByFlag(node));
  45. }
  46. static void testEdgeStringBoundaryChangeValueShortToLong(void)
  47. {
  48. // 复杂链路:
  49. // Create(String) -> ChangeStringValue(长) -> Compare。
  50. // 目标:验证短 value 切换到长 value 后结构正确。
  51. uint32_t longLen = RyanJsonInlineStringSize + 8U;
  52. char *longVal = allocPatternString(longLen, 'v');
  53. TEST_ASSERT_NOT_NULL(longVal);
  54. RyanJson_t obj = RyanJsonParse("{\"s\":\"a\"}");
  55. TEST_ASSERT_NOT_NULL(obj);
  56. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(RyanJsonGetObjectByKey(obj, "s"), longVal));
  57. TEST_ASSERT_EQUAL_STRING(longVal, RyanJsonGetStringValue(RyanJsonGetObjectByKey(obj, "s")));
  58. RyanJson_t expect = RyanJsonCreateObject();
  59. TEST_ASSERT_NOT_NULL(expect);
  60. TEST_ASSERT_TRUE(RyanJsonAddStringToObject(expect, "s", longVal));
  61. TEST_ASSERT_TRUE(RyanJsonCompare(obj, expect));
  62. RyanJsonDelete(expect);
  63. RyanJsonDelete(obj);
  64. free(longVal);
  65. }
  66. static void testEdgeStringBoundaryChangeValueLongToShort(void)
  67. {
  68. // 复杂链路:
  69. // Create(String) -> ChangeStringValue(短) -> Compare。
  70. // 目标:验证长 value 切换到短 value 后结构正确。
  71. uint32_t longLen = RyanJsonInlineStringSize + 8U;
  72. char *longVal = allocPatternString(longLen, 'v');
  73. TEST_ASSERT_NOT_NULL(longVal);
  74. RyanJson_t obj = RyanJsonCreateObject();
  75. TEST_ASSERT_NOT_NULL(obj);
  76. TEST_ASSERT_TRUE(RyanJsonAddStringToObject(obj, "s", longVal));
  77. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(RyanJsonGetObjectByKey(obj, "s"), "bb"));
  78. TEST_ASSERT_EQUAL_STRING("bb", RyanJsonGetStringValue(RyanJsonGetObjectByKey(obj, "s")));
  79. RyanJson_t expect = RyanJsonParse("{\"s\":\"bb\"}");
  80. TEST_ASSERT_NOT_NULL(expect);
  81. TEST_ASSERT_TRUE(RyanJsonCompare(obj, expect));
  82. RyanJsonDelete(expect);
  83. RyanJsonDelete(obj);
  84. free(longVal);
  85. }
  86. static void testEdgeStringBoundaryChangeValueSameLength(void)
  87. {
  88. // 复杂链路:
  89. // Create(String) -> ChangeStringValue(同长度) -> Compare。
  90. // 目标:验证同长度替换不会破坏结构。
  91. RyanJson_t obj = RyanJsonParse("{\"s\":\"abc\"}");
  92. TEST_ASSERT_NOT_NULL(obj);
  93. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(RyanJsonGetObjectByKey(obj, "s"), "xyz"));
  94. TEST_ASSERT_EQUAL_STRING("xyz", RyanJsonGetStringValue(RyanJsonGetObjectByKey(obj, "s")));
  95. RyanJson_t expect = RyanJsonParse("{\"s\":\"xyz\"}");
  96. TEST_ASSERT_NOT_NULL(expect);
  97. TEST_ASSERT_TRUE(RyanJsonCompare(obj, expect));
  98. RyanJsonDelete(expect);
  99. RyanJsonDelete(obj);
  100. }
  101. static void testEdgeStringRoundtripLongValue(void)
  102. {
  103. // 复杂链路:
  104. // Create(Object 长 value) -> Print -> Parse -> Compare。
  105. // 目标:验证长 String value 往返一致。
  106. uint32_t longLen = RyanJsonInlineStringSize + 8U;
  107. char *longVal = allocPatternString(longLen, 'v');
  108. TEST_ASSERT_NOT_NULL(longVal);
  109. RyanJson_t obj = RyanJsonCreateObject();
  110. TEST_ASSERT_NOT_NULL(obj);
  111. TEST_ASSERT_TRUE(RyanJsonAddStringToObject(obj, "s", longVal));
  112. char *printed = RyanJsonPrint(obj, 32, RyanJsonFalse, NULL);
  113. TEST_ASSERT_NOT_NULL(printed);
  114. RyanJson_t reparsed = RyanJsonParse(printed);
  115. TEST_ASSERT_NOT_NULL(reparsed);
  116. TEST_ASSERT_TRUE(RyanJsonCompare(obj, reparsed));
  117. RyanJsonDelete(reparsed);
  118. RyanJsonFree(printed);
  119. RyanJsonDelete(obj);
  120. free(longVal);
  121. }
  122. static void testEdgeStringBoundaryExactInlineLenValue(void)
  123. {
  124. // 复杂链路:
  125. // Create(Object) -> AddStringToObject(value 长度=InlineSize) -> Print/Parse -> Compare。
  126. // 目标:验证边界长度 value 往返一致。
  127. uint32_t valLen = RyanJsonInlineStringSize;
  128. char *val = allocPatternString(valLen, 'v');
  129. TEST_ASSERT_NOT_NULL(val);
  130. RyanJson_t obj = RyanJsonCreateObject();
  131. TEST_ASSERT_NOT_NULL(obj);
  132. TEST_ASSERT_TRUE(RyanJsonAddStringToObject(obj, "s", val));
  133. char *printed = RyanJsonPrint(obj, 32, RyanJsonFalse, NULL);
  134. TEST_ASSERT_NOT_NULL(printed);
  135. RyanJson_t reparsed = RyanJsonParse(printed);
  136. TEST_ASSERT_NOT_NULL(reparsed);
  137. TEST_ASSERT_TRUE(RyanJsonCompare(obj, reparsed));
  138. RyanJsonDelete(reparsed);
  139. RyanJsonFree(printed);
  140. RyanJsonDelete(obj);
  141. free(val);
  142. }
  143. static void testEdgeStringBoundaryInlinePlusOneValue(void)
  144. {
  145. // 复杂链路:
  146. // Create(Object) -> AddStringToObject(value 长度=InlineSize+1) -> Print/Parse -> Compare。
  147. // 目标:验证边界+1 长度 value 往返一致。
  148. uint32_t valLen = RyanJsonInlineStringSize + 1U;
  149. char *val = allocPatternString(valLen, 'v');
  150. TEST_ASSERT_NOT_NULL(val);
  151. RyanJson_t obj = RyanJsonCreateObject();
  152. TEST_ASSERT_NOT_NULL(obj);
  153. TEST_ASSERT_TRUE(RyanJsonAddStringToObject(obj, "s", val));
  154. char *printed = RyanJsonPrint(obj, 32, RyanJsonFalse, NULL);
  155. TEST_ASSERT_NOT_NULL(printed);
  156. RyanJson_t reparsed = RyanJsonParse(printed);
  157. TEST_ASSERT_NOT_NULL(reparsed);
  158. TEST_ASSERT_TRUE(RyanJsonCompare(obj, reparsed));
  159. RyanJsonDelete(reparsed);
  160. RyanJsonFree(printed);
  161. RyanJsonDelete(obj);
  162. free(val);
  163. }
  164. static void testEdgeStringParseInlineBoundaryPlain(void)
  165. {
  166. // 目标:解析路径下,恰好命中 inline 临界长度应保持 inline。
  167. const uint32_t maxInlineLen = RyanJsonInlineStringSize - 1U;
  168. char *value = allocPatternString(maxInlineLen, 'a');
  169. char *jsonText = allocJsonStringWithContent(value);
  170. RyanJson_t root = RyanJsonParse(jsonText);
  171. TEST_ASSERT_NOT_NULL(root);
  172. assertStringNodeMode(root, value, maxInlineLen, RyanJsonFalse);
  173. char *printed = RyanJsonPrint(root, 0, RyanJsonFalse, NULL);
  174. TEST_ASSERT_NOT_NULL(printed);
  175. RyanJson_t roundtrip = RyanJsonParse(printed);
  176. TEST_ASSERT_NOT_NULL(roundtrip);
  177. assertStringNodeMode(roundtrip, value, maxInlineLen, RyanJsonFalse);
  178. RyanJsonDelete(roundtrip);
  179. RyanJsonFree(printed);
  180. RyanJsonDelete(root);
  181. free(jsonText);
  182. free(value);
  183. }
  184. static void testEdgeStringParsePtrBoundaryPlain(void)
  185. {
  186. // 目标:解析路径下,超过 inline 临界长度应切到 ptr。
  187. const uint32_t overInlineLen = RyanJsonInlineStringSize;
  188. char *value = allocPatternString(overInlineLen, 'b');
  189. char *jsonText = allocJsonStringWithContent(value);
  190. RyanJson_t root = RyanJsonParse(jsonText);
  191. TEST_ASSERT_NOT_NULL(root);
  192. assertStringNodeMode(root, value, overInlineLen, RyanJsonTrue);
  193. char *printed = RyanJsonPrint(root, 0, RyanJsonFalse, NULL);
  194. TEST_ASSERT_NOT_NULL(printed);
  195. RyanJson_t roundtrip = RyanJsonParse(printed);
  196. TEST_ASSERT_NOT_NULL(roundtrip);
  197. assertStringNodeMode(roundtrip, value, overInlineLen, RyanJsonTrue);
  198. RyanJsonDelete(roundtrip);
  199. RyanJsonFree(printed);
  200. RyanJsonDelete(root);
  201. free(jsonText);
  202. free(value);
  203. }
  204. static void testEdgeStringParseInlineBoundaryEscaped(void)
  205. {
  206. // 目标:转义 String 的“解码长度”决定 inline/ptr 模式。
  207. const uint32_t maxInlineLen = RyanJsonInlineStringSize - 1U;
  208. char *escaped = allocEscapedUnicodeRepeat(maxInlineLen);
  209. char *jsonText = allocJsonStringWithContent(escaped);
  210. char *expect = allocPatternString(maxInlineLen, 'a');
  211. RyanJson_t root = RyanJsonParse(jsonText);
  212. TEST_ASSERT_NOT_NULL(root);
  213. assertStringNodeMode(root, expect, maxInlineLen, RyanJsonFalse);
  214. RyanJsonDelete(root);
  215. free(expect);
  216. free(jsonText);
  217. free(escaped);
  218. }
  219. static void testEdgeStringParsePtrBoundaryEscaped(void)
  220. {
  221. // 目标:转义 String 解码长度超过 inline 临界后,应切到 ptr。
  222. const uint32_t overInlineLen = RyanJsonInlineStringSize;
  223. char *escaped = allocEscapedUnicodeRepeat(overInlineLen);
  224. char *jsonText = allocJsonStringWithContent(escaped);
  225. char *expect = allocPatternString(overInlineLen, 'a');
  226. RyanJson_t root = RyanJsonParse(jsonText);
  227. TEST_ASSERT_NOT_NULL(root);
  228. assertStringNodeMode(root, expect, overInlineLen, RyanJsonTrue);
  229. RyanJsonDelete(root);
  230. free(expect);
  231. free(jsonText);
  232. free(escaped);
  233. }
  234. void testEdgeStringBoundaryRunner(void)
  235. {
  236. UnitySetTestFile(__FILE__);
  237. RUN_TEST(testEdgeStringBoundaryChangeValueShortToLong);
  238. RUN_TEST(testEdgeStringBoundaryChangeValueLongToShort);
  239. RUN_TEST(testEdgeStringBoundaryChangeValueSameLength);
  240. RUN_TEST(testEdgeStringRoundtripLongValue);
  241. RUN_TEST(testEdgeStringBoundaryExactInlineLenValue);
  242. RUN_TEST(testEdgeStringBoundaryInlinePlusOneValue);
  243. RUN_TEST(testEdgeStringParseInlineBoundaryPlain);
  244. RUN_TEST(testEdgeStringParsePtrBoundaryPlain);
  245. RUN_TEST(testEdgeStringParseInlineBoundaryEscaped);
  246. RUN_TEST(testEdgeStringParsePtrBoundaryEscaped);
  247. }