Files
ligent/tests/test_attach.c
T
2026-10-03 14:13:21 +08:00

178 lines
7.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* test_attach.c - /include 的暂存、glob 展开与体积/类型判断
*
* 交互式挑选(attach_pick)要真终端才能测,由 e2e 第 55 段覆盖;
* 这里测的是不需要人操作的那一半。
*/
#include "attach.h"
#include "image.h"
#include "json.h"
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
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"); \
} \
} while (0)
static void write_file(const char *path, const void *data, size_t n)
{
FILE *f = fopen(path, "wb");
if (!f) { perror(path); exit(2); }
if (n && fwrite(data, 1, n, f) != n) { perror("fwrite"); exit(2); }
fclose(f);
}
static const unsigned char PNG[] = {
0x89, 'P', 'N', 'G', 0x0D, 0x0A, 0x1A, 0x0A, 'p', 'a', 'y', 'l', 'o', 'a', 'd'
};
/* 数一数暂存里某类块有几个 */
static size_t count_type(const JsonValue *parts, const char *type)
{
if (!parts) return 0;
size_t n = 0;
for (size_t i = 0; i < json_array_size((JsonValue *)parts); i++) {
const char *t = json_get_string(json_array_get((JsonValue *)parts, i), "type");
if (t && strcmp(t, type) == 0) n++;
}
return n;
}
/* 记一下回调被问了几次 —— 它只在遇到图片时该被问到。
* 答案和计数放在一起,免得"计数版只实现了一种答案"这种测试自己的错。 */
static int ask_count;
static int ask_answer;
static int counting_ask(void *ud) { (void)ud; ask_count++; return ask_answer; }
int main(void)
{
char tmpl[] = "/tmp/ligent_attach_XXXXXX";
char *dir = mkdtemp(tmpl);
if (!dir) { perror("mkdtemp"); return 2; }
/* 备份目录也指到临时目录,别污染仓库 */
image_set_bindir(dir);
char *f_c = xasprintf("%s/a.c", dir);
char *f_txt = xasprintf("%s/b.txt", dir);
char *f_bin = xasprintf("%s/bin.dat", dir);
char *f_png = xasprintf("%s/pic.png", dir);
char *f_big = xasprintf("%s/big.txt", dir);
write_file(f_c, "int main(void){return 0;}\n", 26);
write_file(f_txt, "hello\n", 6);
write_file(f_bin, "\x00\x01\x02binary", 9);
write_file(f_png, PNG, sizeof PNG);
{
/* 超过单个文件上限(256 KB) */
size_t n = ATTACH_MAX_FILE + 1024;
char *big = xmalloc(n);
memset(big, 'x', n);
write_file(f_big, big, n);
free(big);
}
puts("glob 展开:命中几个就暂存几个");
attach_clear();
size_t skipped = 0;
char err[256];
int added = attach_glob(f_c, NULL, NULL, &skipped, err, sizeof err);
CHECK(added == 1 && attach_count() == 1, "命中一个文件");
CHECK(skipped == 0, "没有跳过任何东西");
JsonValue *parts = attach_take_parts();
CHECK(parts && json_array_size(parts) == 1, "取到 1 个块");
JsonValue *p0 = parts ? json_array_get(parts, 0) : NULL;
CHECK(p0 && strcmp(json_get_string(p0, "type"), "text") == 0,
"文本文件应当是 text 块");
const char *txt = p0 ? json_get_string(p0, "text") : NULL;
CHECK(txt && strstr(txt, "int main") != NULL, "内容带上了");
CHECK(txt && strncmp(txt, "===== ", 6) == 0, "块开头标了来源路径");
CHECK(txt && strchr(txt, '\n') != NULL, "结尾有换行");
/* 只在本地记的来源,绝不能进块里(那会跟着发给服务端) */
CHECK(p0 && json_get_string(p0, "source") == NULL,
"块里不该有自造的 source 字段");
json_free(parts);
CHECK(attach_count() == 0, "取走之后暂存清空");
puts("取走即清空,clear 也是");
attach_glob(f_c, NULL, NULL, &skipped, err, sizeof err);
CHECK(attach_count() == 1, "再附带一次");
attach_clear();
CHECK(attach_count() == 0, "attach_clear 清空");
CHECK(attach_take_parts() == NULL, "清空之后取不到东西");
puts("二进制文件跳过");
attach_clear();
added = attach_glob(f_bin, NULL, NULL, &skipped, err, sizeof err);
CHECK(added == 0 && skipped == 1, "二进制被跳过(added=%d skipped=%zu)",
added, skipped);
puts("超过单个文件上限的跳过");
attach_clear();
added = attach_glob(f_big, NULL, NULL, &skipped, err, sizeof err);
CHECK(added == 0 && skipped == 1, "太大的文本被跳过(added=%d)", added);
puts("图片:认内容不认扩展名,并走备份引用");
attach_clear();
added = attach_glob(f_png, NULL, NULL, &skipped, err, sizeof err);
CHECK(added == 1, "png 被收下");
CHECK(attach_has_image(), "暂存里有图片");
parts = attach_take_parts();
CHECK(count_type(parts, "ligent_image") == 1, "应当是一个 ligent_image 引用块");
json_free(parts);
puts("模型不收图时跳过图片(回调只在遇到图片时被问)");
attach_clear();
ask_count = 0; ask_answer = 1;
added = attach_glob(f_txt, counting_ask, NULL, &skipped, err, sizeof err);
CHECK(added == 1, "纯文本照带");
CHECK(ask_count == 0, "纯文本不该去问'能不能收图'(问了一次就是白探测)");
attach_clear();
ask_count = 0; ask_answer = 0;
added = attach_glob(f_png, counting_ask, NULL, &skipped, err, sizeof err);
CHECK(added == 0 && skipped == 1, "回调说不行就跳过");
CHECK(ask_count == 1, "遇到图片时问了一次,实际 %d", ask_count);
puts("匹配不到 / 参数非法");
attach_clear();
added = attach_glob("/tmp/绝对不存在的模式*.zzz", NULL, NULL, &skipped, err, sizeof err);
CHECK(added == -1 && err[0], "匹配不到返回 -1 并给出原因:%s", err);
added = attach_glob(NULL, NULL, NULL, &skipped, err, sizeof err);
CHECK(added == -1, "NULL 模式返回 -1");
added = attach_glob("", NULL, NULL, &skipped, err, sizeof err);
CHECK(added == -1, "空模式返回 -1");
puts("多个匹配会累加");
attach_clear();
char *pat = xasprintf("%s/*.txt", dir);
added = attach_glob(pat, NULL, NULL, &skipped, err, sizeof err);
CHECK(added == 1, "只有 b.txt 能带(big.txt 超限),实际 %d", added);
CHECK(skipped == 1, "big.txt 被跳过");
free(pat);
attach_clear();
free(f_c); free(f_txt); free(f_bin); free(f_png); free(f_big);
image_set_bindir(".");
char *cmd = xasprintf("rm -rf %s", tmpl);
if (system(cmd) != 0) { }
free(cmd);
printf("\n%d 项检查,%d 项失败\n", checks, failures);
return failures ? 1 : 0;
}