| package handler |
|
|
| import ( |
| "net/http" |
| "net/http/httptest" |
| "testing" |
|
|
| "github.com/Wei-Shaw/sub2api/internal/service" |
| "github.com/gin-gonic/gin" |
| "github.com/stretchr/testify/require" |
| ) |
|
|
| func init() { gin.SetMode(gin.TestMode) } |
|
|
| |
| |
| |
|
|
| func TestNormalizeInboundEndpoint(t *testing.T) { |
| tests := []struct { |
| path string |
| want string |
| }{ |
| |
| {"/v1/messages", EndpointMessages}, |
| {"/v1/chat/completions", EndpointChatCompletions}, |
| {"/v1/responses", EndpointResponses}, |
| {"/v1beta/models", EndpointGeminiModels}, |
|
|
| |
| {"/antigravity/v1/messages", EndpointMessages}, |
| {"/openai/v1/responses", EndpointResponses}, |
| {"/openai/v1/responses/compact", EndpointResponses}, |
| {"/sora/v1/chat/completions", EndpointChatCompletions}, |
| {"/antigravity/v1beta/models/gemini:generateContent", EndpointGeminiModels}, |
|
|
| |
| {"/v1beta/models/*modelAction", EndpointGeminiModels}, |
| {"/v1/responses/*subpath", EndpointResponses}, |
|
|
| |
| {"/v1/embeddings", "/v1/embeddings"}, |
| {"", ""}, |
| {" /v1/messages ", EndpointMessages}, |
| } |
| for _, tt := range tests { |
| t.Run(tt.path, func(t *testing.T) { |
| require.Equal(t, tt.want, NormalizeInboundEndpoint(tt.path)) |
| }) |
| } |
| } |
|
|
| |
| |
| |
|
|
| func TestDeriveUpstreamEndpoint(t *testing.T) { |
| tests := []struct { |
| name string |
| inbound string |
| rawPath string |
| platform string |
| want string |
| }{ |
| |
| {"anthropic messages", EndpointMessages, "/v1/messages", service.PlatformAnthropic, EndpointMessages}, |
|
|
| |
| {"gemini models", EndpointGeminiModels, "/v1beta/models/gemini:gen", service.PlatformGemini, EndpointGeminiModels}, |
|
|
| |
| {"sora completions", EndpointChatCompletions, "/sora/v1/chat/completions", service.PlatformSora, EndpointChatCompletions}, |
|
|
| |
| {"openai responses root", EndpointResponses, "/v1/responses", service.PlatformOpenAI, EndpointResponses}, |
| {"openai responses compact", EndpointResponses, "/openai/v1/responses/compact", service.PlatformOpenAI, "/v1/responses/compact"}, |
| {"openai responses nested", EndpointResponses, "/openai/v1/responses/compact/detail", service.PlatformOpenAI, "/v1/responses/compact/detail"}, |
| {"openai from messages", EndpointMessages, "/v1/messages", service.PlatformOpenAI, EndpointResponses}, |
| {"openai from completions", EndpointChatCompletions, "/v1/chat/completions", service.PlatformOpenAI, EndpointResponses}, |
|
|
| |
| {"antigravity claude", EndpointMessages, "/antigravity/v1/messages", service.PlatformAntigravity, EndpointMessages}, |
| {"antigravity gemini", EndpointGeminiModels, "/antigravity/v1beta/models", service.PlatformAntigravity, EndpointGeminiModels}, |
|
|
| |
| {"unknown platform", "/v1/embeddings", "/v1/embeddings", "unknown", "/v1/embeddings"}, |
| } |
| for _, tt := range tests { |
| t.Run(tt.name, func(t *testing.T) { |
| require.Equal(t, tt.want, DeriveUpstreamEndpoint(tt.inbound, tt.rawPath, tt.platform)) |
| }) |
| } |
| } |
|
|
| |
| |
| |
|
|
| func TestResponsesSubpathSuffix(t *testing.T) { |
| tests := []struct { |
| raw string |
| want string |
| }{ |
| {"/v1/responses", ""}, |
| {"/v1/responses/", ""}, |
| {"/v1/responses/compact", "/compact"}, |
| {"/openai/v1/responses/compact/detail", "/compact/detail"}, |
| {"/v1/messages", ""}, |
| {"", ""}, |
| } |
| for _, tt := range tests { |
| t.Run(tt.raw, func(t *testing.T) { |
| require.Equal(t, tt.want, responsesSubpathSuffix(tt.raw)) |
| }) |
| } |
| } |
|
|
| |
| |
| |
|
|
| func TestInboundEndpointMiddleware(t *testing.T) { |
| router := gin.New() |
| router.Use(InboundEndpointMiddleware()) |
|
|
| var captured string |
| router.POST("/v1/messages", func(c *gin.Context) { |
| captured = GetInboundEndpoint(c) |
| c.Status(http.StatusOK) |
| }) |
|
|
| req := httptest.NewRequest(http.MethodPost, "/v1/messages", nil) |
| rec := httptest.NewRecorder() |
| router.ServeHTTP(rec, req) |
|
|
| require.Equal(t, EndpointMessages, captured) |
| } |
|
|
| func TestGetInboundEndpoint_FallbackWithoutMiddleware(t *testing.T) { |
| rec := httptest.NewRecorder() |
| c, _ := gin.CreateTestContext(rec) |
| c.Request = httptest.NewRequest(http.MethodPost, "/antigravity/v1/messages", nil) |
|
|
| |
| got := GetInboundEndpoint(c) |
| require.Equal(t, EndpointMessages, got) |
| } |
|
|
| func TestGetUpstreamEndpoint_FullFlow(t *testing.T) { |
| rec := httptest.NewRecorder() |
| c, _ := gin.CreateTestContext(rec) |
| c.Request = httptest.NewRequest(http.MethodPost, "/openai/v1/responses/compact", nil) |
|
|
| |
| c.Set(ctxKeyInboundEndpoint, NormalizeInboundEndpoint(c.Request.URL.Path)) |
|
|
| got := GetUpstreamEndpoint(c, service.PlatformOpenAI) |
| require.Equal(t, "/v1/responses/compact", got) |
| } |
|
|