125 lines
5.3 KiB
Go
125 lines
5.3 KiB
Go
package channelbridge
|
||
|
||
// 本文件承载 IM 入站附件摄取的**诚实性与边界**用例(design/24 §4.4;切片 M1),
|
||
// 与 inbound_documents_test.go 是同一批夹具的搬家(夹具留在那边,同包可见):
|
||
//
|
||
// - 拒绝原因必须**分类正确**:超限说超限,绝不笼统说成「格式不支持」;
|
||
// - 渠道只给远程引用(目前适配器的现实形态)时不代取、不静默;
|
||
// - 图片类媒体保持现状(不走文档摄取);
|
||
// - 组合根未接线时照旧跑回合,但模型知道附件读不到。
|
||
|
||
import (
|
||
"context"
|
||
"strings"
|
||
"testing"
|
||
|
||
"git.yeij.top/AskaEth/Cyrene_v2/internal/channel/adapter"
|
||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/documents"
|
||
)
|
||
|
||
// TestInboundOversizeFileIsHonestAboutSize 钉住诚实口径的**分类**:体积超限必须
|
||
// 说「超过体积上限」,绝不能笼统说成「格式不支持」——把原因说错也是不诚实。
|
||
func TestInboundOversizeFileIsHonestAboutSize(t *testing.T) {
|
||
t.Parallel()
|
||
env := newIngestEnv(t, documents.StoreConfig{MaxBytes: 8}, true)
|
||
msg := fileMessage("这个大吗", "big.txt", []byte("这是明显超过八个字节的正文\n"), "text/plain")
|
||
|
||
env.bridge.process(context.Background(), msg)
|
||
|
||
if names := docDirNames(t, env.uploads); len(names) != 0 {
|
||
t.Fatalf("超限附件被落库了:%v", names)
|
||
}
|
||
visible := env.model.visibleText()
|
||
if !strings.Contains(visible, "体积上限") {
|
||
t.Fatalf("超限附件的提示没有点明体积上限:%q", visible)
|
||
}
|
||
if strings.Contains(visible, "格式不在可读白名单内") {
|
||
t.Fatalf("超限附件被说成了「格式不支持」(原因说错):%q", visible)
|
||
}
|
||
if log := env.logs.String(); !strings.Contains(log, "inbound attachment rejected") {
|
||
t.Fatalf("缺少带来源的拒绝日志:%q", log)
|
||
}
|
||
}
|
||
|
||
// TestInboundRemoteOnlyMediaIsHonestWithoutFetch 钉住「字节为空」这一形态:桥接侧
|
||
// **不代取**(受支持格式的代取由适配器在入站时按平台资产白名单完成,切片 IM-1),
|
||
// 字节空 ⇒ 一行诚实提示 + 一条带来源的日志,绝不静默。
|
||
func TestInboundRemoteOnlyMediaIsHonestWithoutFetch(t *testing.T) {
|
||
t.Parallel()
|
||
env := newIngestEnv(t, documents.StoreConfig{}, true)
|
||
msg := directMessage()
|
||
msg.Content = "这个文件里是什么"
|
||
msg.Media = []adapter.Media{{
|
||
Kind: adapter.MediaFile, URL: "https://cdn.example.com/secret-token=abc/report.pdf",
|
||
Name: "report.pdf", Size: 1024, MIMEType: "application/pdf",
|
||
}}
|
||
|
||
env.bridge.process(context.Background(), msg)
|
||
|
||
if names := docDirNames(t, env.uploads); len(names) != 0 {
|
||
t.Fatalf("远程引用的附件被落库了:%v", names)
|
||
}
|
||
visible := env.model.visibleText()
|
||
if !strings.Contains(visible, "report.pdf") || !strings.Contains(visible, "远程引用") {
|
||
t.Fatalf("模型可见视图里没有诚实提示行:%q", visible)
|
||
}
|
||
log := env.logs.String()
|
||
if !strings.Contains(log, "no inlined bytes") {
|
||
t.Fatalf("缺少「无内联字节」的带来源日志:%q", log)
|
||
}
|
||
// 远程引用可能带凭据,绝不进日志。
|
||
if strings.Contains(log, "secret-token=abc") {
|
||
t.Fatalf("日志里出现了远程引用原串(可能含凭据):%q", log)
|
||
}
|
||
}
|
||
|
||
// TestInboundImageMediaKeepsExistingPath 钉住边界:图片类媒体**不**走文档摄取
|
||
// (design/24 §4.2 末:图片走既有视觉链路),因此不落库、不挂文档部件、不产生文档提示行。
|
||
// 它的视觉链路出口是 inbound_images.go 的 data: URI 图片部件(与本文的文档路互不影响)。
|
||
func TestInboundImageMediaKeepsExistingPath(t *testing.T) {
|
||
t.Parallel()
|
||
env := newIngestEnv(t, documents.StoreConfig{}, true)
|
||
msg := directMessage()
|
||
msg.Content = "看这张图"
|
||
msg.Media = []adapter.Media{{
|
||
Kind: adapter.MediaImage, Name: "photo.png", MIMEType: "image/png",
|
||
Data: []byte("\x89PNG\r\n\x1a\n"), Size: 8,
|
||
}}
|
||
|
||
env.bridge.process(context.Background(), msg)
|
||
|
||
if names := docDirNames(t, env.uploads); len(names) != 0 {
|
||
t.Fatalf("图片类媒体被文档摄取落库了:%v", names)
|
||
}
|
||
visible := env.model.visibleText()
|
||
if strings.Contains(visible, "[附件 ") || strings.Contains(visible, "无法读取") {
|
||
t.Fatalf("图片类媒体产生了文档清单/提示行:%q", visible)
|
||
}
|
||
if !strings.Contains(visible, "看这张图") {
|
||
t.Fatalf("用户文本丢了:%q", visible)
|
||
}
|
||
if log := env.logs.String(); strings.Contains(log, "attachment") {
|
||
t.Fatalf("图片类媒体产生了附件日志:%q", log)
|
||
}
|
||
}
|
||
|
||
// TestInboundFileMediaWithoutStoreIsHonest 钉住「未接线」路径:组合根没给落盘配置时,
|
||
// 带文件的消息照旧能跑(模型收到诚实提示),只是不落库 —— 绝不假装读到了。
|
||
func TestInboundFileMediaWithoutStoreIsHonest(t *testing.T) {
|
||
t.Parallel()
|
||
env := newIngestEnv(t, documents.StoreConfig{}, false)
|
||
msg := fileMessage("这个文件呢", "notes.txt", []byte("正文\n"), "text/plain")
|
||
|
||
env.bridge.process(context.Background(), msg)
|
||
|
||
if env.model.calls() == 0 {
|
||
t.Fatal("未接线时回合没有跑到模型")
|
||
}
|
||
if !strings.Contains(env.model.visibleText(), "未接线文档存储") {
|
||
t.Fatalf("未接线时没有诚实提示:%q", env.model.visibleText())
|
||
}
|
||
if log := env.logs.String(); !strings.Contains(log, "document store not wired") {
|
||
t.Fatalf("未接线时没有带来源的日志:%q", log)
|
||
}
|
||
}
|