167 lines
5.6 KiB
Go
167 lines
5.6 KiB
Go
package clients
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/easyai/easyai-ai-gateway/apps/api/internal/store"
|
|
)
|
|
|
|
func TestKelingOmniPayloadPreservesCompatibleSettings(t *testing.T) {
|
|
payload, cleanupIDs, err := (KelingClient{}).kelingOmniPayload(context.Background(), Request{
|
|
Kind: "videos.generations",
|
|
ModelType: "omni_video",
|
|
Body: map[string]any{
|
|
"prompt": "A product reveal",
|
|
"duration": 3,
|
|
"resolution": "720p",
|
|
"aspect_ratio": "16:9",
|
|
"audio": false,
|
|
"watermark_info": map[string]any{"enabled": true},
|
|
"external_task_id": "external-1",
|
|
},
|
|
Candidate: store.RuntimeModelCandidate{
|
|
Provider: "keling",
|
|
ProviderModelName: "kling-video-o1",
|
|
Capabilities: map[string]any{"omni_video": map[string]any{}},
|
|
},
|
|
}, "token")
|
|
if err != nil {
|
|
t.Fatalf("build compatible Omni payload: %v", err)
|
|
}
|
|
if len(cleanupIDs) != 0 ||
|
|
payload["model_name"] != "kling-video-o1" ||
|
|
payload["mode"] != "std" ||
|
|
payload["sound"] != "off" ||
|
|
payload["duration"] != "3" ||
|
|
payload["aspect_ratio"] != "16:9" ||
|
|
payload["external_task_id"] != "external-1" {
|
|
t.Fatalf("unexpected compatible Omni payload: %+v", payload)
|
|
}
|
|
watermark, _ := payload["watermark_info"].(map[string]any)
|
|
if watermark["enabled"] != true {
|
|
t.Fatalf("watermark setting was not preserved: %+v", payload)
|
|
}
|
|
}
|
|
|
|
func TestKelingOmniUpstreamModelNameSeparatesGatewayAliases(t *testing.T) {
|
|
tests := map[string]string{
|
|
"kling-o1": "kling-video-o1",
|
|
"kling-video-o1": "kling-video-o1",
|
|
"kling-3.0-omni": "kling-v3-omni",
|
|
"kling-v3-omni": "kling-v3-omni",
|
|
}
|
|
for configured, want := range tests {
|
|
got := kelingOmniUpstreamModelName(store.RuntimeModelCandidate{ProviderModelName: configured})
|
|
if got != want {
|
|
t.Fatalf("configured=%s got=%s want=%s", configured, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestKelingOmniRejectsGeneratedAudioForO1(t *testing.T) {
|
|
_, _, err := (KelingClient{}).kelingOmniPayload(context.Background(), Request{
|
|
Body: map[string]any{
|
|
"prompt": "A beach",
|
|
"duration": 5,
|
|
"resolution": "1080p",
|
|
"aspect_ratio": "9:16",
|
|
"audio": true,
|
|
},
|
|
Candidate: store.RuntimeModelCandidate{ProviderModelName: "kling-video-o1"},
|
|
}, "token")
|
|
if err == nil || ErrorCode(err) != "invalid_parameter" {
|
|
t.Fatalf("expected generated-audio rejection for O1, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestKelingOmniResumeReturnsUpstreamFailureCodeAndModel(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet || r.URL.Path != "/videos/omni-video/remote-failed" {
|
|
t.Fatalf("unexpected request %s %s", r.Method, r.URL.Path)
|
|
}
|
|
if r.Header.Get("Authorization") != "Bearer upstream-key" {
|
|
t.Fatalf("unexpected Authorization header: %q", r.Header.Get("Authorization"))
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"code": 0,
|
|
"request_id": "failure-request",
|
|
"data": map[string]any{
|
|
"task_id": "remote-failed",
|
|
"task_status": "failed",
|
|
"task_status_msg": "content policy rejection",
|
|
},
|
|
})
|
|
}))
|
|
defer server.Close()
|
|
|
|
_, err := (KelingClient{HTTPClient: server.Client()}).Run(context.Background(), Request{
|
|
Kind: "videos.generations",
|
|
ModelType: "omni_video",
|
|
RemoteTaskID: "remote-failed",
|
|
RemoteTaskPayload: map[string]any{"endpoint": "/videos/omni-video"},
|
|
Candidate: store.RuntimeModelCandidate{
|
|
BaseURL: server.URL,
|
|
Provider: "keling",
|
|
ProviderModelName: "kling-v3-omni",
|
|
Credentials: map[string]any{"apiKey": "upstream-key"},
|
|
PlatformConfig: map[string]any{
|
|
"kelingPollIntervalMs": 10,
|
|
"kelingPollTimeoutSeconds": 1,
|
|
},
|
|
},
|
|
})
|
|
if err == nil || ErrorCode(err) != "keling_task_failed" || !strings.Contains(err.Error(), "content policy rejection") {
|
|
t.Fatalf("expected preserved Keling task failure, got code=%q err=%v", ErrorCode(err), err)
|
|
}
|
|
}
|
|
|
|
func TestKelingOmniPayloadPreservesIntelligentMultiShot(t *testing.T) {
|
|
payload, _, err := (KelingClient{}).kelingOmniPayload(context.Background(), Request{
|
|
Kind: "videos.generations",
|
|
ModelType: "omni_video",
|
|
Body: map[string]any{
|
|
"prompt": "Create three coherent shots",
|
|
"duration": 5,
|
|
"resolution": "1080p",
|
|
"aspect_ratio": "9:16",
|
|
"multi_shot": true,
|
|
"shot_type": "intelligence",
|
|
},
|
|
Candidate: store.RuntimeModelCandidate{
|
|
ProviderModelName: "kling-v3-omni",
|
|
Capabilities: map[string]any{"omni_video": map[string]any{}},
|
|
},
|
|
}, "token")
|
|
if err != nil {
|
|
t.Fatalf("build intelligent multi-shot payload: %v", err)
|
|
}
|
|
if payload["multi_shot"] != true || payload["shot_type"] != "intelligence" || payload["prompt"] != "Create three coherent shots" {
|
|
t.Fatalf("unexpected intelligent multi-shot payload: %+v", payload)
|
|
}
|
|
}
|
|
|
|
func TestKelingVideoSuccessResultPreservesOfficialVideoMetadata(t *testing.T) {
|
|
result := kelingVideoSuccessResult(Request{Candidate: store.RuntimeModelCandidate{ProviderModelName: "kling-video-o1"}}, "remote-1", map[string]any{
|
|
"data": map[string]any{
|
|
"task_result": map[string]any{
|
|
"videos": []any{map[string]any{
|
|
"id": "video-1",
|
|
"url": "https://example.com/video.mp4",
|
|
"watermark_url": "https://example.com/watermarked.mp4",
|
|
"duration": "3",
|
|
}},
|
|
},
|
|
},
|
|
})
|
|
data, _ := result["data"].([]any)
|
|
video, _ := data[0].(map[string]any)
|
|
if video["id"] != "video-1" || video["watermark_url"] != "https://example.com/watermarked.mp4" || video["duration"] != "3" {
|
|
t.Fatalf("official video metadata was lost: %+v", video)
|
|
}
|
|
}
|