178 lines
7.0 KiB
C
178 lines
7.0 KiB
C
/* 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;
|
|
}
|