| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748 |
- #include "testBase.h"
- #define expectCreateNullUnderOom(failAfter, expr, msg) \
- do \
- { \
- UNITY_TEST_OOM_BEGIN((failAfter)); \
- RyanJson_t _node = (expr); \
- UNITY_TEST_OOM_END(); \
- if (_node) { RyanJsonDelete(_node); } \
- TEST_ASSERT_NULL_MESSAGE(_node, (msg)); \
- } while (0)
- static char *allocPatternString(uint32_t len, char ch)
- {
- char *buf = (char *)malloc(len + 1U);
- if (NULL == buf) { return NULL; }
- for (uint32_t i = 0; i < len; i++)
- {
- buf[i] = ch;
- }
- buf[len] = '\0';
- return buf;
- }
- static void testCreateEdgeCases(void)
- {
- // 测试创建空 Array
- RyanJson_t emptyArr = RyanJsonCreateArray();
- TEST_ASSERT_NOT_NULL(emptyArr);
- TEST_ASSERT_EQUAL_INT(0, RyanJsonGetArraySize(emptyArr));
- RyanJsonDelete(emptyArr);
- // 测试通过辅助函数创建空 Array
- // RyanJsonCreateIntArray 传入 NULL 指针和 0 长度
- RyanJson_t nullIntArr = RyanJsonCreateIntArray(NULL, 0);
- // 该场景属于边界输入:只要不崩溃且行为可预测即可。
- // 若实现返回空 Array,则继续校验 size;
- // 若实现返回 NULL,也视为可接受行为。
- if (nullIntArr)
- {
- TEST_ASSERT_EQUAL_INT(0, RyanJsonGetArraySize(nullIntArr));
- RyanJsonDelete(nullIntArr);
- }
- }
- static void testCreatePropertyCheck(void)
- {
- // 验证创建后的节点属性
- RyanJson_t node = RyanJsonCreateInt("age", 25);
- TEST_ASSERT_NOT_NULL(node);
- TEST_ASSERT_EQUAL_STRING("age", RyanJsonGetKey(node));
- TEST_ASSERT_TRUE(RyanJsonIsInt(node));
- TEST_ASSERT_EQUAL_INT(25, RyanJsonGetIntValue(node));
- RyanJsonDelete(node);
- node = RyanJsonCreateDouble("pi", 3.14159);
- TEST_ASSERT_NOT_NULL(node);
- TEST_ASSERT_TRUE(RyanJsonIsDouble(node));
- TEST_ASSERT_TRUE(RyanJsonCompareDouble(3.14159, RyanJsonGetDoubleValue(node)));
- RyanJsonDelete(node);
- node = RyanJsonCreateBool("active", RyanJsonTrue);
- TEST_ASSERT_NOT_NULL(node);
- TEST_ASSERT_TRUE(RyanJsonIsBool(node));
- TEST_ASSERT_EQUAL_INT(RyanJsonTrue, RyanJsonGetBoolValue(node));
- RyanJsonDelete(node);
- }
- static void testAddBoundary(void)
- {
- RyanJson_t obj = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL(obj);
- // INT32 边界
- RyanJsonAddIntToObject(obj, "max", INT32_MAX);
- RyanJsonAddIntToObject(obj, "min", INT32_MIN);
- TEST_ASSERT_EQUAL_INT(INT32_MAX, RyanJsonGetIntValue(RyanJsonGetObjectToKey(obj, "max")));
- TEST_ASSERT_EQUAL_INT(INT32_MIN, RyanJsonGetIntValue(RyanJsonGetObjectToKey(obj, "min")));
- // Double 边界(仅做数值路径校验,不做位级比较)
- RyanJsonAddDoubleToObject(obj, "very_small", 1e-100);
- RyanJsonAddDoubleToObject(obj, "very_big", 1e+100);
- TEST_ASSERT_TRUE(RyanJsonIsDouble(RyanJsonGetObjectToKey(obj, "very_small")));
- TEST_ASSERT_TRUE(RyanJsonIsDouble(RyanJsonGetObjectToKey(obj, "very_big")));
- // 空 key 添加测试
- RyanJsonAddBoolToObject(obj, "", RyanJsonTrue);
- TEST_ASSERT_TRUE(RyanJsonGetBoolValue(RyanJsonGetObjectToKey(obj, "")));
- RyanJsonDelete(obj);
- }
- static void testCreateStandardComplexHierarchy(void)
- {
- RyanJson_t jsonRoot, item;
- // Object 生成测试
- jsonRoot = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL_MESSAGE(jsonRoot, "创建 Object 失败");
- RyanJsonAddIntToObject(jsonRoot, "inter", 16);
- RyanJsonAddDoubleToObject(jsonRoot, "double", 16.89);
- RyanJsonAddStringToObject(jsonRoot, "string", "hello");
- RyanJsonAddBoolToObject(jsonRoot, "boolTrue", RyanJsonTrue);
- RyanJsonAddBoolToObject(jsonRoot, "boolFalse", RyanJsonFalse);
- RyanJsonAddNullToObject(jsonRoot, "null");
- /**
- * @brief Object 添加测试
- *
- */
- item = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL_MESSAGE(item, "创建子 Object 失败");
- RyanJsonAddIntToObject(item, "inter", 16);
- RyanJsonAddDoubleToObject(item, "double", 16.89);
- RyanJsonAddStringToObject(item, "string", "hello");
- RyanJsonAddBoolToObject(item, "boolTrue", RyanJsonTrue);
- RyanJsonAddBoolToObject(item, "boolFalse", RyanJsonFalse);
- RyanJsonAddNullToObject(item, "null");
- RyanJsonAddItemToObject(jsonRoot, "item", item);
- /**
- * @brief Array 添加测试
- *
- */
- int32_t arrayInt[] = {16, 16, 16, 16, 16};
- RyanJsonAddItemToObject(jsonRoot, "arrayInt", RyanJsonCreateIntArray(arrayInt, sizeof(arrayInt) / sizeof(arrayInt[0])));
- double arrayDouble[] = {16.89, 16.89, 16.89, 16.89, 16.89};
- RyanJsonAddItemToObject(jsonRoot, "arrayDouble",
- RyanJsonCreateDoubleArray(arrayDouble, sizeof(arrayDouble) / sizeof(arrayDouble[0])));
- const char *arrayString[] = {"hello", "hello", "hello", "hello", "hello"};
- RyanJsonAddItemToObject(jsonRoot, "arrayString",
- RyanJsonCreateStringArray(arrayString, sizeof(arrayString) / sizeof(arrayString[0])));
- RyanJson_t array = RyanJsonCreateArray();
- TEST_ASSERT_NOT_NULL_MESSAGE(array, "创建 Array 失败");
- RyanJsonAddIntToArray(array, 16);
- RyanJsonAddDoubleToArray(array, 16.89);
- RyanJsonAddStringToArray(array, "hello");
- RyanJsonAddBoolToArray(array, RyanJsonTrue);
- RyanJsonAddBoolToArray(array, RyanJsonFalse);
- RyanJsonAddNullToArray(array);
- RyanJsonAddItemToObject(jsonRoot, "array", array);
- /**
- * @brief Object Array 测试
- *
- */
- RyanJson_t arrayItem = RyanJsonCreateArray();
- TEST_ASSERT_NOT_NULL_MESSAGE(arrayItem, "创建 ObjectArray 失败");
- item = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL_MESSAGE(item, "创建 ObjectArray 项 1 失败");
- RyanJsonAddIntToObject(item, "inter", 16);
- RyanJsonAddDoubleToObject(item, "double", 16.89);
- RyanJsonAddStringToObject(item, "string", "hello");
- RyanJsonAddBoolToObject(item, "boolTrue", RyanJsonTrue);
- RyanJsonAddBoolToObject(item, "boolFalse", RyanJsonFalse);
- RyanJsonAddNullToObject(item, "null");
- RyanJsonAddItemToArray(arrayItem, item);
- item = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL_MESSAGE(item, "创建 ObjectArray 项 2 失败");
- RyanJsonAddIntToObject(item, "inter", 16);
- RyanJsonAddDoubleToObject(item, "double", 16.89);
- RyanJsonAddStringToObject(item, "string", "hello");
- RyanJsonAddBoolToObject(item, "boolTrue", RyanJsonTrue);
- RyanJsonAddBoolToObject(item, "boolFalse", RyanJsonFalse);
- RyanJsonAddNullToObject(item, "null");
- RyanJsonAddItemToArray(arrayItem, item);
- RyanJsonAddItemToObject(jsonRoot, "arrayItem", arrayItem);
- // 最终验证根 Object 结构
- #if true == RyanJsonDefaultAddAtHead
- testCheckRootEx(jsonRoot, RyanJsonTrue);
- #else
- testCheckRootEx(jsonRoot, RyanJsonFalse);
- #endif
- RyanJsonDelete(jsonRoot);
- }
- static void testCreateHugeString(void)
- {
- // 极限大 String 创建(模拟大 Object;为控制测试耗时,先用 10KB 堆内存)
- uint32_t len = 1024 * 10;
- char *hugeStr = (char *)malloc(len + 1);
- TEST_ASSERT_NOT_NULL(hugeStr);
- memset(hugeStr, 'A', len);
- hugeStr[len] = '\0';
- RyanJson_t strJson = RyanJsonCreateString("huge", hugeStr);
- TEST_ASSERT_NOT_NULL(strJson);
- TEST_ASSERT_EQUAL_STRING(hugeStr, RyanJsonGetStringValue(strJson));
- RyanJsonDelete(strJson);
- free(hugeStr);
- // 特殊 Key 创建
- RyanJson_t nullKeyJson = RyanJsonCreateInt(NULL, 123);
- TEST_ASSERT_NOT_NULL(nullKeyJson); // 允许 NULL key(常见于 Array item)
- // 无 key 节点下,RyanJsonGetKey 可能返回值区指针。
- // 因此这里用 RyanJsonIsKey 作为权威判定。
- TEST_ASSERT_FALSE(RyanJsonIsKey(nullKeyJson));
- RyanJsonDelete(nullKeyJson);
- }
- static void testCreateOom(void)
- {
- UNITY_TEST_OOM_BEGIN(0);
- RyanJson_t obj = RyanJsonCreateObject();
- UNITY_TEST_OOM_END();
- if (obj) { RyanJsonDelete(obj); }
- TEST_ASSERT_NULL_MESSAGE(obj, "CreateObject OOM 应返回 NULL");
- }
- static void testCreateArgumentGuards(void)
- {
- TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateString("k", NULL), "CreateString(NULL value) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateIntArray(NULL, 1), "CreateIntArray(NULL,1) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateDoubleArray(NULL, 1), "CreateDoubleArray(NULL,1) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonCreateStringArray(NULL, 1), "CreateStringArray(NULL,1) 应返回 NULL");
- }
- static void testCreateTypedArrayZeroCount(void)
- {
- int32_t intOne[1] = {1};
- double doubleOne[1] = {1.5};
- const char *strOne[1] = {"x"};
- RyanJson_t intArr = RyanJsonCreateIntArray(intOne, 0);
- RyanJson_t doubleArr = RyanJsonCreateDoubleArray(doubleOne, 0);
- RyanJson_t stringArr = RyanJsonCreateStringArray(strOne, 0);
- TEST_ASSERT_NOT_NULL(intArr);
- TEST_ASSERT_NOT_NULL(doubleArr);
- TEST_ASSERT_NOT_NULL(stringArr);
- TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(intArr));
- TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(doubleArr));
- TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(stringArr));
- RyanJsonDelete(stringArr);
- RyanJsonDelete(doubleArr);
- RyanJsonDelete(intArr);
- }
- static void testCreateTypedArrayOomPaths(void)
- {
- int32_t ints[2] = {1, 2};
- double doubles[2] = {1.1, 2.2};
- const char *strs[2] = {"a", "b"};
- expectCreateNullUnderOom(1, RyanJsonCreateIntArray(ints, 2), "CreateIntArray OOM 路径应返回 NULL");
- expectCreateNullUnderOom(1, RyanJsonCreateDoubleArray(doubles, 2), "CreateDoubleArray OOM 路径应返回 NULL");
- expectCreateNullUnderOom(1, RyanJsonCreateStringArray(strs, 2), "CreateStringArray OOM 路径应返回 NULL");
- }
- static void testCreateScalarOom(void)
- {
- expectCreateNullUnderOom(0, RyanJsonCreateInt(NULL, 1), "CreateInt OOM 应返回 NULL");
- expectCreateNullUnderOom(0, RyanJsonCreateDouble(NULL, 1.5), "CreateDouble OOM 应返回 NULL");
- }
- static void testInsertOutOfRangeAndKeyValidation(void)
- {
- // Array:index 超出范围应追加到尾部
- RyanJson_t arr = RyanJsonCreateArray();
- TEST_ASSERT_NOT_NULL(arr);
- RyanJsonAddIntToArray(arr, 1);
- RyanJsonAddIntToArray(arr, 2);
- TEST_ASSERT_TRUE(RyanJsonInsert(arr, 100, RyanJsonCreateInt(NULL, 3)));
- TEST_ASSERT_EQUAL_INT(3, RyanJsonGetSize(arr));
- TEST_ASSERT_EQUAL_INT(3, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr, 2)));
- RyanJsonDelete(arr);
- // Object:item 无 key 应失败
- RyanJson_t obj = RyanJsonCreateObject();
- RyanJsonAddIntToObject(obj, "a", 1);
- RyanJson_t noKey = RyanJsonCreateInt(NULL, 2);
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonInsert(obj, 0, noKey), "Object 插入无 key item 应失败");
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(obj));
- // Object:重复 key 应失败
- #if true == RyanJsonStrictObjectKeyCheck
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonInsert(obj, 0, RyanJsonCreateInt("a", 2)), "严格模式下 Object 插入重复 key 应失败");
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddIntToObject(obj, "a", 3), "严格模式下 AddIntToObject 重复 key 应失败");
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(obj));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "a")));
- #else
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(obj, 0, RyanJsonCreateInt("a", 2)), "非严格模式下 Object 插入重复 key 应成功");
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddIntToObject(obj, "a", 3), "非严格模式下 AddIntToObject 重复 key 应成功");
- TEST_ASSERT_EQUAL_INT(3, RyanJsonGetSize(obj));
- #if true == RyanJsonDefaultAddAtHead
- TEST_ASSERT_EQUAL_INT(3, RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "a")));
- #else
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByKey(obj, "a")));
- #endif
- #endif
- RyanJsonDelete(obj);
- }
- static void testInsertRejectAttachedItem(void)
- {
- RyanJson_t arr1 = RyanJsonCreateArray();
- RyanJson_t arr2 = RyanJsonCreateArray();
- RyanJson_t item = RyanJsonCreateInt(NULL, 1);
- TEST_ASSERT_TRUE(RyanJsonInsert(arr1, 0, item));
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonInsert(arr2, 0, item), "已挂树的 item 不应再次插入");
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(arr1));
- TEST_ASSERT_EQUAL_INT(0, RyanJsonGetSize(arr2));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arr1, 0)));
- RyanJsonDelete(arr1);
- RyanJsonDelete(arr2);
- }
- static void testDetachedItemApi(void)
- {
- TEST_ASSERT_FALSE(RyanJsonIsDetachedItem(NULL));
- RyanJson_t arr = RyanJsonCreateArray();
- RyanJson_t item = RyanJsonCreateInt(NULL, 123);
- TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(item));
- TEST_ASSERT_TRUE(RyanJsonInsert(arr, 0, item));
- TEST_ASSERT_FALSE(RyanJsonIsDetachedItem(item));
- RyanJson_t detached = RyanJsonDetachByIndex(arr, 0);
- TEST_ASSERT_EQUAL_PTR(item, detached);
- TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(detached));
- // 人工篡改到“非法游离态”:next==NULL 但 IsLast==1,应判定为非游离节点
- RyanJsonSetPayloadIsLastByFlag(detached, RyanJsonTrue);
- TEST_ASSERT_FALSE(RyanJsonIsDetachedItem(detached));
- // 恢复状态,避免影响后续释放
- RyanJsonSetPayloadIsLastByFlag(detached, RyanJsonFalse);
- TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(detached));
- RyanJsonDelete(detached);
- RyanJsonDelete(arr);
- }
- static void testAddLargeArrayStress(void)
- {
- // 压力测试:添加大量元素
- int32_t count = 2000; // 2000 个元素
- RyanJson_t arr = RyanJsonCreateArray();
- for (int32_t i = 0; i < count; i++)
- {
- RyanJsonAddIntToArray(arr, i);
- }
- TEST_ASSERT_EQUAL_INT(count, RyanJsonGetArraySize(arr));
- // 验证最后一个
- RyanJson_t last = RyanJsonGetObjectByIndex(arr, count - 1);
- #if true == RyanJsonDefaultAddAtHead
- TEST_ASSERT_EQUAL_INT(0, RyanJsonGetIntValue(last));
- #else
- TEST_ASSERT_EQUAL_INT(count - 1, RyanJsonGetIntValue(last));
- #endif
- RyanJsonDelete(arr);
- // 防御性测试:向非容器添加
- RyanJson_t strNode = RyanJsonCreateString("k", "v");
- // 尝试向 String 节点添加子项,预期失败或不崩溃
- RyanJson_t item = RyanJsonCreateInt("sub", 1);
- RyanJsonBool_e res = RyanJsonInsert(strNode, 0, item);
- TEST_ASSERT_FALSE(res);
- // 该场景 item 是游离节点,Insert 失败会负责释放 item
- RyanJsonDelete(strNode);
- }
- static void testAddItemObjectSemantics(void)
- {
- // AddItemToObject 正常添加容器
- RyanJson_t obj = RyanJsonCreateObject();
- RyanJson_t childArr = RyanJsonCreateArray();
- TEST_ASSERT_NOT_NULL(obj);
- TEST_ASSERT_NOT_NULL(childArr);
- TEST_ASSERT_TRUE(RyanJsonAddIntToArray(childArr, 1));
- TEST_ASSERT_TRUE(RyanJsonAddIntToArray(childArr, 2));
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(obj, "arr", childArr), "AddItemToObject(容器) 应成功");
- RyanJson_t arrNode = RyanJsonGetObjectByKey(obj, "arr");
- TEST_ASSERT_NOT_NULL(arrNode);
- TEST_ASSERT_TRUE(RyanJsonIsArray(arrNode));
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetArraySize(arrNode));
- #if true == RyanJsonDefaultAddAtHead
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrNode, 0)));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrNode, 1)));
- #else
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrNode, 0)));
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(arrNode, 1)));
- #endif
- // AddItemToObject 重复 key(容器)行为由严格模式控制
- RyanJson_t dupObj = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL(dupObj);
- TEST_ASSERT_TRUE(RyanJsonAddIntToObject(dupObj, "k", 99));
- #if true == RyanJsonStrictObjectKeyCheck
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToObject(obj, "arr", dupObj), "严格模式下 AddItemToObject(重复 key) 应失败");
- #else
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(obj, "arr", dupObj), "非严格模式下 AddItemToObject(重复 key) 应成功");
- #endif
- #if true == RyanJsonStrictObjectKeyCheck
- arrNode = RyanJsonGetObjectByKey(obj, "arr");
- TEST_ASSERT_NOT_NULL(arrNode);
- TEST_ASSERT_TRUE(RyanJsonIsArray(arrNode));
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetArraySize(arrNode));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetSize(obj));
- #else
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetSize(obj));
- RyanJson_t firstArrKeyNode = RyanJsonGetObjectByIndex(obj, 0);
- RyanJson_t secondArrKeyNode = RyanJsonGetObjectByIndex(obj, 1);
- TEST_ASSERT_NOT_NULL(firstArrKeyNode);
- TEST_ASSERT_NOT_NULL(secondArrKeyNode);
- TEST_ASSERT_TRUE(RyanJsonIsKey(firstArrKeyNode));
- TEST_ASSERT_TRUE(RyanJsonIsKey(secondArrKeyNode));
- TEST_ASSERT_EQUAL_STRING("arr", RyanJsonGetKey(firstArrKeyNode));
- TEST_ASSERT_EQUAL_STRING("arr", RyanJsonGetKey(secondArrKeyNode));
- #if true == RyanJsonDefaultAddAtHead
- // 头插模式:新插入的 dupObj 在前,旧 Array 在后
- TEST_ASSERT_TRUE(RyanJsonIsObject(firstArrKeyNode));
- TEST_ASSERT_TRUE(RyanJsonIsArray(secondArrKeyNode));
- TEST_ASSERT_EQUAL_INT(99, RyanJsonGetIntValue(RyanJsonGetObjectByKey(firstArrKeyNode, "k")));
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetArraySize(secondArrKeyNode));
- arrNode = RyanJsonGetObjectByKey(obj, "arr");
- TEST_ASSERT_NOT_NULL(arrNode);
- TEST_ASSERT_TRUE(RyanJsonIsObject(arrNode));
- #else
- // 尾插模式:旧 Array 在前,新插入的 dupObj 在后
- TEST_ASSERT_TRUE(RyanJsonIsArray(firstArrKeyNode));
- TEST_ASSERT_TRUE(RyanJsonIsObject(secondArrKeyNode));
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetArraySize(firstArrKeyNode));
- TEST_ASSERT_EQUAL_INT(99, RyanJsonGetIntValue(RyanJsonGetObjectByKey(secondArrKeyNode, "k")));
- arrNode = RyanJsonGetObjectByKey(obj, "arr");
- TEST_ASSERT_NOT_NULL(arrNode);
- TEST_ASSERT_TRUE(RyanJsonIsArray(arrNode));
- #endif
- #endif
- // AddItemToObject 传入标量应失败
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToObject(obj, "scalar", RyanJsonCreateInt(NULL, 7)), "AddItemToObject(标量) 应失败");
- TEST_ASSERT_NULL(RyanJsonGetObjectByKey(obj, "scalar"));
- // 非 Object 调用 AddItemToObject 应失败
- RyanJson_t notObj = RyanJsonCreateInt("num", 1);
- RyanJson_t childObj = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL(notObj);
- TEST_ASSERT_NOT_NULL(childObj);
- TEST_ASSERT_TRUE(RyanJsonAddIntToObject(childObj, "x", 1));
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToObject(notObj, "child", childObj), "非 Object 调用 AddItemToObject 应失败");
- TEST_ASSERT_TRUE(RyanJsonIsInt(notObj));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(notObj));
- RyanJsonDelete(notObj);
- RyanJsonDelete(obj);
- }
- static void testAddItemRejectsAttachedContainer(void)
- {
- // 复杂链路:
- // Parse(源文档) -> AddItemToObject/AddItemToArray(已挂树容器) -> 失败 -> 结构保持。
- // 目标:验证 AddItemToObject/AddItemToArray 仅接受游离容器。
- RyanJson_t src = RyanJsonParse("{\"arr\":[1,2],\"obj\":{\"k\":1}}");
- TEST_ASSERT_NOT_NULL(src);
- RyanJson_t attachedArr = RyanJsonGetObjectToKey(src, "arr");
- RyanJson_t attachedObj = RyanJsonGetObjectToKey(src, "obj");
- TEST_ASSERT_NOT_NULL(attachedArr);
- TEST_ASSERT_NOT_NULL(attachedObj);
- RyanJson_t dstObj = RyanJsonCreateObject();
- RyanJson_t dstArr = RyanJsonCreateArray();
- TEST_ASSERT_NOT_NULL(dstObj);
- TEST_ASSERT_NOT_NULL(dstArr);
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToObject(dstObj, "arr", attachedArr), "AddItemToObject(已挂树容器) 应失败");
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToArray(dstArr, attachedObj), "AddItemToArray(已挂树容器) 应失败");
- // 源文档结构应保持不变
- TEST_ASSERT_EQUAL_UINT32(2U, RyanJsonGetArraySize(RyanJsonGetObjectToKey(src, "arr")));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectToKey(src, "obj", "k")));
- // 目标容器应保持为空
- TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetSize(dstObj));
- TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetArraySize(dstArr));
- RyanJsonDelete(dstArr);
- RyanJsonDelete(dstObj);
- RyanJsonDelete(src);
- }
- static void testAddItemObjectEmptyKeyRoundtrip(void)
- {
- // 复杂链路:
- // Parse(Array) -> AddItemToObject(空 key) -> Print/Parse -> key 与内容校验。
- // 目标:验证空 key 在 AddItemToObject 包装路径下可稳定保留。
- RyanJson_t root = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL(root);
- RyanJson_t child = RyanJsonParse("[1,2]");
- TEST_ASSERT_NOT_NULL(child);
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(root, "", child), "AddItemToObject(空 key) 应成功");
- RyanJson_t node = RyanJsonGetObjectByKey(root, "");
- TEST_ASSERT_NOT_NULL(node);
- TEST_ASSERT_TRUE(RyanJsonIsArray(node));
- TEST_ASSERT_EQUAL_UINT32(2U, RyanJsonGetArraySize(node));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(node, 0)));
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(node, 1)));
- char *printed = RyanJsonPrint(root, 64, RyanJsonFalse, NULL);
- TEST_ASSERT_NOT_NULL(printed);
- RyanJson_t roundtrip = RyanJsonParse(printed);
- TEST_ASSERT_NOT_NULL(roundtrip);
- TEST_ASSERT_TRUE(RyanJsonHasObjectByKey(roundtrip, ""));
- RyanJson_t roundNode = RyanJsonGetObjectByKey(roundtrip, "");
- TEST_ASSERT_NOT_NULL(roundNode);
- TEST_ASSERT_TRUE(RyanJsonIsArray(roundNode));
- TEST_ASSERT_EQUAL_UINT32(2U, RyanJsonGetArraySize(roundNode));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(roundNode, 0)));
- TEST_ASSERT_EQUAL_INT(2, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(roundNode, 1)));
- RyanJsonDelete(roundtrip);
- RyanJsonFree(printed);
- RyanJsonDelete(root);
- }
- static void testAddItemObjectLongKeyWrapRoundtrip(void)
- {
- // 复杂链路:
- // Parse(Object) -> AddItemToObject(长 key) -> Print/Parse -> key 与内容校验。
- // 目标:验证长 key + 包装路径稳定且可往返。
- uint32_t longLen = RyanJsonInlineStringSize + 8U;
- char *longKey = allocPatternString(longLen, 'k');
- TEST_ASSERT_NOT_NULL(longKey);
- RyanJson_t root = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL(root);
- RyanJson_t child = RyanJsonParse("{\"v\":1}");
- TEST_ASSERT_NOT_NULL(child);
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(root, longKey, child), "AddItemToObject(长 key) 应成功");
- RyanJson_t node = RyanJsonGetObjectByKey(root, longKey);
- TEST_ASSERT_NOT_NULL(node);
- TEST_ASSERT_TRUE(RyanJsonIsObject(node));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByKey(node, "v")));
- TEST_ASSERT_EQUAL_UINT32(longLen, (uint32_t)strlen(RyanJsonGetKey(node)));
- char *printed = RyanJsonPrint(root, 128, RyanJsonFalse, NULL);
- TEST_ASSERT_NOT_NULL(printed);
- RyanJson_t roundtrip = RyanJsonParse(printed);
- TEST_ASSERT_NOT_NULL(roundtrip);
- RyanJson_t roundNode = RyanJsonGetObjectByKey(roundtrip, longKey);
- TEST_ASSERT_NOT_NULL(roundNode);
- TEST_ASSERT_TRUE(RyanJsonIsObject(roundNode));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectByKey(roundNode, "v")));
- RyanJsonDelete(roundtrip);
- RyanJsonFree(printed);
- RyanJsonDelete(root);
- free(longKey);
- }
- static void testCreateDetachedReuseAndContainerAssembleChain(void)
- {
- // 复杂链路:
- // Create(root/queue/map/nums) -> Insert(成功) -> 重复 Insert(失败)
- // -> DetachByIndex -> AddItemToObject(包装成功) -> Compare(期望文档) -> Roundtrip。
- // 目标:
- // - 验证已挂树节点重复插入会失败且不破坏结构;
- // - 验证游离节点在 Detach 后可被 AddItemToObject 稳定复用;
- // - 验证创建型链路最终语义可收敛到期望文档。
- #if true == RyanJsonDefaultAddAtHead
- const char *expectText = "{\"queue\":[],\"map\":{\"t1\":{\"name\":\"sync\",\"prio\":1}},\"nums\":[2,1]}";
- #else
- const char *expectText = "{\"queue\":[],\"map\":{\"t1\":{\"name\":\"sync\",\"prio\":1}},\"nums\":[1,2]}";
- #endif
- RyanJson_t root = RyanJsonCreateObject();
- RyanJson_t queue = RyanJsonCreateArray();
- RyanJson_t map = RyanJsonCreateObject();
- const int32_t numsRaw[] = {1, 2};
- RyanJson_t nums = RyanJsonCreateIntArray(numsRaw, (uint32_t)(sizeof(numsRaw) / sizeof(numsRaw[0])));
- TEST_ASSERT_NOT_NULL(root);
- TEST_ASSERT_NOT_NULL(queue);
- TEST_ASSERT_NOT_NULL(map);
- TEST_ASSERT_NOT_NULL(nums);
- TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "queue", queue));
- TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "map", map));
- TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "nums", nums));
- // 挂载后重新获取,避免使用旧缓存指针。
- queue = RyanJsonGetObjectToKey(root, "queue");
- map = RyanJsonGetObjectToKey(root, "map");
- TEST_ASSERT_NOT_NULL(queue);
- TEST_ASSERT_NOT_NULL(map);
- RyanJson_t task = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL(task);
- TEST_ASSERT_TRUE(RyanJsonAddStringToObject(task, "name", "sync"));
- TEST_ASSERT_TRUE(RyanJsonAddIntToObject(task, "prio", 1));
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonInsert(queue, 0, task), "首次插入任务节点应成功");
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonInsert(queue, 1, task), "重复插入已挂树节点应失败");
- TEST_ASSERT_EQUAL_UINT32(1U, RyanJsonGetArraySize(queue));
- RyanJson_t detached = RyanJsonDetachByIndex(queue, 0);
- TEST_ASSERT_NOT_NULL_MESSAGE(detached, "从 queue 分离任务节点失败");
- TEST_ASSERT_TRUE(RyanJsonIsDetachedItem(detached));
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToObject(map, "t1", detached), "将分离节点包装挂载到 map.t1 失败");
- TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonGetArraySize(queue));
- TEST_ASSERT_TRUE(RyanJsonHasObjectToKey(root, "map", "t1", "name"));
- TEST_ASSERT_EQUAL_STRING("sync", RyanJsonGetStringValue(RyanJsonGetObjectToKey(root, "map", "t1", "name")));
- TEST_ASSERT_EQUAL_INT(1, RyanJsonGetIntValue(RyanJsonGetObjectToKey(root, "map", "t1", "prio")));
- RyanJson_t expect = RyanJsonParse(expectText);
- TEST_ASSERT_NOT_NULL(expect);
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root, expect), "Create 组装链路结果与期望文档不一致");
- char *printed = RyanJsonPrint(root, 128, RyanJsonFalse, NULL);
- TEST_ASSERT_NOT_NULL(printed);
- RyanJson_t roundtrip = RyanJsonParse(printed);
- TEST_ASSERT_NOT_NULL(roundtrip);
- TEST_ASSERT_TRUE(RyanJsonCompare(root, roundtrip));
- RyanJsonDelete(roundtrip);
- RyanJsonFree(printed);
- RyanJsonDelete(expect);
- RyanJsonDelete(root);
- }
- static void testCreateAddItemToArrayRejectScalarThenRecover(void)
- {
- // 复杂链路:
- // Create(root/arr) -> AddItemToArray(标量失败) -> AddItemToArray(容器) -> AddIntToArray
- // -> Compare(期望文档) -> Roundtrip。
- // 目标:
- // - 验证 AddItemToArray 仅接受容器节点;
- // - 验证失败后 Array 仍可继续复用;
- // - 验证恢复后的构建结果可稳定打印回读。
- RyanJson_t root = RyanJsonCreateObject();
- RyanJson_t arr = RyanJsonCreateArray();
- TEST_ASSERT_NOT_NULL(root);
- TEST_ASSERT_NOT_NULL(arr);
- TEST_ASSERT_TRUE(RyanJsonAddItemToObject(root, "arr", arr));
- arr = RyanJsonGetObjectToKey(root, "arr");
- TEST_ASSERT_NOT_NULL(arr);
- RyanJson_t scalar = RyanJsonCreateInt(NULL, 7);
- TEST_ASSERT_NOT_NULL(scalar);
- TEST_ASSERT_FALSE_MESSAGE(RyanJsonAddItemToArray(arr, scalar), "AddItemToArray(标量) 应失败");
- TEST_ASSERT_EQUAL_UINT32_MESSAGE(0U, RyanJsonGetArraySize(arr), "失败后 Array 仍应为空");
- RyanJson_t obj = RyanJsonCreateObject();
- TEST_ASSERT_NOT_NULL(obj);
- TEST_ASSERT_TRUE(RyanJsonAddIntToObject(obj, "v", 1));
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonAddItemToArray(arr, obj), "AddItemToArray(容器) 应成功");
- TEST_ASSERT_TRUE(RyanJsonAddIntToArray(arr, 9));
- TEST_ASSERT_EQUAL_UINT32(2U, RyanJsonGetArraySize(arr));
- #if true == RyanJsonDefaultAddAtHead
- RyanJson_t expect = RyanJsonParse("{\"arr\":[9,{\"v\":1}]}");
- #else
- RyanJson_t expect = RyanJsonParse("{\"arr\":[{\"v\":1},9]}");
- #endif
- TEST_ASSERT_NOT_NULL(expect);
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(root, expect), "AddItemToArray 失败恢复后结构不符合预期");
- char *printed = RyanJsonPrint(root, 96, RyanJsonFalse, NULL);
- TEST_ASSERT_NOT_NULL(printed);
- RyanJson_t roundtrip = RyanJsonParse(printed);
- TEST_ASSERT_NOT_NULL(roundtrip);
- TEST_ASSERT_TRUE(RyanJsonCompare(root, roundtrip));
- RyanJsonDelete(roundtrip);
- RyanJsonFree(printed);
- RyanJsonDelete(expect);
- RyanJsonDelete(root);
- }
- static void testCreateInsertUsingAddPositionMacro(void)
- {
- // Create(Array) -> Insert(AddPosition) -> Compare(期望)。
- // 目标:验证 AddPosition 宏始终遵循当前默认插入策略。
- RyanJson_t arr = RyanJsonCreateArray();
- TEST_ASSERT_NOT_NULL(arr);
- TEST_ASSERT_TRUE(RyanJsonInsert(arr, RyanJsonAddPosition, RyanJsonCreateInt(NULL, 1)));
- TEST_ASSERT_TRUE(RyanJsonInsert(arr, RyanJsonAddPosition, RyanJsonCreateInt(NULL, 2)));
- TEST_ASSERT_TRUE(RyanJsonInsert(arr, RyanJsonAddPosition, RyanJsonCreateInt(NULL, 3)));
- #if true == RyanJsonDefaultAddAtHead
- const char *expectText = "[3,2,1]";
- #else
- const char *expectText = "[1,2,3]";
- #endif
- RyanJson_t expect = RyanJsonParse(expectText);
- TEST_ASSERT_NOT_NULL(expect);
- TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompare(arr, expect), "AddPosition 顺序语义错误");
- RyanJsonDelete(expect);
- RyanJsonDelete(arr);
- }
- void testCreateRunner(void)
- {
- UnitySetTestFile(__FILE__);
- RUN_TEST(testCreateEdgeCases);
- RUN_TEST(testCreatePropertyCheck);
- RUN_TEST(testAddBoundary);
- RUN_TEST(testCreateStandardComplexHierarchy);
- RUN_TEST(testCreateHugeString);
- RUN_TEST(testCreateOom);
- RUN_TEST(testCreateArgumentGuards);
- RUN_TEST(testCreateTypedArrayZeroCount);
- RUN_TEST(testCreateTypedArrayOomPaths);
- RUN_TEST(testCreateScalarOom);
- RUN_TEST(testInsertOutOfRangeAndKeyValidation);
- RUN_TEST(testInsertRejectAttachedItem);
- RUN_TEST(testDetachedItemApi);
- RUN_TEST(testCreateInsertUsingAddPositionMacro);
- RUN_TEST(testAddLargeArrayStress);
- RUN_TEST(testAddItemObjectSemantics);
- RUN_TEST(testAddItemRejectsAttachedContainer);
- RUN_TEST(testAddItemObjectEmptyKeyRoundtrip);
- RUN_TEST(testAddItemObjectLongKeyWrapRoundtrip);
- RUN_TEST(testCreateDetachedReuseAndContainerAssembleChain);
- RUN_TEST(testCreateAddItemToArrayRejectScalarThenRecover);
- }
|