diff --git a/backend/internal/pkg/antigravity/client_test.go b/backend/internal/pkg/antigravity/client_test.go index d3e2fd94..394b6128 100644 --- a/backend/internal/pkg/antigravity/client_test.go +++ b/backend/internal/pkg/antigravity/client_test.go @@ -400,7 +400,9 @@ func TestShouldFallbackToNextURL_无错误且200(t *testing.T) { // --------------------------------------------------------------------------- func TestClient_ExchangeCode_成功(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 验证请求方法 @@ -493,7 +495,9 @@ func TestClient_ExchangeCode_成功(t *testing.T) { } func TestClient_ExchangeCode_无ClientSecret(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "") + old := defaultClientSecret + defaultClientSecret = "" + t.Cleanup(func() { defaultClientSecret = old }) client := NewClient("") _, err := client.ExchangeCode(context.Background(), "code", "verifier") @@ -506,7 +510,9 @@ func TestClient_ExchangeCode_无ClientSecret(t *testing.T) { } func TestClient_ExchangeCode_服务器返回错误(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusBadRequest) @@ -531,7 +537,9 @@ func TestClient_ExchangeCode_服务器返回错误(t *testing.T) { // --------------------------------------------------------------------------- func TestClient_RefreshToken_MockServer(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { @@ -590,7 +598,9 @@ func TestClient_RefreshToken_MockServer(t *testing.T) { } func TestClient_RefreshToken_无ClientSecret(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "") + old := defaultClientSecret + defaultClientSecret = "" + t.Cleanup(func() { defaultClientSecret = old }) client := NewClient("") _, err := client.RefreshToken(context.Background(), "refresh-tok") @@ -784,7 +794,9 @@ func newTestClientWithRedirect(redirects map[string]string) *Client { // --------------------------------------------------------------------------- func TestClient_ExchangeCode_Success_RealCall(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { @@ -853,7 +865,9 @@ func TestClient_ExchangeCode_Success_RealCall(t *testing.T) { } func TestClient_ExchangeCode_ServerError_RealCall(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusBadRequest) @@ -878,7 +892,9 @@ func TestClient_ExchangeCode_ServerError_RealCall(t *testing.T) { } func TestClient_ExchangeCode_InvalidJSON_RealCall(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -901,7 +917,9 @@ func TestClient_ExchangeCode_InvalidJSON_RealCall(t *testing.T) { } func TestClient_ExchangeCode_ContextCanceled_RealCall(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(5 * time.Second) // 模拟慢响应 @@ -927,7 +945,9 @@ func TestClient_ExchangeCode_ContextCanceled_RealCall(t *testing.T) { // --------------------------------------------------------------------------- func TestClient_RefreshToken_Success_RealCall(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { @@ -976,7 +996,9 @@ func TestClient_RefreshToken_Success_RealCall(t *testing.T) { } func TestClient_RefreshToken_ServerError_RealCall(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) @@ -998,7 +1020,9 @@ func TestClient_RefreshToken_ServerError_RealCall(t *testing.T) { } func TestClient_RefreshToken_InvalidJSON_RealCall(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -1021,7 +1045,9 @@ func TestClient_RefreshToken_InvalidJSON_RealCall(t *testing.T) { } func TestClient_RefreshToken_ContextCanceled_RealCall(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "test-secret") + old := defaultClientSecret + defaultClientSecret = "test-secret" + t.Cleanup(func() { defaultClientSecret = old }) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(5 * time.Second) diff --git a/backend/internal/pkg/antigravity/oauth_test.go b/backend/internal/pkg/antigravity/oauth_test.go index d8f2b098..da7d3fca 100644 --- a/backend/internal/pkg/antigravity/oauth_test.go +++ b/backend/internal/pkg/antigravity/oauth_test.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "encoding/hex" "net/url" + "os" "strings" "testing" "time" @@ -17,8 +18,14 @@ import ( // --------------------------------------------------------------------------- func TestGetClientSecret_环境变量设置(t *testing.T) { + old := defaultClientSecret + defaultClientSecret = "" + t.Cleanup(func() { defaultClientSecret = old }) t.Setenv(AntigravityOAuthClientSecretEnv, "my-secret-value") + // 需要重新触发 init 逻辑:手动从环境变量读取 + defaultClientSecret = os.Getenv(AntigravityOAuthClientSecretEnv) + secret, err := getClientSecret() if err != nil { t.Fatalf("获取 client_secret 失败: %v", err) @@ -29,11 +36,13 @@ func TestGetClientSecret_环境变量设置(t *testing.T) { } func TestGetClientSecret_环境变量为空(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, "") + old := defaultClientSecret + defaultClientSecret = "" + t.Cleanup(func() { defaultClientSecret = old }) _, err := getClientSecret() if err == nil { - t.Fatal("环境变量为空时应返回错误") + t.Fatal("defaultClientSecret 为空时应返回错误") } if !strings.Contains(err.Error(), AntigravityOAuthClientSecretEnv) { t.Errorf("错误信息应包含环境变量名: got %s", err.Error()) @@ -41,30 +50,31 @@ func TestGetClientSecret_环境变量为空(t *testing.T) { } func TestGetClientSecret_环境变量未设置(t *testing.T) { - // t.Setenv 会在测试结束时恢复,但我们需要确保它不存在 - // 注意:如果 ClientSecret 常量非空,这个测试会直接返回常量值 - // 当前代码中 ClientSecret = "",所以会走环境变量逻辑 - - // 明确设置再取消,确保环境变量不存在 - t.Setenv(AntigravityOAuthClientSecretEnv, "") + old := defaultClientSecret + defaultClientSecret = "" + t.Cleanup(func() { defaultClientSecret = old }) _, err := getClientSecret() if err == nil { - t.Fatal("环境变量未设置时应返回错误") + t.Fatal("defaultClientSecret 为空时应返回错误") } } func TestGetClientSecret_环境变量含空格(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, " ") + old := defaultClientSecret + defaultClientSecret = " " + t.Cleanup(func() { defaultClientSecret = old }) _, err := getClientSecret() if err == nil { - t.Fatal("环境变量仅含空格时应返回错误") + t.Fatal("defaultClientSecret 仅含空格时应返回错误") } } func TestGetClientSecret_环境变量有前后空格(t *testing.T) { - t.Setenv(AntigravityOAuthClientSecretEnv, " valid-secret ") + old := defaultClientSecret + defaultClientSecret = " valid-secret " + t.Cleanup(func() { defaultClientSecret = old }) secret, err := getClientSecret() if err != nil { @@ -671,7 +681,14 @@ func TestConstants_值正确(t *testing.T) { t.Errorf("ClientID 不匹配: got %s", ClientID) } if ClientSecret != "" { - t.Error("ClientSecret 应为空字符串") + t.Error("ClientSecret 常量应为空字符串(默认值已移至 defaultClientSecret)") + } + secret, err := getClientSecret() + if err != nil { + t.Fatalf("getClientSecret 应返回默认值,但报错: %v", err) + } + if secret != "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" { + t.Errorf("默认 client_secret 不匹配: got %s", secret) } if RedirectURI != "http://localhost:8085/callback" { t.Errorf("RedirectURI 不匹配: got %s", RedirectURI) diff --git a/backend/migrations/058_add_sonnet46_to_model_mapping.sql b/backend/migrations/058_add_sonnet46_to_model_mapping.sql index aa7657d7..93e7b39d 100644 --- a/backend/migrations/058_add_sonnet46_to_model_mapping.sql +++ b/backend/migrations/058_add_sonnet46_to_model_mapping.sql @@ -27,11 +27,11 @@ SET credentials = jsonb_set( "gemini-2.5-flash-thinking": "gemini-2.5-flash-thinking", "gemini-2.5-pro": "gemini-2.5-pro", "gemini-3-flash": "gemini-3-flash", - "gemini-3-pro-high": "gemini-3-pro-high", - "gemini-3-pro-low": "gemini-3-pro-low", + "gemini-3-pro-high": "gemini-3.1-pro-high", + "gemini-3-pro-low": "gemini-3.1-pro-low", "gemini-3-pro-image": "gemini-3-pro-image", "gemini-3-flash-preview": "gemini-3-flash", - "gemini-3-pro-preview": "gemini-3-pro-high", + "gemini-3-pro-preview": "gemini-3.1-pro-high", "gemini-3-pro-image-preview": "gemini-3-pro-image", "gpt-oss-120b-medium": "gpt-oss-120b-medium", "tab_flash_lite_preview": "tab_flash_lite_preview"