chore: 规范标点
This commit is contained in:
1 parent
e54390a9f8
commit
15e79887fa
84 files changed
+5439
-5398
No files matched your search
+42
-42
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user