mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-05-10 15:57:52 +08:00
- Updated all references from v6 to v7 for `github.com/router-for-me/CLIProxyAPI`. - Ensured consistency in imports within core libraries, tests, and integration tests. - Added missing tests for new features in Redis Protocol integration.
188 lines
5.2 KiB
Go
188 lines
5.2 KiB
Go
package diff
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
|
|
)
|
|
|
|
func TestDiffOpenAICompatibility(t *testing.T) {
|
|
oldList := []config.OpenAICompatibility{
|
|
{
|
|
Name: "provider-a",
|
|
APIKeyEntries: []config.OpenAICompatibilityAPIKey{
|
|
{APIKey: "key-a"},
|
|
},
|
|
Models: []config.OpenAICompatibilityModel{
|
|
{Name: "m1"},
|
|
},
|
|
},
|
|
}
|
|
newList := []config.OpenAICompatibility{
|
|
{
|
|
Name: "provider-a",
|
|
APIKeyEntries: []config.OpenAICompatibilityAPIKey{
|
|
{APIKey: "key-a"},
|
|
{APIKey: "key-b"},
|
|
},
|
|
Models: []config.OpenAICompatibilityModel{
|
|
{Name: "m1"},
|
|
{Name: "m2"},
|
|
},
|
|
Headers: map[string]string{"X-Test": "1"},
|
|
},
|
|
{
|
|
Name: "provider-b",
|
|
APIKeyEntries: []config.OpenAICompatibilityAPIKey{{APIKey: "key-b"}},
|
|
},
|
|
}
|
|
|
|
changes := DiffOpenAICompatibility(oldList, newList)
|
|
expectContains(t, changes, "provider added: provider-b (api-keys=1, models=0)")
|
|
expectContains(t, changes, "provider updated: provider-a (api-keys 1 -> 2, models 1 -> 2, headers updated)")
|
|
}
|
|
|
|
func TestDiffOpenAICompatibility_RemovedAndUnchanged(t *testing.T) {
|
|
oldList := []config.OpenAICompatibility{
|
|
{
|
|
Name: "provider-a",
|
|
APIKeyEntries: []config.OpenAICompatibilityAPIKey{{APIKey: "key-a"}},
|
|
Models: []config.OpenAICompatibilityModel{{Name: "m1"}},
|
|
},
|
|
}
|
|
newList := []config.OpenAICompatibility{
|
|
{
|
|
Name: "provider-a",
|
|
APIKeyEntries: []config.OpenAICompatibilityAPIKey{{APIKey: "key-a"}},
|
|
Models: []config.OpenAICompatibilityModel{{Name: "m1"}},
|
|
},
|
|
}
|
|
if changes := DiffOpenAICompatibility(oldList, newList); len(changes) != 0 {
|
|
t.Fatalf("expected no changes, got %v", changes)
|
|
}
|
|
|
|
newList = nil
|
|
changes := DiffOpenAICompatibility(oldList, newList)
|
|
expectContains(t, changes, "provider removed: provider-a (api-keys=1, models=1)")
|
|
}
|
|
|
|
func TestOpenAICompatKeyFallbacks(t *testing.T) {
|
|
entry := config.OpenAICompatibility{
|
|
BaseURL: "http://base",
|
|
Models: []config.OpenAICompatibilityModel{{Alias: "alias-only"}},
|
|
}
|
|
key, label := openAICompatKey(entry, 0)
|
|
if key != "base:http://base" || label != "http://base" {
|
|
t.Fatalf("expected base key, got %s/%s", key, label)
|
|
}
|
|
|
|
entry.BaseURL = ""
|
|
key, label = openAICompatKey(entry, 1)
|
|
if key != "alias:alias-only" || label != "alias-only" {
|
|
t.Fatalf("expected alias fallback, got %s/%s", key, label)
|
|
}
|
|
|
|
entry.Models = nil
|
|
key, label = openAICompatKey(entry, 2)
|
|
if key != "index:2" || label != "entry-3" {
|
|
t.Fatalf("expected index fallback, got %s/%s", key, label)
|
|
}
|
|
}
|
|
|
|
func TestOpenAICompatKey_UsesName(t *testing.T) {
|
|
entry := config.OpenAICompatibility{Name: "My-Provider"}
|
|
key, label := openAICompatKey(entry, 0)
|
|
if key != "name:My-Provider" || label != "My-Provider" {
|
|
t.Fatalf("expected name key, got %s/%s", key, label)
|
|
}
|
|
}
|
|
|
|
func TestOpenAICompatKey_SignatureFallbackWhenOnlyAPIKeys(t *testing.T) {
|
|
entry := config.OpenAICompatibility{
|
|
APIKeyEntries: []config.OpenAICompatibilityAPIKey{{APIKey: "k1"}, {APIKey: "k2"}},
|
|
}
|
|
key, label := openAICompatKey(entry, 0)
|
|
if !strings.HasPrefix(key, "sig:") || !strings.HasPrefix(label, "compat-") {
|
|
t.Fatalf("expected signature key, got %s/%s", key, label)
|
|
}
|
|
}
|
|
|
|
func TestOpenAICompatSignature_EmptyReturnsEmpty(t *testing.T) {
|
|
if got := openAICompatSignature(config.OpenAICompatibility{}); got != "" {
|
|
t.Fatalf("expected empty signature, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestOpenAICompatSignature_StableAndNormalized(t *testing.T) {
|
|
a := config.OpenAICompatibility{
|
|
Name: " Provider ",
|
|
BaseURL: "http://base",
|
|
Models: []config.OpenAICompatibilityModel{
|
|
{Name: "m1"},
|
|
{Name: " "},
|
|
{Alias: "A1"},
|
|
},
|
|
Headers: map[string]string{
|
|
"X-Test": "1",
|
|
" ": "ignored",
|
|
},
|
|
APIKeyEntries: []config.OpenAICompatibilityAPIKey{
|
|
{APIKey: "k1"},
|
|
{APIKey: " "},
|
|
},
|
|
}
|
|
b := config.OpenAICompatibility{
|
|
Name: "provider",
|
|
BaseURL: "http://base",
|
|
Models: []config.OpenAICompatibilityModel{
|
|
{Alias: "a1"},
|
|
{Name: "m1"},
|
|
},
|
|
Headers: map[string]string{
|
|
"x-test": "2",
|
|
},
|
|
APIKeyEntries: []config.OpenAICompatibilityAPIKey{
|
|
{APIKey: "k2"},
|
|
},
|
|
}
|
|
|
|
sigA := openAICompatSignature(a)
|
|
sigB := openAICompatSignature(b)
|
|
if sigA == "" || sigB == "" {
|
|
t.Fatalf("expected non-empty signatures, got %q / %q", sigA, sigB)
|
|
}
|
|
if sigA != sigB {
|
|
t.Fatalf("expected normalized signatures to match, got %s / %s", sigA, sigB)
|
|
}
|
|
|
|
c := b
|
|
c.Models = append(c.Models, config.OpenAICompatibilityModel{Name: "m2"})
|
|
if sigC := openAICompatSignature(c); sigC == sigB {
|
|
t.Fatalf("expected signature to change when models change, got %s", sigC)
|
|
}
|
|
}
|
|
|
|
func TestCountOpenAIModelsSkipsBlanks(t *testing.T) {
|
|
models := []config.OpenAICompatibilityModel{
|
|
{Name: "m1"},
|
|
{Name: ""},
|
|
{Alias: ""},
|
|
{Name: " "},
|
|
{Alias: "a1"},
|
|
}
|
|
if got := countOpenAIModels(models); got != 2 {
|
|
t.Fatalf("expected 2 counted models, got %d", got)
|
|
}
|
|
}
|
|
|
|
func TestOpenAICompatKeyUsesModelNameWhenAliasEmpty(t *testing.T) {
|
|
entry := config.OpenAICompatibility{
|
|
Models: []config.OpenAICompatibilityModel{{Name: "model-name"}},
|
|
}
|
|
key, label := openAICompatKey(entry, 5)
|
|
if key != "alias:model-name" || label != "model-name" {
|
|
t.Fatalf("expected model-name fallback, got %s/%s", key, label)
|
|
}
|
|
}
|