mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-16 15:43:13 +08:00
176 lines
6.2 KiB
Go
176 lines
6.2 KiB
Go
//go:build unit
|
|
|
|
package service
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestDiagnoseModelAvailabilityForPlatform_NoModel_AlwaysAvailable(t *testing.T) {
|
|
repo := &mockAccountRepoForPlatform{accounts: nil, accountsByID: map[int64]*Account{}}
|
|
svc := &GatewayService{accountRepo: repo, cfg: testConfig()}
|
|
|
|
diag := svc.DiagnoseModelAvailabilityForPlatform(context.Background(), nil, "", PlatformOpenAI)
|
|
|
|
require.True(t, diag.HasAccountsInPool, "empty model must return HasAccountsInPool=true so caller stays on 503")
|
|
require.True(t, diag.HasModelSupport, "empty model must return HasModelSupport=true so caller stays on 503")
|
|
}
|
|
|
|
func TestDiagnoseModelAvailabilityForPlatform_EmptyPlatform_AlwaysAvailable(t *testing.T) {
|
|
repo := &mockAccountRepoForPlatform{accounts: nil, accountsByID: map[int64]*Account{}}
|
|
svc := &GatewayService{accountRepo: repo, cfg: testConfig()}
|
|
|
|
diag := svc.DiagnoseModelAvailabilityForPlatform(context.Background(), nil, "gpt-5", "")
|
|
|
|
require.True(t, diag.HasAccountsInPool)
|
|
require.True(t, diag.HasModelSupport, "empty platform must fall back to {true,true} so caller stays on 503")
|
|
}
|
|
|
|
func TestDiagnoseModelAvailabilityForPlatform_NilReceiver(t *testing.T) {
|
|
var svc *GatewayService
|
|
|
|
diag := svc.DiagnoseModelAvailabilityForPlatform(context.Background(), nil, "gpt-5", PlatformOpenAI)
|
|
|
|
require.True(t, diag.HasAccountsInPool)
|
|
require.True(t, diag.HasModelSupport)
|
|
}
|
|
|
|
func TestDiagnoseModelAvailabilityForPlatform_NoAccountsInPool(t *testing.T) {
|
|
repo := &mockAccountRepoForPlatform{accounts: nil, accountsByID: map[int64]*Account{}}
|
|
svc := &GatewayService{accountRepo: repo, cfg: testConfig()}
|
|
|
|
diag := svc.DiagnoseModelAvailabilityForPlatform(context.Background(), nil, "gpt-5", PlatformOpenAI)
|
|
|
|
require.False(t, diag.HasAccountsInPool)
|
|
require.False(t, diag.HasModelSupport, "no accounts means no support; caller stays on 503 (empty-pool branch)")
|
|
}
|
|
|
|
func TestDiagnoseModelAvailabilityForPlatform_ExplicitMappingMatches(t *testing.T) {
|
|
repo := &mockAccountRepoForPlatform{
|
|
accounts: []Account{
|
|
{
|
|
ID: 1,
|
|
Platform: PlatformOpenAI,
|
|
Status: StatusActive,
|
|
Schedulable: true,
|
|
Credentials: map[string]any{
|
|
"model_mapping": map[string]any{"gpt-5.1-codex-mini": "gpt-5.1-codex-mini"},
|
|
},
|
|
},
|
|
},
|
|
accountsByID: map[int64]*Account{},
|
|
}
|
|
for i := range repo.accounts {
|
|
repo.accountsByID[repo.accounts[i].ID] = &repo.accounts[i]
|
|
}
|
|
svc := &GatewayService{accountRepo: repo, cfg: testConfig()}
|
|
|
|
diag := svc.DiagnoseModelAvailabilityForPlatform(context.Background(), nil, "gpt-5.1-codex-mini", PlatformOpenAI)
|
|
|
|
require.True(t, diag.HasAccountsInPool)
|
|
require.True(t, diag.HasModelSupport)
|
|
}
|
|
|
|
func TestDiagnoseModelAvailabilityForPlatform_EmptyMappingAllowsAll(t *testing.T) {
|
|
repo := &mockAccountRepoForPlatform{
|
|
accounts: []Account{
|
|
{ID: 1, Platform: PlatformOpenAI, Status: StatusActive, Schedulable: true /* no ModelMapping = allow all */},
|
|
},
|
|
accountsByID: map[int64]*Account{},
|
|
}
|
|
for i := range repo.accounts {
|
|
repo.accountsByID[repo.accounts[i].ID] = &repo.accounts[i]
|
|
}
|
|
svc := &GatewayService{accountRepo: repo, cfg: testConfig()}
|
|
|
|
diag := svc.DiagnoseModelAvailabilityForPlatform(context.Background(), nil, "gpt-5.1-codex-mini", PlatformOpenAI)
|
|
|
|
require.True(t, diag.HasModelSupport, "empty model_mapping must be treated as 'allow all' (Account.IsModelSupported semantics)")
|
|
}
|
|
|
|
func TestDiagnoseModelAvailabilityForPlatform_WildcardMappingMatches(t *testing.T) {
|
|
repo := &mockAccountRepoForPlatform{
|
|
accounts: []Account{
|
|
{
|
|
ID: 1,
|
|
Platform: PlatformOpenAI,
|
|
Status: StatusActive,
|
|
Schedulable: true,
|
|
Credentials: map[string]any{
|
|
"model_mapping": map[string]any{"*": "gpt-5"},
|
|
},
|
|
},
|
|
},
|
|
accountsByID: map[int64]*Account{},
|
|
}
|
|
for i := range repo.accounts {
|
|
repo.accountsByID[repo.accounts[i].ID] = &repo.accounts[i]
|
|
}
|
|
svc := &GatewayService{accountRepo: repo, cfg: testConfig()}
|
|
|
|
diag := svc.DiagnoseModelAvailabilityForPlatform(context.Background(), nil, "gpt-5.1-codex-mini", PlatformOpenAI)
|
|
|
|
require.True(t, diag.HasModelSupport, "wildcard mapping must classify the request as 'serviceable'")
|
|
}
|
|
|
|
func TestDiagnoseModelAvailabilityForPlatform_NoMatchingModel_ReturnsNotFoundSignal(t *testing.T) {
|
|
repo := &mockAccountRepoForPlatform{
|
|
accounts: []Account{
|
|
{
|
|
ID: 1,
|
|
Platform: PlatformOpenAI,
|
|
Status: StatusActive,
|
|
Schedulable: true,
|
|
Credentials: map[string]any{"model_mapping": map[string]any{"gpt-5": "gpt-5"}},
|
|
},
|
|
{
|
|
ID: 2,
|
|
Platform: PlatformOpenAI,
|
|
Status: StatusActive,
|
|
Schedulable: true,
|
|
Credentials: map[string]any{"model_mapping": map[string]any{"gpt-5-mini": "gpt-5-mini"}},
|
|
},
|
|
},
|
|
accountsByID: map[int64]*Account{},
|
|
}
|
|
for i := range repo.accounts {
|
|
repo.accountsByID[repo.accounts[i].ID] = &repo.accounts[i]
|
|
}
|
|
svc := &GatewayService{accountRepo: repo, cfg: testConfig()}
|
|
|
|
diag := svc.DiagnoseModelAvailabilityForPlatform(context.Background(), nil, "gpt-5.1-codex-mini", PlatformOpenAI)
|
|
|
|
require.True(t, diag.HasAccountsInPool, "group has OpenAI accounts")
|
|
require.False(t, diag.HasModelSupport, "no account mapping admits the requested model — handler should return 404")
|
|
}
|
|
|
|
func TestDiagnoseModelAvailabilityForPlatform_WrongPlatformFiltersOut(t *testing.T) {
|
|
// Group has only Anthropic accounts; user routes to OpenAI gateway.
|
|
// Diagnosis must NOT see Anthropic accounts (listSchedulableAccounts filters
|
|
// by platform), so HasAccountsInPool is false and the caller stays on 503.
|
|
repo := &mockAccountRepoForPlatform{
|
|
accounts: []Account{
|
|
{
|
|
ID: 1,
|
|
Platform: PlatformAnthropic,
|
|
Status: StatusActive,
|
|
Schedulable: true,
|
|
Credentials: map[string]any{"model_mapping": map[string]any{"claude-sonnet-4-5": "claude-sonnet-4-5"}},
|
|
},
|
|
},
|
|
accountsByID: map[int64]*Account{},
|
|
}
|
|
for i := range repo.accounts {
|
|
repo.accountsByID[repo.accounts[i].ID] = &repo.accounts[i]
|
|
}
|
|
svc := &GatewayService{accountRepo: repo, cfg: testConfig()}
|
|
|
|
diag := svc.DiagnoseModelAvailabilityForPlatform(context.Background(), nil, "gpt-5", PlatformOpenAI)
|
|
|
|
require.False(t, diag.HasAccountsInPool, "OpenAI route must not see Anthropic accounts in pool")
|
|
require.False(t, diag.HasModelSupport)
|
|
}
|