fuzzerReplace.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #include "RyanJson.h"
  2. #include "RyanJsonFuzzer.h"
  3. /**
  4. * @brief 节点替换测试
  5. *
  6. * 测试 RyanJson 的节点替换功能(ReplaceByKey、ReplaceByIndex)。
  7. * 覆盖场景:
  8. * 异常替换:测试无效参数、类型不匹配、越界索引等错误。
  9. * 递归替换:遍历 Json 树,随机替换子节点为新生成的随机节点。
  10. * 内存管理:确保替换操作后,被替换的节点被正确释放,新节点被正确挂载。
  11. *
  12. * @param state Fuzzer 状态上下文
  13. * @param pJson 当前正在操作的 Json 节点
  14. * @param size 输入数据大小
  15. */
  16. RyanJsonBool_e RyanJsonFuzzerTestReplace(RyanJson_t pJson, uint32_t size)
  17. {
  18. // 一次性覆盖对象 ReplaceByIndex 重复 key 防御分支
  19. static RyanJsonBool_e replaceConflictCovered = RyanJsonFalse;
  20. if (RyanJsonFalse == replaceConflictCovered)
  21. {
  22. RyanJsonBool_e lastIsEnableMemFail = g_fuzzerState.isEnableMemFail;
  23. g_fuzzerState.isEnableMemFail = false;
  24. RyanJson_t obj = RyanJsonCreateObject();
  25. assert(NULL != obj);
  26. assert(RyanJsonTrue == RyanJsonAddIntToObject(obj, "a", 1));
  27. assert(RyanJsonTrue == RyanJsonAddIntToObject(obj, "b", 2));
  28. RyanJson_t newItem = RyanJsonCreateInt("a", 9);
  29. assert(NULL != newItem);
  30. #if true == RyanJsonDefaultAddAtHead
  31. uint32_t replaceIndex = 0;
  32. #else
  33. uint32_t replaceIndex = 1;
  34. #endif
  35. #if true == RyanJsonStrictObjectKeyCheck
  36. assert(RyanJsonFalse == RyanJsonReplaceByIndex(obj, replaceIndex, newItem));
  37. RyanJsonDelete(newItem);
  38. assert(2 == RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "b")));
  39. #else
  40. assert(RyanJsonTrue == RyanJsonReplaceByIndex(obj, replaceIndex, newItem));
  41. assert(NULL == RyanJsonGetObjectByKey(obj, "b"));
  42. #if true == RyanJsonDefaultAddAtHead
  43. assert(9 == RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "a")));
  44. #else
  45. assert(1 == RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "a")));
  46. #endif
  47. #endif
  48. // 同 key 替换应成功(覆盖冲突检测的 skipItem 分支)
  49. newItem = RyanJsonCreateInt("b", 99);
  50. assert(NULL != newItem);
  51. assert(RyanJsonTrue == RyanJsonReplaceByIndex(obj, replaceIndex, newItem));
  52. assert(99 == RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "b")));
  53. RyanJsonDelete(obj);
  54. g_fuzzerState.isEnableMemFail = lastIsEnableMemFail;
  55. replaceConflictCovered = RyanJsonTrue;
  56. }
  57. // 一次性覆盖“通过 Replace 修改 value 类型”的推荐用法
  58. static RyanJsonBool_e replaceTypeSwitchCovered = RyanJsonFalse;
  59. if (RyanJsonFalse == replaceTypeSwitchCovered)
  60. {
  61. RyanJsonBool_e lastIsEnableMemFail = g_fuzzerState.isEnableMemFail;
  62. g_fuzzerState.isEnableMemFail = false;
  63. RyanJson_t obj = RyanJsonCreateObject();
  64. assert(NULL != obj);
  65. assert(RyanJsonTrue == RyanJsonAddIntToObject(obj, "k", 1));
  66. assert(RyanJsonTrue == RyanJsonReplaceByKey(obj, "k", RyanJsonCreateObject()));
  67. RyanJson_t item = RyanJsonGetObjectByKey(obj, "k");
  68. assert(NULL != item && RyanJsonTrue == RyanJsonIsObject(item));
  69. assert(RyanJsonTrue == RyanJsonAddIntToObject(item, "x", 7));
  70. assert(RyanJsonTrue == RyanJsonReplaceByKey(obj, "k", RyanJsonCreateArray()));
  71. item = RyanJsonGetObjectByKey(obj, "k");
  72. assert(NULL != item && RyanJsonTrue == RyanJsonIsArray(item));
  73. RyanJson_t arr = RyanJsonCreateArray();
  74. assert(NULL != arr);
  75. assert(RyanJsonTrue == RyanJsonAddIntToArray(arr, 1));
  76. assert(RyanJsonTrue == RyanJsonReplaceByIndex(arr, 0, RyanJsonCreateObject()));
  77. item = RyanJsonGetObjectByIndex(arr, 0);
  78. assert(NULL != item && RyanJsonTrue == RyanJsonIsObject(item));
  79. RyanJsonDelete(arr);
  80. RyanJsonDelete(obj);
  81. g_fuzzerState.isEnableMemFail = lastIsEnableMemFail;
  82. replaceTypeSwitchCovered = RyanJsonTrue;
  83. }
  84. // 故障注入与异常参数测试
  85. if (RyanJsonFuzzerShouldFail(100))
  86. {
  87. g_fuzzerState.isEnableMemFail = false; // 临时禁用内存失败模拟,确保测试对象创建成功
  88. RyanJson_t strItem = RyanJsonCreateString("", "NULL");
  89. // key 替换异常测试
  90. assert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, NULL, NULL));
  91. assert(RyanJsonFalse == RyanJsonReplaceByKey(pJson, NULL, NULL));
  92. assert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, "NULL", NULL));
  93. assert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, NULL, strItem));
  94. assert(RyanJsonFalse == RyanJsonReplaceByKey(pJson, "NULL", NULL));
  95. assert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, "NULL", strItem));
  96. // 类型错误测试:非对象调用 ReplaceByKey
  97. if (RyanJsonFalse == RyanJsonIsObject(RyanJsonGetObjectByIndex(pJson, 0)))
  98. {
  99. // 如果意外成功(说明 pJson 其实是对象且碰巧存在该 key),
  100. // 需要把 strItem 取回,避免后续 RyanJsonDelete(strItem) 触发重复释放。
  101. if (RyanJsonTrue == RyanJsonReplaceByKey(pJson, "NULL", strItem)) { strItem = RyanJsonDetachByKey(pJson, "NULL"); }
  102. }
  103. // index 替换异常测试
  104. assert(RyanJsonFalse == RyanJsonReplaceByIndex(NULL, 0, NULL));
  105. assert(RyanJsonFalse == RyanJsonReplaceByIndex(pJson, 0, NULL));
  106. assert(RyanJsonFalse == RyanJsonReplaceByIndex(NULL, 0, strItem));
  107. assert(RyanJsonFalse == RyanJsonReplaceByIndex(pJson, 0, NULL));
  108. assert(RyanJsonFalse == RyanJsonReplaceByIndex(NULL, 0, strItem));
  109. // 类型错误测试:非容器调用 ReplaceByIndex
  110. if (RyanJsonFalse == RyanJsonIsArray(pJson) && RyanJsonFalse == RyanJsonIsObject(pJson))
  111. {
  112. assert(RyanJsonFalse == RyanJsonReplaceByIndex(pJson, 0, strItem));
  113. }
  114. // 构造临时对象,测试不存在 key 和越界 index
  115. RyanJson_t objItem = RyanJsonCreateObject();
  116. assert(RyanJsonFalse == RyanJsonReplaceByKey(objItem, "NULL", strItem));
  117. assert(RyanJsonFalse == RyanJsonReplaceByIndex(objItem, 0, strItem));
  118. RyanJsonAddItemToObject(objItem, "item", RyanJsonCreateObject());
  119. assert(RyanJsonFalse == RyanJsonReplaceByKey(objItem, "NULL222", strItem));
  120. assert(RyanJsonFalse == RyanJsonReplaceByIndex(objItem, INT32_MAX, strItem));
  121. // Replace 失败后,item 仍应保持游离态(由调用方继续持有)
  122. {
  123. RyanJson_t keepObjItem = RyanJsonCreateInt("keep", 1);
  124. assert(NULL != keepObjItem);
  125. assert(RyanJsonTrue == RyanJsonIsDetachedItem(keepObjItem));
  126. assert(RyanJsonFalse == RyanJsonReplaceByKey(objItem, "not_found", keepObjItem));
  127. assert(RyanJsonTrue == RyanJsonIsDetachedItem(keepObjItem));
  128. RyanJsonDelete(keepObjItem);
  129. RyanJson_t arrayItem = RyanJsonCreateArray();
  130. assert(NULL != arrayItem);
  131. assert(RyanJsonTrue == RyanJsonAddIntToArray(arrayItem, 9));
  132. RyanJson_t keepArrItem = RyanJsonCreateString(NULL, "keep");
  133. assert(NULL != keepArrItem);
  134. assert(RyanJsonTrue == RyanJsonIsDetachedItem(keepArrItem));
  135. assert(RyanJsonFalse == RyanJsonReplaceByIndex(arrayItem, 7, keepArrItem));
  136. assert(RyanJsonTrue == RyanJsonIsDetachedItem(keepArrItem));
  137. RyanJsonDelete(keepArrItem);
  138. RyanJsonDelete(arrayItem);
  139. }
  140. // 已挂树的 item 不应被 Replace
  141. {
  142. RyanJson_t objA = RyanJsonCreateObject();
  143. RyanJson_t objB = RyanJsonCreateObject();
  144. RyanJsonAddIntToObject(objA, "a", 1);
  145. RyanJsonAddIntToObject(objB, "b", 2);
  146. RyanJson_t attachedObjItem = RyanJsonGetObjectByKey(objA, "a");
  147. assert(attachedObjItem);
  148. assert(RyanJsonFalse == RyanJsonIsDetachedItem(attachedObjItem));
  149. assert(RyanJsonFalse == RyanJsonReplaceByKey(objB, "b", attachedObjItem));
  150. assert(2 == RyanJsonGetIntValue(RyanJsonGetObjectByKey(objB, "b")));
  151. RyanJson_t arr1 = RyanJsonCreateArray();
  152. RyanJson_t arr2 = RyanJsonCreateArray();
  153. RyanJsonAddIntToArray(arr1, 10);
  154. RyanJsonAddIntToArray(arr2, 20);
  155. RyanJson_t attachedArrItem = RyanJsonGetObjectByIndex(arr1, 0);
  156. assert(attachedArrItem);
  157. assert(RyanJsonFalse == RyanJsonIsDetachedItem(attachedArrItem));
  158. assert(RyanJsonFalse == RyanJsonReplaceByIndex(arr2, 0, attachedArrItem));
  159. assert(20 == RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr2, 0)));
  160. RyanJsonDelete(objA);
  161. RyanJsonDelete(objB);
  162. RyanJsonDelete(arr1);
  163. RyanJsonDelete(arr2);
  164. }
  165. g_fuzzerState.isEnableMemFail = true; // 恢复状态
  166. RyanJsonDelete(objItem);
  167. RyanJsonDelete(strItem);
  168. }
  169. // 递归遍历与替换
  170. // 仅处理容器类型(Object/Array)
  171. if (RyanJsonFalse == RyanJsonIsArray(pJson) && RyanJsonFalse == RyanJsonIsObject(pJson)) { return RyanJsonTrue; }
  172. RyanJson_t item = NULL;
  173. RyanJsonObjectForEach(pJson, item)
  174. {
  175. // 递归调用
  176. if (RyanJsonTrue != RyanJsonFuzzerTestReplace(item, size)) { return RyanJsonFalse; }
  177. }
  178. // 按 key 替换(仅 Object)
  179. do
  180. {
  181. if (RyanJsonFalse == RyanJsonIsObject(pJson)) { break; }
  182. // 随机尝试替换 0 / 中间 / 结尾 子节点
  183. uint32_t jsonSize = RyanJsonGetSize(pJson);
  184. if (0 == jsonSize) { break; }
  185. uint32_t index = RyanJsonFuzzerNextRand() % jsonSize;
  186. RyanJson_t targetItem = RyanJsonGetObjectByIndex(pJson, index);
  187. if (NULL == targetItem || RyanJsonTrue != RyanJsonIsKey(targetItem)) { break; }
  188. RyanJson_t newItem = NULL;
  189. uint32_t choice = RyanJsonFuzzerNextRand() % 3;
  190. // 策略一:使用相同 key(覆盖 key 相等分支)
  191. if (0 == choice) { newItem = RyanJsonFuzzerCreateRandomNodeWithKey(pJson, RyanJsonGetKey(targetItem)); }
  192. // 策略二:使用不同 key(覆盖 key 不相等分支,触发 ChangeKey)
  193. else if (1 == choice) { newItem = RyanJsonFuzzerCreateRandomNodeWithKey(pJson, "diff_key_random"); }
  194. // 策略三:不带 key(覆盖无 key 分支,触发 CreateItem)
  195. else
  196. {
  197. newItem = RyanJsonFuzzerCreateRandomNode(pJson);
  198. }
  199. // 尝试替换
  200. if (RyanJsonFalse == RyanJsonReplaceByKey(pJson, RyanJsonGetKey(targetItem), newItem))
  201. {
  202. // 替换失败(可能是内存模拟失败),需手动释放 newItem 防止泄漏
  203. if (NULL != newItem) { RyanJsonDelete(newItem); }
  204. }
  205. } while (0);
  206. // 按 index 替换(Array/Object)
  207. {
  208. uint32_t idx = 0;
  209. uint32_t jsonSize = RyanJsonGetSize(pJson);
  210. if (0 != jsonSize) { idx = size % jsonSize; } // 随机选择一个有效 index
  211. RyanJson_t newItem = RyanJsonFuzzerCreateRandomNode(pJson);
  212. // 执行替换
  213. if (RyanJsonFalse == RyanJsonReplaceByIndex(pJson, idx, newItem))
  214. {
  215. // 替换失败,手动释放
  216. if (NULL != newItem) { RyanJsonDelete(newItem); }
  217. }
  218. }
  219. return RyanJsonTrue;
  220. }