sub2api/backend/internal/pkg/windsurf/chat_media_test.go

116 lines
3.7 KiB
Go

package windsurf
import (
"encoding/base64"
"testing"
)
func TestValidateCascadeImages_AllowedMime(t *testing.T) {
png := base64.StdEncoding.EncodeToString([]byte("\x89PNG\r\n\x1a\nfake"))
tests := []struct {
mime string
wantErr bool
}{
{"image/png", false},
{"image/jpeg", false},
{"image/gif", false},
{"image/svg+xml", false},
{"image/webp", true},
{"text/plain", true},
}
for _, tt := range tests {
imgs := []CascadeImage{{MimeType: tt.mime, Base64Data: png}}
err := ValidateCascadeImages(imgs, DefaultCascadeImageValidationOptions())
if (err != nil) != tt.wantErr {
t.Errorf("mime=%s err=%v wantErr=%v", tt.mime, err, tt.wantErr)
}
}
}
func TestValidateCascadeImages_CountLimit(t *testing.T) {
png := base64.StdEncoding.EncodeToString([]byte("\x89PNG"))
imgs := make([]CascadeImage, 6)
for i := range imgs {
imgs[i] = CascadeImage{MimeType: "image/png", Base64Data: png}
}
err := ValidateCascadeImages(imgs, DefaultCascadeImageValidationOptions())
if err == nil {
t.Fatalf("expected count limit error")
}
}
func TestValidateCascadeImages_InvalidBase64(t *testing.T) {
imgs := []CascadeImage{{MimeType: "image/png", Base64Data: "!!!not-base64"}}
err := ValidateCascadeImages(imgs, DefaultCascadeImageValidationOptions())
if err == nil {
t.Fatalf("expected invalid base64 error")
}
}
func TestValidateCascadeImages_EmptyData(t *testing.T) {
imgs := []CascadeImage{{MimeType: "image/png", Base64Data: ""}}
err := ValidateCascadeImages(imgs, DefaultCascadeImageValidationOptions())
if err == nil {
t.Fatalf("expected empty data error")
}
}
func TestValidateCascadeImages_ByteLimit(t *testing.T) {
big := make([]byte, CascadeImageMaxBytes+1)
imgs := []CascadeImage{{MimeType: "image/png", Base64Data: base64.StdEncoding.EncodeToString(big)}}
err := ValidateCascadeImages(imgs, DefaultCascadeImageValidationOptions())
if err == nil {
t.Fatalf("expected size limit error")
}
}
func TestValidateCascadeImages_PopulatesDigest(t *testing.T) {
png := base64.StdEncoding.EncodeToString([]byte("\x89PNG\r\n\x1a\nfake"))
imgs := []CascadeImage{{MimeType: "image/PNG", Base64Data: png}}
if err := ValidateCascadeImages(imgs, DefaultCascadeImageValidationOptions()); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if imgs[0].SHA256 == "" {
t.Errorf("sha256 should be populated")
}
if imgs[0].ByteLen == 0 {
t.Errorf("byteLen should be populated")
}
if imgs[0].MimeType != "image/png" {
t.Errorf("mime should be normalized to lowercase, got %q", imgs[0].MimeType)
}
}
func TestBuildImageDigests(t *testing.T) {
imgs := []CascadeImage{
{MimeType: "image/png", SHA256: "abc", ByteLen: 10, Caption: "x", Base64Data: "ignored"},
{MimeType: "image/jpeg", SHA256: "def", ByteLen: 20},
}
out := BuildImageDigests(imgs)
if len(out) != 2 {
t.Fatalf("expected 2 digests, got %d", len(out))
}
if out[0].MimeType != "image/png" || out[0].SHA256 != "abc" || out[0].ByteLen != 10 || out[0].Caption != "x" {
t.Errorf("digest[0] mismatch: %+v", out[0])
}
// ImageDigest 不应包含 base64 字段
// (这个通过结构体字段检查,而非运行时 — 此处只是确认编译通过)
}
func TestComputeImageDigest(t *testing.T) {
img := CascadeImage{MimeType: "IMAGE/PNG", Base64Data: base64.StdEncoding.EncodeToString([]byte("hello"))}
if err := ComputeImageDigest(&img); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if img.ByteLen != 5 {
t.Errorf("byteLen=%d want 5", img.ByteLen)
}
// sha256("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
if img.SHA256 != "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" {
t.Errorf("sha256 mismatch: %s", img.SHA256)
}
if img.MimeType != "image/png" {
t.Errorf("mime not normalized: %s", img.MimeType)
}
}