| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- #include "testBase.h"
- static void testLoadFailureNullAndWhitespace(void)
- {
- // NULL 和空字符串
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse(NULL), "Parse(NULL) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse(""), "Parse(\"\") 应返回 NULL");
- // 仅有空白字符
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse(" "), "Parse(只含空格) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("\t\r\n"), "Parse(只含换行符) 应返回 NULL");
- }
- static void testLoadFailureTruncated(void)
- {
- // 畸形 Json(缺少闭合)
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("[1, 2, 3"), "Parse(未闭合数组) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\": 1"), "Parse(未闭合对象) 应返回 NULL");
- // 截断的输入 (非正常结束)
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{"), "截断的对象应解析失败");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("["), "截断的数组应解析失败");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":"), "缺少值的对象应解析失败");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1"), "未闭合的对象应解析失败");
- // 未闭合字符串
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("\"just a string"), "未闭合字符串应解析失败");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":\"unterminated}"), "未闭合字符串应解析失败");
- }
- static void testLoadFailureInvalidTokens(void)
- {
- // 非法字符开头
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("x123"), "Parse(非法开头) 应返回 NULL");
- // 无效数字
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"inter\":16poi}"), "应拒绝无效数字 16poi");
- // 无效浮点数
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"double\":16.8yu9}"), "应拒绝无效浮点数 16.8yu9");
- // boolTrue 拼写错误
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"boolTrue\":tru}"), "应拒绝错误拼写的 true (tru)");
- // boolFalse 拼写错误
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"boolFalse\":fale}"), "应拒绝错误拼写的 false (fale)");
- // null 拼写错误
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"null\":nul}"), "应拒绝错误拼写的 null (nul)");
- // null 大写错误(Json 规范要求小写)
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"null\":NULL}"), "应拒绝大写的 NULL");
- // 缺少逗号
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"inter\":16\"double\":16.89}"), "应拒绝缺少逗号的对象");
- // 数组项缺少逗号
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("[16,16.89\"hello\"]"), "应拒绝数组项缺少逗号");
- // 键值缺少引号
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"item:{\"inter\":16}}"), "应拒绝键值缺少引号");
- // 嵌套对象键值缺少引号
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"item\":{inter:16}}"), "应拒绝嵌套对象键值缺少引号");
- // 多余引号
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"item\":{\"\"double\":16.89}}"), "应拒绝多余引号");
- // 键值后多余逗号或引号
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"item\":{\"inter\":16\"\"}}"), "应拒绝非法结尾引号");
- // 数组中无效数字
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"arrayInt\":[16,16,16m,16,16]}"), "应拒绝数组中含有无效数字 16m");
- }
- static void testLoadFailureInvalidNumbers(void)
- {
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("012"), "Parse(前导 0) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":01}"), "Parse(01) 应返回 NULL (不允许前导 0)");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":-01}"), "Parse(-01) 应返回 NULL (不允许前导 0)");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":00}"), "Parse(00) 应返回 NULL (不允许前导 0)");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":+1}"), "Parse(+1) 应返回 NULL (Json 不允许前导 +)");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":--1}"), "Parse(--1) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1.2.3}"), "Parse(1.2.3) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1.}"), "Parse(1.) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":-.1}"), "Parse(-.1) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":-}"), "Parse(-) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1e}"), "Parse(1e) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1e+}"), "Parse(1e+) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1e-}"), "Parse(1e-) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1e309}"), "Parse(1e309) 应返回 NULL (溢出)");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("1e2147483647"), "Parse(纯数字指数边界) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("1e2147483648"), "Parse(纯数字指数累积溢出) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("1e-2147483648"), "Parse(纯数字负指数累积溢出) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1e2147483648}"), "Parse(指数累积溢出) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1e-2147483648}"), "Parse(负指数累积溢出) 应返回 NULL");
- }
- static void testLoadFailureHugeNumberOverflow(void)
- {
- // 超长整数:应在数值累乘过程中触发 isfinite 防御并失败
- const uint32_t intLen = 1024;
- char *hugeInt = (char *)malloc((size_t)intLen + 1U);
- TEST_ASSERT_NOT_NULL(hugeInt);
- hugeInt[0] = '1';
- memset(hugeInt + 1, '9', intLen - 1U);
- hugeInt[intLen] = '\0';
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse(hugeInt), "Parse(超长整数溢出) 应返回 NULL");
- free(hugeInt);
- // 超长小数:同样应触发 isfinite 防御并失败
- const uint32_t fracLen = 1024;
- char *hugeFrac = (char *)malloc((size_t)fracLen + 3U);
- TEST_ASSERT_NOT_NULL(hugeFrac);
- hugeFrac[0] = '0';
- hugeFrac[1] = '.';
- memset(hugeFrac + 2, '9', fracLen);
- hugeFrac[fracLen + 2U] = '\0';
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse(hugeFrac), "Parse(超长小数溢出) 应返回 NULL");
- free(hugeFrac);
- }
- static void testLoadFailureInvalidEscapes(void)
- {
- // 疯狂的转义符
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":\"\\\"}"), "Parse(末尾转义未完成) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":\"\\v\"}"), "Parse(非法转义 \\v) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":\"\\x12\"}"), "Parse(非法转义 \\x12) 应返回 NULL");
- // 控制字符插入
- // Json 规范不允许未转义的控制字符(0x00-0x1F)
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":\"\x01\"}"), "Parse(含控制字符 0x01) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":\"\n\"}"), "Parse(含未转义换行) 应返回 NULL");
- }
- static void testLoadFailureInvalidUnicode(void)
- {
- // Unicode 截断
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"invalid\":\"\\u123\"}"), "应拒绝截断的 Unicode");
- // 非法十六进制字符
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"invalid\":\"\\uGGGG\"}"), "应拒绝非法 Unicode GGGG");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"invalid\":\"\\u00ZZ\"}"), "应拒绝非法 Unicode 00ZZ");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"invalid\":\"\\u00!!\"}"), "应拒绝非法 Unicode 00!!");
- // UTF-16 代理对错误
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"invalid\":\"\\uD800\"}"), "应拒绝缺少低位代理的高位代理");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"invalid\":\"\\uDC00\"}"), "应拒绝单独低位代理");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"invalid\":\"\\uD800\\u0041\"}"), "应拒绝无效代理对");
- }
- static void testLoadFailureInvalidStructure(void)
- {
- // 结构混乱
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1, \"b\":2, }"), "Parse(尾部逗号) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1, , \"b\":2}"), "Parse(双逗号) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1 : \"b\":2}"), "Parse(冒号代替逗号) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1 \"b\":2}"), "Parse(缺少逗号) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1,}"), "Parse(对象尾逗号) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1,,\"b\":2}"), "Parse(对象双逗号) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":}"), "Parse(缺少值) 应返回 NULL");
- #if true == RyanJsonStrictObjectKeyCheck
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"dup\":1,\"dup\":2}"), "严格模式 Parse(对象重复 key) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"obj\":{\"dup\":1,\"dup\":2}}"), "严格模式 Parse(嵌套对象重复 key) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("[{\"dup\":1,\"dup\":2}]"), "严格模式 Parse(数组内对象重复 key) 应返回 NULL");
- #else
- RyanJson_t dupObj = RyanJsonParse("{\"dup\":1,\"dup\":2}");
- RyanJson_t dupNestedObj = RyanJsonParse("{\"obj\":{\"dup\":1,\"dup\":2}}");
- RyanJson_t dupInArray = RyanJsonParse("[{\"dup\":1,\"dup\":2}]");
- TEST_ASSERT_NOT_NULL_MESSAGE(dupObj, "非严格模式 Parse(对象重复 key) 应成功");
- TEST_ASSERT_NOT_NULL_MESSAGE(dupNestedObj, "非严格模式 Parse(嵌套对象重复 key) 应成功");
- TEST_ASSERT_NOT_NULL_MESSAGE(dupInArray, "非严格模式 Parse(数组内对象重复 key) 应成功");
- RyanJsonDelete(dupObj);
- RyanJsonDelete(dupNestedObj);
- RyanJsonDelete(dupInArray);
- #endif
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("[,1]"), "Parse(数组前置逗号) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("[1,,2]"), "Parse(数组双逗号) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("[1,]"), "Parse(数组尾逗号) 应返回 NULL");
- }
- static void testLoadFailureDuplicateKeyAfterDecode(void)
- {
- #if true == RyanJsonStrictObjectKeyCheck
- // 转义后 key 冲突("\u0061" == "a")
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"a\":1,\"\\u0061\":2}"), "严格模式 Parse(转义后重复 key) 应返回 NULL");
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"\\u0061\":1,\"a\":2}"), "严格模式 Parse(转义后重复 key 反序) 应返回 NULL");
- // 大小写字符同理:"\u0041" == "A"
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"A\":1,\"\\u0041\":2}"), "严格模式 Parse(转义后重复大写 key) 应返回 NULL");
- // 空 key 重复
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse("{\"\":1,\"\":2}"), "严格模式 Parse(空 key 重复) 应返回 NULL");
- #else
- RyanJson_t dupEscaped1 = RyanJsonParse("{\"a\":1,\"\\u0061\":2}");
- RyanJson_t dupEscaped2 = RyanJsonParse("{\"\\u0061\":1,\"a\":2}");
- RyanJson_t dupEscaped3 = RyanJsonParse("{\"A\":1,\"\\u0041\":2}");
- RyanJson_t dupEscaped4 = RyanJsonParse("{\"\":1,\"\":2}");
- TEST_ASSERT_NOT_NULL_MESSAGE(dupEscaped1, "非严格模式 Parse(转义后重复 key) 应成功");
- TEST_ASSERT_NOT_NULL_MESSAGE(dupEscaped2, "非严格模式 Parse(转义后重复 key 反序) 应成功");
- TEST_ASSERT_NOT_NULL_MESSAGE(dupEscaped3, "非严格模式 Parse(转义后重复大写 key) 应成功");
- TEST_ASSERT_NOT_NULL_MESSAGE(dupEscaped4, "非严格模式 Parse(空 key 重复) 应成功");
- RyanJsonDelete(dupEscaped1);
- RyanJsonDelete(dupEscaped2);
- RyanJsonDelete(dupEscaped3);
- RyanJsonDelete(dupEscaped4);
- #endif
- }
- static void testLoadFailureMalformedNesting(void)
- {
- // 深度嵌套但没有闭合
- char deepOpen[200];
- memset(deepOpen, '[', 199);
- deepOpen[199] = '\0';
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse(deepOpen), "Parse(199个[) 应返回 NULL");
- // 深度嵌套但不匹配
- char deepMix[200];
- memset(deepMix, '[', 100);
- memset(deepMix + 100, '}', 99); // 应该是 ]
- deepMix[199] = '\0';
- TEST_ASSERT_NULL_MESSAGE(RyanJsonParse(deepMix), "Parse(100个[ + 99个}) 应返回 NULL");
- }
- static void testLoadParseOptionsFailure(void)
- {
- // 禁止尾部垃圾:requireNullTerminator = true
- const char *text = " {\"a\":1} trailing";
- RyanJson_t json = RyanJsonParseOptions(text, (uint32_t)strlen(text), RyanJsonTrue, NULL);
- TEST_ASSERT_NULL_MESSAGE(json, "ParseOptions(require null terminator) 应失败");
- }
- static int32_t gLoadFailAfter = -1;
- static int32_t gLoadAllocCount = 0;
- static void *loadFailMalloc(size_t size)
- {
- if (gLoadFailAfter >= 0 && gLoadAllocCount++ >= gLoadFailAfter) { return NULL; }
- return unityTestMalloc(size);
- }
- static void *loadFailRealloc(void *block, size_t size)
- {
- if (gLoadFailAfter >= 0 && gLoadAllocCount++ >= gLoadFailAfter) { return NULL; }
- return unityTestRealloc(block, size);
- }
- static void loadSetFailAfter(int32_t n)
- {
- gLoadFailAfter = n;
- gLoadAllocCount = 0;
- RyanJsonInitHooks(loadFailMalloc, unityTestFree, loadFailRealloc);
- }
- static void loadRestoreHooks(void)
- {
- RyanJsonInitHooks(unityTestMalloc, unityTestFree, unityTestRealloc);
- gLoadFailAfter = -1;
- gLoadAllocCount = 0;
- }
- static void testLoadFailureOomParse(void)
- {
- const char *longKeyJson =
- "{\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\":1}";
- loadSetFailAfter(0);
- RyanJson_t json = RyanJsonParse("{\"a\":1}");
- loadRestoreHooks();
- if (json) { RyanJsonDelete(json); }
- TEST_ASSERT_NULL_MESSAGE(json, "Parse OOM(根节点分配失败) 应返回 NULL");
- loadSetFailAfter(1); // root 成功,key buffer 失败
- json = RyanJsonParse(longKeyJson);
- loadRestoreHooks();
- if (json) { RyanJsonDelete(json); }
- TEST_ASSERT_NULL_MESSAGE(json, "Parse OOM 应返回 NULL");
- }
- void testLoadFailureRunner(void)
- {
- UnitySetTestFile(__FILE__);
- RUN_TEST(testLoadFailureNullAndWhitespace);
- RUN_TEST(testLoadFailureTruncated);
- RUN_TEST(testLoadFailureInvalidTokens);
- RUN_TEST(testLoadFailureInvalidNumbers);
- RUN_TEST(testLoadFailureHugeNumberOverflow);
- RUN_TEST(testLoadFailureInvalidEscapes);
- RUN_TEST(testLoadFailureInvalidUnicode);
- RUN_TEST(testLoadFailureInvalidStructure);
- RUN_TEST(testLoadFailureDuplicateKeyAfterDecode);
- RUN_TEST(testLoadFailureMalformedNesting);
- RUN_TEST(testLoadParseOptionsFailure);
- RUN_TEST(testLoadFailureOomParse);
- }
|