237 lines
7.5 KiB
Go
237 lines
7.5 KiB
Go
package cliproxy
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/router-for-me/CLIProxyAPI/v7/internal/pluginhost"
|
|
"github.com/router-for-me/CLIProxyAPI/v7/internal/runtime/executor"
|
|
"github.com/router-for-me/CLIProxyAPI/v7/internal/watcher"
|
|
sdkAuth "github.com/router-for-me/CLIProxyAPI/v7/sdk/auth"
|
|
coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
|
|
"github.com/router-for-me/CLIProxyAPI/v7/sdk/config"
|
|
sdktranslator "github.com/router-for-me/CLIProxyAPI/v7/sdk/translator"
|
|
)
|
|
|
|
func TestEnsureExecutorsForAuth_CodexDoesNotReplaceInNormalMode(t *testing.T) {
|
|
service := &Service{
|
|
cfg: &config.Config{},
|
|
coreManager: coreauth.NewManager(nil, nil, nil),
|
|
}
|
|
auth := &coreauth.Auth{
|
|
ID: "codex-auth-1",
|
|
Provider: "codex",
|
|
Status: coreauth.StatusActive,
|
|
}
|
|
|
|
service.ensureExecutorsForAuth(auth)
|
|
firstExecutor, okFirst := service.coreManager.Executor("codex")
|
|
if !okFirst || firstExecutor == nil {
|
|
t.Fatal("expected codex executor after first bind")
|
|
}
|
|
|
|
service.ensureExecutorsForAuth(auth)
|
|
secondExecutor, okSecond := service.coreManager.Executor("codex")
|
|
if !okSecond || secondExecutor == nil {
|
|
t.Fatal("expected codex executor after second bind")
|
|
}
|
|
|
|
if firstExecutor != secondExecutor {
|
|
t.Fatal("expected codex executor to stay unchanged in normal mode")
|
|
}
|
|
}
|
|
|
|
func TestEnsureExecutorsForAuthWithMode_CodexForceReplace(t *testing.T) {
|
|
service := &Service{
|
|
cfg: &config.Config{},
|
|
coreManager: coreauth.NewManager(nil, nil, nil),
|
|
}
|
|
auth := &coreauth.Auth{
|
|
ID: "codex-auth-2",
|
|
Provider: "codex",
|
|
Status: coreauth.StatusActive,
|
|
}
|
|
|
|
service.ensureExecutorsForAuth(auth)
|
|
firstExecutor, okFirst := service.coreManager.Executor("codex")
|
|
if !okFirst || firstExecutor == nil {
|
|
t.Fatal("expected codex executor after first bind")
|
|
}
|
|
|
|
service.ensureExecutorsForAuthWithMode(auth, true)
|
|
secondExecutor, okSecond := service.coreManager.Executor("codex")
|
|
if !okSecond || secondExecutor == nil {
|
|
t.Fatal("expected codex executor after forced rebind")
|
|
}
|
|
|
|
if firstExecutor == secondExecutor {
|
|
t.Fatal("expected codex executor replacement in force mode")
|
|
}
|
|
}
|
|
|
|
func TestSyncPluginModelRuntime_UnrelatedAuthDoesNotReplaceWebsocketExecutor(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
provider string
|
|
homeEnabled bool
|
|
}{
|
|
{name: "codex standard mode", provider: "codex"},
|
|
{name: "codex home mode", provider: "codex", homeEnabled: true},
|
|
{name: "xai standard mode", provider: "xai"},
|
|
{name: "xai home mode", provider: "xai", homeEnabled: true},
|
|
}
|
|
|
|
for _, tt := range testCases {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ctx := context.Background()
|
|
cfg := &config.Config{}
|
|
cfg.Home.Enabled = tt.homeEnabled
|
|
service := &Service{
|
|
cfg: cfg,
|
|
coreManager: coreauth.NewManager(nil, nil, nil),
|
|
pluginHost: pluginhost.New(),
|
|
}
|
|
providerAuth := &coreauth.Auth{
|
|
ID: tt.provider + "-auth",
|
|
Provider: tt.provider,
|
|
Status: coreauth.StatusActive,
|
|
}
|
|
unrelatedAuth := &coreauth.Auth{
|
|
ID: "unrelated-auth",
|
|
Provider: "claude",
|
|
Status: coreauth.StatusActive,
|
|
}
|
|
t.Cleanup(func() {
|
|
GlobalModelRegistry().UnregisterClient(providerAuth.ID)
|
|
GlobalModelRegistry().UnregisterClient(unrelatedAuth.ID)
|
|
sdkAuth.RegisterPluginAuthParser(nil)
|
|
sdktranslator.SetPluginHooks(nil)
|
|
})
|
|
|
|
if _, errRegister := service.coreManager.Register(ctx, providerAuth); errRegister != nil {
|
|
t.Fatalf("register %s auth: %v", tt.provider, errRegister)
|
|
}
|
|
if _, errRegister := service.coreManager.Register(ctx, unrelatedAuth); errRegister != nil {
|
|
t.Fatalf("register unrelated auth: %v", errRegister)
|
|
}
|
|
service.ensureExecutorsForAuth(providerAuth)
|
|
firstExecutor, okFirst := service.coreManager.Executor(tt.provider)
|
|
if !okFirst || firstExecutor == nil {
|
|
t.Fatalf("expected %s executor before plugin model sync", tt.provider)
|
|
}
|
|
|
|
updatedAuth := unrelatedAuth.Clone()
|
|
updatedAuth.Label = "updated unrelated auth"
|
|
service.handleAuthUpdate(ctx, watcher.AuthUpdate{
|
|
Action: watcher.AuthUpdateActionModify,
|
|
ID: updatedAuth.ID,
|
|
Auth: updatedAuth,
|
|
})
|
|
|
|
secondExecutor, okSecond := service.coreManager.Executor(tt.provider)
|
|
if !okSecond || secondExecutor == nil {
|
|
t.Fatalf("expected %s executor after plugin model sync", tt.provider)
|
|
}
|
|
if firstExecutor != secondExecutor {
|
|
t.Fatalf("expected unrelated auth sync to preserve the %s executor", tt.provider)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEnsureExecutorsForAuth_XAIDoesNotReplaceInNormalMode(t *testing.T) {
|
|
service := &Service{
|
|
cfg: &config.Config{},
|
|
coreManager: coreauth.NewManager(nil, nil, nil),
|
|
}
|
|
auth := &coreauth.Auth{
|
|
ID: "xai-auth-1",
|
|
Provider: "xai",
|
|
Status: coreauth.StatusActive,
|
|
}
|
|
|
|
service.ensureExecutorsForAuth(auth)
|
|
firstExecutor, okFirst := service.coreManager.Executor("xai")
|
|
if !okFirst || firstExecutor == nil {
|
|
t.Fatal("expected xai executor after first bind")
|
|
}
|
|
if _, isXAIAutoExecutor := firstExecutor.(*executor.XAIAutoExecutor); !isXAIAutoExecutor {
|
|
t.Fatalf("xai executor type = %T, want *executor.XAIAutoExecutor", firstExecutor)
|
|
}
|
|
|
|
service.ensureExecutorsForAuth(auth)
|
|
secondExecutor, okSecond := service.coreManager.Executor("xai")
|
|
if !okSecond || secondExecutor == nil {
|
|
t.Fatal("expected xai executor after second bind")
|
|
}
|
|
if firstExecutor != secondExecutor {
|
|
t.Fatal("expected xai executor to stay unchanged in normal mode")
|
|
}
|
|
}
|
|
|
|
func TestEnsureExecutorsForAuthWithMode_XAIForceReplace(t *testing.T) {
|
|
service := &Service{
|
|
cfg: &config.Config{},
|
|
coreManager: coreauth.NewManager(nil, nil, nil),
|
|
}
|
|
auth := &coreauth.Auth{
|
|
ID: "xai-auth-2",
|
|
Provider: "xai",
|
|
Status: coreauth.StatusActive,
|
|
}
|
|
|
|
service.ensureExecutorsForAuth(auth)
|
|
firstExecutor, okFirst := service.coreManager.Executor("xai")
|
|
if !okFirst || firstExecutor == nil {
|
|
t.Fatal("expected xai executor after first bind")
|
|
}
|
|
|
|
service.ensureExecutorsForAuthWithMode(auth, true)
|
|
secondExecutor, okSecond := service.coreManager.Executor("xai")
|
|
if !okSecond || secondExecutor == nil {
|
|
t.Fatal("expected xai executor after forced rebind")
|
|
}
|
|
if firstExecutor == secondExecutor {
|
|
t.Fatal("expected xai executor replacement in force mode")
|
|
}
|
|
if _, isXAIAutoExecutor := secondExecutor.(*executor.XAIAutoExecutor); !isXAIAutoExecutor {
|
|
t.Fatalf("xai executor type = %T, want *executor.XAIAutoExecutor", secondExecutor)
|
|
}
|
|
}
|
|
|
|
func TestEnsureExecutorsForAuth_XAIReplacesExecutorAfterConfigUpdate(t *testing.T) {
|
|
service := &Service{
|
|
cfg: &config.Config{},
|
|
coreManager: coreauth.NewManager(nil, nil, nil),
|
|
pluginHost: pluginhost.New(),
|
|
}
|
|
t.Cleanup(func() {
|
|
sdkAuth.RegisterPluginAuthParser(nil)
|
|
sdktranslator.SetPluginHooks(nil)
|
|
})
|
|
auth := &coreauth.Auth{
|
|
ID: "xai-auth-config-update",
|
|
Provider: "xai",
|
|
Status: coreauth.StatusActive,
|
|
}
|
|
|
|
service.ensureExecutorsForAuth(auth)
|
|
firstExecutor, okFirst := service.coreManager.Executor("xai")
|
|
if !okFirst || firstExecutor == nil {
|
|
t.Fatal("expected xai executor before config update")
|
|
}
|
|
|
|
service.applyWatcherConfigUpdate(&config.Config{})
|
|
service.ensureExecutorsForAuth(auth)
|
|
|
|
secondExecutor, okSecond := service.coreManager.Executor("xai")
|
|
if !okSecond || secondExecutor == nil {
|
|
t.Fatal("expected xai executor after config update")
|
|
}
|
|
if firstExecutor == secondExecutor {
|
|
t.Fatal("expected stale xai executor replacement after config update")
|
|
}
|
|
if _, isXAIAutoExecutor := secondExecutor.(*executor.XAIAutoExecutor); !isXAIAutoExecutor {
|
|
t.Fatalf("xai executor type = %T, want *executor.XAIAutoExecutor", secondExecutor)
|
|
}
|
|
}
|