mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-09-08 17:11:19 +08:00
- Adjusted `resolveConfigCodexStyleKey` to include `validateIndexCredentials` for stricter credential checks. - Enhanced logic in `buildCodexConfigModels` to handle empty model lists more effectively. - Standardized credential matching with helper functions for improved maintainability.
189 lines
5.7 KiB
Go
189 lines
5.7 KiB
Go
package cliproxy
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
|
|
internalconfig "github.com/router-for-me/CLIProxyAPI/v7/internal/config"
|
|
internalregistry "github.com/router-for-me/CLIProxyAPI/v7/internal/registry"
|
|
coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
|
|
"github.com/router-for-me/CLIProxyAPI/v7/sdk/config"
|
|
)
|
|
|
|
func TestRegisterModelsForAuthCodexAPIKeyModels(t *testing.T) {
|
|
defaultModels := internalregistry.GetCodexProModels()
|
|
if len(defaultModels) == 0 {
|
|
t.Fatal("expected Codex Pro default models")
|
|
}
|
|
|
|
excludedModelID := defaultModels[0].ID
|
|
tests := []struct {
|
|
name string
|
|
entry config.CodexKey
|
|
wantIDs map[string]struct{}
|
|
}{
|
|
{
|
|
name: "defaults without configuration",
|
|
entry: config.CodexKey{APIKey: "default-key"},
|
|
wantIDs: codexModelIDSet(defaultModels),
|
|
},
|
|
{
|
|
name: "explicit configuration replaces defaults",
|
|
entry: config.CodexKey{
|
|
APIKey: "configured-key",
|
|
Models: []internalconfig.CodexModel{{
|
|
Name: "upstream-codex", Alias: "configured-codex",
|
|
}},
|
|
},
|
|
wantIDs: map[string]struct{}{"configured-codex": {}},
|
|
},
|
|
{
|
|
name: "exclusions apply to defaults",
|
|
entry: config.CodexKey{
|
|
APIKey: "excluded-key",
|
|
ExcludedModels: []string{excludedModelID},
|
|
},
|
|
wantIDs: codexModelIDSet(defaultModels[1:]),
|
|
},
|
|
}
|
|
|
|
for index := range tests {
|
|
testCase := tests[index]
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
authID := fmt.Sprintf("codex-api-key-models-%d", index)
|
|
modelRegistry := internalregistry.GetGlobalRegistry()
|
|
modelRegistry.UnregisterClient(authID)
|
|
t.Cleanup(func() { modelRegistry.UnregisterClient(authID) })
|
|
|
|
service := &Service{cfg: &config.Config{CodexKey: []config.CodexKey{testCase.entry}}}
|
|
auth := &coreauth.Auth{
|
|
ID: authID,
|
|
Provider: "codex",
|
|
Status: coreauth.StatusActive,
|
|
Attributes: map[string]string{
|
|
coreauth.AttributeAPIKey: testCase.entry.APIKey,
|
|
coreauth.AttributeConfigIndex: "0",
|
|
coreauth.AttributeSource: "config:codex:test",
|
|
},
|
|
}
|
|
|
|
service.registerModelsForAuth(context.Background(), auth)
|
|
gotIDs := codexModelIDSet(modelRegistry.GetModelsForClient(authID))
|
|
if len(gotIDs) != len(testCase.wantIDs) {
|
|
t.Fatalf("registered model IDs = %#v, want %#v", gotIDs, testCase.wantIDs)
|
|
}
|
|
for modelID := range testCase.wantIDs {
|
|
if _, ok := gotIDs[modelID]; !ok {
|
|
t.Errorf("missing registered model %q", modelID)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRegisterModelsForAuthCodexAPIKeyDefaultRequiresConfigMatch(t *testing.T) {
|
|
defaultIDs := codexModelIDSet(internalregistry.GetCodexProModels())
|
|
tests := []struct {
|
|
name string
|
|
config config.Config
|
|
attributes map[string]string
|
|
wantIDs map[string]struct{}
|
|
}{
|
|
{
|
|
name: "valid index with unmatched API key",
|
|
config: config.Config{CodexKey: []config.CodexKey{{
|
|
APIKey: "configured-key",
|
|
}}},
|
|
attributes: map[string]string{
|
|
coreauth.AttributeAPIKey: "stale-key",
|
|
coreauth.AttributeConfigIndex: "0",
|
|
coreauth.AttributeSource: "config:codex:stale",
|
|
},
|
|
wantIDs: map[string]struct{}{},
|
|
},
|
|
{
|
|
name: "valid index with unmatched base URL",
|
|
config: config.Config{CodexKey: []config.CodexKey{{
|
|
APIKey: "configured-key", BaseURL: "https://new.example.com",
|
|
}}},
|
|
attributes: map[string]string{
|
|
coreauth.AttributeAPIKey: "configured-key",
|
|
coreauth.AttributeConfigIndex: "0",
|
|
coreauth.AttributeSource: "config:codex:stale",
|
|
"base_url": "https://old.example.com",
|
|
},
|
|
wantIDs: map[string]struct{}{},
|
|
},
|
|
{
|
|
name: "stale index falls back to matching credentials",
|
|
config: config.Config{CodexKey: []config.CodexKey{
|
|
{
|
|
APIKey: "wrong-key",
|
|
Models: []internalconfig.CodexModel{{Name: "wrong-model"}},
|
|
},
|
|
{APIKey: "configured-key"},
|
|
}},
|
|
attributes: map[string]string{
|
|
coreauth.AttributeAPIKey: "configured-key",
|
|
coreauth.AttributeConfigIndex: "0",
|
|
coreauth.AttributeSource: "config:codex:stale",
|
|
},
|
|
wantIDs: defaultIDs,
|
|
},
|
|
{
|
|
name: "API key ignores OAuth plan type",
|
|
config: config.Config{CodexKey: []config.CodexKey{{
|
|
APIKey: "configured-key",
|
|
}}},
|
|
attributes: map[string]string{
|
|
coreauth.AttributeAPIKey: "configured-key",
|
|
coreauth.AttributeConfigIndex: "0",
|
|
coreauth.AttributeSource: "config:codex:test",
|
|
"plan_type": "free",
|
|
},
|
|
wantIDs: defaultIDs,
|
|
},
|
|
}
|
|
|
|
for index := range tests {
|
|
testCase := tests[index]
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
authID := fmt.Sprintf("codex-api-key-config-match-%d", index)
|
|
modelRegistry := internalregistry.GetGlobalRegistry()
|
|
modelRegistry.UnregisterClient(authID)
|
|
modelRegistry.RegisterClient(authID, "codex", []*internalregistry.ModelInfo{{ID: "stale-model"}})
|
|
t.Cleanup(func() { modelRegistry.UnregisterClient(authID) })
|
|
|
|
service := &Service{cfg: &testCase.config}
|
|
auth := &coreauth.Auth{
|
|
ID: authID,
|
|
Provider: "codex",
|
|
Status: coreauth.StatusActive,
|
|
Attributes: testCase.attributes,
|
|
}
|
|
|
|
service.registerModelsForAuth(context.Background(), auth)
|
|
gotIDs := codexModelIDSet(modelRegistry.GetModelsForClient(authID))
|
|
if len(gotIDs) != len(testCase.wantIDs) {
|
|
t.Fatalf("registered model IDs = %#v, want %#v", gotIDs, testCase.wantIDs)
|
|
}
|
|
for modelID := range testCase.wantIDs {
|
|
if _, ok := gotIDs[modelID]; !ok {
|
|
t.Errorf("missing registered model %q", modelID)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func codexModelIDSet(models []*internalregistry.ModelInfo) map[string]struct{} {
|
|
ids := make(map[string]struct{}, len(models))
|
|
for _, model := range models {
|
|
if model != nil && model.ID != "" {
|
|
ids[model.ID] = struct{}{}
|
|
}
|
|
}
|
|
return ids
|
|
}
|