package main import ( "os" "path/filepath" "strings" "testing" ) // TestWireDocumentGC_IsWired 是一道「接线存在性」防回归检查(切片 S7;与 // TestWireChannels_WiresInboundDocumentStore 同一手法)。 // // 组合根本身无法在单元测试里实例化(开库、迁移、绑端口,而后端还在运行),因此 // 「引用计数确实被接上」「启动期/定时清扫确实被拉起」「关闭时确实被停掉」只能在 // 源码层钉住:少任何一处,GC 都会**静默不工作**(消息照写、文件照留、日志里一句 // 都没有),而这不会让任何既有用例变红。 // // 最后一段是 `.env.example` 的同步检查(AGENTS §10 铁律):新键必须与代码里的 // env 标签**逐字一致**,否则照模板部署的新实例会漏配且静默失效。 func TestWireDocumentGC_IsWired(t *testing.T) { t.Parallel() seams := map[string][]string{ "wire_services.go": { // 引用计数写入面注入 history(消息落库/编辑/删除都在那里增减)。 "history.WithDocumentRefs(documents.NewRefCounter(a.log))", // 回收循环必须在关库之前停下(清扫用那条连接池)。 "a.docGC.stop()", }, "wire_document_gc.go": { "documents.NewGC(documents.GCConfig{", // 目录口径与网关上传、摄取层读取逐字同源(`/uploads/documents`)。 `UploadsDir: filepath.Join(docDataDir, "uploads", "documents")`, "Interval: a.cfg.Server.DocumentGCInterval", "Retention: a.cfg.Server.DocumentRetention", }, "main.go": { // 启动期清扫 + 定时:没有这一行,GC 只存在于代码里而从不运行。 "a.startDocumentGC(ctx)", }, } for file, wants := range seams { src, err := os.ReadFile(file) if err != nil { t.Fatalf("read %s: %v", file, err) } for _, want := range wants { if !strings.Contains(string(src), want) { t.Fatalf("%s 里找不到 %q —— 文档引用计数/回收没有被接上组合根", file, want) } } } // .env.example 的两个新键必须与代码里的 env 标签逐字一致。 raw, err := os.ReadFile(filepath.Join("..", "..", ".env.example")) if err != nil { t.Fatalf("read .env.example: %v", err) } for _, key := range []string{"DOCUMENT_GC_INTERVAL=", "DOCUMENT_RETENTION="} { if !strings.Contains(string(raw), key) { t.Fatalf(".env.example 里找不到 %q(新 env 键必须同步模板,AGENTS §10)", key) } } }