testChange.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. #include "testBase.h"
  2. static void testChangeEdgeCases(void)
  3. {
  4. // 测试 NULL 输入处理
  5. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeBoolValue(NULL, true), "ChangeBoolValue(NULL) 应返回 False");
  6. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeIntValue(NULL, 1), "ChangeIntValue(NULL) 应返回 False");
  7. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeDoubleValue(NULL, 1.0), "ChangeDoubleValue(NULL) 应返回 False");
  8. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeStringValue(NULL, "test"), "ChangeStringValue(NULL) 应返回 False");
  9. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeKey(NULL, "key"), "ChangeKey(NULL) 应返回 False");
  10. // 测试类型不匹配处理
  11. RyanJson_t intNode = RyanJsonCreateInt(NULL, 1);
  12. RyanJson_t doubleNode = RyanJsonCreateDouble(NULL, 1.0);
  13. RyanJson_t boolNode = RyanJsonCreateBool(NULL, RyanJsonTrue);
  14. RyanJson_t strNode = RyanJsonCreateString(NULL, "s");
  15. RyanJson_t keyedStrNode = RyanJsonCreateString("k", "v");
  16. RyanJson_t keyedBoolNode = RyanJsonCreateBool("flag", RyanJsonTrue);
  17. TEST_ASSERT_NOT_NULL(intNode);
  18. TEST_ASSERT_NOT_NULL(doubleNode);
  19. TEST_ASSERT_NOT_NULL(boolNode);
  20. TEST_ASSERT_NOT_NULL(strNode);
  21. TEST_ASSERT_NOT_NULL(keyedStrNode);
  22. TEST_ASSERT_NOT_NULL(keyedBoolNode);
  23. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeIntValue(doubleNode, 3), "ChangeIntValue(非Int节点) 应返回 False");
  24. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeDoubleValue(intNode, 3.14), "ChangeDoubleValue(非Double节点) 应返回 False");
  25. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeBoolValue(intNode, RyanJsonTrue), "ChangeBoolValue(非Bool节点) 应返回 False");
  26. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeStringValue(intNode, "x"), "ChangeStringValue(非String节点) 应返回 False");
  27. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeKey(strNode, "k2"), "ChangeKey(无Key的String节点) 应返回 False");
  28. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeKey(keyedStrNode, NULL), "ChangeKey(key!=NULL 前置条件) 应返回 False");
  29. // 失败后原值应保持不变
  30. TEST_ASSERT_TRUE_MESSAGE(RyanJsonGetBoolValue(boolNode), "bool 初始值错误");
  31. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeIntValue(boolNode, 9), "ChangeIntValue(Bool节点) 应返回 False");
  32. TEST_ASSERT_TRUE_MESSAGE(RyanJsonGetBoolValue(boolNode), "失败后 bool 值不应变化");
  33. TEST_ASSERT_EQUAL_INT_MESSAGE(1, RyanJsonGetIntValue(intNode), "int 初始值错误");
  34. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeDoubleValue(intNode, 8.8), "ChangeDoubleValue(Int节点) 应返回 False");
  35. TEST_ASSERT_EQUAL_INT_MESSAGE(1, RyanJsonGetIntValue(intNode), "失败后 int 值不应变化");
  36. TEST_ASSERT_EQUAL_STRING_MESSAGE("v", RyanJsonGetStringValue(keyedStrNode), "string 初始值错误");
  37. TEST_ASSERT_FALSE_MESSAGE(RyanJsonChangeBoolValue(keyedStrNode, RyanJsonFalse), "ChangeBoolValue(String节点) 应返回 False");
  38. TEST_ASSERT_EQUAL_STRING_MESSAGE("v", RyanJsonGetStringValue(keyedStrNode), "失败后 string 值不应变化");
  39. TEST_ASSERT_EQUAL_STRING_MESSAGE("k", RyanJsonGetKey(keyedStrNode), "失败后 key 不应变化");
  40. // 有 key 的非字符串节点允许改 key,且值不应改变
  41. TEST_ASSERT_TRUE_MESSAGE(RyanJsonChangeKey(keyedBoolNode, "flag2"), "ChangeKey(Bool+Key 节点) 应成功");
  42. TEST_ASSERT_EQUAL_STRING_MESSAGE("flag2", RyanJsonGetKey(keyedBoolNode), "Bool 节点改 key 失败");
  43. TEST_ASSERT_TRUE_MESSAGE(RyanJsonGetBoolValue(keyedBoolNode), "Bool 节点改 key 后 value 不应变化");
  44. RyanJsonDelete(intNode);
  45. RyanJsonDelete(doubleNode);
  46. RyanJsonDelete(boolNode);
  47. RyanJsonDelete(strNode);
  48. RyanJsonDelete(keyedStrNode);
  49. RyanJsonDelete(keyedBoolNode);
  50. }
  51. static void testChangeValueStress(void)
  52. {
  53. RyanJson_t root = RyanJsonCreateObject();
  54. RyanJsonAddStringToObject(root, "k", "v");
  55. // 高频修改 strValue
  56. // 变为超长
  57. char *longStr = (char *)malloc(1000);
  58. memset(longStr, 'A', 999);
  59. longStr[999] = '\0';
  60. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(RyanJsonGetObjectByKey(root, "k"), longStr));
  61. TEST_ASSERT_EQUAL_STRING(longStr, RyanJsonGetStringValue(RyanJsonGetObjectByKey(root, "k")));
  62. // 变为特殊字符
  63. const char *specials = "\t\n\r\b\f\"\\/";
  64. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(RyanJsonGetObjectByKey(root, "k"), specials));
  65. TEST_ASSERT_EQUAL_STRING(specials, RyanJsonGetStringValue(RyanJsonGetObjectByKey(root, "k")));
  66. // 变为空串
  67. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(RyanJsonGetObjectByKey(root, "k"), ""));
  68. TEST_ASSERT_EQUAL_STRING("", RyanJsonGetStringValue(RyanJsonGetObjectByKey(root, "k")));
  69. // 高频修改 key
  70. // 变为超长
  71. TEST_ASSERT_TRUE(RyanJsonChangeKey(RyanJsonGetObjectByKey(root, "k"), longStr));
  72. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(root, longStr));
  73. // 变为空 key
  74. TEST_ASSERT_TRUE(RyanJsonChangeKey(RyanJsonGetObjectByKey(root, longStr), ""));
  75. TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(root, ""));
  76. free(longStr);
  77. RyanJsonDelete(root);
  78. }
  79. static void testChangeScalarAndStorageMode(void)
  80. {
  81. char jsonstr[] =
  82. "{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null,"
  83. "\"item\":{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null},"
  84. "\"arrayInt\":[16,16,16,16,16],\"arrayDouble\":[16.89,16.89,16.89,16.89,16.89],"
  85. "\"arrayString\":[\"hello\",\"hello\",\"hello\",\"hello\",\"hello\"],"
  86. "\"array\":[16,16.89,\"hello\",true,false,null],"
  87. "\"arrayItem\":[{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null},"
  88. "{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null}],"
  89. "\"string2222\":\"hello\",\"0\":\"1\",\"nameaaaaaaaaaaaaaaaaaaaaaaaaaaaa\":\"Mash\",\"2\":\"3\",\"name\":"
  90. "\"Mashaaaaaaaaaaaaaaaaaaaaaaaa\"}";
  91. RyanJson_t jsonRoot = RyanJsonParse(jsonstr);
  92. TEST_ASSERT_NOT_NULL_MESSAGE(jsonRoot, "解析基础 Json 失败");
  93. /**
  94. * @brief 修改基本类型
  95. */
  96. // 修改整数
  97. RyanJsonChangeIntValue(RyanJsonGetObjectToKey(jsonRoot, "inter"), 20);
  98. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsInt(RyanJsonGetObjectToKey(jsonRoot, "inter")), "字段 'inter' 修改后不是整数");
  99. TEST_ASSERT_EQUAL_INT_MESSAGE(20, RyanJsonGetIntValue(RyanJsonGetObjectToKey(jsonRoot, "inter")), "字段 'inter' 值不匹配");
  100. // 修改浮点数
  101. RyanJsonChangeDoubleValue(RyanJsonGetObjectToKey(jsonRoot, "double"), 20.89);
  102. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDouble(RyanJsonGetObjectToKey(jsonRoot, "double")), "字段 'double' 修改后不是浮点数");
  103. TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareDouble(RyanJsonGetDoubleValue(RyanJsonGetObjectToKey(jsonRoot, "double")), 20.89),
  104. "字段 'double' 值不匹配");
  105. // 修改 Key (inline 模式,不超过长度)
  106. RyanJsonChangeKey(RyanJsonGetObjectByKey(jsonRoot, "0"), "type");
  107. TEST_ASSERT_EQUAL_STRING_MESSAGE("type", RyanJsonGetKey(RyanJsonGetObjectToKey(jsonRoot, "type")), "字段 'type' 的 Key 不匹配");
  108. TEST_ASSERT_EQUAL_STRING_MESSAGE("1", RyanJsonGetStringValue(RyanJsonGetObjectToKey(jsonRoot, "type")), "字段 'type' 的内容不匹配");
  109. // 修改 Key (从 inline 转 ptr 模式)
  110. RyanJsonChangeKey(RyanJsonGetObjectByKey(jsonRoot, "type"), "type000000000000000");
  111. TEST_ASSERT_EQUAL_STRING_MESSAGE("type000000000000000", RyanJsonGetKey(RyanJsonGetObjectToKey(jsonRoot, "type000000000000000")),
  112. "长 Key 模式下的 Key 不匹配");
  113. TEST_ASSERT_EQUAL_STRING_MESSAGE("1", RyanJsonGetStringValue(RyanJsonGetObjectToKey(jsonRoot, "type000000000000000")),
  114. "长 Key 模式下的内容不匹配");
  115. // 修改 Key (从 ptr 转 inline 模式)
  116. RyanJsonChangeKey(RyanJsonGetObjectByKey(jsonRoot, "nameaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), "na");
  117. TEST_ASSERT_EQUAL_STRING_MESSAGE("na", RyanJsonGetKey(RyanJsonGetObjectToKey(jsonRoot, "na")), "回退到 inline 模式的 Key 不匹配");
  118. TEST_ASSERT_EQUAL_STRING_MESSAGE("Mash", RyanJsonGetStringValue(RyanJsonGetObjectToKey(jsonRoot, "na")),
  119. "回退到 inline 模式的内容不匹配");
  120. // 修改 Value (inline 模式,不超过长度)
  121. RyanJsonChangeStringValue(RyanJsonGetObjectByKey(jsonRoot, "2"), "type");
  122. TEST_ASSERT_EQUAL_STRING_MESSAGE("2", RyanJsonGetKey(RyanJsonGetObjectToKey(jsonRoot, "2")), "字段 '2' 的 Key 不匹配");
  123. TEST_ASSERT_EQUAL_STRING_MESSAGE("type", RyanJsonGetStringValue(RyanJsonGetObjectToKey(jsonRoot, "2")), "字段 '2' 的新内容不匹配");
  124. // 修改 Value (从 ptr 转 inline 模式)
  125. RyanJsonChangeStringValue(RyanJsonGetObjectByKey(jsonRoot, "name"), "Ma");
  126. TEST_ASSERT_EQUAL_STRING_MESSAGE("name", RyanJsonGetKey(RyanJsonGetObjectToKey(jsonRoot, "name")), "字段 'name' 的 Key 不匹配");
  127. TEST_ASSERT_EQUAL_STRING_MESSAGE("Ma", RyanJsonGetStringValue(RyanJsonGetObjectToKey(jsonRoot, "name")),
  128. "回退到 inline 模式的 Value 不匹配");
  129. // 修改 Value (从 ptr 转 ptr 模式)
  130. RyanJsonChangeStringValue(RyanJsonGetObjectByKey(jsonRoot, "name"), "Mashaaaaaaaaaaaaaaaaaaaaaaaa");
  131. TEST_ASSERT_EQUAL_STRING_MESSAGE("name", RyanJsonGetKey(RyanJsonGetObjectToKey(jsonRoot, "name")), "字段 'name' 的 Key 不匹配");
  132. TEST_ASSERT_EQUAL_STRING_MESSAGE("Mashaaaaaaaaaaaaaaaaaaaaaaaa", RyanJsonGetStringValue(RyanJsonGetObjectToKey(jsonRoot, "name")),
  133. "长 Value 模式下的内容不匹配");
  134. // 修改字符串
  135. RyanJsonChangeStringValue(RyanJsonGetObjectToKey(jsonRoot, "string"), "world");
  136. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsString(RyanJsonGetObjectToKey(jsonRoot, "string")), "字段 'string' 修改后不是字符串");
  137. TEST_ASSERT_EQUAL_STRING_MESSAGE("world", RyanJsonGetStringValue(RyanJsonGetObjectToKey(jsonRoot, "string")),
  138. "字段 'string' 内容不匹配");
  139. // 修改 boolValue (true -> false)
  140. RyanJsonChangeBoolValue(RyanJsonGetObjectToKey(jsonRoot, "boolTrue"), RyanJsonFalse);
  141. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsBool(RyanJsonGetObjectToKey(jsonRoot, "boolTrue")), "字段 'boolTrue' 类型错误");
  142. TEST_ASSERT_EQUAL_INT_MESSAGE(RyanJsonFalse, RyanJsonGetBoolValue(RyanJsonGetObjectToKey(jsonRoot, "boolTrue")),
  143. "字段 'boolTrue' 值错误");
  144. // 修改 boolValue (false -> true)
  145. RyanJsonChangeBoolValue(RyanJsonGetObjectToKey(jsonRoot, "boolFalse"), RyanJsonTrue);
  146. TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsBool(RyanJsonGetObjectToKey(jsonRoot, "boolFalse")), "字段 'boolFalse' 类型错误");
  147. TEST_ASSERT_EQUAL_INT_MESSAGE(RyanJsonTrue, RyanJsonGetBoolValue(RyanJsonGetObjectToKey(jsonRoot, "boolFalse")),
  148. "字段 'boolFalse' 值错误");
  149. /**
  150. * @brief 修改数组元素 (arrayInt)
  151. */
  152. RyanJsonChangeIntValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(jsonRoot, "arrayInt"), 0), 99);
  153. TEST_ASSERT_EQUAL_INT_MESSAGE(99, RyanJsonGetIntValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(jsonRoot, "arrayInt"), 0)),
  154. "数组元素修改失败");
  155. /**
  156. * @brief 修改数组元素 (arrayDouble)
  157. */
  158. RyanJsonChangeDoubleValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(jsonRoot, "arrayDouble"), 1), 99.99);
  159. TEST_ASSERT_TRUE_MESSAGE(
  160. RyanJsonCompareDouble(RyanJsonGetDoubleValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(jsonRoot, "arrayDouble"), 1)),
  161. 99.99),
  162. "数组浮点元素修改失败");
  163. /**
  164. * @brief 修改数组元素 (arrayString)
  165. */
  166. RyanJsonChangeStringValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(jsonRoot, "arrayString"), 2), "changedString");
  167. TEST_ASSERT_EQUAL_STRING_MESSAGE(
  168. "changedString", RyanJsonGetStringValue(RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(jsonRoot, "arrayString"), 2)),
  169. "数组字符串元素修改失败");
  170. /**
  171. * @brief 修改嵌套对象
  172. */
  173. RyanJson_t nestedObj = RyanJsonGetObjectToKey(jsonRoot, "item");
  174. RyanJsonChangeStringValue(RyanJsonGetObjectToKey(nestedObj, "string"), "nestedWorld");
  175. TEST_ASSERT_EQUAL_STRING_MESSAGE("nestedWorld", RyanJsonGetStringValue(RyanJsonGetObjectToKey(nestedObj, "string")),
  176. "嵌套对象修改失败");
  177. /**
  178. * @brief 修改数组对象中的字段 (arrayItem[0].inter -> 123)
  179. */
  180. RyanJson_t arrayItem0 = RyanJsonGetObjectToIndex(RyanJsonGetObjectToKey(jsonRoot, "arrayItem"), 0);
  181. RyanJsonChangeIntValue(RyanJsonGetObjectToKey(arrayItem0, "inter"), 123);
  182. TEST_ASSERT_EQUAL_INT_MESSAGE(123, RyanJsonGetIntValue(RyanJsonGetObjectToKey(arrayItem0, "inter")), "数组中对象的字段修改失败");
  183. char *str = RyanJsonPrint(jsonRoot, 1024, RyanJsonTrue, NULL);
  184. RyanJsonFree(str);
  185. RyanJsonDelete(jsonRoot);
  186. /**
  187. * @brief 验证创建后的内存模式库切换 (Create -> Change)
  188. */
  189. RyanJson_t json = RyanJsonCreateString("key", "val");
  190. TEST_ASSERT_NOT_NULL(json);
  191. TEST_ASSERT_EQUAL_STRING_MESSAGE("val", RyanJsonGetStringValue(json), "Inline 模式初次设置失败");
  192. // 修改为长字符串 (触发自动切换到 ptr 模式)
  193. const char *longVal = "This is a very long string that definitely exceeds the inline threshold of RyanJson structure.";
  194. RyanJsonChangeStringValue(json, longVal);
  195. TEST_ASSERT_EQUAL_STRING_MESSAGE(longVal, RyanJsonGetStringValue(json), "切换到 Ptr 模式后值错误");
  196. // 修改回短字符串
  197. RyanJsonChangeStringValue(json, "new");
  198. TEST_ASSERT_EQUAL_STRING_MESSAGE("new", RyanJsonGetStringValue(json), "切回短字符串后值错误");
  199. // 修改 Key 为长 Key
  200. const char *longKey = "a_very_long_key_name_to_trigger_ptr_mode_for_key_storage_in_ryanjson";
  201. RyanJsonChangeKey(json, longKey);
  202. TEST_ASSERT_EQUAL_STRING_MESSAGE(longKey, RyanJsonGetKey(json), "Key 切换到 Ptr 模式后错误");
  203. RyanJsonDelete(json);
  204. }
  205. static void testChangeInlineCalcBoundary(void)
  206. {
  207. /**
  208. * 这个测试的目标:
  209. * 验证 RyanJsonInternalChangeString 的容量判断在“临界长度”处是否正确;
  210. * 验证 value 和 key 两条路径都会发生 inline <-> ptr 的双向切换;
  211. * 不依赖固定常量(例如 keyLen=255),而是基于当前编译配置动态计算边界。
  212. *
  213. * 背景:
  214. * RyanJsonInternalChangeString 的判定核心是:
  215. * if ((mallocSize + keyLenFieldBytes) <= RyanJsonInlineStringSize) => inline
  216. * else => ptr
  217. *
  218. * 因此这里分别构造:
  219. * - 恰好满足 <= 的输入(应保持/切回 inline)
  220. * - 超过 1 字节的输入(应切到 ptr)
  221. */
  222. uint32_t inlineSize = RyanJsonInlineStringSize;
  223. uint32_t fixedKeyLen = 1;
  224. uint32_t fixedValueLen = 1;
  225. /**
  226. * value 边界计算(固定 key="k"):
  227. * 需要占用的总 inline 空间 = keyFieldLen + keyLen + '\0' + valueLen + '\0'
  228. * 先算出不含 value 内容本体时的固定开销 baseNeedForValue,
  229. * 再反推出 value 能放进 inline 的最大长度 maxInlineValueLen。
  230. */
  231. uint32_t keyFieldLenForValue = RyanJsonInternalDecodeKeyLenField(RyanJsonInternalCalcLenBytes(fixedKeyLen));
  232. uint32_t baseNeedForValue = keyFieldLenForValue + fixedKeyLen + 1 + 1; // keyField + key + '\0' + value '\0'
  233. TEST_ASSERT_TRUE_MESSAGE(inlineSize >= baseNeedForValue, "inline 大小异常,无法完成边界测试");
  234. uint32_t maxInlineValueLen = inlineSize - baseNeedForValue;
  235. // valueInline: 恰好命中 inline 临界;valuePtr: 比临界多 1 字节,必须走 ptr
  236. char *valueInline = (char *)malloc((size_t)maxInlineValueLen + 1U);
  237. char *valuePtr = (char *)malloc((size_t)maxInlineValueLen + 2U);
  238. TEST_ASSERT_NOT_NULL(valueInline);
  239. TEST_ASSERT_NOT_NULL(valuePtr);
  240. memset(valueInline, 'v', maxInlineValueLen);
  241. valueInline[maxInlineValueLen] = '\0';
  242. memset(valuePtr, 'p', maxInlineValueLen + 1U);
  243. valuePtr[maxInlineValueLen + 1U] = '\0';
  244. RyanJson_t valueNode = RyanJsonCreateString("k", "");
  245. TEST_ASSERT_NOT_NULL(valueNode);
  246. // 临界长度:应为 inline
  247. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(valueNode, valueInline));
  248. TEST_ASSERT_FALSE_MESSAGE(RyanJsonGetPayloadStrIsPtrByFlag(valueNode), "value 临界长度应为 inline");
  249. // 超临界:应切到 ptr
  250. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(valueNode, valuePtr));
  251. TEST_ASSERT_TRUE_MESSAGE(RyanJsonGetPayloadStrIsPtrByFlag(valueNode), "value 超过临界长度应切到 ptr");
  252. // 回退到临界:应能从 ptr 回到 inline(覆盖回切逻辑)
  253. TEST_ASSERT_TRUE(RyanJsonChangeStringValue(valueNode, valueInline));
  254. TEST_ASSERT_FALSE_MESSAGE(RyanJsonGetPayloadStrIsPtrByFlag(valueNode), "value 回退到临界长度应切回 inline");
  255. /**
  256. * key 边界计算(固定 value="v"):
  257. * keyLen 变化时,keyLenField 可能从 1/2/4 字节变化,
  258. * 所以不能硬编码某个 keyLen,必须遍历找到“当前配置下最大可 inline 的 key 长度”。
  259. */
  260. uint32_t maxInlineKeyLen = 0;
  261. for (uint32_t keyLen = 0; keyLen <= inlineSize; keyLen++)
  262. {
  263. uint32_t keyFieldLen = RyanJsonInternalDecodeKeyLenField(RyanJsonInternalCalcLenBytes(keyLen));
  264. uint32_t need = keyFieldLen + keyLen + 1 + fixedValueLen + 1;
  265. if (need <= inlineSize) { maxInlineKeyLen = keyLen; }
  266. }
  267. // 交叉校验:maxInlineKeyLen 应满足 inline;maxInlineKeyLen+1 应超过 inline
  268. uint32_t inlineNeed =
  269. RyanJsonInternalDecodeKeyLenField(RyanJsonInternalCalcLenBytes(maxInlineKeyLen)) + maxInlineKeyLen + 1 + fixedValueLen + 1;
  270. uint32_t ptrNeed = RyanJsonInternalDecodeKeyLenField(RyanJsonInternalCalcLenBytes(maxInlineKeyLen + 1U)) + (maxInlineKeyLen + 1U) +
  271. 1 + fixedValueLen + 1;
  272. TEST_ASSERT_TRUE_MESSAGE(inlineNeed <= inlineSize, "inline key 临界值计算错误");
  273. TEST_ASSERT_TRUE_MESSAGE(ptrNeed > inlineSize, "ptr key 临界值计算错误");
  274. // keyInline: 恰好临界;keyPtr: 超临界 1 字节
  275. char *keyInline = (char *)malloc((size_t)maxInlineKeyLen + 1U);
  276. char *keyPtr = (char *)malloc((size_t)maxInlineKeyLen + 2U);
  277. TEST_ASSERT_NOT_NULL(keyInline);
  278. TEST_ASSERT_NOT_NULL(keyPtr);
  279. memset(keyInline, 'k', maxInlineKeyLen);
  280. keyInline[maxInlineKeyLen] = '\0';
  281. memset(keyPtr, 'K', maxInlineKeyLen + 1U);
  282. keyPtr[maxInlineKeyLen + 1U] = '\0';
  283. RyanJson_t keyNode = RyanJsonCreateString("", "v");
  284. TEST_ASSERT_NOT_NULL(keyNode);
  285. // key 临界长度:应为 inline
  286. TEST_ASSERT_TRUE(RyanJsonChangeKey(keyNode, keyInline));
  287. TEST_ASSERT_FALSE_MESSAGE(RyanJsonGetPayloadStrIsPtrByFlag(keyNode), "key 临界长度应为 inline");
  288. // key 超临界:应切到 ptr
  289. TEST_ASSERT_TRUE(RyanJsonChangeKey(keyNode, keyPtr));
  290. TEST_ASSERT_TRUE_MESSAGE(RyanJsonGetPayloadStrIsPtrByFlag(keyNode), "key 超过临界长度应切到 ptr");
  291. // key 回退临界:应切回 inline
  292. TEST_ASSERT_TRUE(RyanJsonChangeKey(keyNode, keyInline));
  293. TEST_ASSERT_FALSE_MESSAGE(RyanJsonGetPayloadStrIsPtrByFlag(keyNode), "key 回退到临界长度应切回 inline");
  294. // 释放临时资源,避免单测内存泄漏
  295. RyanJsonDelete(valueNode);
  296. RyanJsonDelete(keyNode);
  297. free(valueInline);
  298. free(valuePtr);
  299. free(keyInline);
  300. free(keyPtr);
  301. }
  302. void testChangeRunner(void)
  303. {
  304. UnitySetTestFile(__FILE__);
  305. RUN_TEST(testChangeEdgeCases);
  306. RUN_TEST(testChangeValueStress);
  307. RUN_TEST(testChangeScalarAndStorageMode);
  308. RUN_TEST(testChangeInlineCalcBoundary);
  309. }