#include "testBase.h" /** * @brief Json 公共校验辅助函数 */ void printJsonDebug(RyanJson_t json) { char *str = RyanJsonPrint(json, 1024, RyanJsonTrue, NULL); testLog("aa %s\r\n", str); RyanJsonFree(str); } void rootNodeCheckTest(RyanJson_t json) { TEST_ASSERT_NOT_NULL_MESSAGE(json, "根节点检查:输入 Json 为空"); // 校验 Int 字段 RyanJson_t inter = RyanJsonGetObjectToKey(json, "inter"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsInt(inter), "字段 'inter' 不是 Int 类型"); TEST_ASSERT_EQUAL_INT_MESSAGE(16, RyanJsonGetIntValue(inter), "字段 'inter' 值不正确"); // 校验 Double 字段 RyanJson_t dbl = RyanJsonGetObjectToKey(json, "double"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDouble(dbl), "字段 'double' 不是 Double 类型"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareDouble(RyanJsonGetDoubleValue(dbl), 16.89), "字段 'double' 值不正确"); // 校验 String 字段 RyanJson_t str = RyanJsonGetObjectToKey(json, "string"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsString(str), "字段 'string' 不是 String 类型"); TEST_ASSERT_EQUAL_STRING_MESSAGE("hello", RyanJsonGetStringValue(str), "字段 'string' 值不正确"); // 校验 Bool 字段(true) RyanJson_t bTrue = RyanJsonGetObjectToKey(json, "boolTrue"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsBool(bTrue), "字段 'boolTrue' 不是 Bool 类型"); TEST_ASSERT_EQUAL_INT_MESSAGE(RyanJsonTrue, RyanJsonGetBoolValue(bTrue), "字段 'boolTrue' 值不正确"); // 校验 Bool 字段(false) RyanJson_t bFalse = RyanJsonGetObjectToKey(json, "boolFalse"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsBool(bFalse), "字段 'boolFalse' 不是 Bool 类型"); TEST_ASSERT_EQUAL_INT_MESSAGE(RyanJsonFalse, RyanJsonGetBoolValue(bFalse), "字段 'boolFalse' 值不正确"); // 校验 Null 字段 TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsNull(RyanJsonGetObjectToKey(json, "null")), "字段 'null' 不是 Null 类型"); } void itemNodeCheckTest(RyanJson_t json) { RyanJson_t item = RyanJsonGetObjectToKey(json, "item"); TEST_ASSERT_NOT_NULL_MESSAGE(item, "字段 'item' 不存在"); rootNodeCheckTest(item); } void arrayNodeCheckTest(RyanJson_t json, RyanJsonBool_e isReversed) { TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsArray(RyanJsonGetObjectToKey(json, "arrayInt")), "arrayInt 不是 Array"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsArray(RyanJsonGetObjectToKey(json, "arrayDouble")), "arrayDouble 不是 Array"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsArray(RyanJsonGetObjectToKey(json, "arrayString")), "arrayString 不是 Array"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsArray(RyanJsonGetObjectToKey(json, "array")), "array 不是 Array"); // 校验混合 Array(含 Int/Double/String/Bool/Null):[16, 16.89, "hello", true, false, Null] RyanJson_t array = RyanJsonGetObjectToKey(json, "array"); TEST_ASSERT_EQUAL_INT_MESSAGE(6, RyanJsonGetSize(array), "混合 Array 长度不正确"); if (isReversed) { TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsNull(RyanJsonGetObjectByIndex(array, 0)), "混合 Array[0]不是 Null"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsBool(RyanJsonGetObjectByIndex(array, 1)), "混合 Array[1]不是 Bool 值"); TEST_ASSERT_EQUAL_INT_MESSAGE(RyanJsonFalse, RyanJsonGetBoolValue(RyanJsonGetObjectByIndex(array, 1)), "混合 Array[1]值错误"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsBool(RyanJsonGetObjectByIndex(array, 2)), "混合 Array[2]不是 Bool 值"); TEST_ASSERT_EQUAL_INT_MESSAGE(RyanJsonTrue, RyanJsonGetBoolValue(RyanJsonGetObjectByIndex(array, 2)), "混合 Array[2]值错误"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsString(RyanJsonGetObjectByIndex(array, 3)), "混合 Array[3]不是 String"); TEST_ASSERT_EQUAL_STRING_MESSAGE("hello", RyanJsonGetStringValue(RyanJsonGetObjectByIndex(array, 3)), "混合 Array[3]值错误"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDouble(RyanJsonGetObjectByIndex(array, 4)), "混合 Array[4]不是 Double"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareDouble(RyanJsonGetDoubleValue(RyanJsonGetObjectByIndex(array, 4)), 16.89), "混合 Array[4]值错误"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsInt(RyanJsonGetObjectByIndex(array, 5)), "混合 Array[5]不是 Int"); TEST_ASSERT_EQUAL_INT_MESSAGE(16, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(array, 5)), "混合 Array[5]值错误"); } else { TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsInt(RyanJsonGetObjectByIndex(array, 0)), "混合 Array[0]不是 Int"); TEST_ASSERT_EQUAL_INT_MESSAGE(16, RyanJsonGetIntValue(RyanJsonGetObjectByIndex(array, 0)), "混合 Array[0]值错误"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDouble(RyanJsonGetObjectByIndex(array, 1)), "混合 Array[1]不是 Double"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareDouble(RyanJsonGetDoubleValue(RyanJsonGetObjectByIndex(array, 1)), 16.89), "混合 Array[1]值错误"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsString(RyanJsonGetObjectByIndex(array, 2)), "混合 Array[2]不是 String"); TEST_ASSERT_EQUAL_STRING_MESSAGE("hello", RyanJsonGetStringValue(RyanJsonGetObjectByIndex(array, 2)), "混合 Array[2]值错误"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsBool(RyanJsonGetObjectByIndex(array, 3)), "混合 Array[3]不是 Bool 值"); TEST_ASSERT_EQUAL_INT_MESSAGE(RyanJsonTrue, RyanJsonGetBoolValue(RyanJsonGetObjectByIndex(array, 3)), "混合 Array[3]值错误"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsBool(RyanJsonGetObjectByIndex(array, 4)), "混合 Array[4]不是 Bool 值"); TEST_ASSERT_EQUAL_INT_MESSAGE(RyanJsonFalse, RyanJsonGetBoolValue(RyanJsonGetObjectByIndex(array, 4)), "混合 Array[4]值错误"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsNull(RyanJsonGetObjectByIndex(array, 5)), "混合 Array[5]不是 Null"); } // 校验强类型 Array RyanJson_t arrayInt = RyanJsonGetObjectToKey(json, "arrayInt"); for (int32_t i = 0; i < RyanJsonGetSize(arrayInt); i++) { RyanJson_t item = RyanJsonGetObjectByIndex(arrayInt, i); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsInt(item), "arrayInt 元素不是 Int"); TEST_ASSERT_EQUAL_INT_MESSAGE(16, RyanJsonGetIntValue(item), "arrayInt 元素值错误"); } RyanJson_t arrayDouble = RyanJsonGetObjectToKey(json, "arrayDouble"); for (int32_t i = 0; i < RyanJsonGetSize(arrayDouble); i++) { RyanJson_t item = RyanJsonGetObjectByIndex(arrayDouble, i); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsDouble(item), "arrayDouble 元素不是 Double"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonCompareDouble(RyanJsonGetDoubleValue(item), 16.89), "arrayDouble 元素值错误"); } RyanJson_t arrayString = RyanJsonGetObjectToKey(json, "arrayString"); for (int32_t i = 0; i < RyanJsonGetSize(arrayString); i++) { RyanJson_t item = RyanJsonGetObjectByIndex(arrayString, i); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsString(item), "arrayString 元素不是 String"); TEST_ASSERT_EQUAL_STRING_MESSAGE("hello", RyanJsonGetStringValue(item), "arrayString 元素值错误"); } } void arrayItemNodeCheckTest(RyanJson_t json) { RyanJson_t arrayItem = RyanJsonGetObjectToKey(json, "arrayItem"); TEST_ASSERT_TRUE_MESSAGE(RyanJsonIsArray(arrayItem), "arrayItem 不是 Array"); TEST_ASSERT_EQUAL_INT_MESSAGE(2, RyanJsonGetSize(arrayItem), "arrayItem 长度错误"); rootNodeCheckTest(RyanJsonGetObjectToIndex(arrayItem, 0)); rootNodeCheckTest(RyanJsonGetObjectToIndex(arrayItem, 1)); } void testCheckRootEx(RyanJson_t pJson, RyanJsonBool_e isReversed) { rootNodeCheckTest(pJson); itemNodeCheckTest(pJson); arrayNodeCheckTest(pJson, isReversed); arrayItemNodeCheckTest(pJson); } void testCheckRoot(RyanJson_t pJson) { testCheckRootEx(pJson, RyanJsonFalse); } static void testUtilsMinifyNoExtraSpace(void) { char buf[4]; buf[0] = 'a'; buf[1] = 'b'; buf[2] = 'c'; buf[3] = 'X'; // 哨兵:不应被覆盖 uint32_t count = RyanJsonMinify(buf, 3); TEST_ASSERT_EQUAL_UINT32(3, count); TEST_ASSERT_EQUAL_UINT8('a', (uint8_t)buf[0]); TEST_ASSERT_EQUAL_UINT8('b', (uint8_t)buf[1]); TEST_ASSERT_EQUAL_UINT8('c', (uint8_t)buf[2]); TEST_ASSERT_EQUAL_UINT8('X', (uint8_t)buf[3]); } static void testUtilsMinifyZeroLengthNoWrite(void) { char buf[] = "{}"; uint32_t count = RyanJsonMinify(buf, 0); TEST_ASSERT_EQUAL_UINT32(0U, count); TEST_ASSERT_EQUAL_STRING("{}", buf); } static void testUtilsMinifyWriteTerminatorWhenSpaceRemain(void) { /* * textLen=4 时,压缩后 "abc" 长度为 3: * - 返回值应为 3 * - 因为 3 < 4,函数应在 buf[3] 写入 '\0' * - buf[4] 是哨兵,必须保持不变 */ char buf[5]; buf[0] = 'a'; buf[1] = ' '; buf[2] = 'b'; buf[3] = 'c'; buf[4] = '#'; uint32_t count = RyanJsonMinify(buf, 4); TEST_ASSERT_EQUAL_UINT32(3, count); TEST_ASSERT_EQUAL_UINT8('a', (uint8_t)buf[0]); TEST_ASSERT_EQUAL_UINT8('b', (uint8_t)buf[1]); TEST_ASSERT_EQUAL_UINT8('c', (uint8_t)buf[2]); TEST_ASSERT_EQUAL_UINT8('\0', (uint8_t)buf[3]); TEST_ASSERT_EQUAL_UINT8('#', (uint8_t)buf[4]); } static void testUtilsMinifyNoTerminatorOverflow(void) { uint8_t rawBuf[8] = {'{', '\"', 'a', '\"', ':', '1', '}', '#'}; uint32_t count = RyanJsonMinify((char *)rawBuf, 7); TEST_ASSERT_EQUAL_UINT32(7U, count); TEST_ASSERT_EQUAL_UINT8((uint8_t)'#', rawBuf[7]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'{', rawBuf[0]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'\"', rawBuf[1]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'a', rawBuf[2]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'\"', rawBuf[3]); TEST_ASSERT_EQUAL_UINT8((uint8_t)':', rawBuf[4]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'1', rawBuf[5]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'}', rawBuf[6]); } static void testUtilsMinifyCommentOnlyToEmpty(void) { char buf[] = "/*comment*/"; uint32_t count = RyanJsonMinify(buf, (int32_t)strlen(buf)); TEST_ASSERT_EQUAL_UINT32(0U, count); TEST_ASSERT_EQUAL_STRING("", buf); } static void testUtilsMinifyWhitespaceOnlyWritesTerminator(void) { char buf[4] = {' ', '\t', '\n', '#'}; uint32_t count = RyanJsonMinify(buf, 3); TEST_ASSERT_EQUAL_UINT32(0U, count); TEST_ASSERT_EQUAL_UINT8((uint8_t)'\0', (uint8_t)buf[0]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'#', (uint8_t)buf[3]); } static void testUtilsMinifyTruncatedEscapeDoesNotOverread(void) { char rawTruncated[3] = {'\"', 'a', '\\'}; uint32_t count = RyanJsonMinify(rawTruncated, 3); TEST_ASSERT_EQUAL_UINT32(3U, count); TEST_ASSERT_EQUAL_UINT8((uint8_t)'\"', (uint8_t)rawTruncated[0]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'a', (uint8_t)rawTruncated[1]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'\\', (uint8_t)rawTruncated[2]); } static void testUtilsMinifyInvalidArgsNoWrite(void) { // 参数守护分支:无论是 NULL 指针还是负长度,都只能返回 0, // 且不得写坏调用方传入的缓冲区内容。 char buf[5] = {'{', '}', '!', '#', '@'}; TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonMinify(NULL, 4)); TEST_ASSERT_EQUAL_UINT32(0U, RyanJsonMinify(buf, -1)); TEST_ASSERT_EQUAL_UINT8((uint8_t)'{', (uint8_t)buf[0]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'}', (uint8_t)buf[1]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'!', (uint8_t)buf[2]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'#', (uint8_t)buf[3]); TEST_ASSERT_EQUAL_UINT8((uint8_t)'@', (uint8_t)buf[4]); } void testUtilsRunner(void) { UnitySetTestFile(__FILE__); RUN_TEST(testUtilsMinifyNoExtraSpace); RUN_TEST(testUtilsMinifyZeroLengthNoWrite); RUN_TEST(testUtilsMinifyWriteTerminatorWhenSpaceRemain); RUN_TEST(testUtilsMinifyNoTerminatorOverflow); RUN_TEST(testUtilsMinifyCommentOnlyToEmpty); RUN_TEST(testUtilsMinifyWhitespaceOnlyWritesTerminator); RUN_TEST(testUtilsMinifyTruncatedEscapeDoesNotOverread); RUN_TEST(testUtilsMinifyInvalidArgsNoWrite); }