The test request was using maxOutputTokens: 1, which caused Google API to generate only 1 token. When decoded, this single token produced "It" as the response, making it look like an error. Changed: - Content: "." → "Test connection" (more meaningful prompt) - MaxTokens: 1 → 10 (enough tokens to verify connection is working) This fixes the issue where account test always showed "It" in the response, which was actually just the truncated output from the single-token generation. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
8.0 KiB
8.0 KiB
本地单元测试指南:Antigravity 账号验证
概述
本指南帮助你在本地环境中,不通过 HTTP,直接调用服务器代码来测试 Antigravity 账号 ID 68 的连接性。
当前测试状态
✅ 基础验证已通过:
- 账号 ID: 68
- 平台: antigravity
- 类型: oauth
- 凭证完整性: ✓
- Token 有效期: ✓ (有效期至 2026-04-11 18:25:54)
- Project ID: kinetic-sum-r3tp7
运行基础测试
cd backend
go test -v -run TestAntigravityCredentialsValidation ./internal/service
预期输出:
=== RUN TestAntigravityCredentialsValidation
...
--- PASS: TestAntigravityCredentialsValidation (0.00s)
PASS
ok github.com/Wei-Shaw/sub2api/internal/service 0.607s
问题诊断:找出 "IT" 错误的来源
当前问题:HTTP 请求返回了 "IT" 错误,这不是一个有意义的错误消息。
可能的原因
-
错误消息被截断
- 原始错误可能是 "INTERNAL_ERROR" 或其他,但在某个地方被截断成 "IT"
- 问题位置:
account_test_service.go中的sendErrorAndEnd或错误处理逻辑
-
HTTP 响应体包含不完整的字符
- 上游 API 返回的错误响应可能被不完整地处理
- 问题位置:
antigravity_gateway_service.go中的TestConnection或antigravityRetryLoop
-
编码错误
- 错误消息在 SSE 流中被破坏
- 问题位置:
account_test_service.go中的 SSE 事件处理
创建增强的诊断测试
创建文件:backend/internal/service/antigravity_test_diagnostic_test.go
package service
import (
"context"
"testing"
"time"
)
// TestAntigravityDiagnoseConnectionError 诊断性测试
// 直接调用 AntigravityGatewayService.TestConnection,捕获完整的错误信息
func TestAntigravityDiagnoseConnectionError(t *testing.T) {
// 这个测试需要依赖注入:
// - AccountRepository
// - TokenProvider
// - HTTPUpstream
// - AntigravityGatewayService
//
// 由于本地测试无法访问真实数据库和配置,
// 需要在集成测试环境中运行
t.Skip("Requires integration test environment with database access")
// 伪代码:实际实现步骤
// 1. 从数据库获取账号
// account, err := accountRepo.GetByID(ctx, 68)
// if err != nil {
// t.Fatalf("Failed to load account: %v", err)
// }
// 2. 调用 TestConnection
// result, err := gatewayService.TestConnection(ctx, account, "claude-opus-4-6")
//
// if err != nil {
// // 完整的错误信息应该会显示在这里,而不是 "IT"
// t.Logf("Error type: %T", err)
// t.Logf("Error message: %s", err.Error())
// t.Logf("Error details: %#v", err)
//
// // 进行根因分析
// analyzeAntigravityError(t, err, account)
// return
// }
//
// t.Logf("✅ Test passed")
// t.Logf("Response: %+v", result)
}
// analyzeAntigravityError 分析 Antigravity 错误的根本原因
func analyzeAntigravityError(t *testing.T, err error, account *Account) {
t.Logf("📊 Error Analysis for Account %d:", account.ID)
t.Logf(" Error type: %T", err)
t.Logf(" Error message: %s", err.Error())
// 检查是否是 AccountSwitchError
// if switchErr, ok := IsAntigravityAccountSwitchError(err); ok {
// t.Logf(" ⚠️ Account Switch Error:")
// t.Logf(" Original Account ID: %d", switchErr.OriginalAccountID)
// t.Logf(" Rate Limited Model: %s", switchErr.RateLimitedModel)
// return
// }
// 其他错误分析...
}
实际诊断步骤
步骤 1:增加日志记录
编辑 account_test_service.go 的 sendErrorAndEnd 函数:
func (s *AccountTestService) sendErrorAndEnd(c *gin.Context, msg string) error {
// ADD: 完整的错误日志
log.Printf("[DIAGNOSTIC] sendErrorAndEnd called with message: %q (len=%d)", msg, len(msg))
s.sendEvent(c, TestEvent{
Type: "test_error",
Error: msg,
Success: false,
})
s.sendEvent(c, TestEvent{Type: "test_complete", Success: false})
return nil
}
步骤 2:追踪 routeAntigravityTest 的路径
编辑 account_test_service.go 的 routeAntigravityTest 函数:
func (s *AccountTestService) routeAntigravityTest(c *gin.Context, account *Account, modelID string, prompt string) error {
log.Printf("[DIAGNOSTIC] routeAntigravityTest: account=%d, platform=%s, type=%s, modelID=%s",
account.ID, account.Platform, account.Type, modelID)
if account.Type == AccountTypeAPIKey {
log.Printf("[DIAGNOSTIC] Using APIKey path")
if strings.HasPrefix(modelID, "gemini-") {
return s.testGeminiAccountConnection(c, account, modelID, prompt)
}
return s.testClaudeAccountConnection(c, account, modelID)
}
log.Printf("[DIAGNOSTIC] Using testAntigravityAccountConnection path")
return s.testAntigravityAccountConnection(c, account, modelID)
}
步骤 3:在 TestConnection 中增加诊断日志
编辑 antigravity_gateway_service.go 的 TestConnection 函数:
func (s *AntigravityGatewayService) TestConnection(ctx context.Context, account *Account, modelID string) (*TestConnectionResult, error) {
log.Printf("[DIAGNOSTIC] TestConnection start: account=%d, modelID=%s", account.ID, modelID)
// ... 现有代码 ...
accessToken, err := s.tokenProvider.GetAccessToken(ctx, account)
if err != nil {
errMsg := fmt.Sprintf("获取 access_token 失败: %w", err)
log.Printf("[DIAGNOSTIC] GetAccessToken failed: %v", err)
return nil, errors.New(errMsg)
}
log.Printf("[DIAGNOSTIC] Access token obtained successfully")
// ... 继续现有代码 ...
result, err := s.antigravityRetryLoop(p)
if err != nil {
log.Printf("[DIAGNOSTIC] antigravityRetryLoop failed with error type %T: %v", err, err)
return nil, err
}
log.Printf("[DIAGNOSTIC] TestConnection completed successfully")
return &TestConnectionResult{Text: text, MappedModel: mappedModel}, nil
}
在完整环境中运行诊断
方法 A:使用现有的测试端点
使用你的 curl 命令,但启用详细日志:
# 启用应用的详细日志记录
export LOGLEVEL=debug
# 运行测试端点
curl -X POST 'https://temp365.top/api/v1/admin/accounts/68/test' \
-H 'Content-Type: application/json' \
-H 'authorization: Bearer YOUR_JWT_TOKEN' \
-d '{"model_id":"claude-opus-4-6","prompt":""}' \
-v
方法 B:编写集成测试
创建 backend/internal/service/antigravity_integration_test.go:
// 这个文件需要:
// 1. 数据库连接
// 2. 真实的 HTTP 客户端配置
// 3. 配置文件
//
// 在完整的开发环境中运行
预期的完整错误消息示例
正确的错误消息应该类似于:
"Invalid access token"
"Account not found"
"Project ID not available"
"Google API returned 401: Invalid credentials"
"Network timeout connecting to upstream"
"Request rate limit exceeded for model claude-opus-4-6"
如果返回的是 "IT",说明:
- ❌ 错误被截断(原文可能是 20+ 个字符,被截断成 2 个)
- ❌ 字符编码问题(UTF-8/ASCII 混淆)
- ❌ SSE 流中的损坏数据
日志文件位置
在完整服务运行中,查看日志:
# 应用日志
tail -f /var/log/sub2api/server.log | grep "DIAGNOSTIC"
# Docker 日志
docker logs -f <container-id> | grep "DIAGNOSTIC"
下一步
- ✅ 已完成:本地基础验证
- ⏭️ 待做:增加诊断日志并重新测试
- ⏭️ 待做:分析完整的错误消息
- ⏭️ 待做:修复根本原因
参考代码位置
-
账号测试服务:
backend/internal/service/account_test_service.goTestAccountConnection()- 第 162 行testAntigravityAccountConnection()- 第 629 行routeAntigravityTest()- 第 617 行sendErrorAndEnd()- 查找函数定义
-
Antigravity 网关服务:
backend/internal/service/antigravity_gateway_service.goTestConnection()- 第 1114 行antigravityRetryLoop()- 查找函数定义
-
HTTP 处理器:
backend/internal/handler/admin/account_handler.goTest()- 第 671 行(路由处理)
创建时间: 2026-04-11
测试版本: v1
状态: 就绪 ✓