package store import ( "testing" "oneblog/internal/model" ) func countKind(refs []model.FileRef, kind string) int { n := 0 for _, r := range refs { if r.Kind == kind { n++ } } return n } // 同一个 key 在正文里的三种形态都要认出来:R2 直链、本地 /uploads、缩略图路径。 func TestFileReferencesMatchesKeyNotURL(t *testing.T) { s := openTestStore(t) const key = "2026/09/deadbeefcafe.png" if _, err := s.Create(model.PostInput{ Kind: model.KindLong, Title: "直链引用", Slug: "r2", CoverURL: "https://cdn.example.com/" + key, ContentMd: "正文配图 ![图](https://cdn.example.com/" + key + ")", Status: model.StatusPublished, }); err != nil { t.Fatal(err) } if _, err := s.Create(model.PostInput{ Kind: model.KindShort, Slug: "local", ContentMd: "本地形态 ![](/uploads/" + key + ") 和缩略图 ![](/uploads/thumb/" + key + "?w=480)", Status: model.StatusDraft, }); err != nil { t.Fatal(err) } refs, err := s.FileReferences(key) if err != nil { t.Fatal(err) } // 两篇文章各算一处:同一行里多次命中不重复计 if len(refs) != 2 { t.Fatalf("want 2 refs, got %+v", refs) } if countKind(refs, "post") != 2 { t.Fatalf("两条都该是 post: %+v", refs) } // 草稿也要报出来(发布后就会图裂) if refs[1].Status != model.StatusDraft { t.Fatalf("草稿状态没带出来: %+v", refs[1]) } } func TestFileReferencesProjectsAndAvatar(t *testing.T) { s := openTestStore(t) const key = "2026/09/111122223333.webp" if _, err := s.CreateProject(model.ProjectInput{ Title: "ONE", Slug: "one", CoverURL: "/uploads/" + key, Status: model.StatusPublished, }); err != nil { t.Fatal(err) } if err := s.SetSetting("owner_avatar_key", key); err != nil { t.Fatal(err) } refs, err := s.FileReferences(key) if err != nil { t.Fatal(err) } if countKind(refs, "project") != 1 { t.Fatalf("项目封面没查到: %+v", refs) } if countKind(refs, "avatar") != 1 { t.Fatalf("站主头像没查到: %+v", refs) } } // 没被引用、以及 key 为空时都不能误报——空 pattern 会 LIKE '%%' 命中全库。 func TestFileReferencesNoFalsePositive(t *testing.T) { s := openTestStore(t) if _, err := s.Create(model.PostInput{ Kind: model.KindLong, Title: "无关", Slug: "x", ContentMd: "正文里没有这张图", CoverURL: "/uploads/2026/09/aaaa.png", Status: model.StatusPublished, }); err != nil { t.Fatal(err) } // 同内容不同月上传出的 key 只是月份段不同,不该互相命中 refs, err := s.FileReferences("2026/10/aaaa.png") if err != nil { t.Fatal(err) } if len(refs) != 0 { t.Fatalf("换月的 key 误报: %+v", refs) } empty, err := s.FileReferences("") if err != nil { t.Fatal(err) } if len(empty) != 0 { t.Fatalf("空 key 不该匹配任何东西,得到 %+v", empty) } }