97 lines
3.8 KiB
Go
97 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.cin.su/m/Assistant/adapters/multimodal"
|
|
"git.cin.su/m/Assistant/contracts/capability"
|
|
)
|
|
|
|
func TestMultimodalTranscriptionHandlerReturnsLocalResult(t *testing.T) {
|
|
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/inference" || r.Method != http.MethodPost {
|
|
t.Fatalf("unexpected upstream request: %s %s", r.Method, r.URL.Path)
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]string{"text": "добрый день"})
|
|
}))
|
|
defer upstream.Close()
|
|
server := multimodalGateway{speech: multimodal.SpeechClient{BaseURL: upstream.URL, Client: upstream.Client()}, now: time.Now}
|
|
request := multipartRequest(t, "/v1/multimodal/transcribe", "voice.wav", []byte("audio"))
|
|
response := httptest.NewRecorder()
|
|
server.handler(capability.MultimodalTranscribe)(response, request)
|
|
if response.Code != http.StatusOK || !bytes.Contains(response.Body.Bytes(), []byte("добрый день")) {
|
|
t.Fatalf("status=%d body=%s", response.Code, response.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestMultimodalImageGenerationFailsClosedWhenSkillIsUnbound(t *testing.T) {
|
|
server := multimodalGateway{now: time.Now}
|
|
body := &bytes.Buffer{}
|
|
writer := multipart.NewWriter(body)
|
|
if err := writer.WriteField("prompt", "green bird"); err != nil || writer.Close() != nil {
|
|
t.Fatal("failed to build generation request")
|
|
}
|
|
request := httptest.NewRequest(http.MethodPost, "/v1/multimodal/generate-image", body)
|
|
request.Header.Set("Content-Type", writer.FormDataContentType())
|
|
response := httptest.NewRecorder()
|
|
server.handler(capability.MultimodalGenerateImage)(response, request)
|
|
if response.Code != http.StatusBadGateway || !bytes.Contains(response.Body.Bytes(), []byte("unavailable")) {
|
|
t.Fatalf("status=%d body=%s", response.Code, response.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestImageRequestSizeUsesExplicitSizeOrQualityTarget(t *testing.T) {
|
|
for _, test := range []struct {
|
|
name string
|
|
prompt string
|
|
requested string
|
|
want string
|
|
}{
|
|
{name: "explicit", prompt: "нарисуй птицу", requested: "768x512", want: "768x512"},
|
|
{name: "hd", prompt: "нарисуй птицу в HD", want: "1024x1024"},
|
|
{name: "uhd", prompt: "draw a bird in UHD", want: "2048x2048"},
|
|
{name: "ordinary", prompt: "нарисуй птицу", want: ""},
|
|
{name: "invalid explicit", prompt: "нарисуй птицу", requested: "100x100", want: ""},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
if got := imageRequestSize(test.prompt, test.requested); got != test.want {
|
|
t.Fatalf("imageRequestSize(%q, %q) = %q, want %q", test.prompt, test.requested, got, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMultimodalVideoUnderstandingFailsClosedWhenSkillIsUnbound(t *testing.T) {
|
|
server := multimodalGateway{now: time.Now}
|
|
request := multipartRequest(t, "/v1/multimodal/video-understand", "clip.mp4", []byte("video"))
|
|
response := httptest.NewRecorder()
|
|
server.handler(capability.MultimodalUnderstandVideo)(response, request)
|
|
if response.Code != http.StatusBadGateway || !bytes.Contains(response.Body.Bytes(), []byte("unavailable")) {
|
|
t.Fatalf("status=%d body=%s", response.Code, response.Body.String())
|
|
}
|
|
}
|
|
|
|
func multipartRequest(t *testing.T, path, filename string, data []byte) *http.Request {
|
|
t.Helper()
|
|
body := &bytes.Buffer{}
|
|
writer := multipart.NewWriter(body)
|
|
part, err := writer.CreateFormFile("file", filename)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := part.Write(data); err != nil || writer.Close() != nil {
|
|
t.Fatal("failed to build multipart request")
|
|
}
|
|
request := httptest.NewRequest(http.MethodPost, path, body)
|
|
request = request.WithContext(context.Background())
|
|
request.Header.Set("Content-Type", writer.FormDataContentType())
|
|
return request
|
|
}
|