fuzzerDuplicate.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include "RyanJson.h"
  2. #include "RyanJsonFuzzer.h"
  3. /**
  4. * @brief 复制与比较测试
  5. *
  6. * 测试深度复制与结构比较能力。
  7. * 覆盖场景:
  8. * 深度复制正确性:验证复制后的对象与原对象在结构和值上完全一致。
  9. * 独立性验证:验证修改复制后的对象不会影响原对象。
  10. * 内存管理:验证复制过程中的内存分配与释放。
  11. *
  12. * @param state Fuzzer 状态上下文
  13. * @param pJson 需要复制的源 Json 对象
  14. */
  15. RyanJsonBool_e RyanJsonFuzzerTestDuplicate(RyanJson_t pJson)
  16. {
  17. RyanJsonBool_e result = RyanJsonTrue;
  18. char *jsonStr = NULL;
  19. char *jsonStrDup = NULL;
  20. RyanJson_t pJsonDup = NULL;
  21. // 序列化原始对象
  22. uint32_t len = 0;
  23. // 使用非格式化输出,减少空白差异干扰
  24. jsonStr = RyanJsonPrint(pJson, 100, RyanJsonFalse, &len);
  25. RyanJsonCheckGotoExit(NULL != jsonStr);
  26. // 执行深度复制
  27. pJsonDup = RyanJsonDuplicate(pJson);
  28. RyanJsonCheckGotoExit(NULL != pJsonDup);
  29. // 参数与边界场景测试
  30. // 测试对 NULL 的复制
  31. assert(NULL == RyanJsonDuplicate(NULL));
  32. assert(0 == RyanJsonGetSize(NULL));
  33. // 结构完整性验证
  34. // 验证节点数量一致
  35. assert(RyanJsonGetSize(pJson) == RyanJsonGetSize(pJsonDup));
  36. // 执行结构比较
  37. // RyanJsonCompare:比较 key 与 value
  38. // RyanJsonCompareOnlyKey:仅比较 key(结构)
  39. RyanJsonCompare(pJson, pJsonDup);
  40. RyanJsonCompareOnlyKey(pJson, pJsonDup);
  41. // 比较接口边界测试
  42. assert(RyanJsonTrue == RyanJsonCompare(pJson, pJson)); // 自比较
  43. assert(RyanJsonFalse == RyanJsonCompare(NULL, pJsonDup));
  44. assert(RyanJsonFalse == RyanJsonCompare(pJson, NULL));
  45. assert(RyanJsonFalse == RyanJsonCompare(NULL, NULL)); // 约定:两个 NULL 不相等
  46. assert(RyanJsonTrue == RyanJsonCompareOnlyKey(pJson, pJson));
  47. assert(RyanJsonFalse == RyanJsonCompareOnlyKey(NULL, pJsonDup));
  48. assert(RyanJsonFalse == RyanJsonCompareOnlyKey(pJson, NULL));
  49. assert(RyanJsonFalse == RyanJsonCompareOnlyKey(NULL, NULL));
  50. // 序列化一致性验证
  51. uint32_t lenDup = 0;
  52. jsonStrDup = RyanJsonPrint(pJsonDup, 100, RyanJsonFalse, &lenDup);
  53. RyanJsonCheckGotoExit(NULL != jsonStrDup && lenDup > 0);
  54. // 验证序列化后的字符串内容完全一致
  55. RyanJsonCheckCode(len == lenDup && 0 == memcmp(jsonStr, jsonStrDup, (size_t)len), {
  56. // printf("len:%" PRIu32 ", dupLen:%" PRIu32 "\r\n", len, lenDup);
  57. // printf("jsonStr:%s, jsonStrDup:%s\r\n", jsonStr, jsonStrDup);
  58. RyanJsonCheckGotoExit(0);
  59. });
  60. // 独立性验证
  61. // 修改原对象(如果可能)或修改副本,验证互不影响
  62. // 这里选择修改副本(pJsonDup),因为后续会销毁副本
  63. if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
  64. {
  65. // 先执行删除操作
  66. RyanJsonDelete(RyanJsonDetachByIndex(pJsonDup, 0));
  67. if (RyanJsonGetSize(pJsonDup) > 1) { RyanJsonDelete(RyanJsonDetachByIndex(pJsonDup, 1)); }
  68. // 如果修改后仍是容器
  69. if (RyanJsonIsArray(pJsonDup) || RyanJsonIsObject(pJsonDup))
  70. {
  71. RyanJson_t item;
  72. // 修改 key
  73. RyanJsonObjectForEach(pJsonDup, item)
  74. {
  75. if (RyanJsonIsKey(item))
  76. {
  77. RyanJsonChangeKey(item, "modify_key_test");
  78. break; // 只改第一个找到的
  79. }
  80. }
  81. // 修改 Bool 值
  82. RyanJsonObjectForEach(pJsonDup, item)
  83. {
  84. if (RyanJsonIsBool(item))
  85. {
  86. RyanJsonChangeBoolValue(item, !RyanJsonGetBoolValue(item));
  87. break;
  88. }
  89. }
  90. // 再次修改 Object 节点中的 key
  91. RyanJsonObjectForEach(pJsonDup, item)
  92. {
  93. if (RyanJsonIsKey(item) && RyanJsonIsObject(item))
  94. {
  95. RyanJsonChangeKey(item, "modify_obj_key_test");
  96. break;
  97. }
  98. }
  99. }
  100. // 验证修改后的副本与原对象不再相等
  101. // 注意:如果原对象本来就是空的,或者修改没有实际生效(例如没找到对应类型的节点),这里可能会相等
  102. // 所以这里只调用比较函数增加覆盖率,不强制断言 False,因为逻辑极其复杂
  103. RyanJsonCompare(pJson, pJsonDup);
  104. RyanJsonCompareOnlyKey(pJson, pJsonDup);
  105. }
  106. exit__:
  107. if (jsonStr)
  108. {
  109. RyanJsonFree(jsonStr);
  110. jsonStr = NULL;
  111. }
  112. if (pJsonDup)
  113. {
  114. RyanJsonDelete(pJsonDup);
  115. pJsonDup = NULL;
  116. }
  117. if (jsonStrDup)
  118. {
  119. RyanJsonFree(jsonStrDup);
  120. jsonStrDup = NULL;
  121. }
  122. return result;
  123. }