package service import ( "context" "testing" "fashionapi/internal/dto" ) // TestFetchLookImagesUsesProvidedKeys 验证「媒体机直传」分支: // payload 里带 main_key / detail_keys 时,worker 不应下载、不应上传, // 而是直接把 key 当作要落库的存储地址,且 cover 取首张主图。 // // 这条路径是媒体拆分的核心保证:一旦这里退化成下载 URL, // 后端又会重新背上带宽瓶颈,而错误会非常隐蔽(只是变慢,不报错)。 func TestFetchLookImagesUsesProvidedKeys(t *testing.T) { s := &IngestService{} // 不装配 uploader/vision:走 key 分支时它们都不该被用到 looks := []dto.RunwayLook{ { MainKey: "runway/aaaa.jpg", MainSize: 100, DetailKeys: []string{"runway/bbbb.jpg"}, DetailSizes: []int64{200}, }, { // 第二张混用旧形态:没有 key,带 URL(这里只验主图,不触发网络) MainKey: "runway/cccc.jpg", MainSize: 300, }, } cover, rows, vecs, keys, failed, _ := s.fetchLookImages(context.Background(), looks, "runway") if failed { t.Fatal("key 分支不应被判定为失败") } if cover != "runway/aaaa.jpg" { t.Fatalf("cover 应取首张主图 key,实际 %q", cover) } if len(rows) != 3 { t.Fatalf("应落 3 行(2 主图 + 1 细节图),实际 %d", len(rows)) } if rows[0].Image != "runway/aaaa.jpg" || rows[0].IsDetail != 0 { t.Fatalf("第 1 行应为 aaaa 主图,实际 %+v", rows[0]) } if rows[1].Image != "runway/bbbb.jpg" || rows[1].IsDetail != 1 { t.Fatalf("第 2 行应为 bbbb 细节图,实际 %+v", rows[1]) } if rows[1].ImageSize != 200 || rows[0].ImageSize != 100 { t.Fatalf("字节数应来自 payload,实际 %d / %d", rows[0].ImageSize, rows[1].ImageSize) } // 媒体机上传的 key 不进回滚清单(内容寻址、可能与他人共享) if len(keys) != 0 { t.Fatalf("key 分支不应产生回滚清单,实际 %v", keys) } if len(vecs) != len(rows) { t.Fatalf("vecs 应与 rows 对齐,实际 %d vs %d", len(vecs), len(rows)) } for i, v := range vecs { if v != nil { t.Fatalf("第 %d 张不应带向量(向量由 CLIP 回填),实际 %v", i, v) } } if got := countMainImages(rows); got != 2 { t.Fatalf("主图数应为 2,实际 %d", got) } } // TestSha1FromKey 锁住「从内容寻址 key 反推 sha1」的行为:批次内去重依赖它, // 若解析退化(例如带上目录前缀),同一张图会被重复落库。 func TestSha1FromKey(t *testing.T) { cases := map[string]string{ "runway/4080435af23d8f80bbbcf9e6f55a5f1d00c49685.jpg": "4080435af23d8f80bbbcf9e6f55a5f1d00c49685", "street/abc123.png": "abc123", "plain-key": "plain-key", } for in, want := range cases { if got := sha1FromKey(in); got != want { t.Fatalf("sha1FromKey(%q) = %q,期望 %q", in, got, want) } } }