Files

110 lines
4.9 KiB
Go
Raw Permalink Normal View History

package handler
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/Wei-Shaw/sub2api/internal/config"
middleware2 "github.com/Wei-Shaw/sub2api/internal/server/middleware"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
)
const validSystemOneHandlerBody = `{"model":"jev-latest","state":"sample","questions":{"q":{"type":"noul","instructions":"Evaluate"}}}`
func newSystemOneHandlerContext(body string) (*gin.Context, *httptest.ResponseRecorder) {
gin.SetMode(gin.TestMode)
recorder := httptest.NewRecorder()
c, _ := gin.CreateTestContext(recorder)
c.Request = httptest.NewRequest(http.MethodPost, "/v1/systemone", strings.NewReader(body))
c.Request.Header.Set("Content-Type", "application/json")
return c, recorder
}
func TestSystemOneRequiresAuthentication(t *testing.T) {
c, recorder := newSystemOneHandlerContext(validSystemOneHandlerBody)
(&GatewayHandler{}).SystemOne(c)
require.Equal(t, http.StatusUnauthorized, recorder.Code)
require.Contains(t, recorder.Body.String(), "authentication_error")
}
func TestSystemOneRejectsNonTypeSafeGroupBeforeScheduling(t *testing.T) {
c, recorder := newSystemOneHandlerContext(validSystemOneHandlerBody)
groupID := int64(3)
c.Set(string(middleware2.ContextKeyAPIKey), &service.APIKey{ID: 4, UserID: 5, GroupID: &groupID, Group: &service.Group{ID: groupID, Platform: service.PlatformOpenAI}})
c.Set(string(middleware2.ContextKeyUser), middleware2.AuthSubject{UserID: 5, Concurrency: 1})
(&GatewayHandler{cfg: &config.Config{Gateway: config.GatewayConfig{MaxBodySize: 1 << 20}}}).SystemOne(c)
require.Equal(t, http.StatusNotFound, recorder.Code)
require.Contains(t, recorder.Body.String(), "only available for TypeSafe")
}
func newTypeSafeGroupContext(t *testing.T, path, body, groupPlatform string) (*gin.Context, *httptest.ResponseRecorder) {
t.Helper()
c, recorder := newSystemOneHandlerContext(body)
c.Request = httptest.NewRequest(http.MethodPost, path, strings.NewReader(body))
c.Request.Header.Set("Content-Type", "application/json")
groupID := int64(9)
c.Set(string(middleware2.ContextKeyAPIKey), &service.APIKey{ID: 4, UserID: 5, GroupID: &groupID, Group: &service.Group{ID: groupID, Platform: groupPlatform}})
c.Set(string(middleware2.ContextKeyUser), middleware2.AuthSubject{UserID: 5, Concurrency: 1})
return c, recorder
}
func TestRejectSystemOneOnlyPlatform(t *testing.T) {
write := func(c *gin.Context, status int, errType, message string) {
c.JSON(status, gin.H{"type": errType, "message": message})
}
c, recorder := newTypeSafeGroupContext(t, "/v1/messages", `{}`, service.PlatformTypeSafe)
require.True(t, rejectSystemOneOnlyPlatform(c, mustAPIKey(t, c), write))
require.Equal(t, http.StatusNotFound, recorder.Code)
require.Contains(t, recorder.Body.String(), systemOneOnlyPlatformMessage)
c, _ = newTypeSafeGroupContext(t, "/v1/messages", `{}`, service.PlatformComposite)
require.False(t, rejectSystemOneOnlyPlatform(c, mustAPIKey(t, c), write))
c.Request = c.Request.WithContext(service.WithResolvedTargetPlatform(c.Request.Context(), service.PlatformTypeSafe))
require.True(t, rejectSystemOneOnlyPlatform(c, mustAPIKey(t, c), write))
c, _ = newTypeSafeGroupContext(t, "/v1/messages", `{}`, service.PlatformAnthropic)
require.False(t, rejectSystemOneOnlyPlatform(c, mustAPIKey(t, c), write))
c, _ = newTypeSafeGroupContext(t, "/antigravity/v1/messages", `{}`, service.PlatformTypeSafe)
c.Set(string(middleware2.ContextKeyForcePlatform), service.PlatformAntigravity)
require.False(t, rejectSystemOneOnlyPlatform(c, mustAPIKey(t, c), write))
}
func mustAPIKey(t *testing.T, c *gin.Context) *service.APIKey {
t.Helper()
apiKey, ok := middleware2.GetAPIKeyFromContext(c)
require.True(t, ok)
return apiKey
}
func TestTypeSafeGroupsRejectNonSystemOneProtocolsBeforeScheduling(t *testing.T) {
h := &GatewayHandler{
cfg: &config.Config{Gateway: config.GatewayConfig{MaxBodySize: 1 << 20}},
gatewayService: &service.GatewayService{},
}
for _, tc := range []struct {
name string
path string
body string
handler func(*gin.Context)
}{
{"messages", "/v1/messages", `{"model":"jev-latest","max_tokens":1,"messages":[{"role":"user","content":"hi"}]}`, h.Messages},
{"count_tokens", "/v1/messages/count_tokens", `{"model":"jev-latest","messages":[{"role":"user","content":"hi"}]}`, h.CountTokens},
{"chat_completions", "/v1/chat/completions", `{"model":"jev-latest","messages":[{"role":"user","content":"hi"}]}`, h.ChatCompletions},
{"responses", "/v1/responses", `{"model":"jev-latest","input":"hi"}`, h.Responses},
} {
t.Run(tc.name, func(t *testing.T) {
c, recorder := newTypeSafeGroupContext(t, tc.path, tc.body, service.PlatformTypeSafe)
tc.handler(c)
require.Equal(t, http.StatusNotFound, recorder.Code, recorder.Body.String())
require.Contains(t, recorder.Body.String(), systemOneOnlyPlatformMessage)
})
}
}