package config_test import ( "fmt" "os" "path/filepath" "reflect" "strings" "testing" "iop/packages/go/config" ) func TestLoadEdge_EdgeIdentity(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := "server:\n listen: \"0.0.0.0:9090\"\nedge:\n id: \"edge-dgx-group\"\n name: \"DGX Group\"\n" if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } if cfg.Edge.ID != "edge-dgx-group" { t.Fatalf("expected edge.id=%q, got %q", "edge-dgx-group", cfg.Edge.ID) } if cfg.Edge.Name != "DGX Group" { t.Fatalf("expected edge.name=%q, got %q", "DGX Group", cfg.Edge.Name) } } func TestLoadEdge_EdgeIdentityEmptyByDefault(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") if err := os.WriteFile(f, []byte("server:\n listen: \"0.0.0.0:9090\"\n"), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } if cfg.Edge.ID != "" || cfg.Edge.Name != "" { t.Fatalf("expected empty edge identity by default, got id=%q name=%q", cfg.Edge.ID, cfg.Edge.Name) } } func TestLoadEdge_OpenAIDefaults(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") if err := os.WriteFile(f, []byte("server:\n listen: \"0.0.0.0:9090\"\n"), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } if cfg.OpenAI.Enabled { t.Fatal("expected openai.enabled=false by default") } if cfg.OpenAI.Listen != "0.0.0.0:18081" { t.Fatalf("expected openai.listen default, got %q", cfg.OpenAI.Listen) } if cfg.OpenAI.BearerToken != "" { t.Fatalf("expected openai.bearer_token empty by default, got %q", cfg.OpenAI.BearerToken) } if cfg.OpenAI.ProviderAuth.Enabled { t.Fatal("expected openai.provider_auth.enabled=false by default") } if cfg.OpenAI.ProviderAuth.FromHeader != "" || cfg.OpenAI.ProviderAuth.TargetHeader != "" || cfg.OpenAI.ProviderAuth.Scheme != "" || cfg.OpenAI.ProviderAuth.Required { t.Fatalf("expected openai.provider_auth fields empty/false by default, got %+v", cfg.OpenAI.ProviderAuth) } if cfg.OpenAI.Adapter != "ollama" { t.Fatalf("expected openai.adapter=%q, got %q", "ollama", cfg.OpenAI.Adapter) } if cfg.OpenAI.SessionID != "openai" { t.Fatalf("expected openai.session_id=%q, got %q", "openai", cfg.OpenAI.SessionID) } if cfg.OpenAI.TimeoutSec != 120 { t.Fatalf("expected openai.timeout_sec=120, got %d", cfg.OpenAI.TimeoutSec) } if !cfg.OpenAI.StrictOutput { t.Fatal("expected openai.strict_output=true") } if cfg.OpenAI.StrictStreamBuffer { t.Fatal("expected openai.strict_stream_buffer=false") } if cfg.Metrics.Port != 19092 { t.Fatalf("expected metrics.port=19092, got %d", cfg.Metrics.Port) } if cfg.LongContextThresholdTokens != 100000 { t.Fatalf("expected long_context_threshold_tokens=100000 by default, got %d", cfg.LongContextThresholdTokens) } } func TestLoadEdge_LongContextThresholdOverride(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" long_context_threshold_tokens: 120000 ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } if cfg.LongContextThresholdTokens != 120000 { t.Fatalf("expected long_context_threshold_tokens=120000, got %d", cfg.LongContextThresholdTokens) } } func TestLoadEdge_LongContextThresholdRejectsNonPositive(t *testing.T) { for _, tc := range []struct { name string value int }{ {name: "zero", value: 0}, {name: "negative", value: -1}, } { t.Run(tc.name, func(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := fmt.Sprintf(` server: listen: "0.0.0.0:9090" long_context_threshold_tokens: %d `, tc.value) if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } _, err := config.LoadEdge(f) if err == nil { t.Fatal("expected error for non-positive long_context_threshold_tokens") } if !strings.Contains(err.Error(), "long_context_threshold_tokens must be positive") { t.Fatalf("expected error mentioning positive threshold, got %v", err) } }) } } func TestLoadEdge_OpenAIOverride(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" openai: enabled: true provider_id: "test-provider" listen: "127.0.0.1:8088" bearer_token: "secret-token" node: "node0" adapter: "ollama" target: "llama-test" models: - "llama-test" session_id: "cline" timeout_sec: 45 strict_output: false strict_stream_buffer: true ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } if !cfg.OpenAI.Enabled { t.Fatal("expected openai.enabled=true") } if cfg.OpenAI.Listen != "127.0.0.1:8088" || cfg.OpenAI.NodeRef != "node0" { t.Fatalf("unexpected openai routing config: %+v", cfg.OpenAI) } if cfg.OpenAI.BearerToken != "secret-token" { t.Fatalf("expected openai.bearer_token=%q, got %q", "secret-token", cfg.OpenAI.BearerToken) } if cfg.OpenAI.Target != "llama-test" || len(cfg.OpenAI.Models) != 1 || cfg.OpenAI.Models[0] != "llama-test" { t.Fatalf("unexpected openai model config: %+v", cfg.OpenAI) } if cfg.OpenAI.SessionID != "cline" || cfg.OpenAI.TimeoutSec != 45 { t.Fatalf("unexpected openai execution config: %+v", cfg.OpenAI) } if cfg.OpenAI.StrictOutput { t.Fatalf("unexpected openai strict output config: %+v", cfg.OpenAI) } if !cfg.OpenAI.StrictStreamBuffer { t.Fatalf("unexpected openai strict stream buffer config: %+v", cfg.OpenAI) } } func TestLoadEdge_OpenAIProviderAuthEnabledDefaults(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" openai: provider_auth: enabled: true ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } auth := cfg.OpenAI.ProviderAuth if !auth.Enabled { t.Fatal("expected provider_auth.enabled=true") } if auth.FromHeader != "X-IOP-Provider-Authorization" { t.Fatalf("expected default from_header, got %q", auth.FromHeader) } if auth.TargetHeader != "Authorization" { t.Fatalf("expected default target_header, got %q", auth.TargetHeader) } if auth.Scheme != "Bearer" { t.Fatalf("expected default scheme Bearer, got %q", auth.Scheme) } if !auth.Required { t.Fatal("expected required=true by default when provider_auth is enabled") } } func TestLoadEdge_OpenAIProviderAuthOverride(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" openai: provider_auth: enabled: true from_header: "X-Seulgivibe-Token" target_header: "X-Provider-Authorization" scheme: "Token" required: false ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } auth := cfg.OpenAI.ProviderAuth if !auth.Enabled { t.Fatal("expected provider_auth.enabled=true") } if auth.FromHeader != "X-Seulgivibe-Token" || auth.TargetHeader != "X-Provider-Authorization" || auth.Scheme != "Token" || auth.Required { t.Fatalf("unexpected provider_auth override: %+v", auth) } } func TestLoadEdge_OpenAIProviderAuthRejectsBlankHeaders(t *testing.T) { for _, tc := range []struct { name string field string wantMsg string }{ {name: "from_header", field: "from_header", wantMsg: "from_header"}, {name: "target_header", field: "target_header", wantMsg: "target_header"}, } { t.Run(tc.name, func(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := fmt.Sprintf(` server: listen: "0.0.0.0:9090" openai: provider_auth: enabled: true %s: " " `, tc.field) if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } _, err := config.LoadEdge(f) if err == nil { t.Fatal("expected blank provider_auth header error") } if !strings.Contains(err.Error(), tc.wantMsg) { t.Fatalf("expected error mentioning %q, got %v", tc.wantMsg, err) } }) } } func TestLoadEdge_OpenAIProviderAuthRejectsInboundCallerAuthHeaders(t *testing.T) { for _, tc := range []struct { name string header string }{ {name: "Authorization exact", header: "Authorization"}, {name: "authorization lowercase", header: "authorization"}, {name: "AUTHORIZATION uppercase", header: "AUTHORIZATION"}, {name: "Authorization with whitespace", header: " Authorization "}, {name: "X-Api-Key exact", header: "X-Api-Key"}, {name: "x-api-key lowercase", header: "x-api-key"}, {name: "X-API-KEY uppercase", header: "X-API-KEY"}, {name: "X-Api-Key with whitespace", header: " X-Api-Key "}, } { t.Run(tc.name, func(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := fmt.Sprintf(` server: listen: "0.0.0.0:9090" openai: provider_auth: enabled: true from_header: %q `, tc.header) if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } _, err := config.LoadEdge(f) if err == nil { t.Fatalf("expected error for inbound caller auth header %q", tc.header) } if !strings.Contains(err.Error(), "must not reuse inbound caller authentication header") { t.Fatalf("expected error mentioning inbound caller authentication header, got %v", err) } }) } } func TestNormalizeProviderTypeOpenAICompatibleAliases(t *testing.T) { cases := []struct { name string in string want string }{ {name: "openai compat", in: "openai_compat", want: "openai_compat"}, {name: "openai api", in: "openai_api", want: "openai_compat"}, {name: "vllm", in: "vllm", want: "openai_compat"}, {name: "vllm mlx", in: "vllm-mlx", want: "openai_compat"}, {name: "lemonade", in: "lemonade", want: "openai_compat"}, {name: "sglang", in: "sglang", want: "openai_compat"}, {name: "seulgivibe claude", in: "seulgivibe_claude", want: "openai_compat"}, {name: "seulgivibe openai", in: "seulgivibe_openai", want: "openai_compat"}, {name: "normalized case and space", in: " VLLM-MLX ", want: "openai_compat"}, {name: "ollama", in: "ollama", want: "ollama"}, {name: "cli", in: "cli", want: "cli"}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { if got := config.NormalizeProviderType(tc.in); got != tc.want { t.Fatalf("NormalizeProviderType(%q) = %q, want %q", tc.in, got, tc.want) } }) } } func TestLoadEdge_OpenAIPrincipalTokens(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" openai: enabled: true provider_id: "test-provider" principal_tokens: - token_ref: "iop-tok-alice" token_hash_sha256: "` + strings.Repeat("a1", 32) + `" principal_ref: "user:alice" principal_alias: "alice" - token_ref: "iop-tok-bob" token_hash_sha256: "` + strings.Repeat("b2", 32) + `" principal_ref: "user:bob" ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } if len(cfg.OpenAI.PrincipalTokens) != 2 { t.Fatalf("expected 2 principal_tokens, got %d", len(cfg.OpenAI.PrincipalTokens)) } first := cfg.OpenAI.PrincipalTokens[0] if first.TokenRef != "iop-tok-alice" || first.PrincipalRef != "user:alice" || first.PrincipalAlias != "alice" { t.Fatalf("unexpected first principal token: %+v", first) } if first.TokenHashSHA256 != strings.Repeat("a1", 32) { t.Fatalf("unexpected token hash: %q", first.TokenHashSHA256) } second := cfg.OpenAI.PrincipalTokens[1] if second.TokenRef != "iop-tok-bob" || second.PrincipalRef != "user:bob" || second.PrincipalAlias != "" { t.Fatalf("unexpected second principal token: %+v", second) } } func TestLoadEdge_OpenAIPrincipalTokensAllowMultipleTokensPerPrincipal(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" openai: enabled: true provider_id: "test-provider" principal_tokens: - token_ref: "alice-app-a" token_hash_sha256: "` + strings.Repeat("a1", 32) + `" principal_ref: "user:alice" principal_alias: "alice" - token_ref: "alice-app-b" token_hash_sha256: "` + strings.Repeat("b2", 32) + `" principal_ref: "user:alice" principal_alias: "alice" ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } if len(cfg.OpenAI.PrincipalTokens) != 2 { t.Fatalf("expected 2 principal_tokens, got %d", len(cfg.OpenAI.PrincipalTokens)) } if cfg.OpenAI.PrincipalTokens[0].PrincipalRef != cfg.OpenAI.PrincipalTokens[1].PrincipalRef { t.Fatalf("expected both tokens to map to the same principal: %+v", cfg.OpenAI.PrincipalTokens) } if cfg.OpenAI.PrincipalTokens[0].TokenRef == cfg.OpenAI.PrincipalTokens[1].TokenRef { t.Fatalf("token_ref must distinguish app/integration tokens: %+v", cfg.OpenAI.PrincipalTokens) } } func TestLoadEdge_OpenAIPrincipalTokensRejectInvalid(t *testing.T) { validHash := strings.Repeat("a1", 32) for _, tc := range []struct { name string yaml string }{ { name: "duplicate token_ref", yaml: ` openai: principal_tokens: - token_ref: "dup" token_hash_sha256: "` + validHash + `" principal_ref: "user:alice" - token_ref: "dup" token_hash_sha256: "` + strings.Repeat("b2", 32) + `" principal_ref: "user:bob" `, }, { name: "duplicate token_hash_sha256", yaml: ` openai: principal_tokens: - token_ref: "one" token_hash_sha256: "` + validHash + `" principal_ref: "user:alice" - token_ref: "two" token_hash_sha256: "` + validHash + `" principal_ref: "user:bob" `, }, { name: "empty principal_ref", yaml: ` openai: principal_tokens: - token_ref: "one" token_hash_sha256: "` + validHash + `" principal_ref: "" `, }, { name: "non-hex hash", yaml: ` openai: principal_tokens: - token_ref: "one" token_hash_sha256: "` + strings.Repeat("z", 64) + `" principal_ref: "user:alice" `, }, { name: "non-64-length hash", yaml: ` openai: principal_tokens: - token_ref: "one" token_hash_sha256: "abcd" principal_ref: "user:alice" `, }, } { t.Run(tc.name, func(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") body := "server:\n listen: \"0.0.0.0:9090\"\n" + tc.yaml if err := os.WriteFile(f, []byte(body), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } if _, err := config.LoadEdge(f); err == nil { t.Fatal("expected validation error, got nil") } }) } } // TestOpenAIPrincipalTokenConf_NoRawTokenField guards against reintroducing a // raw-token-storing field on the principal token mapping struct: only // token_ref, token_hash_sha256, principal_ref, and principal_alias are // allowed YAML keys. func TestOpenAIPrincipalTokenConf_NoRawTokenField(t *testing.T) { allowed := map[string]struct{}{ "token_ref": {}, "token_hash_sha256": {}, "principal_ref": {}, "principal_alias": {}, } typ := reflect.TypeOf(config.OpenAIPrincipalTokenConf{}) for i := 0; i < typ.NumField(); i++ { tag := typ.Field(i).Tag.Get("yaml") key := strings.SplitN(tag, ",", 2)[0] if _, ok := allowed[key]; !ok { t.Fatalf("unexpected field %q (yaml tag %q) on OpenAIPrincipalTokenConf; raw token values must not be stored in config", typ.Field(i).Name, tag) } } } func TestEdgeOpenAIProviderAuthConf_NoRawTokenField(t *testing.T) { allowed := map[string]struct{}{ "enabled": {}, "from_header": {}, "target_header": {}, "scheme": {}, "required": {}, } typ := reflect.TypeOf(config.EdgeOpenAIProviderAuthConf{}) for i := 0; i < typ.NumField(); i++ { tag := typ.Field(i).Tag.Get("yaml") key := strings.SplitN(tag, ",", 2)[0] if _, ok := allowed[key]; !ok { t.Fatalf("unexpected field %q (yaml tag %q) on EdgeOpenAIProviderAuthConf; raw provider tokens must not be stored in config", typ.Field(i).Name, tag) } } } func TestLoadEdge_OpenAIRouteCatalog(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" openai: enabled: true provider_id: "test-provider" listen: "0.0.0.0:18081" adapter: "ollama" model_routes: - model: "model-a" adapter: "ollama" target: "llama3" node: "node-01" session_id: "sess-a" timeout_sec: 30 max_queue: 10 queue_timeout_ms: 5000 - model: "model-b" adapter: "vllm" target: "qwen" ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } if len(cfg.OpenAI.ModelRoutes) != 2 { t.Fatalf("expected 2 model_routes, got %d", len(cfg.OpenAI.ModelRoutes)) } r0 := cfg.OpenAI.ModelRoutes[0] if r0.Model != "model-a" || r0.Adapter != "ollama" || r0.Target != "llama3" { t.Errorf("route[0] mismatch: %+v", r0) } if r0.NodeRef != "node-01" || r0.SessionID != "sess-a" || r0.TimeoutSec != 30 { t.Errorf("route[0] optional fields mismatch: %+v", r0) } if r0.MaxQueue != 10 || r0.QueueTimeoutMS != 5000 { t.Errorf("route[0] queue policy mismatch: max_queue=%d, queue_timeout_ms=%d", r0.MaxQueue, r0.QueueTimeoutMS) } r1 := cfg.OpenAI.ModelRoutes[1] if r1.Model != "model-b" || r1.Adapter != "vllm" || r1.Target != "qwen" { t.Errorf("route[1] mismatch: %+v", r1) } if r1.MaxQueue != 0 || r1.QueueTimeoutMS != 0 { t.Errorf("route[1] queue policy should default to 0: max_queue=%d, queue_timeout_ms=%d", r1.MaxQueue, r1.QueueTimeoutMS) } } func TestLoadEdge_OpenAIRouteCatalogDuplicateModelRejects(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" openai: model_routes: - model: "model-a" adapter: "ollama" target: "llama3" - model: "model-a" adapter: "vllm" target: "qwen" ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } _, err := config.LoadEdge(f) if err == nil { t.Fatal("expected error for duplicate model route") } if !strings.Contains(err.Error(), "model_routes") || !strings.Contains(err.Error(), "model-a") { t.Fatalf("expected error mentioning model_routes and model-a, got %v", err) } } func TestLoadEdge_OpenAIRouteCatalogEmptyModelRejects(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" openai: model_routes: - model: "" target: "llama3" ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } _, err := config.LoadEdge(f) if err == nil { t.Fatal("expected error for empty model in route catalog") } if !strings.Contains(err.Error(), "model_routes") { t.Fatalf("expected error mentioning model_routes, got %v", err) } } func TestLoadEdge_OpenAIRouteCatalogQueuePolicyRejectsNegative(t *testing.T) { dir := t.TempDir() // Test negative max_queue f1 := filepath.Join(dir, "edge_neg_max.yaml") yaml1 := ` server: listen: "0.0.0.0:9090" openai: model_routes: - model: "model-a" target: "llama3" max_queue: -1 ` if err := os.WriteFile(f1, []byte(yaml1), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } _, err := config.LoadEdge(f1) if err == nil { t.Fatal("expected error for negative max_queue") } if !strings.Contains(err.Error(), "max_queue must be non-negative") { t.Fatalf("expected error mentioning max_queue must be non-negative, got %v", err) } // Test negative queue_timeout_ms f2 := filepath.Join(dir, "edge_neg_timeout.yaml") yaml2 := ` server: listen: "0.0.0.0:9090" openai: model_routes: - model: "model-a" target: "llama3" queue_timeout_ms: -500 ` if err := os.WriteFile(f2, []byte(yaml2), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } _, err = config.LoadEdge(f2) if err == nil { t.Fatal("expected error for negative queue_timeout_ms") } if !strings.Contains(err.Error(), "queue_timeout_ms must be non-negative") { t.Fatalf("expected error mentioning queue_timeout_ms must be non-negative, got %v", err) } } // NormalizeAdapters regression tests func TestLoadEdge_OpenAICompatInstances(t *testing.T) { dir := t.TempDir() f := filepath.Join(dir, "edge.yaml") yaml := ` server: listen: "0.0.0.0:9090" nodes: - alias: "lemonade-node" adapters: openai_compat_instances: - name: "lemonade" enabled: true provider: "lemonade" endpoint: "http://127.0.0.1:13305" headers: Authorization: "Bearer test-key" capacity: 4 max_queue: 10 queue_timeout_ms: 1500 request_timeout_ms: 30000 ` if err := os.WriteFile(f, []byte(yaml), 0o600); err != nil { t.Fatalf("write yaml: %v", err) } cfg, err := config.LoadEdge(f) if err != nil { t.Fatalf("load: %v", err) } if len(cfg.Nodes) == 0 { t.Fatal("expected 1 node") } insts := cfg.Nodes[0].Adapters.OpenAICompatInstances if len(insts) != 1 { t.Fatalf("expected 1 openai_compat instance, got %d", len(insts)) } inst := insts[0] if inst.Name != "lemonade" || inst.Provider != "lemonade" || inst.Endpoint != "http://127.0.0.1:13305" { t.Errorf("unexpected instance config: %+v", inst) } if inst.Headers["authorization"] != "Bearer test-key" { t.Errorf("expected header authorization Bearer test-key, got %q", inst.Headers["authorization"]) } if inst.Capacity != 4 || inst.MaxQueue != 10 || inst.QueueTimeoutMS != 1500 || inst.RequestTimeoutMS != 30000 { t.Errorf("unexpected queue config: %+v", inst) } } func TestNormalizeAdapters_OpenAICompatIdempotent(t *testing.T) { a := config.AdaptersConf{ OpenAICompat: config.OpenAICompatConf{ Enabled: true, Provider: "lemonade", Endpoint: "http://127.0.0.1:13305", Headers: map[string]string{"X-Test": "val"}, }, } if err := config.NormalizeAdapters(&a); err != nil { t.Fatalf("first normalize: %v", err) } if len(a.OpenAICompatInstances) != 1 { t.Fatalf("expected 1 instance after first normalize, got %d", len(a.OpenAICompatInstances)) } if err := config.NormalizeAdapters(&a); err != nil { t.Fatalf("second normalize (idempotent): %v", err) } if len(a.OpenAICompatInstances) != 1 { t.Fatalf("expected still 1 instance after second normalize, got %d", len(a.OpenAICompatInstances)) } } func TestNormalizeAdapters_OpenAICompatConflictErrors(t *testing.T) { a := config.AdaptersConf{ OpenAICompat: config.OpenAICompatConf{Enabled: true, Endpoint: "http://127.0.0.1:13305"}, OpenAICompatInstances: []config.OpenAICompatInstanceConf{ {Name: "openai_compat", Enabled: true, Endpoint: "http://other-host:13305"}, }, } if err := config.NormalizeAdapters(&a); err == nil { t.Fatal("expected error for conflicting legacy openai_compat and explicit instance with same name") } } func TestNormalizeAdapters_OpenAICompatDuplicateNameRejects(t *testing.T) { a := config.AdaptersConf{ OpenAICompatInstances: []config.OpenAICompatInstanceConf{ {Name: "same", Enabled: true, Endpoint: "http://127.0.0.1:13305"}, {Name: "same", Enabled: true, Endpoint: "http://127.0.0.2:13305"}, }, } if err := config.NormalizeAdapters(&a); err == nil { t.Fatal("expected error for duplicate openai_compat instance name") } } func TestNormalizeAdapters_OpenAICompatQueueValidation(t *testing.T) { a := config.AdaptersConf{ OpenAICompatInstances: []config.OpenAICompatInstanceConf{ {Name: "test", Enabled: true, Endpoint: "http://127.0.0.1:13305", Capacity: -1}, }, } err := config.NormalizeAdapters(&a) if err == nil { t.Fatal("expected negative provider queue config error") } if !strings.Contains(err.Error(), "capacity") { t.Fatalf("expected error to mention capacity, got %v", err) } } // S02 REVIEW_VLLM_CONFIG: vLLM OpenAI-compatible route + instance fixture // verifies that alias/target/provider/endpoint/no-headers/timeout/queue are // preserved through config load and mapper/factory contract.