chore: 规范标点

This commit is contained in:
pluv committed 2026-10-03 14:43:43 +08:00
1 parent e54390a9f8
commit 15e79887fa
84 files changed
+5439 -5398

No files matched your search

+42 -42
View File
@@ -44,14 +44,14 @@ static void test_defaults(void)
LigentConfig c;
config_defaults(&c);
CHECK(strcmp(c.model, "deepseek-flash") == 0,
"默认模型应为 deepseek-flash,实际 %s", c.model);
"默认模型应为 deepseek-flash, 实际 %s", c.model);
CHECK(strcmp(c.base_url, "https://api.deepseek.com/v1") == 0,
"默认 base_url 应为 DeepSeek,实际 %s", c.base_url);
"默认 base_url 应为 DeepSeek, 实际 %s", c.base_url);
CHECK(c.api_key && c.api_key[0] == '\0', "默认 api_key 应为空");
CHECK(c.stream == 1, "默认应开启流式");
CHECK(c.use_tools == 1, "默认应启用工具");
/* 默认不限往返次数:0(或负数)= 不限,只有正数才是上限 */
CHECK(c.max_steps == 0, "默认应不限往返次数,实际 %d", c.max_steps);
/* 默认不限往返次数:0 (或负数)= 不限, 只有正数才是上限 */
CHECK(c.max_steps == 0, "默认应不限往返次数, 实际 %d", c.max_steps);
config_free(&c);
}
@@ -70,13 +70,13 @@ static void test_env_key(void)
setenv("DEEPSEEK_API_KEY", "sk-deepseek", 1);
config_apply_env(&c);
CHECK(strcmp(c.api_key, "sk-deepseek") == 0,
"应读 $DEEPSEEK_API_KEY,实际 [%s]", c.api_key);
"应读 $DEEPSEEK_API_KEY, 实际 [%s]", c.api_key);
/* LIGENT_API_KEY 作为显式覆盖优先 */
setenv("LIGENT_API_KEY", "sk-explicit", 1);
config_apply_env(&c);
CHECK(strcmp(c.api_key, "sk-explicit") == 0,
"LIGENT_API_KEY 应覆盖,实际 [%s]", c.api_key);
"LIGENT_API_KEY 应覆盖, 实际 [%s]", c.api_key);
/* OPENAI_API_KEY 只在端点确实是 OpenAI 时才兜底 ——
* 把 OpenAI 的密钥发给 DeepSeek 的端点是没有意义的 */
@@ -92,7 +92,7 @@ static void test_env_key(void)
c.base_url = xstrdup("https://api.openai.com/v1");
config_apply_env(&c);
CHECK(strcmp(c.api_key, "sk-openai") == 0,
"OpenAI 端点应兜底到 OPENAI_API_KEY,实际 %s", c.api_key);
"OpenAI 端点应兜底到 OPENAI_API_KEY, 实际 %s", c.api_key);
unset_all();
config_free(&c);
@@ -121,7 +121,7 @@ static void test_env_others(void)
unset_all();
config_free(&c);
/* 环境变量是临时开关:写错了应当被忽略,而不是把程序拦下来 */
/* 环境变量是临时开关:写错了应当被忽略, 而不是把程序拦下来 */
config_defaults(&c);
setenv("LIGENT_THINKING", "随便写的", 1);
setenv("LIGENT_REASONING_EFFORT", "超高", 1);
@@ -198,7 +198,7 @@ static void test_file_thinking(void)
unlink(t2);
}
/* 写错了必须报错,不能静默忽略 —— 配置文件是长期存在的,静默会让人困惑 */
/* 写错了必须报错, 不能静默忽略 —— 配置文件是长期存在的, 静默会让人困惑 */
char t3[] = "/tmp/ligent_think_XXXXXX";
fd = mkstemp(t3);
if (fd >= 0) {
@@ -259,7 +259,7 @@ static void test_file_override(void)
CHECK(strcmp(c.base_url, "http://localhost:11434/v1") == 0, "base_url 覆盖");
CHECK(strcmp(c.model, "qwen2.5:14b") == 0, "model 覆盖");
CHECK(strcmp(c.api_key, "sk-from-env") == 0,
"${MY_SECRET} 应被展开,实际 [%s]", c.api_key);
"${MY_SECRET} 应被展开, 实际 [%s]", c.api_key);
CHECK(c.temperature > 0.29 && c.temperature < 0.31, "temperature 覆盖");
CHECK(c.max_tokens == 4096, "max_tokens 覆盖");
CHECK(c.max_steps == 9, "max_steps 覆盖");
@@ -267,10 +267,10 @@ static void test_file_override(void)
CHECK(c.use_tools == 0, "tools 覆盖");
CHECK(c.config_path && strcmp(c.config_path, tmpl) == 0, "记录配置文件路径");
/* 坏配置应报错而不是静默通过。
/* 坏配置应报错而不是静默通过.
*
* 解析器的报错跟着界面语言走(json_parse_ui),所以下面这段断语先把语言
* 钉住,再顺手把英文那份也验一遍 —— 位置信息两种语言都得有。 */
* 解析器的报错跟着界面语言走 (json_parse_ui), 所以下面这段断语先把语言
* 钉住, 再顺手把英文那份也验一遍 —— 位置信息两种语言都得有. */
char tmpl2[] = "/tmp/ligent_bad_XXXXXX";
int fd2 = mkstemp(tmpl2);
if (fd2 >= 0) {
@@ -284,7 +284,7 @@ static void test_file_override(void)
CHECK(config_load_file(&c2, tmpl2, err, sizeof err) != 0,
"非法 JSON 应加载失败");
CHECK(err[0] != '\0', "应给出错误信息");
/* 报错必须带上文件路径与出错位置,否则用户无从下手 */
/* 报错必须带上文件路径与出错位置, 否则用户无从下手 */
CHECK(strstr(err, tmpl2) != NULL, "错误信息应含文件路径: %s", err);
CHECK(strstr(err, "行") != NULL, "错误信息应含出错位置: %s", err);
config_free(&c2);
@@ -294,7 +294,7 @@ static void test_file_override(void)
config_defaults(&c3);
CHECK(config_load_file(&c3, tmpl2, err, sizeof err) != 0 &&
strstr(err, "line") != NULL,
"英文界面下报错也带位置(且是英文): %s", err);
"英文界面下报错也带位置 (且是英文): %s", err);
config_free(&c3);
i18n_set_lang(LIGENT_LANG_ZH);
unlink(tmpl2);
@@ -305,7 +305,7 @@ static void test_file_override(void)
unset_all();
}
/* 配置只认二进制所在目录:不做用户级、系统级,也不做当前目录查找 */
/* 配置只认二进制所在目录:不做用户级、系统级, 也不做当前目录查找 */
static void test_binary_dir_lookup(void)
{
puts("配置位置 = 二进制所在目录");
@@ -319,7 +319,7 @@ static void test_binary_dir_lookup(void)
CHECK(canon && dir && str_starts_with(canon, dir),
"规范路径应位于二进制目录下: %s / %s", canon, dir);
/* 当前目录放一份 ligent.json,它绝不能被加载 */
/* 当前目录放一份 ligent.json, 它绝不能被加载 */
char tmpl[] = "/tmp/ligent_cwd_XXXXXX";
char *tmp = mkdtemp(tmpl);
if (!tmp) { free(dir); free(canon); return; }
@@ -343,7 +343,7 @@ static void test_binary_dir_lookup(void)
CHECK(!loaded_from_cwd, "不应加载当前工作目录下的 ligent.json");
CHECK(got_dir && dir && strcmp(got_dir, dir) == 0,
"config_dir 应是二进制目录,实际 %s", got_dir ? got_dir : "(null)");
"config_dir 应是二进制目录, 实际 %s", got_dir ? got_dir : "(null)");
free(got_dir);
free(saved);
@@ -369,16 +369,16 @@ static int load_temp_config(LigentConfig *c, const char *json)
return rc;
}
/* 厂商专属的环境变量不能越权覆盖配置文件里写好的密钥。
* 这正是用户踩到的坑:配置写了 OpenRouter 的 key,
* shell 里残留的 DEEPSEEK_API_KEY 把它顶掉,于是 A 家的密钥发给了 B 家。 */
/* 厂商专属的环境变量不能越权覆盖配置文件里写好的密钥.
* 这正是用户踩到的坑:配置写了 OpenRouter 的 key,
* shell 里残留的 DEEPSEEK_API_KEY 把它顶掉, 于是 A 家的密钥发给了 B 家. */
static void test_env_key_precedence(void)
{
puts("api_key 优先级:厂商环境变量不得越权");
unset_all();
setenv("DEEPSEEK_API_KEY", "sk-leftover-in-shell", 1);
/* 1) 配置文件写了 key => 它就是最终值,环境变量顶不掉 */
/* 1) 配置文件写了 key => 它就是最终值, 环境变量顶不掉 */
LigentConfig c;
config_defaults(&c);
CHECK(load_temp_config(&c,
@@ -386,7 +386,7 @@ static void test_env_key_precedence(void)
"\"api_key\":\"sk-or-v1-from-file\"}") == 0, "加载配置失败");
config_apply_env(&c);
CHECK(strcmp(c.api_key, "sk-or-v1-from-file") == 0,
"配置文件里的 key 不应被残留环境变量顶掉,实际 %s", c.api_key);
"配置文件里的 key 不应被残留环境变量顶掉, 实际 %s", c.api_key);
config_free(&c);
/* 2) 配置文件没写 key + 端点就是 DeepSeek => 用 DEEPSEEK_API_KEY 兜底 */
@@ -395,19 +395,19 @@ static void test_env_key_precedence(void)
"加载配置失败");
config_apply_env(&c);
CHECK(strcmp(c.api_key, "sk-leftover-in-shell") == 0,
"DeepSeek 端点应能用 DEEPSEEK_API_KEY 兜底,实际 %s", c.api_key);
"DeepSeek 端点应能用 DEEPSEEK_API_KEY 兜底, 实际 %s", c.api_key);
config_free(&c);
/* 3) 配置文件没写 key + 端点是别家 => 不猜,宁可空着让用户看到明确提示 */
/* 3) 配置文件没写 key + 端点是别家 => 不猜, 宁可空着让用户看到明确提示 */
config_defaults(&c);
CHECK(load_temp_config(&c, "{\"base_url\":\"https://openrouter.ai/api/v1\"}") == 0,
"加载配置失败");
config_apply_env(&c);
CHECK(c.api_key[0] == '\0',
"base_url 指向别家时不应拿 DeepSeek 的密钥去猜,实际 %s", c.api_key);
"base_url 指向别家时不应拿 DeepSeek 的密钥去猜, 实际 %s", c.api_key);
config_free(&c);
/* 4) LIGENT_API_KEY 是显式覆盖,任何时候都最高 */
/* 4) LIGENT_API_KEY 是显式覆盖, 任何时候都最高 */
setenv("LIGENT_API_KEY", "sk-explicit", 1);
config_defaults(&c);
CHECK(load_temp_config(&c,
@@ -415,46 +415,46 @@ static void test_env_key_precedence(void)
"\"api_key\":\"sk-or-v1-from-file\"}") == 0, "加载配置失败");
config_apply_env(&c);
CHECK(strcmp(c.api_key, "sk-explicit") == 0,
"LIGENT_API_KEY 应最高优先,实际 %s", c.api_key);
"LIGENT_API_KEY 应最高优先, 实际 %s", c.api_key);
config_free(&c);
unset_all();
}
/* 软链接:配置目录要跟着"用户实际调用那个文件"走。
* 否则把 ligent 软链到 ~/bin 之后,配置会被悄悄挪到源文件所在的目录,
* 用户放在 ~/bin 旁边的 ligent.json 就永远读不到。 */
/* 软链接:配置目录要跟着"用户实际调用那个文件"走.
* 否则把 ligent 软链到 ~/bin 之后, 配置会被悄悄挪到源文件所在的目录,
* 用户放在 ~/bin 旁边的 ligent.json 就永远读不到. */
static void test_symlink_dir(void)
{
puts("软链接:配置目录跟着软链接走");
char self[PATH_MAX];
ssize_t n = readlink("/proc/self/exe", self, sizeof self - 1);
if (n <= 0) { puts(" (没有 /proc/self/exe,跳过)"); return; }
if (n <= 0) { puts(" (没有 /proc/self/exe, 跳过)"); return; }
self[n] = '\0';
char tmpl[] = "/tmp/ligent_link_XXXXXX";
char *dir = mkdtemp(tmpl);
if (!dir) { puts(" (mkdtemp 失败,跳过)"); return; }
if (!dir) { puts(" (mkdtemp 失败, 跳过)"); return; }
char *link = xasprintf("%s/ligent", dir);
if (symlink(self, link) != 0) {
puts(" (symlink 失败,跳过)");
puts(" (symlink 失败, 跳过)");
free(link); rmdir(dir);
return;
}
/* 核心:指向软链接时取软链接所在目录,而不是源文件所在目录 */
/* 核心:指向软链接时取软链接所在目录, 而不是源文件所在目录 */
char *got = config_binary_dir(link);
CHECK(got && strcmp(got, dir) == 0,
"应取软链接所在目录 %s,实际 %s", dir, got ? got : "(null)");
"应取软链接所在目录 %s, 实际 %s", dir, got ? got : "(null)");
free(got);
/* 路径里的 . 应被规范化,但最后一段仍不解析 */
/* 路径里的 . 应被规范化, 但最后一段仍不解析 */
char *dotted = xasprintf("%s/./ligent", dir);
got = config_binary_dir(dotted);
CHECK(got && strcmp(got, dir) == 0,
"带 . 的路径应规范化,实际 %s", got ? got : "(null)");
"带 . 的路径应规范化, 实际 %s", got ? got : "(null)");
free(got); free(dotted);
/* argv[0] 只是个名字时经 $PATH 找到的仍应是软链接本身 */
@@ -463,18 +463,18 @@ static void test_symlink_dir(void)
setenv("PATH", newpath, 1);
got = config_binary_dir("ligent");
CHECK(got && strcmp(got, dir) == 0,
"$PATH 找到软链接时应取它所在目录,实际 %s", got ? got : "(null)");
"$PATH 找到软链接时应取它所在目录, 实际 %s", got ? got : "(null)");
free(got);
if (saved) setenv("PATH", saved, 1); else unsetenv("PATH");
free(saved); free(newpath);
/* 直接用真实文件时,取的还是真实目录 */
/* 直接用真实文件时, 取的还是真实目录 */
char *selfdir = xstrdup(self);
char *slash = strrchr(selfdir, '/');
if (slash) *slash = '\0';
got = config_binary_dir(self);
CHECK(got && strcmp(got, selfdir) == 0,
"真实文件应取真实目录 %s,实际 %s", selfdir, got ? got : "(null)");
"真实文件应取真实目录 %s, 实际 %s", selfdir, got ? got : "(null)");
free(got); free(selfdir);
unlink(link);
@@ -493,6 +493,6 @@ int main(void)
test_binary_dir_lookup();
test_env_key_precedence();
test_symlink_dir();
printf("\n%d 项检查,%d 项失败\n", checks, failures);
printf("\n%d 项检查, %d 项失败\n", checks, failures);
return failures ? 1 : 0;
}