style: 应用 clang-format

This commit is contained in:
pluv committed 2026-10-04 13:50:33 +08:00
1 parent 016a45bc6e
commit d1612f1d31
65 files changed
+7288 -5983

No files matched your search

+92 -68
View File
@@ -9,25 +9,26 @@
static int failures = 0;
static int checks = 0;
#define CHECK(cond, ...) \
do { \
checks++; \
if (!(cond)) { \
failures++; \
printf(" ✗ %s:%d: ", __FILE__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
} \
#define CHECK(cond, ...) \
do { \
checks++; \
if (!(cond)) { \
failures++; \
printf(" ✗ %s:%d: ", __FILE__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
} \
} while (0)
static void test_basic(void)
{
static void test_basic(void) {
puts("test_basic");
char err[256];
JsonValue *v = json_parse("{\"a\": 1, \"b\": [true, false, null], \"c\": \"hi\"}",
err, sizeof err);
JsonValue *v =
json_parse("{\"a\": 1, \"b\": [true, false, null], \"c\": \"hi\"}", err,
sizeof err);
CHECK(v != NULL, "解析失败: %s", err);
if (!v) return;
if (!v)
return;
CHECK(json_get_number(v, "a", -1) == 1, "a 应为 1");
CHECK(json_array_size(json_object_get(v, "b")) == 3, "b 应有 3 个元素");
CHECK(json_bool_value(json_array_get(json_object_get(v, "b"), 0), 0) == 1,
@@ -41,18 +42,20 @@ static void test_basic(void)
CHECK(v2 != NULL, "往返解析失败: %s", err);
char *dump2 = json_dump(v2);
CHECK(strcmp(dump, dump2) == 0, "往返不一致:\n %s\n %s", dump, dump2);
free(dump); free(dump2);
json_free(v); json_free(v2);
free(dump);
free(dump2);
json_free(v);
json_free(v2);
}
static void test_escapes(void)
{
static void test_escapes(void) {
puts("test_escapes");
char err[256];
JsonValue *v = json_parse("\"a\\nb\\t\\\"c\\\\d\\u4e2d\\u6587\\uD83D\\uDE00\"",
err, sizeof err);
JsonValue *v = json_parse(
"\"a\\nb\\t\\\"c\\\\d\\u4e2d\\u6587\\uD83D\\uDE00\"", err, sizeof err);
CHECK(v != NULL, "解析失败: %s", err);
if (!v) return;
if (!v)
return;
const char *s = json_string_value(v);
CHECK(strcmp(s, "a\nb\t\"c\\d中文😀") == 0, "转义解码错误: [%s]", s);
@@ -61,16 +64,18 @@ static void test_escapes(void)
CHECK(v2 != NULL, "转义往返失败: %s / %s", q, err);
CHECK(v2 && strcmp(json_string_value(v2), s) == 0, "转义往返内容不一致");
free(q);
json_free(v); json_free(v2);
json_free(v);
json_free(v2);
}
static void test_numbers(void)
{
static void test_numbers(void) {
puts("test_numbers");
char err[256];
JsonValue *v = json_parse("[0, -1, 3.5, 1e3, -2.5e-2, 123456789012]", err, sizeof err);
JsonValue *v =
json_parse("[0, -1, 3.5, 1e3, -2.5e-2, 123456789012]", err, sizeof err);
CHECK(v != NULL, "解析失败: %s", err);
if (!v) return;
if (!v)
return;
CHECK(json_number_value(json_array_get(v, 0), -1) == 0, "[0]");
CHECK(json_number_value(json_array_get(v, 1), 0) == -1, "[1]");
CHECK(json_number_value(json_array_get(v, 2), 0) == 3.5, "[2]");
@@ -92,24 +97,34 @@ static void test_numbers(void)
}
/* 边界上合法的写法不能被误伤 */
const char *ok_nums[] = {
"0", "-0", "0.0", "10", "-1.5", "1e3", "1E3", "1e+3", "1e-3", "0.1e10",
"123456789012345678901234567890", "1e308",
"0",
"-0",
"0.0",
"10",
"-1.5",
"1e3",
"1E3",
"1e+3",
"1e-3",
"0.1e10",
"123456789012345678901234567890",
"1e308",
};
for (size_t i = 0; i < sizeof ok_nums / sizeof ok_nums[0]; i++) {
JsonValue *g = json_parse(ok_nums[i], err, sizeof err);
CHECK(g != NULL && g->type == JSON_NUMBER,
"合法数字被拒: [%s] (%s)", ok_nums[i], err);
CHECK(g != NULL && g->type == JSON_NUMBER, "合法数字被拒: [%s] (%s)",
ok_nums[i], err);
json_free(g);
}
}
static void test_invalid(void)
{
static void test_invalid(void) {
puts("test_invalid");
char err[256];
const char *bad[] = {
"{", "}", "[1,]", "{\"a\":}", "\"unterminated", "tru", "{\"a\" 1}",
"[1 2]", "01abc", "", " ", "{\"a\":1}}", "[1,2] extra",
"{", "}", "[1,]", "{\"a\":}", "\"unterminated",
"tru", "{\"a\" 1}", "[1 2]", "01abc", "",
" ", "{\"a\":1}}", "[1,2] extra",
};
for (size_t i = 0; i < sizeof bad / sizeof bad[0]; i++) {
JsonValue *v = json_parse(bad[i], err, sizeof err);
@@ -118,12 +133,12 @@ static void test_invalid(void)
}
/* 空字符串是合法 JSON 字符串 */
JsonValue *e = json_parse("\"\"", err, sizeof err);
CHECK(e != NULL && strcmp(json_string_value(e), "") == 0, "空字符串应为合法");
CHECK(e != NULL && strcmp(json_string_value(e), "") == 0,
"空字符串应为合法");
json_free(e);
}
static void test_builders(void)
{
static void test_builders(void) {
puts("test_builders");
JsonValue *o = json_new_object();
json_object_set_string(o, "model", "gpt-x");
@@ -133,30 +148,34 @@ static void test_builders(void)
json_array_push(arr, json_new_string("a"));
json_array_push(arr, json_new_string("b"));
json_object_set(o, "items", arr);
json_object_set_string(o, "model", "gpt-y"); /* 覆盖 */
json_object_set_string(o, "model", "gpt-y"); /* 覆盖 */
char *s = json_dump(o);
CHECK(strcmp(s, "{\"model\":\"gpt-y\",\"n\":3,\"ok\":true,\"items\":[\"a\",\"b\"]}") == 0,
CHECK(strcmp(s, "{\"model\":\"gpt-y\",\"n\":3,\"ok\":true,\"items\":[\"a\","
"\"b\"]}") == 0,
"构造结果不对: %s", s);
free(s);
/* clone 独立性 */
JsonValue *c = json_clone(o);
json_object_set_string(o, "model", "changed");
CHECK(strcmp(json_get_string(c, "model"), "gpt-y") == 0, "clone 应相互独立");
CHECK(strcmp(json_get_string(c, "model"), "gpt-y") == 0,
"clone 应相互独立");
json_object_remove(o, "model");
CHECK(json_object_get(o, "model") == NULL, "remove 应删除键");
json_free(o); json_free(c);
json_free(o);
json_free(c);
}
static void test_nested_depth(void)
{
static void test_nested_depth(void) {
puts("test_nested_depth");
char err[256];
size_t n = 300;
char *deep = xmalloc(n * 2 + 1);
for (size_t i = 0; i < n; i++) deep[i] = '[';
for (size_t i = 0; i < n; i++) deep[n + i] = ']';
for (size_t i = 0; i < n; i++)
deep[i] = '[';
for (size_t i = 0; i < n; i++)
deep[n + i] = ']';
deep[n * 2] = '\0';
JsonValue *v = json_parse(deep, err, sizeof err);
CHECK(v == NULL, "超深嵌套应被拒绝");
@@ -168,8 +187,7 @@ static void test_nested_depth(void)
}
/* 报错必须能定位: 只有"语法错了"而不知道错在哪, 等于没有报错 */
static void test_error_location(void)
{
static void test_error_location(void) {
puts("test_error_location");
char err[256];
JsonValue *v;
@@ -192,7 +210,8 @@ static void test_error_location(void)
/* 缺冒号 */
v = json_parse("{\"a\" 1}", err, sizeof err);
CHECK(v == NULL, "缺冒号应报错");
CHECK(strstr(err, "第 1 行") && strstr(err, "':'") != NULL, "缺冒号: %s", err);
CHECK(strstr(err, "第 1 行") && strstr(err, "':'") != NULL, "缺冒号: %s",
err);
json_free(v);
/* 尾部多余内容 */
@@ -220,30 +239,29 @@ static void test_error_location(void)
json_free(v);
}
/* 序列化出去的东西必须是**合法 UTF-8**.
/* 序列化出去的东西必须是**合法 UTF-8**.
*
* 服务端会因为请求体里有非法 UTF-8 直接回
* 400 ... invalid unicode code point
* 而那段坏数据一旦进了对话历史, 之后每次请求都会失败 —— 除非丢掉整轮对话.
* 而那段坏数据一旦进了对话历史, 之后每次请求都会失败 —— 除非丢掉整轮对话.
* 坏字节的来源很日常: 某条命令在非 UTF-8 locale 下打出来的路径、被截断的多
* 字节字符、二进制垃圾. 所以这条不能只靠"在入口清理", 必须在序列化器这层兜住:
* 出口是唯一能保证"发出去的永远合法"的地方.
* 字节字符、二进制垃圾. 所以这条不能只靠"在入口清理", 必须在序列化器这层兜住:
* 出口是唯一能保证"发出去的永远合法"的地方.
*
* 这个校验函数故意用 utf8_seq_len 自己走一遍, 而不是信任 dump 的实现 ——
* 断言的是**产物**的性质, 不是实现的自述. */
static int utf8_all_valid(const char *s)
{
static int utf8_all_valid(const char *s) {
size_t n = strlen(s), i = 0;
while (i < n) {
size_t adv = utf8_seq_len(s + i, n - i);
if (adv == 0) return 0;
if (adv == 0)
return 0;
i += adv;
}
return 1;
}
static void test_dump_utf8_safety(void)
{
static void test_dump_utf8_safety(void) {
puts("test_dump_utf8_safety");
/* utf8_seq_len: 合法序列返回长度 */
@@ -262,19 +280,25 @@ static void test_dump_utf8_safety(void)
/* 各种坏字节经 json_dump 之后, 整份输出必须是合法 UTF-8 */
static const char *bad[] = {
"a\x80" "b", /* 孤立续字节 */
"a\xe4\xb8" "b", /* 截断的 3 字节序列 */
"a\xc0\xaf" "b", /* 过长编码 (历史上被用来夹带 '/') */
"a\xed\xa0\x80" "b", /* UTF-16 代理区 */
"a\xf5\x80\x80\x80" "b", /* 超出 U+10FFFF */
"\xff\xfe", /* 二进制垃圾 */
"\xe4\xb8\xad\x80\xe6", /* 合法中文里夹一个坏字节 */
"a\x80"
"b", /* 孤立续字节 */
"a\xe4\xb8"
"b", /* 截断的 3 字节序列 */
"a\xc0\xaf"
"b", /* 过长编码 (历史上被用来夹带 '/') */
"a\xed\xa0\x80"
"b", /* UTF-16 代理区 */
"a\xf5\x80\x80\x80"
"b", /* 超出 U+10FFFF */
"\xff\xfe", /* 二进制垃圾 */
"\xe4\xb8\xad\x80\xe6", /* 合法中文里夹一个坏字节 */
};
for (size_t k = 0; k < sizeof bad / sizeof bad[0]; k++) {
JsonValue *o = json_new_object();
json_object_set_string(o, "content", bad[k]);
char *d = json_dump(o);
CHECK(utf8_all_valid(d), "第 %zu 个坏输入序列化后仍含非法 UTF-8: %s", k, d);
CHECK(utf8_all_valid(d), "第 %zu 个坏输入序列化后仍含非法 UTF-8: %s", k,
d);
/* 而且我们的解析器 (和服务端一样严格)必须收得下 */
char err[256];
JsonValue *back = json_parse(d, err, sizeof err);
@@ -294,14 +318,14 @@ static void test_dump_utf8_safety(void)
json_object_set_string(o, "content", "中文 😀 tail");
char *d = json_dump(o);
CHECK(strstr(d, "中文") != NULL, "合法中文不该被改动: %s", d);
CHECK(strstr(d, "\xf0\x9f\x98\x80") != NULL, "合法 emoji 不该被改动: %s", d);
CHECK(strstr(d, "\xf0\x9f\x98\x80") != NULL, "合法 emoji 不该被改动: %s",
d);
CHECK(strstr(d, "\xef\xbf\xbd") == NULL, "合法输入不该出现替换字符: %s", d);
free(d);
json_free(o);
}
int main(void)
{
int main(void) {
test_basic();
test_escapes();
test_numbers();