Browse Source

test: 拆分fuzzer测试文件,更新字典

RyanCW 1 month ago
parent
commit
10593b6abb

+ 13 - 743
test/fuzzer/RyanJsonFuzzer.c

@@ -1,736 +1,6 @@
-#include "RyanJsonTest.h"
-#include <signal.h>
+#include "RyanJsonFuzzer.h"
 
-#define RyanJsonCheckGotoExit(EX)                                                                                                          \
-	RyanJsonCheckCode(EX, {                                                                                                            \
-		result = RyanJsonFalse;                                                                                                    \
-		goto exit__;                                                                                                               \
-	})
-
-static RyanJsonBool_e isEnableRandomMemFail = RyanJsonTrue;
-
-static RyanJsonBool_e RyanJsonFuzzerTestByParseAndPrint(RyanJson_t pJson, const char *data, uint32_t size)
-{
-	isEnableRandomMemFail = RyanJsonFalse;
-	RyanJson_t testItem = RyanJsonCreateObject();
-	RyanJson_t testItem2 = RyanJsonCreateObject();
-	RyanJsonSetType(testItem, 0);
-	RyanJsonSetType(testItem2, 0);
-	RyanJsonAssert(NULL == RyanJsonPrint(testItem, 100, RyanJsonFalse, NULL));
-	RyanJsonAssert(NULL == RyanJsonDuplicate(testItem));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonCompare(testItem, testItem2));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonCompareOnlyKey(testItem, testItem2));
-
-	// 测试pJson类型错误情况
-	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(testItem, 0, RyanJsonCreateString("key", "true")));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(testItem2, UINT32_MAX, RyanJsonCreateString("key", "true")));
-
-	RyanJsonSetType(testItem, RyanJsonTypeObject);
-	RyanJsonSetType(testItem2, RyanJsonTypeObject);
-
-	// 测试pJson为obj,但是item没有key的情况
-	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(pJson, 0, RyanJsonCreateString(NULL, "true")));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(pJson, UINT32_MAX, RyanJsonCreateString(NULL, "true")));
-
-	RyanJsonAssert(RyanJsonTrue == RyanJsonInsert(pJson, 0, RyanJsonCreateString("key", "true")));
-	RyanJsonDelete(testItem);
-	RyanJsonDelete(testItem2);
-	isEnableRandomMemFail = RyanJsonTrue;
-
-	RyanJsonAssert(NULL == RyanJsonPrint(NULL, 100, RyanJsonFalse, NULL));
-	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(NULL, NULL, 100, RyanJsonFalse, NULL));
-	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(pJson, NULL, 100, RyanJsonFalse, NULL));
-	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(NULL, (char *)data, 100, RyanJsonFalse, NULL));
-	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(pJson, (char *)data, 0, RyanJsonFalse, NULL));
-
-	uint32_t len = 0;
-	char *jsonStr = RyanJsonPrint(pJson, size % 5 ? 100 : 0, size % 2 ? RyanJsonFalse : RyanJsonTrue, &len);
-	RyanJsonCheckReturnFalse(NULL != jsonStr && len > 0);
-
-	char *jsonStrCopy = RyanJsonPrint(pJson, size % 5 ? 100 : 0, size % 2 ? RyanJsonFalse : RyanJsonTrue, NULL); // 不传递len
-	RyanJsonAssert(0 == strncmp(jsonStr, jsonStrCopy, len));
-	RyanJsonFree(jsonStr);
-	RyanJsonFree(jsonStrCopy);
-
-	uint32_t bufLen = len * 3;
-	if (bufLen < size * 2) { bufLen = size * 2; }
-	if (bufLen < 2048) { bufLen = 2048; }
-	char *buf = (char *)malloc((size_t)bufLen);
-	{
-		uint32_t len2 = 0;
-		char *jsonStr2 = RyanJsonPrintPreallocated(pJson, buf, bufLen, size % 2 ? RyanJsonFalse : RyanJsonTrue, &len2);
-		// printf("len: %d, len2: %d, str: %s\r\n", len, len2, NULL == jsonStr2 ? "NULL" : jsonStr2);
-		RyanJsonCheckCode(NULL != jsonStr2 && len == len2, {
-			free(buf);
-			return RyanJsonFalse;
-		});
-	}
-
-	memcpy(buf, data, (size_t)size);
-	buf[size] = 0;
-	RyanJson_t jsonRoot = RyanJsonParse(buf);
-	RyanJsonCheckCode(NULL != jsonRoot, {
-		free(buf);
-		return RyanJsonFalse;
-	});
-
-	// 测试多次打印结果是否一致
-	{
-		uint32_t len3 = 0;
-		char *jsonStr3 = RyanJsonPrint(jsonRoot, 100, size % 2 ? RyanJsonFalse : RyanJsonTrue, &len3); // 以带格式方式将数据打印出来
-		RyanJsonCheckCode(NULL != jsonStr3 && len == len3, {
-			free(buf);
-			if (jsonStr3) { RyanJsonFree(jsonStr3); }
-			RyanJsonDelete(jsonRoot);
-			return RyanJsonFalse;
-		});
-
-		RyanJsonFree(jsonStr3);
-	}
-
-	{
-		RyanJsonPrintPreallocated(jsonRoot, buf, bufLen / 15, RyanJsonTrue, NULL);
-	}
-
-	free(buf);
-	RyanJsonDelete(jsonRoot);
-	return RyanJsonTrue;
-}
-
-static RyanJsonBool_e RyanJsonFuzzerTestByDup(RyanJson_t pJson)
-{
-	RyanJsonBool_e result = RyanJsonTrue;
-	char *jsonStr = NULL;
-	char *jsonStrDup = NULL;
-	RyanJson_t pJsonDup = NULL;
-
-	// 测试打印和复制功能
-	uint32_t len = 0;
-	uint32_t dupLen = 0;
-
-	jsonStr = RyanJsonPrint(pJson, 100, RyanJsonFalse, &len);
-	RyanJsonCheckGotoExit(NULL != jsonStr && len > 0);
-
-	pJsonDup = RyanJsonDuplicate(pJson);
-	RyanJsonCheckGotoExit(NULL != pJsonDup);
-
-	// 测试dup失败情况
-	RyanJsonCheckGotoExit(NULL == RyanJsonDuplicate(NULL));
-
-	// 判断复制json的size是否一致
-	RyanJsonCheckGotoExit(0 == RyanJsonGetSize(NULL));
-	RyanJsonCheckGotoExit(RyanJsonGetSize(pJson) == RyanJsonGetSize(pJsonDup));
-	RyanJsonCompare(pJson, pJsonDup);
-	RyanJsonCompareOnlyKey(pJson, pJsonDup);
-	// assert(RyanJsonTrue == RyanJsonCompare(pJson, pJsonDup)); // 大浮点数判断容易出错
-	// RyanJsonCheckGotoExit(RyanJsonTrue == RyanJsonCompareOnlyKey(pJson, pJsonDup)); // 重复key也会失败
-
-	// 测试compare特殊情况
-	RyanJsonCheckGotoExit(RyanJsonTrue == RyanJsonCompare(pJson, pJson));
-	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompare(NULL, pJsonDup));
-	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompare(pJson, NULL));
-	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompare(NULL, NULL));
-
-	// 测试compareKey特殊情况
-	RyanJsonCheckGotoExit(RyanJsonTrue == RyanJsonCompareOnlyKey(pJson, pJson));
-	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompareOnlyKey(NULL, pJsonDup));
-	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompareOnlyKey(pJson, NULL));
-	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompareOnlyKey(NULL, NULL));
-
-	jsonStrDup = RyanJsonPrint(pJsonDup, 100, RyanJsonFalse, &dupLen); // 以带格式方式将数据打印出来
-	RyanJsonCheckGotoExit(NULL != jsonStrDup && dupLen > 0);
-
-	RyanJsonCheckCode(len == dupLen && 0 == memcmp(jsonStr, jsonStrDup, (size_t)len), {
-		printf("len:%" PRIu32 ", dupLen:%" PRIu32 "\r\n", len, dupLen);
-		printf("jsonStr:%s, jsonStrDup:%s\r\n", jsonStr, jsonStrDup);
-		RyanJsonCheckGotoExit(0);
-	});
-
-	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
-	{
-		// 测试size不相等
-		RyanJsonDelete(RyanJsonDetachByIndex(pJson, 0));
-		// 增加分支覆盖率
-		if (RyanJsonGetSize(pJson) > 2) { RyanJsonDelete(RyanJsonDetachByIndex(pJson, 1)); }
-
-		if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
-		{
-			// 改变key
-			RyanJson_t item;
-			RyanJsonObjectForEach(pJson, item)
-			{
-				if (RyanJsonIsKey(item))
-				{
-					RyanJsonChangeKey(item, "key12231123");
-					break;
-				}
-			}
-
-			// 改变value
-			RyanJsonObjectForEach(pJson, item)
-			{
-				if (RyanJsonIsBool(item))
-				{
-					RyanJsonChangeBoolValue(item, !RyanJsonGetBoolValue(item));
-					break;
-				}
-			}
-
-			// 改变obj的key
-			RyanJsonObjectForEach(pJson, item)
-			{
-				if (RyanJsonIsKey(item) && RyanJsonIsObject(item))
-				{
-					RyanJsonChangeKey(item, "key12231123");
-					break;
-				}
-			}
-		}
-
-		RyanJsonCompare(pJson, pJsonDup);
-		RyanJsonCompareOnlyKey(pJson, pJsonDup);
-	}
-exit__:
-
-	if (jsonStr)
-	{
-		RyanJsonFree(jsonStr);
-		jsonStr = NULL;
-	}
-	if (pJsonDup)
-	{
-		RyanJsonDelete(pJsonDup);
-		pJsonDup = NULL;
-	}
-	if (jsonStrDup)
-	{
-		RyanJsonFree(jsonStrDup);
-		jsonStrDup = NULL;
-	}
-
-	return result;
-}
-
-static RyanJsonBool_e RyanJsonFuzzerTestByForEachChange(RyanJson_t pJson, uint32_t size)
-{
-	RyanJsonIsNull(pJson);
-
-	if (RyanJsonIsKey(pJson))
-	{
-		char *key = (char *)malloc(strlen(RyanJsonGetKey(pJson)) + 1);
-		if (key)
-		{
-			memcpy(key, RyanJsonGetKey(pJson), strlen(RyanJsonGetKey(pJson)));
-			key[strlen(RyanJsonGetKey(pJson))] = 0;
-
-			RyanJsonChangeKey(pJson, "key");
-			RyanJsonChangeKey(pJson, key);
-			free(key);
-		}
-	}
-	if (RyanJsonIsBool(pJson)) { RyanJsonChangeBoolValue(pJson, !RyanJsonGetBoolValue(pJson)); }
-	if (RyanJsonIsNumber(pJson))
-	{
-		if (RyanJsonIsInt(pJson))
-		{
-			int32_t value = RyanJsonGetIntValue(pJson);
-			RyanJsonChangeIntValue(pJson, (int32_t)size);
-			RyanJsonChangeIntValue(pJson, value);
-		}
-		if (RyanJsonIsDouble(pJson))
-		{
-			double value = RyanJsonGetDoubleValue(pJson);
-			RyanJsonChangeDoubleValue(pJson, size * 1.123456789);
-			RyanJsonChangeDoubleValue(pJson, value);
-		}
-	}
-
-	if (RyanJsonIsString(pJson))
-	{
-		char *value = (char *)malloc(strlen(RyanJsonGetStringValue(pJson)) + 1);
-		if (value)
-		{
-			memcpy(value, RyanJsonGetStringValue(pJson), strlen(RyanJsonGetStringValue(pJson)));
-			value[strlen(RyanJsonGetStringValue(pJson))] = 0;
-
-			RyanJsonChangeStringValue(pJson, "hello world");
-			RyanJsonChangeStringValue(pJson, "h");
-			RyanJsonChangeStringValue(pJson, value);
-
-			free(value);
-		}
-	}
-
-	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
-	{
-		RyanJson_t item;
-		RyanJsonArrayForEach(pJson, item)
-		{
-			RyanJsonCheckReturnFalse(RyanJsonTrue == RyanJsonFuzzerTestByForEachChange(item, size));
-		}
-	}
-
-	return RyanJsonTrue;
-}
-
-static RyanJsonBool_e RyanJsonFuzzerTestByForEachGet2(RyanJson_t lastJson, RyanJson_t pJson, uint32_t index, uint32_t size)
-{
-	RyanJsonIsNull(pJson);
-
-	RyanJsonAssert(NULL == RyanJsonGetKey(NULL));
-	RyanJsonAssert(NULL == RyanJsonGetStringValue(NULL));
-	RyanJsonAssert(0 == RyanJsonGetIntValue(NULL));
-	RyanJsonAssert(0 == RyanJsonGetDoubleValue(NULL));
-	RyanJsonAssert(NULL == RyanJsonGetObjectValue(NULL));
-	RyanJsonAssert(NULL == RyanJsonGetArrayValue(NULL));
-
-	RyanJsonAssert(NULL == RyanJsonGetObjectByKey(NULL, NULL));
-	RyanJsonAssert(NULL == RyanJsonGetObjectByKey(pJson, NULL));
-	RyanJsonAssert(NULL == RyanJsonGetObjectByKey(NULL, "NULL"));
-
-	RyanJsonAssert(NULL == RyanJsonGetObjectByKeys(NULL, NULL));
-	RyanJsonAssert(NULL == RyanJsonGetObjectByKeys(pJson, NULL));
-	RyanJsonAssert(NULL == RyanJsonGetObjectByKeys(NULL, "NULL"));
-	if (!RyanJsonIsObject(pJson)) // pJson类型错误
-	{
-		RyanJsonAssert(NULL == RyanJsonGetObjectByKey(pJson, "NULL"));
-	}
-
-	RyanJsonAssert(NULL == RyanJsonGetObjectByIndex(NULL, 10));
-	if (!RyanJsonIsArray(pJson) && !RyanJsonIsObject(pJson)) // pJson类型错误
-	{
-		RyanJsonAssert(NULL == RyanJsonGetObjectByIndex(pJson, 0));
-	}
-
-	if (RyanJsonIsKey(pJson)) { RyanJsonGetObjectToKey(lastJson, RyanJsonGetKey(pJson)); }
-	else
-	{
-		RyanJsonGetObjectToIndex(lastJson, index);
-	}
-
-	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
-	{
-		RyanJson_t item;
-		RyanJsonObjectForEach(pJson, item) { RyanJsonFuzzerTestByForEachGet2(pJson, item, index, size); }
-	}
-
-	return RyanJsonTrue;
-}
-
-static RyanJsonBool_e RyanJsonFuzzerTestByForEachGet(RyanJson_t pJson, uint32_t size)
-{
-	RyanJsonAssert(RyanJsonFalse == RyanJsonIsKey(NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonIsNull(NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonIsBool(NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonIsNumber(NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonIsString(NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonIsArray(NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonIsObject(NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonIsInt(NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonIsDouble(NULL));
-
-	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
-	{
-		RyanJson_t item;
-		uint32_t index = 0;
-		RyanJsonObjectForEach(pJson, item)
-		{
-			RyanJsonFuzzerTestByForEachGet2(pJson, item, index, size);
-			index++;
-		}
-	}
-	return RyanJsonTrue;
-}
-
-static RyanJson_t RyanJsonFuzzerCreateRandomNode(RyanJson_t pJson)
-{
-	static int32_t count = 0;
-	static int32_t count2 = 0;
-	count++;
-	char *key = "true";
-	if (count % 10 > 5) { key = NULL; }
-	switch (count % 50)
-	{
-	case 0: return RyanJsonCreateArray();
-	case 1: return RyanJsonCreateObject();
-	case 2:
-		count2++;
-		if (0 == count2 % 10) { return RyanJsonDuplicate(pJson); }
-	case 11:
-	case 12:
-	case 13: return RyanJsonCreateBool(key, RyanJsonTrue);
-	case 20:
-	case 21:
-	case 22: return RyanJsonCreateInt(key, count);
-	case 31:
-	case 32:
-	case 33: return RyanJsonCreateDouble(key, count * 1.123456789);
-
-	default: return RyanJsonCreateString(key, "true");
-	}
-}
-
-static RyanJsonBool_e RyanJsonFuzzerTestByForEachCreate(RyanJson_t pJson, uint32_t size)
-{
-	// RyanJsonInsert的特殊情况
-	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(NULL, UINT32_MAX, RyanJsonCreateString("key", "string")));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(pJson, UINT32_MAX, NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(NULL, 0, NULL));
-
-	RyanJsonAssert(NULL == RyanJsonCreateString(NULL, NULL));
-	RyanJsonAssert(NULL == RyanJsonCreateString("NULL", NULL));
-
-	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeStringValue(NULL, NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeStringValue(pJson, NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeStringValue(NULL, "NULL"));
-	if (!RyanJsonIsKey(pJson) && !RyanJsonIsString(pJson)) // pJson类型错误
-	{
-		RyanJsonAssert(RyanJsonFalse == RyanJsonChangeStringValue(pJson, "NULL"));
-	}
-
-	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(NULL, NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(pJson, NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(NULL, "NULL"));
-	if (!RyanJsonIsKey(pJson) && !RyanJsonIsString(pJson)) // pJson类型错误
-	{
-		RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(pJson, "NULL"));
-	}
-
-	// 测试没有key但是有strValue的
-	if (!RyanJsonIsKey(pJson) && RyanJsonIsString(pJson)) { RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(pJson, "NULL")); }
-
-	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeIntValue(NULL, 0));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeDoubleValue(NULL, 0));
-
-	RyanJsonAssert(RyanJsonFalse == RyanJsonAddItemToObject(NULL, NULL, NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonAddItemToObject(pJson, NULL, NULL));
-
-	RyanJsonAssert(NULL == RyanJsonCreateIntArray(NULL, 0));
-	RyanJsonAssert(NULL == RyanJsonCreateDoubleArray(NULL, 0));
-	RyanJsonAssert(NULL == RyanJsonCreateStringArray(NULL, 0));
-
-	RyanJsonAssert(RyanJsonFalse == RyanJsonHasObjectToKey(NULL, "0", "1", "2", "3"));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonHasObjectToIndex(NULL, 0, 1, 2, 3));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonHasObjectToKey(pJson, "0", "1", "2", "3"));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonHasObjectToIndex(pJson, 0, 1, 2, 3));
-
-	char *key = "keyaaa";
-	RyanJsonAddNullToObject(pJson, key);
-	if (RyanJsonIsKey(pJson)) { key = RyanJsonGetKey(pJson); }
-	if (RyanJsonIsBool(pJson)) { RyanJsonAddBoolToObject(pJson, key, RyanJsonGetBoolValue(pJson)); }
-	if (RyanJsonIsNumber(pJson))
-	{
-		if (RyanJsonIsInt(pJson))
-		{
-			RyanJsonAddIntToObject(pJson, key, RyanJsonGetIntValue(pJson));
-			int arrayInt[] = {RyanJsonGetIntValue(pJson), RyanJsonGetIntValue(pJson), RyanJsonGetIntValue(pJson),
-					  RyanJsonGetIntValue(pJson), RyanJsonGetIntValue(pJson)};
-			RyanJsonAddItemToObject(pJson, (size % 2) ? key : "arrayString",
-						RyanJsonCreateIntArray(arrayInt, sizeof(arrayInt) / sizeof(arrayInt[0])));
-		}
-		if (RyanJsonIsDouble(pJson))
-		{
-			RyanJsonAddDoubleToObject(pJson, key, RyanJsonGetDoubleValue(pJson));
-			double arrayDouble[] = {RyanJsonGetDoubleValue(pJson), RyanJsonGetDoubleValue(pJson), RyanJsonGetDoubleValue(pJson),
-						RyanJsonGetDoubleValue(pJson), RyanJsonGetDoubleValue(pJson)};
-			RyanJsonAddItemToObject(pJson, (size % 2) ? key : "arrayString",
-						RyanJsonCreateDoubleArray(arrayDouble, sizeof(arrayDouble) / sizeof(arrayDouble[0])));
-		}
-	}
-
-	if (RyanJsonIsString(pJson))
-	{
-		RyanJsonAddStringToObject(pJson, key, RyanJsonGetStringValue(pJson));
-		const char *arrayString[] = {RyanJsonGetStringValue(pJson), RyanJsonGetStringValue(pJson), RyanJsonGetStringValue(pJson),
-					     RyanJsonGetStringValue(pJson), RyanJsonGetStringValue(pJson)};
-		RyanJsonAddItemToObject(pJson, (size % 2) ? key : "arrayString",
-					RyanJsonCreateStringArray(arrayString, sizeof(arrayString) / sizeof(arrayString[0])));
-	}
-
-	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
-	{
-		RyanJson_t item;
-
-		RyanJsonObjectForEach(pJson, item) { RyanJsonFuzzerTestByForEachCreate(item, size); }
-
-		RyanJson_t pJson2 = RyanJsonFuzzerCreateRandomNode(pJson);
-		RyanJsonAddItemToObject(pJson, key, pJson2);
-
-		if (RyanJsonIsArray(pJson))
-		{
-			RyanJsonAddNullToArray(pJson);
-			RyanJsonAddBoolToArray(pJson, size % 2 ? RyanJsonTrue : RyanJsonFalse);
-			RyanJsonAddItemToArray(pJson, RyanJsonFuzzerCreateRandomNode(RyanJsonGetArrayValue(pJson)));
-		}
-	}
-
-	return RyanJsonTrue;
-}
-
-/**
- * @brief 测试 Json 的 Replace 功能(保护根节点)
- *
- * @param pJson 待测试的 Json 节点
- * @param size  用于计算 index 的模数
- * @param isFirst 是否为第一次调用(根节点)
- * @return RyanJsonBool_e
- */
-static RyanJsonBool_e RyanJsonFuzzerTestByForEachReplace(RyanJson_t pJson, uint32_t size)
-{
-	{
-		isEnableRandomMemFail = RyanJsonFalse;
-		RyanJson_t strItem = RyanJsonCreateString("", "NULL");
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, NULL, NULL));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(pJson, NULL, NULL));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, "NULL", NULL));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, NULL, strItem));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(pJson, "NULL", NULL));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, "NULL", strItem));
-		if (!RyanJsonIsObject(pJson)) // pJson类型错误
-		{
-			RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(pJson, "NULL", strItem));
-		}
-
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(NULL, 0, NULL));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(pJson, 0, NULL));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(NULL, 0, strItem));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(pJson, 0, NULL));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(NULL, 0, strItem));
-		if (!RyanJsonIsArray(pJson) && !RyanJsonIsObject(pJson)) // pJson类型错误
-		{
-			RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(pJson, 0, strItem));
-		}
-
-		RyanJson_t objItem = RyanJsonCreateObject();
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(objItem, "NULL", strItem));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(objItem, 0, strItem));
-
-		RyanJsonAddItemToObject(objItem, "item", RyanJsonCreateObject());
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(objItem, "NULL222", strItem));
-		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(objItem, INT32_MAX, strItem));
-		isEnableRandomMemFail = RyanJsonTrue;
-
-		RyanJsonDelete(objItem);
-		RyanJsonDelete(strItem);
-	}
-
-	// 只处理数组或对象
-	if (!(RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))) { return RyanJsonTrue; }
-
-	// 递归替换子节点
-	RyanJson_t item = NULL;
-	RyanJson_t LastItem = NULL;
-	RyanJsonObjectForEach(pJson, item)
-	{
-		if (RyanJsonTrue != RyanJsonFuzzerTestByForEachReplace(item, size)) { return RyanJsonFalse; }
-		LastItem = item;
-	}
-
-	// 只有非根节点才做替换
-
-	// 按 key 替换(仅对象)
-	// 不要动第一个节点
-	if (RyanJsonIsObject(pJson))
-	{
-		if (LastItem && RyanJsonIsKey(LastItem))
-		{
-			RyanJson_t newNode = RyanJsonFuzzerCreateRandomNode(pJson);
-			if (RyanJsonFalse == RyanJsonReplaceByKey(pJson, RyanJsonGetKey(LastItem), newNode))
-			{
-				if (newNode) { RyanJsonDelete(newNode); }
-				return RyanJsonFalse;
-			}
-		}
-	}
-
-	// 按 index 替换
-	{
-		uint32_t idx = RyanJsonGetSize(pJson) % size;
-		RyanJson_t newNode = RyanJsonFuzzerCreateRandomNode(pJson);
-		if (RyanJsonFalse == RyanJsonReplaceByIndex(pJson, (size % 25) ? idx : 0, newNode))
-		{
-			if (newNode) { RyanJsonDelete(newNode); }
-			return RyanJsonFalse;
-		}
-	}
-
-	return RyanJsonTrue;
-}
-
-/**
- * @brief 测试 Json 的 Detach 分离功能(保护根节点)
- *
- * @param pJson 待测试的 Json 节点
- * @param size  用于计算 index 的模数
- * @param isFirst 是否为第一次调用(根节点)
- * @return RyanJsonBool_e
- */
-static RyanJsonBool_e RyanJsonFuzzerTestByForEachDetach(RyanJson_t pJson, uint32_t size)
-{
-	RyanJsonAssert(RyanJsonFalse == RyanJsonDetachByKey(NULL, NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonDetachByKey(pJson, NULL));
-	RyanJsonAssert(RyanJsonFalse == RyanJsonDetachByKey(NULL, "NULL"));
-	if (!RyanJsonIsObject(pJson)) // pJson类型错误
-	{
-		RyanJsonAssert(NULL == RyanJsonDetachByKey(pJson, "NULL"));
-	}
-
-	RyanJsonAssert(NULL == RyanJsonDetachByIndex(NULL, 10));
-	if (!RyanJsonIsArray(pJson) && !RyanJsonIsObject(pJson)) // pJson类型错误
-	{
-		RyanJsonAssert(NULL == RyanJsonDetachByIndex(pJson, 0));
-	}
-
-	if (!(RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))) { return RyanJsonTrue; }
-
-	// 递归遍历子节点
-	RyanJson_t item = NULL;
-	RyanJson_t LastItem = NULL;
-	RyanJsonObjectForEach(pJson, item)
-	{
-		RyanJsonFuzzerTestByForEachDetach(item, size);
-		LastItem = item;
-	}
-
-	// 只有非根节点才做 detach
-
-	// 按 key 分离(仅对象)
-	if (RyanJsonIsObject(pJson))
-	{
-		if (LastItem && RyanJsonIsKey(LastItem))
-		{
-			RyanJson_t detached = RyanJsonDetachByKey(pJson, RyanJsonGetKey(LastItem));
-			if (detached) { RyanJsonDelete(detached); }
-
-			// RyanJsonAssert(RyanJsonFalse == RyanJsonDetachByKey(pJson, RyanJsonGetKey(LastItem)));
-		}
-	}
-
-	// 按 index 分离
-	{
-		uint32_t idx = RyanJsonGetSize(pJson) % size;
-		RyanJson_t detached = RyanJsonDetachByIndex(pJson, (size % 25) ? idx : 0);
-		if (detached) { RyanJsonDelete(detached); }
-	}
-
-	return RyanJsonTrue;
-}
-
-/**
- * @brief 测试 Json 的 Delete 功能(保护根节点)
- *
- * @param pJson 待测试的 Json 节点
- * @param size  用于计算 index 的模数
- * @param isFirst 是否为第一次调用(根节点)
- * @return RyanJsonBool_e
- */
-static RyanJsonBool_e RyanJsonFuzzerTestByForEachDelete(RyanJson_t pJson, uint32_t size)
-{
-	if (!(RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))) { return RyanJsonTrue; }
-
-	// -------- 测试错误的 delete 调用 --------
-	// Key 删除错误用例
-	RyanJsonDeleteByKey(pJson, "non_exist_key");
-	RyanJsonDeleteByKey(NULL, "some_key");
-	RyanJsonDeleteByKey(pJson, NULL);
-	RyanJsonDeleteByKey(NULL, NULL);
-
-	// Index 删除错误用例
-	RyanJsonDeleteByIndex(pJson, RyanJsonGetSize(pJson)); // 越界
-	RyanJsonDeleteByIndex(NULL, (RyanJsonGetSize(pJson) % size));
-	RyanJsonDeleteByIndex(pJson, -size); // 负数
-	RyanJsonDeleteByIndex(NULL, -size);
-
-	// 递归遍历子节点
-	RyanJson_t item = NULL;
-	RyanJson_t LastItem = NULL;
-	RyanJsonObjectForEach(pJson, item)
-	{
-		RyanJsonFuzzerTestByForEachDelete(item, size);
-		LastItem = item;
-	}
-
-	// -------- 正常删除逻辑(保护根节点) --------
-
-	// 按 key 删除(仅对象)
-	if (RyanJsonIsObject(pJson))
-	{
-		if (LastItem && RyanJsonIsKey(LastItem))
-		{
-
-			// printf("key is %d %s\r\n", RyanJsonGetType(LastItem),
-			//        RyanJsonGetKey(LastItem) == NULL ? "NULL" : RyanJsonGetKey(LastItem));
-			RyanJsonDeleteByKey(pJson, RyanJsonGetKey(LastItem));
-		}
-	}
-
-	// 按 index 删除
-	uint32_t idx = RyanJsonGetSize(pJson) % size;
-	RyanJsonDeleteByIndex(pJson, (size % 25) ? idx : 0);
-
-	return RyanJsonTrue;
-}
-
-static RyanJsonBool_e RyanJsonFuzzerTestByMinify(const char *data, uint32_t size)
-{
-	char *buf = (char *)malloc(size + 100);
-	memcpy(buf, data, size);
-	memset(buf + size, 0, 100);
-
-	uint32_t size2 = RyanJsonMinify(buf, (int32_t)size);
-	// 非法情况
-	{
-		RyanJsonCheckReturnFalse(0 == RyanJsonMinify(NULL, 0));
-		RyanJsonCheckReturnFalse(0 == RyanJsonMinify(NULL, 10));
-		RyanJsonCheckReturnFalse(0 == RyanJsonMinify(NULL, -10));
-		RyanJsonCheckReturnFalse(0 == RyanJsonMinify(buf, -10));
-	}
-
-	// 内存泄漏就是上面出错了
-	RyanJson_t pJson2 = RyanJsonParseOptions(buf, size2, size % 2 ? RyanJsonTrue : RyanJsonFalse, NULL);
-	free(buf);
-	if (NULL != pJson2)
-	{
-		uint32_t len = 0;
-		char *jsonStr = RyanJsonPrint(pJson2, 100, RyanJsonFalse, &len); // 以带格式方式将数据打印出来
-		RyanJsonCheckCode(NULL != jsonStr && len > 0, {
-			RyanJsonDelete(pJson2);
-			return RyanJsonFalse;
-		});
-		RyanJsonFree(jsonStr);
-		RyanJsonDelete(pJson2);
-	}
-	else
-	{
-		return RyanJsonFalse;
-	}
-
-	return RyanJsonTrue;
-}
-
-static void *RyanJsonFuzzerMalloc(size_t size)
-{
-	static int32_t count = 0;
-	count++;
-	if (RyanJsonTrue == isEnableRandomMemFail)
-	{
-		if (0 == count % 598) { return NULL; }
-	}
-	return (char *)v_malloc(size);
-}
-
-static void RyanJsonFuzzerFree(void *block) { v_free(block); }
-
-static void *RyanJsonFuzzerRealloc(void *block, size_t size)
-{
-	static int32_t count = 0;
-	count++;
-	if (RyanJsonTrue == isEnableRandomMemFail)
-	{
-		if (0 == count % 508) { return NULL; }
-	}
-	return (char *)v_realloc(block, size);
-}
+RyanJsonBool_e isEnableRandomMemFail = RyanJsonTrue;
 
 int LLVMFuzzerTestOneInput(const char *data, uint32_t size)
 {
@@ -743,13 +13,13 @@ int LLVMFuzzerTestOneInput(const char *data, uint32_t size)
 	RyanJsonInitHooks(RyanJsonFuzzerMalloc, RyanJsonFuzzerFree, NULL);
 	RyanJsonInitHooks(NULL, NULL, NULL);
 
-	RyanJsonInitHooks(RyanJsonFuzzerMalloc, RyanJsonFuzzerFree, size % 2 ? NULL : RyanJsonFuzzerRealloc);
+	RyanJsonInitHooks(RyanJsonFuzzerMalloc, RyanJsonFuzzerFree, 0 != size % 2 ? NULL : RyanJsonFuzzerRealloc);
 
 	RyanJsonAssert(NULL == RyanJsonParseOptions(NULL, 100, RyanJsonFalse, NULL));
 	RyanJsonAssert(NULL == RyanJsonParseOptions(data, 0, RyanJsonFalse, NULL));
 
 	const char *parseEndPtr = NULL;
-	RyanJson_t pJson = RyanJsonParseOptions(data, size, size % 3 ? RyanJsonTrue : RyanJsonFalse, &parseEndPtr);
+	RyanJson_t pJson = RyanJsonParseOptions(data, size, 0 != size % 3 ? RyanJsonTrue : RyanJsonFalse, &parseEndPtr);
 	if (NULL != pJson)
 	{
 		assert(NULL != parseEndPtr && parseEndPtr - data <= size);
@@ -758,7 +28,7 @@ int LLVMFuzzerTestOneInput(const char *data, uint32_t size)
 			isEnableRandomMemFail = RyanJsonFalse;
 			RyanJson_t pJson2 = RyanJsonDuplicate(pJson);
 			isEnableRandomMemFail = RyanJsonTrue;
-			RyanJsonCheckCode(RyanJsonFuzzerTestByForEachDelete(pJson2, size), {
+			RyanJsonCheckCode(RyanJsonFuzzerTestDelete(pJson2, size), {
 				RyanJsonDelete(pJson2);
 				goto exit__;
 			});
@@ -769,21 +39,21 @@ int LLVMFuzzerTestOneInput(const char *data, uint32_t size)
 			isEnableRandomMemFail = RyanJsonFalse;
 			RyanJson_t pJson2 = RyanJsonDuplicate(pJson);
 			isEnableRandomMemFail = RyanJsonTrue;
-			RyanJsonCheckCode(RyanJsonFuzzerTestByForEachDetach(pJson2, size), {
+			RyanJsonCheckCode(RyanJsonFuzzerTestDetach(pJson2, size), {
 				RyanJsonDelete(pJson2);
 				goto exit__;
 			});
 			RyanJsonDelete(pJson2);
 		}
 
-		RyanJsonFuzzerTestByMinify(data, size);
-		RyanJsonFuzzerTestByParseAndPrint(pJson, data, size);
-		RyanJsonFuzzerTestByForEachGet(pJson, size);
+		RyanJsonFuzzerTestMinify(data, size);
+		RyanJsonFuzzerTestParse(pJson, data, size);
+		RyanJsonFuzzerTestGet(pJson, size);
 
-		RyanJsonFuzzerTestByDup(pJson);
-		RyanJsonCheckCode(RyanJsonFuzzerTestByForEachChange(pJson, size), { goto exit__; });
-		RyanJsonCheckCode(RyanJsonFuzzerTestByForEachCreate(pJson, size), { goto exit__; });
-		RyanJsonCheckCode(RyanJsonFuzzerTestByForEachReplace(pJson, size), { goto exit__; });
+		RyanJsonFuzzerTestDuplicate(pJson);
+		RyanJsonCheckCode(RyanJsonFuzzerTestModify(pJson, size), { goto exit__; });
+		RyanJsonCheckCode(RyanJsonFuzzerTestCreate(pJson, size), { goto exit__; });
+		RyanJsonCheckCode(RyanJsonFuzzerTestReplace(pJson, size), { goto exit__; });
 
 		RyanJsonDelete(pJson);
 	}

+ 255 - 201
test/fuzzer/RyanJsonFuzzer.dict

@@ -1,258 +1,312 @@
-# 基本关键字
+# =====================================================
+# RyanJson Fuzzer Dictionary
+# 用于 libFuzzer 的 JSON 模糊测试字典
+# =====================================================
+
+# ===================
+# 基本 JSON 关键字
+# ===================
 "true"
 "false"
 "null"
 
-# 对象结构
+# ===================
+# JSON 结构符号
+# ===================
+# 对象
 "{"
 "}"
 ":"
 ","
 
-# 数组结构
+# 数组
 "["
 "]"
 
-# 常见字符串模式
+# 字符串
+"\""
+
+# ===================
+# 常见键名
+# ===================
 "\"key\""
 "\"value\""
 "\"name\""
 "\"id\""
-"\"string\""
-"\"number\""
-"\"message\""
 "\"data\""
 "\"status\""
 "\"error\""
-"""
-"\"name"
-"\\"
-
-# 数字边界
+"\"message\""
+"\"type\""
+"\"result\""
+"\"code\""
+"\"items\""
+"\"count\""
+"\"total\""
+"\"list\""
+
+# ===================
+# 整数值
+# ===================
 "0"
-"0000"
 "1"
 "-1"
-"1234567890"
+"123"
+"-123"
+"2147483647"
+"-2147483648"
+"9223372036854775807"
+"-9223372036854775808"
+"999999999999999999999999999"
+"-999999999999999999999999999"
+
+# ===================
+# 浮点数值
+# ===================
+"0.0"
+"0.1"
+"-0.1"
 "3.14159"
+"3.141592653589793"
+"1.7976931348623157e308"
+"-1.7976931348623157e308"
+"2.2250738585072014e-308"
 "1e10"
+"1e-10"
+"-1e10"
 "-1e-10"
-"-21474836470"
-"999999999999999999999999999"
-"-999999999999999999999999999"
-"-"
-"000-000"
-"-0045.12348"
+"1E10"
+"1E-10"
+"1e+10"
+"1.5e+9999"
+"1e9999"
+"-1e9999"
+"123e100000"
+"-123e100000"
+"123e-10000000"
+"123.456e-789"
+
+# ===================
+# 特殊浮点数边界
+# ===================
+"0.000001"
+"0.0000001"
+"999999.999999"
+"1000000.0"
+"0.123456789012345678901234567890"
+
+# ===================
+# 科学计数法错误
+# ===================
+"1e"
+"1e+"
+"1e-"
+"1eE"
+"1eAbc"
+".1e10"
+"1."
+"1.e10"
+"-.1"
+
+# ===================
+# 前导零错误
+# ===================
+"00"
+"01"
 "0123"
-"0123.123"
-
-# 嵌套结构
+"-00"
+"-01"
+"-0123"
+"00.123"
+
+# ===================
+# 简单结构
+# ===================
+"{}"
+"[]"
 "{\"a\":1}"
+"{\"a\":\"b\"}"
+"[1]"
 "[1,2,3]"
+"[true,false,null]"
+
+# ===================
+# 嵌套结构
+# ===================
 "{\"obj\":{\"nested\":true}}"
-"{\"arr\":[{\"x\":1},{\"y\":2}]}"
+"{\"arr\":[1,2,3]}"
+"[{\"id\":1},{\"id\":2}]"
 "{\"deep\":{\"nest\":{\"more\":{\"inner\":{\"flag\":true}}}}}"
-"[{\"id\":1,\"val\":true},{\"id\":2,\"val\":false}]"
-
-# 复杂对象
-"{\"inter\":16,\"double\":16.89,\"string\":\"hello\",\"boolTrue\":true,\"boolFalse\":false,\"null\":null}"
-"{\"items\":[{\"id\":1},{\"id\":2},{\"id\":3}]}"
-"{\"user\":{\"id\":123,\"name\":\"Alice\",\"roles\":[\"admin\",\"editor\"]}}"
-"{\"response\":{\"status\":200,\"data\":[{\"id\":1},{\"id\":2}]}}"
+"[[[[[[1]]]]]]"
+"{\"a\":{\"b\":{\"c\":{\"d\":{\"e\":null}}}}}"
+
+# ===================
+# 混合类型示例
+# ===================
+"{\"int\":16,\"double\":16.89,\"string\":\"hello\",\"bool\":true,\"null\":null}"
+"[16,16.89,\"hello\",true,false,null]"
+"{\"mixed\":[1,\"two\",true,null,{\"nested\":\"obj\"}]}"
+
+# ===================
+# 转义字符
+# ===================
+"\\n"
+"\\r"
+"\\t"
+"\\b"
+"\\f"
+"\\\""
+"\\\\"
+"\\/"
+"\\u0000"
+"\\u0020"
+"\\u00FF"
+"\\uFFFF"
+
+# ===================
+# Unicode 转义
+# ===================
+"\\u4F60\\u597D"
+"\\u4E16\\u754C"
+"\\uD83D\\uDE00"
+"\\uD83C\\uDF0D"
+
+# Unicode 代理对边界
+"\\uD800\\uDC00"
+"\\uDBFF\\uDFFF"
 
-# 边界结构
-# 键未加引号
+# 错误的 Unicode
+"\\uD800"
+"\\uDFFF"
+"\\uZZZZ"
+"\\u12"
+"\\u123"
+"\\uD800\\u0041"
+
+# ===================
+# 特殊字符串
+# ===================
+"{\"empty\":\"\"}"
+"{\"space\":\" \"}"
+"{\"tab\":\"\\t\"}"
+"{\"newline\":\"\\n\"}"
+"{\"unicode\":\"\\u4E2D\\u6587\"}"
+"{\"emoji\":\"\\uD83D\\uDE00\"}"
+
+# ===================
+# RESTful 风格响应
+# ===================
+"{\"status\":200,\"message\":\"OK\"}"
+"{\"status\":404,\"error\":\"Not Found\"}"
+"{\"status\":500,\"error\":\"Internal Server Error\"}"
+"{\"code\":0,\"data\":null}"
+"{\"success\":true,\"data\":[]}"
+"{\"success\":false,\"message\":\"Error\"}"
+
+# ===================
+# 分页响应
+# ===================
+"{\"page\":1,\"pageSize\":10,\"total\":100,\"data\":[]}"
+"{\"offset\":0,\"limit\":20,\"items\":[]}"
+
+# ===================
+# 重复键(测试处理)
+# ===================
+"{\"key\":1,\"key\":2}"
+"{\"a\":\"first\",\"a\":\"second\"}"
+"{\"dup\":true,\"dup\":false}"
+
+# ===================
+# 语法错误示例
+# ===================
+# 缺少引号
 "{a:1}"
+"{key:\"value\"}"
 
 # 缺少冒号
 "{\"a\" 1}"
 
 # 缺少逗号
 "{\"a\":1 \"b\":2}"
+"[1 2 3]"
 
 # 多余逗号
 "{\"a\":1,}"
-
-# 数组尾逗号
 "[1,2,3,]"
-
-# 空对象错误
 "{,}"
-
-# 空数组错误
 "[,]"
+"[1,,2]"
 
-# 未闭合字符串
-"{\"a\":\"value}"
-
-# 单引号字符串
-"{\"a\":'value'}"
-
-# 非法转义
-"{\"a\":\"\\q\"}"
+# 未闭合
+"{\"a\":1"
+"[1,2,3"
+"{\"str\":\"unclosed"
+"["
+"{"
 
-# 非法 Unicode 转义
-"{\"a\":\"\\uZZZZ\"}"
+# 单引号(非法)
+"{'a':'b'}"
 
-# 位数不足
-"{\"a\":\"\\u12\"}"
+# 注释(非法)
+"// comment"
+"/* block */"
+"{\"a\":1}// trailing"
 
+# ===================
 # 控制字符
-"{\"a\":\"\\x07\"}"
-
-# 小数点后无数字
-"1."
-
-# 科学计数法错误
-"1e"
-
-# 科学计数法错误
-"1e+"
-"1eEabc"
-"1eAebE"
-
-# 超大指数
-"1e9999"
+# ===================
+"\x00"
+"\x01"
+"\x1F"
+"\x7F"
+
+# ===================
+# 非法字节序列
+# ===================
+"\xC0\xAF"
+"\xFF\xFF"
+"\xFE\xFF"
+"\x80"
+"\xBF"
 
-# 拼写错误
+# ===================
+# 边缘 token
+# ===================
 "True"
 "False"
 "Null"
+"TRUE"
+"FALSE"
+"NULL"
 "tru"
+"fals"
 "nul"
 
-# 顶层错误
-"string"
-"123"
-"true"
-"null"
-
-# 注释错误:单行
-"// comment"
-"/* block comment */"
-
-# 非 UTF-8 字节流
-"\xC0\xAF"
-"\xFF\xFF"
-"\xFE\xFF"
-
-# 空结构
-"{}"
-"[]"
-
-# 特殊转义
-"\\n"
-"\\r"
-"\\t"
-"\\b"
-"\\f"
-"\\u0000"
-"\\uD800\\uDC00"
-"\\uDBFF\\uDFFF"
-"\\\""
-"\\\\"
-"/"
-
-# 一维对象,覆盖所有 JSON 类型
-"{\"string\":\"hello\",\"number\":123,\"boolean_true\":true,\"boolean_false\":false,\"null_value\":null,\"array\":[1,\"two\",false,null],\"object\":{\"nested_key\":\"nested_value\"}}"
-
-# 错误重复结构
-"[{\"error\":4,\"error\":\"45\"}]"
-"[{\"id\":1,\"id\":2}]"
-"[{\"name\":\"Alice\",\"name\":\"Bob\"}]"
-"[{\"value\":true,\"value\":false}]"
-"[{\"unicode\":\"\\u4F60\\u597D\",\"unicode\":\"\\u4E16\\u754C\"}]"
-"[{\"data\":[1,2,3],\"data\":{\"x\":1}}]"
-"[{\"nested\":{\"a\":1},\"nested\":{\"a\":2}}]"
-"[{\"error\":null,\"error\":999}]"
-"[{\"flag\":false,\"flag\":true}]"
-"[{\"number\":123,\"number\":\"123\"}]"
-"[{\"list\":[1,2],\"list\":[3,4]}]"
-
-# Unicode 示例(转义形式)
-"{\"unicode\":\"\\u4F60\\u597D\"}"
-"{\"unicode\":\"\\u4E16\\u754C\"}"
-"{\"unicode\":\"\\uD83C\\uDF0D\"}"
-"{\"unicode\":\"\\uD83D\\uDE00\"}"
-# 孤立高代理
-"{\"unicode\":\"\\uD800\"}" 
-# 孤立低代理         
-"{\"unicode\":\"\\uDFFF\"}"  
-# 超出最大码点        
-"{\"unicode\":\"\\u110000\"}" 
- # 非十六进制       
-"{\"unicode\":\"\\uZZZZ\"}"    
-# 位数不足     
-"{\"unicode\":\"\\u12\"}"     
-# 错误代理配对       
-"{\"unicode\":\"\\uD800\\u0041\"}"   
-
-# RESTful 风格常见响应
-"{\"status\":200,\"message\":\"OK\"}"
-"{\"status\":404,\"error\":\"Not Found\"}"
-"{\"status\":500,\"error\":\"Internal Server Error\"}"
-"{\"status\":401,\"error\":\"Unauthorized\"}"
-"{\"status\":403,\"error\":\"Forbidden\"}"
-
-# RESTful 数据响应
-"{\"status\":200,\"data\":{\"id\":1,\"name\":\"Alice\"}}"
-"{\"status\":200,\"data\":[{\"id\":1,\"name\":\"Alice\"},{\"id\":2,\"name\":\"Bob\"}]}"
-"{\"status\":200,\"data\":{\"items\":[{\"id\":1,\"value\":true},{\"id\":2,\"value\":false}]}}"
-
-# RESTful 分页响应
-"{\"status\":200,\"page\":1,\"pageSize\":10,\"total\":100,\"data\":[{\"id\":1},{\"id\":2}]}"
-"{\"status\":200,\"meta\":{\"page\":2,\"limit\":20},\"data\":[{\"id\":21},{\"id\":22}]}"
-
-# RESTful 错误响应
-"{\"error\":{\"code\":1234,\"message\":\"Invalid request\"}}"
-"{\"error\":{\"code\":5678,\"message\":\"Timeout\"}}"
-
-# RESTful 响应
-"{\"status\":200,\"user\":{\"id\":123,\"name\":\"Alice\",\"roles\":[\"admin\",\"editor\"]},\"token\":\"abcdef123456\"}"
-"{\"status\":200,\"config\":{\"theme\":\"dark\",\"language\":\"en\"},\"features\":[\"chat\",\"upload\",\"search\"]}"
-
-# 循环/深度嵌套场景
-"{\"a\":{\"b\":{\"c\":{\"d\":{\"e\":{\"f\":{\"g\":true}}}}}}}"
-"[[[[[[[[[[1]]]]]]]]]]"
-"{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}"
-"[{\"a\":[{\"b\":[{\"c\":[{\"d\":true}]}]}]}]"
-"{\"a\":[{\"b\":[{\"c\":[{\"d\":[{\"e\":false}]}]}]}]}"
-"{\"node\":{\"id\":1,\"child\":{\"id\":2,\"child\":{\"id\":3,\"child\":{\"id\":4}}}}}"
-"{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":{\"x\":null}}}}}}"
-"{\"status\":200,\"data\":{\"items\":[{\"id\":1,\"children\":[{\"id\":2,\"children\":[{\"id\":3}]}]}]}}"
-"{\"mixed\":[{\"obj\":{\"arr\":[{\"obj\":{\"arr\":[{\"obj\":{\"arr\":[true]}]}]}]}}]}"
-
-# 极端情况
-"{\"long\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}"
-"{\"big\":999999999999999999999999999}"
-"[[],[],[],[],[],[],[],[],[],[]]"
-"{\"nestedArray\":[[1,2],[3,4],[5,[6,[7,[8]]]]]}"
-"{\"escape\":\"line1\\nline2\\tTabbed\"}"
-"{\"mixed\":[16,16.89,\"hello\",true,false,null,{\"deep\":{}}]}"
-
-# 非法/边界片段(测试错误处理)
-",{}"
-":[]"
-"[[]]"
-",[]"
-":{}"
-"''"
-"\\x00"
-"\\0"
-
-"//"
-"/**/"
-
-"\x01\x00"
+# ===================
+# 极端嵌套
+# ===================
+"[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]"
+"{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{}}}}}}}}}}}"
+
+# ===================
+# 超长字符串
+# ===================
+"{\"long\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}"
+
+# ===================
+# 空白字符变体
+# ===================
+" { } "
+"\x09{\x09}\x09"
+"\x0a[\x0a]\x0a"
+"\x0d\x0a{\x0d\x0a}\x0d\x0a"
+"{ \"a\" : 1 }"
+"[  1  ,  2  ,  3  ]"
+
+# ===================
+# 二进制边界测试
+# ===================
 "\x00\x00\x00\x00"
-"\x00\x00\x00\x00\x00\x00\x00\x00"
-"\x00\x00\x00\x00\x00\x00\x00\x01"
-"\x01\x00\x00\x00\x00\x00\x00\x00"
-"\x10\x00\x00\x00\x00\x00\x00\x00"
-
-"\xff\xff"
-"\xfe\xff\xff\xee"
-"\xff\xff\xff\xff"
-"\xfe\xff\xff\xff\xff\xff\xff\xfa"
-"\xfb\xff\xff\xff\xff\xff\xff\xff"
-"\xff\xff\xff\xff\xff\xff\xff\xff"
+"\xFF\xFF\xFF\xFF"
+"\x01\x00\x00\x00"
+"\x00\x00\x00\x01"

+ 63 - 0
test/fuzzer/RyanJsonFuzzer.h

@@ -0,0 +1,63 @@
+#ifndef RyanJsonFuzzer_h
+#define RyanJsonFuzzer_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "RyanJsonTest.h"
+#include <signal.h>
+
+/**
+ * @brief 公共宏定义
+ */
+#define RyanJsonCheckGotoExit(EX)                                                                                                          \
+	RyanJsonCheckCode(EX, {                                                                                                            \
+		result = RyanJsonFalse;                                                                                                    \
+		goto exit__;                                                                                                               \
+	})
+
+/**
+ * @brief 全局变量声明
+ */
+extern RyanJsonBool_e isEnableRandomMemFail;
+
+/**
+ * @brief 内存钩子函数
+ */
+extern void *RyanJsonFuzzerMalloc(size_t size);
+extern void RyanJsonFuzzerFree(void *block);
+extern void *RyanJsonFuzzerRealloc(void *block, size_t size);
+
+/**
+ * @brief 解析打印测试函数
+ */
+extern RyanJsonBool_e RyanJsonFuzzerTestParse(RyanJson_t pJson, const char *data, uint32_t size);
+extern RyanJsonBool_e RyanJsonFuzzerTestMinify(const char *data, uint32_t size);
+
+/**
+ * @brief 复制比较测试函数
+ */
+extern RyanJsonBool_e RyanJsonFuzzerTestDuplicate(RyanJson_t pJson);
+
+/**
+ * @brief 修改操作测试函数
+ */
+extern RyanJsonBool_e RyanJsonFuzzerTestModify(RyanJson_t pJson, uint32_t size);
+extern RyanJsonBool_e RyanJsonFuzzerTestGet(RyanJson_t pJson, uint32_t size);
+extern RyanJsonBool_e RyanJsonFuzzerVerifyGet(RyanJson_t lastJson, RyanJson_t pJson, uint32_t index, uint32_t size);
+
+/**
+ * @brief 创建操作测试函数
+ */
+extern RyanJson_t RyanJsonFuzzerCreateRandomNode(RyanJson_t pJson);
+extern RyanJsonBool_e RyanJsonFuzzerTestCreate(RyanJson_t pJson, uint32_t size);
+extern RyanJsonBool_e RyanJsonFuzzerTestReplace(RyanJson_t pJson, uint32_t size);
+extern RyanJsonBool_e RyanJsonFuzzerTestDetach(RyanJson_t pJson, uint32_t size);
+extern RyanJsonBool_e RyanJsonFuzzerTestDelete(RyanJson_t pJson, uint32_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 307 - 0
test/fuzzer/RyanJsonFuzzerCreate.c

@@ -0,0 +1,307 @@
+#include "RyanJsonFuzzer.h"
+
+RyanJson_t RyanJsonFuzzerCreateRandomNode(RyanJson_t pJson)
+{
+	static int32_t count = 0;
+	static int32_t count2 = 0;
+	count++;
+	char *key = "true";
+	if (0 != count % 10 && 5 < count % 10) { key = NULL; }
+	switch (count % 50)
+	{
+	case 0: return RyanJsonCreateArray();
+	case 1: return RyanJsonCreateObject();
+	case 2:
+		count2++;
+		if (0 == count2 % 10) { return RyanJsonDuplicate(pJson); }
+		// fallthrough
+	case 11:
+	case 12:
+	case 13: return RyanJsonCreateBool(key, RyanJsonTrue);
+	case 20:
+	case 21:
+	case 22: return RyanJsonCreateInt(key, count);
+	case 31:
+	case 32:
+	case 33: return RyanJsonCreateDouble(key, count * 1.123456789);
+
+	default: return RyanJsonCreateString(key, "true");
+	}
+}
+
+RyanJsonBool_e RyanJsonFuzzerTestCreate(RyanJson_t pJson, uint32_t size)
+{
+	// RyanJsonInsert的特殊情况
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(NULL, UINT32_MAX, RyanJsonCreateString("key", "string")));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(pJson, UINT32_MAX, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(NULL, 0, NULL));
+
+	RyanJsonAssert(NULL == RyanJsonCreateString(NULL, NULL));
+	RyanJsonAssert(NULL == RyanJsonCreateString("NULL", NULL));
+
+	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeStringValue(NULL, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeStringValue(pJson, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeStringValue(NULL, "NULL"));
+	if (RyanJsonFalse == RyanJsonIsKey(pJson) && RyanJsonFalse == RyanJsonIsString(pJson)) // pJson类型错误
+	{
+		RyanJsonAssert(RyanJsonFalse == RyanJsonChangeStringValue(pJson, "NULL"));
+	}
+
+	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(NULL, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(pJson, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(NULL, "NULL"));
+	if (RyanJsonFalse == RyanJsonIsKey(pJson) && RyanJsonFalse == RyanJsonIsString(pJson)) // pJson类型错误
+	{
+		RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(pJson, "NULL"));
+	}
+
+	// 测试没有key但是有strValue的
+	if (RyanJsonFalse == RyanJsonIsKey(pJson) && RyanJsonTrue == RyanJsonIsString(pJson)) { RyanJsonAssert(RyanJsonFalse == RyanJsonChangeKey(pJson, "NULL")); }
+
+	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeIntValue(NULL, 0));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonChangeDoubleValue(NULL, 0));
+
+	RyanJsonAssert(RyanJsonFalse == RyanJsonAddItemToObject(NULL, NULL, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonAddItemToObject(pJson, NULL, NULL));
+
+	RyanJsonAssert(NULL == RyanJsonCreateIntArray(NULL, 0));
+	RyanJsonAssert(NULL == RyanJsonCreateDoubleArray(NULL, 0));
+	RyanJsonAssert(NULL == RyanJsonCreateStringArray(NULL, 0));
+
+	RyanJsonAssert(RyanJsonFalse == RyanJsonHasObjectToKey(NULL, "0", "1", "2", "3"));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonHasObjectToIndex(NULL, 0, 1, 2, 3));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonHasObjectToKey(pJson, "0", "1", "2", "3"));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonHasObjectToIndex(pJson, 0, 1, 2, 3));
+
+	char *key = "keyaaa";
+	RyanJsonAddNullToObject(pJson, key);
+	if (RyanJsonTrue == RyanJsonIsKey(pJson)) { key = RyanJsonGetKey(pJson); }
+	if (RyanJsonTrue == RyanJsonIsBool(pJson)) { RyanJsonAddBoolToObject(pJson, key, RyanJsonGetBoolValue(pJson)); }
+	if (RyanJsonTrue == RyanJsonIsNumber(pJson))
+	{
+		if (RyanJsonTrue == RyanJsonIsInt(pJson))
+		{
+			RyanJsonAddIntToObject(pJson, key, RyanJsonGetIntValue(pJson));
+			int32_t arrayInt[] = {RyanJsonGetIntValue(pJson), RyanJsonGetIntValue(pJson), RyanJsonGetIntValue(pJson),
+					  RyanJsonGetIntValue(pJson), RyanJsonGetIntValue(pJson)};
+			RyanJsonAddItemToObject(pJson, (0 != size % 2) ? key : "arrayString",
+						RyanJsonCreateIntArray(arrayInt, sizeof(arrayInt) / sizeof(arrayInt[0])));
+		}
+		if (RyanJsonTrue == RyanJsonIsDouble(pJson))
+		{
+			RyanJsonAddDoubleToObject(pJson, key, RyanJsonGetDoubleValue(pJson));
+			double arrayDouble[] = {RyanJsonGetDoubleValue(pJson), RyanJsonGetDoubleValue(pJson), RyanJsonGetDoubleValue(pJson),
+						RyanJsonGetDoubleValue(pJson), RyanJsonGetDoubleValue(pJson)};
+			RyanJsonAddItemToObject(pJson, (0 != size % 2) ? key : "arrayString",
+						RyanJsonCreateDoubleArray(arrayDouble, sizeof(arrayDouble) / sizeof(arrayDouble[0])));
+		}
+	}
+
+	if (RyanJsonTrue == RyanJsonIsString(pJson))
+	{
+		RyanJsonAddStringToObject(pJson, key, RyanJsonGetStringValue(pJson));
+		const char *arrayString[] = {RyanJsonGetStringValue(pJson), RyanJsonGetStringValue(pJson), RyanJsonGetStringValue(pJson),
+					     RyanJsonGetStringValue(pJson), RyanJsonGetStringValue(pJson)};
+		RyanJsonAddItemToObject(pJson, (0 != size % 2) ? key : "arrayString",
+					RyanJsonCreateStringArray(arrayString, sizeof(arrayString) / sizeof(arrayString[0])));
+	}
+
+	if (RyanJsonTrue == RyanJsonIsArray(pJson) || RyanJsonTrue == RyanJsonIsObject(pJson))
+	{
+		RyanJson_t item;
+
+		RyanJsonObjectForEach(pJson, item) { RyanJsonFuzzerTestCreate(item, size); }
+
+		RyanJson_t pJson2 = RyanJsonFuzzerCreateRandomNode(pJson);
+		RyanJsonAddItemToObject(pJson, key, pJson2);
+
+		if (RyanJsonTrue == RyanJsonIsArray(pJson))
+		{
+			RyanJsonAddNullToArray(pJson);
+			RyanJsonAddBoolToArray(pJson, 0 != size % 2 ? RyanJsonTrue : RyanJsonFalse);
+			RyanJsonAddItemToArray(pJson, RyanJsonFuzzerCreateRandomNode(RyanJsonGetArrayValue(pJson)));
+		}
+	}
+
+	return RyanJsonTrue;
+}
+
+RyanJsonBool_e RyanJsonFuzzerTestReplace(RyanJson_t pJson, uint32_t size)
+{
+	{
+		isEnableRandomMemFail = RyanJsonFalse;
+		RyanJson_t strItem = RyanJsonCreateString("", "NULL");
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, NULL, NULL));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(pJson, NULL, NULL));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, "NULL", NULL));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, NULL, strItem));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(pJson, "NULL", NULL));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(NULL, "NULL", strItem));
+		if (RyanJsonFalse == RyanJsonIsObject(pJson)) // pJson类型错误
+		{
+			RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(pJson, "NULL", strItem));
+		}
+
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(NULL, 0, NULL));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(pJson, 0, NULL));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(NULL, 0, strItem));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(pJson, 0, NULL));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(NULL, 0, strItem));
+		if (RyanJsonFalse == RyanJsonIsArray(pJson) && RyanJsonFalse == RyanJsonIsObject(pJson)) // pJson类型错误
+		{
+			RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(pJson, 0, strItem));
+		}
+
+		RyanJson_t objItem = RyanJsonCreateObject();
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(objItem, "NULL", strItem));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(objItem, 0, strItem));
+
+		RyanJsonAddItemToObject(objItem, "item", RyanJsonCreateObject());
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByKey(objItem, "NULL222", strItem));
+		RyanJsonAssert(RyanJsonFalse == RyanJsonReplaceByIndex(objItem, INT32_MAX, strItem));
+		isEnableRandomMemFail = RyanJsonTrue;
+
+		RyanJsonDelete(objItem);
+		RyanJsonDelete(strItem);
+	}
+
+	// 只处理数组或对象
+	if (RyanJsonFalse == RyanJsonIsArray(pJson) && RyanJsonFalse == RyanJsonIsObject(pJson)) { return RyanJsonTrue; }
+
+	// 递归替换子节点
+	RyanJson_t item = NULL;
+	RyanJson_t LastItem = NULL;
+	RyanJsonObjectForEach(pJson, item)
+	{
+		if (RyanJsonTrue != RyanJsonFuzzerTestReplace(item, size)) { return RyanJsonFalse; }
+		LastItem = item;
+	}
+
+	// 只有非根节点才做替换
+
+	// 按 key 替换(仅对象)
+	// 不要动第一个节点
+	if (RyanJsonTrue == RyanJsonIsObject(pJson))
+	{
+		if (NULL != LastItem && RyanJsonTrue == RyanJsonIsKey(LastItem))
+		{
+			RyanJson_t newNode = RyanJsonFuzzerCreateRandomNode(pJson);
+			if (RyanJsonFalse == RyanJsonReplaceByKey(pJson, RyanJsonGetKey(LastItem), newNode))
+			{
+				if (NULL != newNode) { RyanJsonDelete(newNode); }
+				return RyanJsonFalse;
+			}
+		}
+	}
+
+	// 按 index 替换
+	{
+		uint32_t idx = RyanJsonGetSize(pJson) % size;
+		RyanJson_t newNode = RyanJsonFuzzerCreateRandomNode(pJson);
+		if (RyanJsonFalse == RyanJsonReplaceByIndex(pJson, (0 != size % 25) ? idx : 0, newNode))
+		{
+			if (NULL != newNode) { RyanJsonDelete(newNode); }
+			return RyanJsonFalse;
+		}
+	}
+
+	return RyanJsonTrue;
+}
+
+RyanJsonBool_e RyanJsonFuzzerTestDetach(RyanJson_t pJson, uint32_t size)
+{
+	RyanJsonAssert(RyanJsonFalse == RyanJsonDetachByKey(NULL, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonDetachByKey(pJson, NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonDetachByKey(NULL, "NULL"));
+	if (RyanJsonFalse == RyanJsonIsObject(pJson)) // pJson类型错误
+	{
+		RyanJsonAssert(NULL == RyanJsonDetachByKey(pJson, "NULL"));
+	}
+
+	RyanJsonAssert(NULL == RyanJsonDetachByIndex(NULL, 10));
+	if (RyanJsonFalse == RyanJsonIsArray(pJson) && RyanJsonFalse == RyanJsonIsObject(pJson)) // pJson类型错误
+	{
+		RyanJsonAssert(NULL == RyanJsonDetachByIndex(pJson, 0));
+	}
+
+	if (RyanJsonFalse == RyanJsonIsArray(pJson) && RyanJsonFalse == RyanJsonIsObject(pJson)) { return RyanJsonTrue; }
+
+	// 递归遍历子节点
+	RyanJson_t item = NULL;
+	RyanJson_t LastItem = NULL;
+	RyanJsonObjectForEach(pJson, item)
+	{
+		RyanJsonFuzzerTestDetach(item, size);
+		LastItem = item;
+	}
+
+	// 只有非根节点才做 detach
+
+	// 按 key 分离(仅对象)
+	if (RyanJsonTrue == RyanJsonIsObject(pJson))
+	{
+		if (NULL != LastItem && RyanJsonTrue == RyanJsonIsKey(LastItem))
+		{
+			RyanJson_t detached = RyanJsonDetachByKey(pJson, RyanJsonGetKey(LastItem));
+			if (NULL != detached) { RyanJsonDelete(detached); }
+
+			// RyanJsonAssert(RyanJsonFalse == RyanJsonDetachByKey(pJson, RyanJsonGetKey(LastItem)));
+		}
+	}
+
+	// 按 index 分离
+	{
+		uint32_t idx = RyanJsonGetSize(pJson) % size;
+		RyanJson_t detached = RyanJsonDetachByIndex(pJson, (0 != size % 25) ? idx : 0);
+		if (NULL != detached) { RyanJsonDelete(detached); }
+	}
+
+	return RyanJsonTrue;
+}
+
+RyanJsonBool_e RyanJsonFuzzerTestDelete(RyanJson_t pJson, uint32_t size)
+{
+	if (RyanJsonFalse == RyanJsonIsArray(pJson) && RyanJsonFalse == RyanJsonIsObject(pJson)) { return RyanJsonTrue; }
+
+	// -------- 测试错误的 delete 调用 --------
+	// Key 删除错误用例
+	RyanJsonDeleteByKey(pJson, "non_exist_key");
+	RyanJsonDeleteByKey(NULL, "some_key");
+	RyanJsonDeleteByKey(pJson, NULL);
+	RyanJsonDeleteByKey(NULL, NULL);
+
+	// Index 删除错误用例
+	RyanJsonDeleteByIndex(pJson, RyanJsonGetSize(pJson)); // 越界
+	RyanJsonDeleteByIndex(NULL, (RyanJsonGetSize(pJson) % size));
+	RyanJsonDeleteByIndex(pJson, (uint32_t)(-(int32_t)size)); // 负数
+	RyanJsonDeleteByIndex(NULL, (uint32_t)(-(int32_t)size));
+
+	// 递归遍历子节点
+	RyanJson_t item = NULL;
+	RyanJson_t LastItem = NULL;
+	RyanJsonObjectForEach(pJson, item)
+	{
+		RyanJsonFuzzerTestDelete(item, size);
+		LastItem = item;
+	}
+
+	// -------- 正常删除逻辑(保护根节点) --------
+
+	// 按 key 删除(仅对象)
+	if (RyanJsonTrue == RyanJsonIsObject(pJson))
+	{
+		if (NULL != LastItem && RyanJsonTrue == RyanJsonIsKey(LastItem))
+		{
+
+			// printf("key is %d %s\r\n", RyanJsonGetType(LastItem),
+			//        RyanJsonGetKey(LastItem) == NULL ? "NULL" : RyanJsonGetKey(LastItem));
+			RyanJsonDeleteByKey(pJson, RyanJsonGetKey(LastItem));
+		}
+	}
+
+	// 按 index 删除
+	uint32_t idx = RyanJsonGetSize(pJson) % size;
+	RyanJsonDeleteByIndex(pJson, (0 != size % 25) ? idx : 0);
+
+	return RyanJsonTrue;
+}

+ 115 - 0
test/fuzzer/RyanJsonFuzzerDup.c

@@ -0,0 +1,115 @@
+#include "RyanJsonFuzzer.h"
+
+RyanJsonBool_e RyanJsonFuzzerTestDuplicate(RyanJson_t pJson)
+{
+	RyanJsonBool_e result = RyanJsonTrue;
+	char *jsonStr = NULL;
+	char *jsonStrDup = NULL;
+	RyanJson_t pJsonDup = NULL;
+
+	// 测试打印和复制功能
+	uint32_t len = 0;
+	uint32_t dupLen = 0;
+
+	jsonStr = RyanJsonPrint(pJson, 100, RyanJsonFalse, &len);
+	RyanJsonCheckGotoExit(NULL != jsonStr && len > 0);
+
+	pJsonDup = RyanJsonDuplicate(pJson);
+	RyanJsonCheckGotoExit(NULL != pJsonDup);
+
+	// 测试dup失败情况
+	RyanJsonCheckGotoExit(NULL == RyanJsonDuplicate(NULL));
+
+	// 判断复制json的size是否一致
+	RyanJsonCheckGotoExit(0 == RyanJsonGetSize(NULL));
+	RyanJsonCheckGotoExit(RyanJsonGetSize(pJson) == RyanJsonGetSize(pJsonDup));
+	RyanJsonCompare(pJson, pJsonDup);
+	RyanJsonCompareOnlyKey(pJson, pJsonDup);
+	// assert(RyanJsonTrue == RyanJsonCompare(pJson, pJsonDup)); // 大浮点数判断容易出错
+	// RyanJsonCheckGotoExit(RyanJsonTrue == RyanJsonCompareOnlyKey(pJson, pJsonDup)); // 重复key也会失败
+
+	// 测试compare特殊情况
+	RyanJsonCheckGotoExit(RyanJsonTrue == RyanJsonCompare(pJson, pJson));
+	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompare(NULL, pJsonDup));
+	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompare(pJson, NULL));
+	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompare(NULL, NULL));
+
+	// 测试compareKey特殊情况
+	RyanJsonCheckGotoExit(RyanJsonTrue == RyanJsonCompareOnlyKey(pJson, pJson));
+	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompareOnlyKey(NULL, pJsonDup));
+	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompareOnlyKey(pJson, NULL));
+	RyanJsonCheckGotoExit(RyanJsonFalse == RyanJsonCompareOnlyKey(NULL, NULL));
+
+	jsonStrDup = RyanJsonPrint(pJsonDup, 100, RyanJsonFalse, &dupLen); // 以带格式方式将数据打印出来
+	RyanJsonCheckGotoExit(NULL != jsonStrDup && dupLen > 0);
+
+	RyanJsonCheckCode(len == dupLen && 0 == memcmp(jsonStr, jsonStrDup, (size_t)len), {
+		printf("len:%" PRIu32 ", dupLen:%" PRIu32 "\r\n", len, dupLen);
+		printf("jsonStr:%s, jsonStrDup:%s\r\n", jsonStr, jsonStrDup);
+		RyanJsonCheckGotoExit(0);
+	});
+
+	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
+	{
+		// 测试size不相等
+		RyanJsonDelete(RyanJsonDetachByIndex(pJson, 0));
+		// 增加分支覆盖率
+		if (RyanJsonGetSize(pJson) > 2) { RyanJsonDelete(RyanJsonDetachByIndex(pJson, 1)); }
+
+		if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
+		{
+			// 改变key
+			RyanJson_t item;
+			RyanJsonObjectForEach(pJson, item)
+			{
+				if (RyanJsonIsKey(item))
+				{
+					RyanJsonChangeKey(item, "key12231123");
+					break;
+				}
+			}
+
+			// 改变value
+			RyanJsonObjectForEach(pJson, item)
+			{
+				if (RyanJsonIsBool(item))
+				{
+					RyanJsonChangeBoolValue(item, !RyanJsonGetBoolValue(item));
+					break;
+				}
+			}
+
+			// 改变obj的key
+			RyanJsonObjectForEach(pJson, item)
+			{
+				if (RyanJsonIsKey(item) && RyanJsonIsObject(item))
+				{
+					RyanJsonChangeKey(item, "key12231123");
+					break;
+				}
+			}
+		}
+
+		RyanJsonCompare(pJson, pJsonDup);
+		RyanJsonCompareOnlyKey(pJson, pJsonDup);
+	}
+exit__:
+
+	if (jsonStr)
+	{
+		RyanJsonFree(jsonStr);
+		jsonStr = NULL;
+	}
+	if (pJsonDup)
+	{
+		RyanJsonDelete(pJsonDup);
+		pJsonDup = NULL;
+	}
+	if (jsonStrDup)
+	{
+		RyanJsonFree(jsonStrDup);
+		jsonStrDup = NULL;
+	}
+
+	return result;
+}

+ 26 - 0
test/fuzzer/RyanJsonFuzzerMemory.c

@@ -0,0 +1,26 @@
+#include "RyanJsonFuzzer.h"
+
+static int32_t mallocCount = 0;
+static int32_t reallocCount = 0;
+
+void *RyanJsonFuzzerMalloc(size_t size)
+{
+	mallocCount++;
+	if (RyanJsonTrue == isEnableRandomMemFail)
+	{
+		if (0 == mallocCount % 598) { return NULL; }
+	}
+	return (char *)v_malloc(size);
+}
+
+void RyanJsonFuzzerFree(void *block) { v_free(block); }
+
+void *RyanJsonFuzzerRealloc(void *block, size_t size)
+{
+	reallocCount++;
+	if (RyanJsonTrue == isEnableRandomMemFail)
+	{
+		if (0 == reallocCount % 508) { return NULL; }
+	}
+	return (char *)v_realloc(block, size);
+}

+ 132 - 0
test/fuzzer/RyanJsonFuzzerModify.c

@@ -0,0 +1,132 @@
+#include "RyanJsonFuzzer.h"
+
+RyanJsonBool_e RyanJsonFuzzerTestModify(RyanJson_t pJson, uint32_t size)
+{
+	RyanJsonIsNull(pJson);
+
+	if (RyanJsonIsKey(pJson))
+	{
+		char *key = (char *)malloc(strlen(RyanJsonGetKey(pJson)) + 1);
+		if (key)
+		{
+			memcpy(key, RyanJsonGetKey(pJson), strlen(RyanJsonGetKey(pJson)));
+			key[strlen(RyanJsonGetKey(pJson))] = 0;
+
+			RyanJsonChangeKey(pJson, "key");
+			RyanJsonChangeKey(pJson, key);
+			free(key);
+		}
+	}
+	if (RyanJsonIsBool(pJson)) { RyanJsonChangeBoolValue(pJson, !RyanJsonGetBoolValue(pJson)); }
+	if (RyanJsonIsNumber(pJson))
+	{
+		if (RyanJsonIsInt(pJson))
+		{
+			int32_t value = RyanJsonGetIntValue(pJson);
+			RyanJsonChangeIntValue(pJson, (int32_t)size);
+			RyanJsonChangeIntValue(pJson, value);
+		}
+		if (RyanJsonIsDouble(pJson))
+		{
+			double value = RyanJsonGetDoubleValue(pJson);
+			RyanJsonChangeDoubleValue(pJson, size * 1.123456789);
+			RyanJsonChangeDoubleValue(pJson, value);
+		}
+	}
+
+	if (RyanJsonIsString(pJson))
+	{
+		char *value = (char *)malloc(strlen(RyanJsonGetStringValue(pJson)) + 1);
+		if (value)
+		{
+			memcpy(value, RyanJsonGetStringValue(pJson), strlen(RyanJsonGetStringValue(pJson)));
+			value[strlen(RyanJsonGetStringValue(pJson))] = 0;
+
+			RyanJsonChangeStringValue(pJson, "hello world");
+			RyanJsonChangeStringValue(pJson, "h");
+			RyanJsonChangeStringValue(pJson, value);
+
+			free(value);
+		}
+	}
+
+	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
+	{
+		RyanJson_t item;
+		RyanJsonArrayForEach(pJson, item)
+		{
+			RyanJsonCheckReturnFalse(RyanJsonTrue == RyanJsonFuzzerTestModify(item, size));
+		}
+	}
+
+	return RyanJsonTrue;
+}
+
+RyanJsonBool_e RyanJsonFuzzerVerifyGet(RyanJson_t lastJson, RyanJson_t pJson, uint32_t index, uint32_t size)
+{
+	RyanJsonIsNull(pJson);
+
+	RyanJsonAssert(NULL == RyanJsonGetKey(NULL));
+	RyanJsonAssert(NULL == RyanJsonGetStringValue(NULL));
+	RyanJsonAssert(0 == RyanJsonGetIntValue(NULL));
+	RyanJsonAssert(RyanJsonTrue == RyanJsonCompareDouble(RyanJsonGetDoubleValue(NULL), 0.0));
+	RyanJsonAssert(NULL == RyanJsonGetObjectValue(NULL));
+	RyanJsonAssert(NULL == RyanJsonGetArrayValue(NULL));
+
+	RyanJsonAssert(NULL == RyanJsonGetObjectByKey(NULL, NULL));
+	RyanJsonAssert(NULL == RyanJsonGetObjectByKey(pJson, NULL));
+	RyanJsonAssert(NULL == RyanJsonGetObjectByKey(NULL, "NULL"));
+
+	RyanJsonAssert(NULL == RyanJsonGetObjectByKeys(NULL, NULL));
+	RyanJsonAssert(NULL == RyanJsonGetObjectByKeys(pJson, NULL));
+	RyanJsonAssert(NULL == RyanJsonGetObjectByKeys(NULL, "NULL"));
+	if (!RyanJsonIsObject(pJson)) // pJson类型错误
+	{
+		RyanJsonAssert(NULL == RyanJsonGetObjectByKey(pJson, "NULL"));
+	}
+
+	RyanJsonAssert(NULL == RyanJsonGetObjectByIndex(NULL, 10));
+	if (!RyanJsonIsArray(pJson) && !RyanJsonIsObject(pJson)) // pJson类型错误
+	{
+		RyanJsonAssert(NULL == RyanJsonGetObjectByIndex(pJson, 0));
+	}
+
+	if (RyanJsonIsKey(pJson)) { RyanJsonGetObjectToKey(lastJson, RyanJsonGetKey(pJson)); }
+	else
+	{
+		RyanJsonGetObjectToIndex(lastJson, index);
+	}
+
+	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
+	{
+		RyanJson_t item;
+		RyanJsonObjectForEach(pJson, item) { RyanJsonFuzzerVerifyGet(pJson, item, index, size); }
+	}
+
+	return RyanJsonTrue;
+}
+
+RyanJsonBool_e RyanJsonFuzzerTestGet(RyanJson_t pJson, uint32_t size)
+{
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsKey(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsNull(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsBool(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsNumber(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsString(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsArray(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsObject(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsInt(NULL));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonIsDouble(NULL));
+
+	if (RyanJsonIsArray(pJson) || RyanJsonIsObject(pJson))
+	{
+		RyanJson_t item;
+		uint32_t index = 0;
+		RyanJsonObjectForEach(pJson, item)
+		{
+			RyanJsonFuzzerVerifyGet(pJson, item, index, size);
+			index++;
+		}
+	}
+	return RyanJsonTrue;
+}

+ 126 - 0
test/fuzzer/RyanJsonFuzzerParse.c

@@ -0,0 +1,126 @@
+#include "RyanJsonFuzzer.h"
+
+RyanJsonBool_e RyanJsonFuzzerTestParse(RyanJson_t pJson, const char *data, uint32_t size)
+{
+	isEnableRandomMemFail = RyanJsonFalse;
+	RyanJson_t testItem = RyanJsonCreateObject();
+	RyanJson_t testItem2 = RyanJsonCreateObject();
+	RyanJsonSetType(testItem, 0);
+	RyanJsonSetType(testItem2, 0);
+	RyanJsonAssert(NULL == RyanJsonPrint(testItem, 100, RyanJsonFalse, NULL));
+	RyanJsonAssert(NULL == RyanJsonDuplicate(testItem));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonCompare(testItem, testItem2));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonCompareOnlyKey(testItem, testItem2));
+
+	// 测试pJson类型错误情况
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(testItem, 0, RyanJsonCreateString("key", "true")));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(testItem2, UINT32_MAX, RyanJsonCreateString("key", "true")));
+
+	RyanJsonSetType(testItem, RyanJsonTypeObject);
+	RyanJsonSetType(testItem2, RyanJsonTypeObject);
+
+	// 测试pJson为obj,但是item没有key的情况
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(pJson, 0, RyanJsonCreateString(NULL, "true")));
+	RyanJsonAssert(RyanJsonFalse == RyanJsonInsert(pJson, UINT32_MAX, RyanJsonCreateString(NULL, "true")));
+
+	RyanJsonAssert(RyanJsonTrue == RyanJsonInsert(pJson, 0, RyanJsonCreateString("key", "true")));
+	RyanJsonDelete(testItem);
+	RyanJsonDelete(testItem2);
+	isEnableRandomMemFail = RyanJsonTrue;
+
+	RyanJsonAssert(NULL == RyanJsonPrint(NULL, 100, RyanJsonFalse, NULL));
+	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(NULL, NULL, 100, RyanJsonFalse, NULL));
+	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(pJson, NULL, 100, RyanJsonFalse, NULL));
+	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(NULL, (char *)data, 100, RyanJsonFalse, NULL));
+	RyanJsonAssert(NULL == RyanJsonPrintPreallocated(pJson, (char *)data, 0, RyanJsonFalse, NULL));
+
+	uint32_t len = 0;
+	char *jsonStr = RyanJsonPrint(pJson, size % 5 ? 100 : 0, size % 2 ? RyanJsonFalse : RyanJsonTrue, &len);
+	RyanJsonCheckReturnFalse(NULL != jsonStr && len > 0);
+
+	char *jsonStrCopy = RyanJsonPrint(pJson, size % 5 ? 100 : 0, size % 2 ? RyanJsonFalse : RyanJsonTrue, NULL); // 不传递len
+	RyanJsonAssert(0 == strncmp(jsonStr, jsonStrCopy, len));
+	RyanJsonFree(jsonStr);
+	RyanJsonFree(jsonStrCopy);
+
+	uint32_t bufLen = len * 3;
+	if (bufLen < size * 2) { bufLen = size * 2; }
+	if (bufLen < 2048) { bufLen = 2048; }
+	char *buf = (char *)malloc((size_t)bufLen);
+	{
+		uint32_t len2 = 0;
+		char *jsonStr2 = RyanJsonPrintPreallocated(pJson, buf, bufLen, size % 2 ? RyanJsonFalse : RyanJsonTrue, &len2);
+		// printf("len: %d, len2: %d, str: %s\r\n", len, len2, NULL == jsonStr2 ? "NULL" : jsonStr2);
+		RyanJsonCheckCode(NULL != jsonStr2 && len == len2, {
+			free(buf);
+			return RyanJsonFalse;
+		});
+	}
+
+	memcpy(buf, data, (size_t)size);
+	buf[size] = 0;
+	RyanJson_t jsonRoot = RyanJsonParse(buf);
+	RyanJsonCheckCode(NULL != jsonRoot, {
+		free(buf);
+		return RyanJsonFalse;
+	});
+
+	// 测试多次打印结果是否一致
+	{
+		uint32_t len3 = 0;
+		char *jsonStr3 = RyanJsonPrint(jsonRoot, 100, size % 2 ? RyanJsonFalse : RyanJsonTrue, &len3); // 以带格式方式将数据打印出来
+		RyanJsonCheckCode(NULL != jsonStr3 && len == len3, {
+			free(buf);
+			if (jsonStr3) { RyanJsonFree(jsonStr3); }
+			RyanJsonDelete(jsonRoot);
+			return RyanJsonFalse;
+		});
+
+		RyanJsonFree(jsonStr3);
+	}
+
+	{
+		RyanJsonPrintPreallocated(jsonRoot, buf, bufLen / 15, RyanJsonTrue, NULL);
+	}
+
+	free(buf);
+	RyanJsonDelete(jsonRoot);
+	return RyanJsonTrue;
+}
+
+RyanJsonBool_e RyanJsonFuzzerTestMinify(const char *data, uint32_t size)
+{
+	char *buf = (char *)malloc(size + 100);
+	memcpy(buf, data, size);
+	memset(buf + size, 0, 100);
+
+	uint32_t size2 = RyanJsonMinify(buf, (int32_t)size);
+	// 非法情况
+	{
+		RyanJsonCheckReturnFalse(0 == RyanJsonMinify(NULL, 0));
+		RyanJsonCheckReturnFalse(0 == RyanJsonMinify(NULL, 10));
+		RyanJsonCheckReturnFalse(0 == RyanJsonMinify(NULL, -10));
+		RyanJsonCheckReturnFalse(0 == RyanJsonMinify(buf, -10));
+	}
+
+	// 内存泄漏就是上面出错了
+	RyanJson_t pJson2 = RyanJsonParseOptions(buf, size2, size % 2 ? RyanJsonTrue : RyanJsonFalse, NULL);
+	free(buf);
+	if (NULL != pJson2)
+	{
+		uint32_t len = 0;
+		char *jsonStr = RyanJsonPrint(pJson2, 100, RyanJsonFalse, &len); // 以带格式方式将数据打印出来
+		RyanJsonCheckCode(NULL != jsonStr && len > 0, {
+			RyanJsonDelete(pJson2);
+			return RyanJsonFalse;
+		});
+		RyanJsonFree(jsonStr);
+		RyanJsonDelete(pJson2);
+	}
+	else
+	{
+		return RyanJsonFalse;
+	}
+
+	return RyanJsonTrue;
+}