test(host): harden gateway and acceptance validation

This commit is contained in:
phamnazage-jpg
2026-05-21 15:45:55 +08:00
parent 2649956b59
commit 7c6e18f94d
3 changed files with 261 additions and 11 deletions

View File

@@ -217,6 +217,89 @@ func TestSub2APIHostAdapterChecksGatewayAccess(t *testing.T) {
}
}
func TestSub2APIHostAdapterSeparatesAccountModelsFromGatewayModels(t *testing.T) {
server := newSub2APIStubServer(t, sub2APIStubConfig{
requireAPIKey: true,
version: "0.1.126",
accountModels: []map[string]any{{"id": "deepseek-account-only", "display_name": "DeepSeek Account Only", "type": "chat"}},
gatewayModels: []map[string]any{{"id": "deepseek-gateway-only"}},
gatewayExpectedKey: "managed-user-key",
})
defer server.Close()
client, err := sub2api.NewClient(server.URL, sub2api.WithAPIKey("api-key"))
if err != nil {
t.Fatalf("NewClient() error = %v", err)
}
accountModels, err := client.GetAccountModels(context.Background(), "account_1")
if err != nil {
t.Fatalf("GetAccountModels() error = %v", err)
}
if len(accountModels) != 1 || accountModels[0].ID != "deepseek-account-only" {
t.Fatalf("GetAccountModels() = %+v, want admin account models only", accountModels)
}
gatewayResult, err := client.CheckGatewayAccess(context.Background(), sub2api.GatewayAccessCheckRequest{
APIKey: "managed-user-key",
ExpectedModel: "deepseek-gateway-only",
})
if err != nil {
t.Fatalf("CheckGatewayAccess() error = %v", err)
}
if !gatewayResult.OK || !gatewayResult.HasExpectedModel {
t.Fatalf("CheckGatewayAccess() = %+v, want gateway models only", gatewayResult)
}
if len(gatewayResult.Models) != 1 || gatewayResult.Models[0] != "deepseek-gateway-only" {
t.Fatalf("gateway models = %+v, want gateway-only model list", gatewayResult.Models)
}
if gatewayResult.Models[0] == accountModels[0].ID {
t.Fatalf("gateway models = %+v unexpectedly matched account models %+v", gatewayResult.Models, accountModels)
}
}
func TestSub2APIHostAdapterGatewayProbeDoesNotReuseAdminCredential(t *testing.T) {
server := newSub2APIStubServer(t, sub2APIStubConfig{
requireAPIKey: true,
version: "0.1.126",
gatewayExpectedKey: "managed-user-key",
})
defer server.Close()
client, err := sub2api.NewClient(server.URL, sub2api.WithAPIKey("api-key"))
if err != nil {
t.Fatalf("NewClient() error = %v", err)
}
result, err := client.CheckGatewayAccess(context.Background(), sub2api.GatewayAccessCheckRequest{
APIKey: "managed-user-key",
ExpectedModel: "deepseek-chat",
})
if err != nil {
t.Fatalf("CheckGatewayAccess() error = %v", err)
}
if !result.OK {
t.Fatalf("CheckGatewayAccess() = %+v, want OK=true with managed user key", result)
}
wrongKeyResult, err := client.CheckGatewayAccess(context.Background(), sub2api.GatewayAccessCheckRequest{
APIKey: "api-key",
ExpectedModel: "deepseek-chat",
})
if err != nil {
t.Fatalf("CheckGatewayAccess() with admin key error = %v", err)
}
if wrongKeyResult.OK {
t.Fatalf("CheckGatewayAccess() with admin key = %+v, want OK=false", wrongKeyResult)
}
if wrongKeyResult.StatusCode != http.StatusUnauthorized {
t.Fatalf("StatusCode = %d, want %d", wrongKeyResult.StatusCode, http.StatusUnauthorized)
}
if wrongKeyResult.HasExpectedModel {
t.Fatalf("CheckGatewayAccess() with admin key = %+v, want HasExpectedModel=false", wrongKeyResult)
}
}
func TestSub2APIHostAdapterDeletesManagedResources(t *testing.T) {
server := newSub2APIStubServer(t, sub2APIStubConfig{
requireAPIKey: true,
@@ -277,13 +360,35 @@ func TestSub2APIHostAdapterListManagedResources(t *testing.T) {
}
type sub2APIStubConfig struct {
requireAPIKey bool
version string
requireAPIKey bool
version string
accountModels []map[string]any
gatewayModels []map[string]any
gatewayExpectedKey string
}
func newSub2APIStubServer(t *testing.T, cfg sub2APIStubConfig) *httptest.Server {
t.Helper()
accountModels := cfg.accountModels
if len(accountModels) == 0 {
accountModels = []map[string]any{
{"id": "deepseek-chat", "display_name": "DeepSeek Chat", "type": "chat"},
{"id": "deepseek-reasoner", "display_name": "DeepSeek Reasoner", "type": "reasoning"},
}
}
gatewayModels := cfg.gatewayModels
if len(gatewayModels) == 0 {
gatewayModels = []map[string]any{
{"id": "deepseek-chat"},
{"id": "deepseek-reasoner"},
}
}
gatewayExpectedKey := cfg.gatewayExpectedKey
if gatewayExpectedKey == "" {
gatewayExpectedKey = "user-api-key"
}
mux := http.NewServeMux()
mux.HandleFunc("/api/v1/admin/system/version", func(w http.ResponseWriter, r *http.Request) {
if !mustStubAuth(t, w, r, cfg.requireAPIKey) {
@@ -458,10 +563,7 @@ func newSub2APIStubServer(t *testing.T, cfg sub2APIStubConfig) *httptest.Server
}
writeJSON(t, w, http.StatusOK, map[string]any{
"data": map[string]any{
"items": []map[string]any{
{"id": "deepseek-chat", "display_name": "DeepSeek Chat", "type": "chat"},
{"id": "deepseek-reasoner", "display_name": "DeepSeek Reasoner", "type": "reasoning"},
},
"items": accountModels,
},
})
default:
@@ -489,16 +591,13 @@ func newSub2APIStubServer(t *testing.T, cfg sub2APIStubConfig) *httptest.Server
})
})
mux.HandleFunc("/v1/models", func(w http.ResponseWriter, r *http.Request) {
if got := r.Header.Get("x-api-key"); got != "user-api-key" {
if got := r.Header.Get("x-api-key"); got != gatewayExpectedKey {
w.WriteHeader(http.StatusUnauthorized)
_, _ = w.Write([]byte(`{"error":"unauthorized"}`))
return
}
writeJSON(t, w, http.StatusOK, map[string]any{
"data": []map[string]any{
{"id": "deepseek-chat"},
{"id": "deepseek-reasoner"},
},
"data": gatewayModels,
})
})