| package synthesizer |
|
|
| import ( |
| "reflect" |
| "strings" |
| "testing" |
|
|
| "github.com/router-for-me/CLIProxyAPI/v6/internal/config" |
| coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" |
| ) |
|
|
| func TestNewStableIDGenerator(t *testing.T) { |
| gen := NewStableIDGenerator() |
| if gen == nil { |
| t.Fatal("expected non-nil generator") |
| } |
| if gen.counters == nil { |
| t.Fatal("expected non-nil counters map") |
| } |
| } |
|
|
| func TestStableIDGenerator_Next(t *testing.T) { |
| tests := []struct { |
| name string |
| kind string |
| parts []string |
| wantPrefix string |
| }{ |
| { |
| name: "basic gemini apikey", |
| kind: "gemini:apikey", |
| parts: []string{"test-key", ""}, |
| wantPrefix: "gemini:apikey:", |
| }, |
| { |
| name: "claude with base url", |
| kind: "claude:apikey", |
| parts: []string{"sk-ant-xxx", "https://api.anthropic.com"}, |
| wantPrefix: "claude:apikey:", |
| }, |
| { |
| name: "empty parts", |
| kind: "codex:apikey", |
| parts: []string{}, |
| wantPrefix: "codex:apikey:", |
| }, |
| } |
|
|
| for _, tt := range tests { |
| t.Run(tt.name, func(t *testing.T) { |
| gen := NewStableIDGenerator() |
| id, short := gen.Next(tt.kind, tt.parts...) |
|
|
| if !strings.Contains(id, tt.wantPrefix) { |
| t.Errorf("expected id to contain %q, got %q", tt.wantPrefix, id) |
| } |
| if short == "" { |
| t.Error("expected non-empty short id") |
| } |
| if len(short) != 12 { |
| t.Errorf("expected short id length 12, got %d", len(short)) |
| } |
| }) |
| } |
| } |
|
|
| func TestStableIDGenerator_Stability(t *testing.T) { |
| gen1 := NewStableIDGenerator() |
| gen2 := NewStableIDGenerator() |
|
|
| id1, _ := gen1.Next("gemini:apikey", "test-key", "https://api.example.com") |
| id2, _ := gen2.Next("gemini:apikey", "test-key", "https://api.example.com") |
|
|
| if id1 != id2 { |
| t.Errorf("same inputs should produce same ID: got %q and %q", id1, id2) |
| } |
| } |
|
|
| func TestStableIDGenerator_CollisionHandling(t *testing.T) { |
| gen := NewStableIDGenerator() |
|
|
| id1, short1 := gen.Next("gemini:apikey", "same-key") |
| id2, short2 := gen.Next("gemini:apikey", "same-key") |
|
|
| if id1 == id2 { |
| t.Error("collision should be handled with suffix") |
| } |
| if short1 == short2 { |
| t.Error("short ids should differ") |
| } |
| if !strings.Contains(short2, "-1") { |
| t.Errorf("second short id should contain -1 suffix, got %q", short2) |
| } |
| } |
|
|
| func TestStableIDGenerator_NilReceiver(t *testing.T) { |
| var gen *StableIDGenerator = nil |
| id, short := gen.Next("test:kind", "part") |
|
|
| if id != "test:kind:000000000000" { |
| t.Errorf("expected test:kind:000000000000, got %q", id) |
| } |
| if short != "000000000000" { |
| t.Errorf("expected 000000000000, got %q", short) |
| } |
| } |
|
|
| func TestApplyAuthExcludedModelsMeta(t *testing.T) { |
| tests := []struct { |
| name string |
| auth *coreauth.Auth |
| cfg *config.Config |
| perKey []string |
| authKind string |
| wantHash bool |
| wantKind string |
| }{ |
| { |
| name: "apikey with excluded models", |
| auth: &coreauth.Auth{ |
| Provider: "gemini", |
| Attributes: make(map[string]string), |
| }, |
| cfg: &config.Config{}, |
| perKey: []string{"model-a", "model-b"}, |
| authKind: "apikey", |
| wantHash: true, |
| wantKind: "apikey", |
| }, |
| { |
| name: "oauth with provider excluded models", |
| auth: &coreauth.Auth{ |
| Provider: "claude", |
| Attributes: make(map[string]string), |
| }, |
| cfg: &config.Config{ |
| OAuthExcludedModels: map[string][]string{ |
| "claude": {"claude-2.0"}, |
| }, |
| }, |
| perKey: nil, |
| authKind: "oauth", |
| wantHash: true, |
| wantKind: "oauth", |
| }, |
| { |
| name: "nil auth", |
| auth: nil, |
| cfg: &config.Config{}, |
| }, |
| { |
| name: "nil config", |
| auth: &coreauth.Auth{Provider: "test"}, |
| cfg: nil, |
| authKind: "apikey", |
| }, |
| { |
| name: "nil attributes initialized", |
| auth: &coreauth.Auth{ |
| Provider: "gemini", |
| Attributes: nil, |
| }, |
| cfg: &config.Config{}, |
| perKey: []string{"model-x"}, |
| authKind: "apikey", |
| wantHash: true, |
| wantKind: "apikey", |
| }, |
| { |
| name: "apikey with duplicate excluded models", |
| auth: &coreauth.Auth{ |
| Provider: "gemini", |
| Attributes: make(map[string]string), |
| }, |
| cfg: &config.Config{}, |
| perKey: []string{"model-a", "MODEL-A", "model-b", "model-a"}, |
| authKind: "apikey", |
| wantHash: true, |
| wantKind: "apikey", |
| }, |
| } |
|
|
| for _, tt := range tests { |
| t.Run(tt.name, func(t *testing.T) { |
| ApplyAuthExcludedModelsMeta(tt.auth, tt.cfg, tt.perKey, tt.authKind) |
|
|
| if tt.auth != nil && tt.cfg != nil { |
| if tt.wantHash { |
| if _, ok := tt.auth.Attributes["excluded_models_hash"]; !ok { |
| t.Error("expected excluded_models_hash in attributes") |
| } |
| } |
| if tt.wantKind != "" { |
| if got := tt.auth.Attributes["auth_kind"]; got != tt.wantKind { |
| t.Errorf("expected auth_kind=%s, got %s", tt.wantKind, got) |
| } |
| } |
| } |
| }) |
| } |
| } |
|
|
| func TestAddConfigHeadersToAttrs(t *testing.T) { |
| tests := []struct { |
| name string |
| headers map[string]string |
| attrs map[string]string |
| want map[string]string |
| }{ |
| { |
| name: "basic headers", |
| headers: map[string]string{ |
| "Authorization": "Bearer token", |
| "X-Custom": "value", |
| }, |
| attrs: map[string]string{"existing": "key"}, |
| want: map[string]string{ |
| "existing": "key", |
| "header:Authorization": "Bearer token", |
| "header:X-Custom": "value", |
| }, |
| }, |
| { |
| name: "empty headers", |
| headers: map[string]string{}, |
| attrs: map[string]string{"existing": "key"}, |
| want: map[string]string{"existing": "key"}, |
| }, |
| { |
| name: "nil headers", |
| headers: nil, |
| attrs: map[string]string{"existing": "key"}, |
| want: map[string]string{"existing": "key"}, |
| }, |
| { |
| name: "nil attrs", |
| headers: map[string]string{"key": "value"}, |
| attrs: nil, |
| want: nil, |
| }, |
| { |
| name: "skip empty keys and values", |
| headers: map[string]string{ |
| "": "value", |
| "key": "", |
| " ": "value", |
| "valid": "valid-value", |
| }, |
| attrs: make(map[string]string), |
| want: map[string]string{ |
| "header:valid": "valid-value", |
| }, |
| }, |
| } |
|
|
| for _, tt := range tests { |
| t.Run(tt.name, func(t *testing.T) { |
| addConfigHeadersToAttrs(tt.headers, tt.attrs) |
| if !reflect.DeepEqual(tt.attrs, tt.want) { |
| t.Errorf("expected %v, got %v", tt.want, tt.attrs) |
| } |
| }) |
| } |
| } |
|
|