Some checks failed
Security Scan / backend-security (push) Failing after 3s
Security Scan / frontend-security (push) Failing after 5s
CI / test (push) Failing after 3s
CI / frontend (push) Failing after 3s
CI / golangci-lint (push) Failing after 3s
CI / windsurf-platform (macos-latest) (push) Has been cancelled
CI / windsurf-platform (windows-latest) (push) Has been cancelled
81 lines
2.5 KiB
Go
81 lines
2.5 KiB
Go
package antigravity
|
||
|
||
import (
|
||
"encoding/json"
|
||
"testing"
|
||
|
||
"github.com/stretchr/testify/require"
|
||
)
|
||
|
||
// 验证 EnableAICredits 选项控制 v1internal.enabledCreditTypes 的注入。
|
||
// 注入 ["GOOGLE_ONE_AI"] 是让 free 配额耗尽的请求落到 paidTier.availableCredits 的关键。
|
||
func TestTransformClaudeToGemini_AICreditsInjection(t *testing.T) {
|
||
baseReq := func() *ClaudeRequest {
|
||
return &ClaudeRequest{
|
||
Model: "claude-sonnet-4-5",
|
||
Messages: []ClaudeMessage{
|
||
{Role: "user", Content: json.RawMessage(`[{"type":"text","text":"hi"}]`)},
|
||
},
|
||
}
|
||
}
|
||
|
||
cases := []struct {
|
||
name string
|
||
enable bool
|
||
wantCredits []string
|
||
}{
|
||
{name: "默认关闭_不注入", enable: false, wantCredits: nil},
|
||
{name: "显式启用_注入_GOOGLE_ONE_AI", enable: true, wantCredits: []string{CreditTypeGoogleOneAI}},
|
||
}
|
||
|
||
for _, tc := range cases {
|
||
t.Run(tc.name, func(t *testing.T) {
|
||
opts := DefaultTransformOptions()
|
||
opts.EnableAICredits = tc.enable
|
||
|
||
body, err := TransformClaudeToGeminiWithOptions(baseReq(), "project-1", "claude-sonnet-4-5", opts)
|
||
require.NoError(t, err)
|
||
|
||
// 用 raw map 校验 omitempty 语义(nil 时字段必须缺失,不能是 [])
|
||
var raw map[string]any
|
||
require.NoError(t, json.Unmarshal(body, &raw))
|
||
|
||
if tc.wantCredits == nil {
|
||
_, present := raw["enabledCreditTypes"]
|
||
require.False(t, present, "enabledCreditTypes 在禁用时不应出现在 payload 顶层")
|
||
return
|
||
}
|
||
|
||
require.Contains(t, raw, "enabledCreditTypes")
|
||
var typed V1InternalRequest
|
||
require.NoError(t, json.Unmarshal(body, &typed))
|
||
require.Equal(t, tc.wantCredits, typed.EnabledCreditTypes)
|
||
})
|
||
}
|
||
}
|
||
|
||
// 验证 enabledCreditTypes 注入位置在 v1internal 顶层,不是内层 request 子对象。
|
||
// 这与 CLIProxyAPI 真实行为一致;放错位置上游会忽略字段。
|
||
func TestTransformClaudeToGemini_AICreditsLocation_顶层(t *testing.T) {
|
||
opts := DefaultTransformOptions()
|
||
opts.EnableAICredits = true
|
||
|
||
req := &ClaudeRequest{
|
||
Model: "claude-sonnet-4-5",
|
||
Messages: []ClaudeMessage{
|
||
{Role: "user", Content: json.RawMessage(`[{"type":"text","text":"hi"}]`)},
|
||
},
|
||
}
|
||
body, err := TransformClaudeToGeminiWithOptions(req, "p", "claude-sonnet-4-5", opts)
|
||
require.NoError(t, err)
|
||
|
||
var raw map[string]any
|
||
require.NoError(t, json.Unmarshal(body, &raw))
|
||
|
||
require.Contains(t, raw, "enabledCreditTypes", "必须在顶层")
|
||
if inner, ok := raw["request"].(map[string]any); ok {
|
||
_, presentInInner := inner["enabledCreditTypes"]
|
||
require.False(t, presentInInner, "不能放在内层 request 子对象")
|
||
}
|
||
}
|