81 lines
2.8 KiB
Go
81 lines
2.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"mime/multipart"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/basketikun/infinite-canvas/model"
|
|
)
|
|
|
|
func TestAIUpstreamErrorDetail(t *testing.T) {
|
|
got := aiUpstreamErrorDetail([]byte(`{"error":{"code":"InvalidParameter","message":"reference video fps is invalid"}}`))
|
|
if got != "InvalidParameter reference video fps is invalid" {
|
|
t.Fatalf("detail = %q", got)
|
|
}
|
|
}
|
|
|
|
func TestAIUpstreamErrorDetailExplainsSensitiveVideo(t *testing.T) {
|
|
got := aiUpstreamErrorDetail([]byte(`{"error":{"code":"InputVideoSensitiveContentDetected.PrivacyInformation","message":"The request failed because the input video may contain real person."}}`))
|
|
if !strings.Contains(got, "参考视频疑似包含真人") || !strings.Contains(got, "asset://") {
|
|
t.Fatalf("detail = %q", got)
|
|
}
|
|
}
|
|
|
|
func TestSafeUpstreamTextTruncates(t *testing.T) {
|
|
got := safeUpstreamText(strings.Repeat("错", 320))
|
|
if len([]rune(got)) != 303 {
|
|
t.Fatalf("truncated rune length = %d", len([]rune(got)))
|
|
}
|
|
}
|
|
|
|
func TestAdaptAIRequestForSub2APIImagesUsesURLResponseFormat(t *testing.T) {
|
|
body, contentType, err := adaptAIRequestForChannel([]byte(`{"model":"gpt-image-1","prompt":"cat"}`), "application/json", "/images/generations", model.ModelChannel{Compatibility: "sub2api"})
|
|
if err != nil {
|
|
t.Fatalf("adaptAIRequestForChannel returned error: %v", err)
|
|
}
|
|
if contentType != "application/json" {
|
|
t.Fatalf("contentType = %q", contentType)
|
|
}
|
|
var payload map[string]any
|
|
if err := json.Unmarshal(body, &payload); err != nil {
|
|
t.Fatalf("invalid json body: %v", err)
|
|
}
|
|
if got := payload["response_format"]; got != "url" {
|
|
t.Fatalf("response_format = %#v, want url", got)
|
|
}
|
|
}
|
|
|
|
func TestAdaptAIRequestForSub2APIImageEditsUpdatesMultipartResponseFormat(t *testing.T) {
|
|
var input bytes.Buffer
|
|
writer := multipart.NewWriter(&input)
|
|
_ = writer.WriteField("model", "gpt-image-1")
|
|
_ = writer.WriteField("response_format", "b64_json")
|
|
part, err := writer.CreateFormFile("image", "input.png")
|
|
if err != nil {
|
|
t.Fatalf("CreateFormFile: %v", err)
|
|
}
|
|
_, _ = part.Write([]byte("png"))
|
|
if err := writer.Close(); err != nil {
|
|
t.Fatalf("Close multipart writer: %v", err)
|
|
}
|
|
|
|
body, contentType, err := adaptAIRequestForChannel(input.Bytes(), writer.FormDataContentType(), "/images/edits", model.ModelChannel{Compatibility: "sub2api"})
|
|
if err != nil {
|
|
t.Fatalf("adaptAIRequestForChannel returned error: %v", err)
|
|
}
|
|
reader := multipart.NewReader(bytes.NewReader(body), strings.TrimPrefix(contentType, "multipart/form-data; boundary="))
|
|
form, err := reader.ReadForm(1024)
|
|
if err != nil {
|
|
t.Fatalf("ReadForm: %v", err)
|
|
}
|
|
if got := form.Value["response_format"]; len(got) != 1 || got[0] != "url" {
|
|
t.Fatalf("response_format = %#v, want [url]", got)
|
|
}
|
|
if files := form.File["image"]; len(files) != 1 || files[0].Filename != "input.png" {
|
|
t.Fatalf("image file = %#v", files)
|
|
}
|
|
}
|