testUsageRecipes.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include "testBase.h"
  2. static void testUsageRecipeMinifyParseAddAndRoundtrip(void)
  3. {
  4. // 复杂链路:
  5. // Minify -> Parse -> AddIntToObject -> Print -> Parse -> Compare。
  6. // 目标:验证用户侧常见“压缩输入后再增量构造”的完整文档管线。
  7. char raw[] = "{ /*c*/ \"a\" : 1 }";
  8. uint32_t len = RyanJsonMinify(raw, (int32_t)(sizeof(raw) - 1U));
  9. raw[len] = '\0';
  10. RyanJson_t root = RyanJsonParse(raw);
  11. TEST_ASSERT_NOT_NULL(root);
  12. TEST_ASSERT_TRUE(RyanJsonAddIntToObject(root, "b", 2));
  13. char *printed = RyanJsonPrint(root, 32, RyanJsonFalse, NULL);
  14. TEST_ASSERT_NOT_NULL(printed);
  15. RyanJson_t reparsed = RyanJsonParse(printed);
  16. TEST_ASSERT_NOT_NULL(reparsed);
  17. RyanJson_t expect = RyanJsonParse("{\"a\":1,\"b\":2}");
  18. TEST_ASSERT_NOT_NULL(expect);
  19. TEST_ASSERT_TRUE(RyanJsonCompare(reparsed, expect));
  20. RyanJsonDelete(expect);
  21. RyanJsonDelete(reparsed);
  22. RyanJsonFree(printed);
  23. RyanJsonDelete(root);
  24. }
  25. static void testUsageRecipeMinifyParseReplaceAndRoundtrip(void)
  26. {
  27. // 复杂链路:
  28. // Minify -> Parse -> ReplaceByKey/ReplaceByIndex -> Print -> Parse -> Compare。
  29. // 目标:验证用户侧“压缩输入后再局部替换”的文档管线。
  30. char raw[] = "/*h*/{\"cfg\":{\"x\":1},\"arr\":[1,2]}/*t*/";
  31. uint32_t minLen = RyanJsonMinify(raw, (int32_t)strlen(raw));
  32. TEST_ASSERT_EQUAL_STRING("{\"cfg\":{\"x\":1},\"arr\":[1,2]}", raw);
  33. TEST_ASSERT_EQUAL_UINT32((uint32_t)strlen(raw), minLen);
  34. RyanJson_t root = RyanJsonParse(raw);
  35. TEST_ASSERT_NOT_NULL_MESSAGE(root, "Minify 后文档解析失败");
  36. RyanJson_t cfgNew = RyanJsonParse("{\"x\":2,\"y\":3}");
  37. TEST_ASSERT_NOT_NULL(cfgNew);
  38. TEST_ASSERT_TRUE_MESSAGE(RyanJsonReplaceByKey(root, "cfg", cfgNew), "ReplaceByKey(cfg) 失败");
  39. TEST_ASSERT_TRUE_MESSAGE(RyanJsonReplaceByIndex(RyanJsonGetObjectToKey(root, "arr"), 1, RyanJsonCreateInt(NULL, 5)),
  40. "ReplaceByIndex(arr[1]) 失败");
  41. RyanJson_t expect = RyanJsonParse("{\"cfg\":{\"x\":2,\"y\":3},\"arr\":[1,5]}");
  42. TEST_ASSERT_NOT_NULL(expect);
  43. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root, expect), "Minify + Replace 后结果与期望文档不一致");
  44. char *printed = RyanJsonPrint(root, 128, RyanJsonFalse, NULL);
  45. TEST_ASSERT_NOT_NULL(printed);
  46. RyanJson_t roundtrip = RyanJsonParse(printed);
  47. TEST_ASSERT_NOT_NULL(roundtrip);
  48. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root, roundtrip), "Minify + Replace 链路往返 Compare 应相等");
  49. RyanJsonDelete(roundtrip);
  50. RyanJsonFree(printed);
  51. RyanJsonDelete(expect);
  52. RyanJsonDelete(root);
  53. }
  54. static void testUsageRecipeMinifyStreamParseOptionsMergeDocs(void)
  55. {
  56. // 复杂链路:
  57. // Minify(多文档流) -> ParseOptions(doc1) -> ParseOptions(doc2) -> AddItemToObject(root, parsedRoot)
  58. // -> Print -> Parse -> Compare。
  59. // 目标:验证注释流经 Minify 后,可顺序解析多个文档,
  60. // 且“第二个解析出来的根 Array 文档”可直接作为容器挂到第一个根 Object 上。
  61. char raw[] = "/*lead*/ {\"meta\":{\"id\":1}} /*mid*/ [1,{\"k\":2},[]] /*tail*/";
  62. uint32_t minLen = RyanJsonMinify(raw, (int32_t)strlen(raw));
  63. TEST_ASSERT_EQUAL_STRING("{\"meta\":{\"id\":1}}[1,{\"k\":2},[]]", raw);
  64. TEST_ASSERT_EQUAL_UINT32((uint32_t)strlen(raw), minLen);
  65. const char *end = NULL;
  66. RyanJson_t doc1 = RyanJsonParseOptions(raw, minLen, RyanJsonFalse, &end);
  67. TEST_ASSERT_NOT_NULL_MESSAGE(doc1, "流文档 #1 解析失败");
  68. TEST_ASSERT_NOT_NULL(end);
  69. uint32_t remain = (uint32_t)(minLen - (uint32_t)(end - raw));
  70. RyanJson_t doc2 = RyanJsonParseOptions(end, remain, RyanJsonTrue, NULL);
  71. TEST_ASSERT_NOT_NULL_MESSAGE(doc2, "流文档 #2 解析失败");
  72. TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(doc1, "payload", doc2), "将解析出的根 Array 挂到 doc1.payload 失败");
  73. RyanJson_t expect = RyanJsonParse("{\"meta\":{\"id\":1},\"payload\":[1,{\"k\":2},[]]}");
  74. TEST_ASSERT_NOT_NULL(expect);
  75. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(doc1, expect), "多文档合并后的结果与期望文档不一致");
  76. char *printed = RyanJsonPrint(doc1, 128, RyanJsonFalse, NULL);
  77. TEST_ASSERT_NOT_NULL(printed);
  78. RyanJson_t roundtrip = RyanJsonParse(printed);
  79. TEST_ASSERT_NOT_NULL(roundtrip);
  80. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(doc1, roundtrip), "多文档合并链路往返 Compare 应相等");
  81. RyanJsonDelete(roundtrip);
  82. RyanJsonFree(printed);
  83. RyanJsonDelete(expect);
  84. RyanJsonDelete(doc1);
  85. }
  86. static void testUsageRecipeCreateCollectorFromMinifiedStreamDocs(void)
  87. {
  88. // 复杂链路:
  89. // Minify(多文档流) -> ParseOptions(doc1/doc2/doc3) -> Create(ArrayRoot)
  90. // -> Insert(顺序收集 Object/Array/标量 根文档) -> Print -> Parse -> Compare。
  91. // 目标:验证用户可先 Create 收集容器,再顺序吸收 ParseOptions 解析出的多份顶层文档;
  92. // 该链路与“parsed root 直接合并 parsed root”不同,专门覆盖 create-root + parsed-docs 的 recipe。
  93. char raw[] = "/*lead*/ {\"meta\":{\"id\":1}} /*mid*/ [3,{\"k\":4}] /*tail*/ true";
  94. uint32_t minLen = RyanJsonMinify(raw, (int32_t)strlen(raw));
  95. TEST_ASSERT_EQUAL_STRING("{\"meta\":{\"id\":1}}[3,{\"k\":4}]true", raw);
  96. TEST_ASSERT_EQUAL_UINT32((uint32_t)strlen(raw), minLen);
  97. RyanJson_t collector = RyanJsonCreateArray();
  98. TEST_ASSERT_NOT_NULL_MESSAGE(collector, "创建收集根 Array 失败");
  99. const char *end1 = NULL;
  100. RyanJson_t doc1 = RyanJsonParseOptions(raw, minLen, RyanJsonFalse, &end1);
  101. TEST_ASSERT_NOT_NULL_MESSAGE(doc1, "流文档 #1(object) 解析失败");
  102. TEST_ASSERT_NOT_NULL(end1);
  103. TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(collector, RyanJsonGetArraySize(collector), doc1), "将流文档 #1 插入收集 Array 失败");
  104. uint32_t remain1 = (uint32_t)(minLen - (uint32_t)(end1 - raw));
  105. const char *end2 = NULL;
  106. RyanJson_t doc2 = RyanJsonParseOptions(end1, remain1, RyanJsonFalse, &end2);
  107. TEST_ASSERT_NOT_NULL_MESSAGE(doc2, "流文档 #2(array) 解析失败");
  108. TEST_ASSERT_NOT_NULL(end2);
  109. TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(collector, RyanJsonGetArraySize(collector), doc2), "将流文档 #2 插入收集 Array 失败");
  110. uint32_t remain2 = (uint32_t)(minLen - (uint32_t)(end2 - raw));
  111. const char *end3 = NULL;
  112. RyanJson_t doc3 = RyanJsonParseOptions(end2, remain2, RyanJsonTrue, &end3);
  113. TEST_ASSERT_NOT_NULL_MESSAGE(doc3, "流文档 #3(bool) 解析失败");
  114. TEST_ASSERT_NOT_NULL(end3);
  115. TEST_ASSERT_EQUAL_CHAR('\0', *end3);
  116. TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(collector, RyanJsonGetArraySize(collector), doc3), "将流文档 #3 插入收集 Array 失败");
  117. RyanJson_t expect = RyanJsonParse("[{\"meta\":{\"id\":1}},[3,{\"k\":4}],true]");
  118. TEST_ASSERT_NOT_NULL(expect);
  119. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(collector, expect), "create-root 收集多文档流后的结构不符合预期");
  120. char *printed = RyanJsonPrint(collector, 160, RyanJsonFalse, NULL);
  121. TEST_ASSERT_NOT_NULL(printed);
  122. RyanJson_t roundtrip = RyanJsonParse(printed);
  123. TEST_ASSERT_NOT_NULL(roundtrip);
  124. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(collector, roundtrip), "create-root 收集多文档流后的往返 Compare 应相等");
  125. RyanJsonDelete(roundtrip);
  126. RyanJsonFree(printed);
  127. RyanJsonDelete(expect);
  128. RyanJsonDelete(collector);
  129. }
  130. void testUsageRecipesRunner(void)
  131. {
  132. UnitySetTestFile(__FILE__);
  133. RUN_TEST(testUsageRecipeMinifyParseAddAndRoundtrip);
  134. RUN_TEST(testUsageRecipeMinifyParseReplaceAndRoundtrip);
  135. RUN_TEST(testUsageRecipeMinifyStreamParseOptionsMergeDocs);
  136. RUN_TEST(testUsageRecipeCreateCollectorFromMinifiedStreamDocs);
  137. }