package openai_compat import ( "context" "net/http" "net/http/httptest" "strings" "testing" "go.uber.org/zap" "iop/apps/node/internal/runtime" "iop/packages/go/config" ) func TestOpenAICompatCapabilitiesQueryModels(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/v1/models" { t.Fatalf("unexpected path %s", r.URL.Path) } _, _ = w.Write([]byte(`{"object":"list","data":[{"id":"model-a"},{"id":"model-b"}]}`)) })) defer server.Close() adapter := New(config.OpenAICompatConf{ Provider: "lemonade", Endpoint: server.URL, Capacity: 10, MaxQueue: 20, QueueTimeoutMS: 5000, RequestTimeoutMS: 10000, }, zap.NewNop()) caps, err := adapter.Capabilities(context.Background()) if err != nil { t.Fatalf("Capabilities failed: %v", err) } if caps.AdapterName != Name { t.Fatalf("AdapterName: got %q want %q", caps.AdapterName, Name) } if got := strings.Join(caps.Targets, ","); got != "model-a,model-b" { t.Fatalf("targets: got %q", got) } if caps.MaxConcurrency != 10 { t.Fatalf("expected MaxConcurrency 10, got %d", caps.MaxConcurrency) } if caps.MaxQueue != 20 || caps.QueueTimeoutMS != 5000 || caps.RequestTimeoutMS != 10000 { t.Fatalf("queue config: got %+v", caps) } if caps.ProviderStatus != runtime.ProviderStatusAvailable { t.Fatalf("expected available, got %s", caps.ProviderStatus) } adapterDefault := New(config.OpenAICompatConf{Endpoint: server.URL}, zap.NewNop()) capsDefault, err := adapterDefault.Capabilities(context.Background()) if err != nil { t.Fatalf("Capabilities failed: %v", err) } if capsDefault.MaxConcurrency != 8 { t.Fatalf("expected default MaxConcurrency 8, got %d", capsDefault.MaxConcurrency) } } func TestOpenAICompatProbeProviderAvailability(t *testing.T) { t.Run("200_ok_and_target_hit", func(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/v1/models" { t.Fatalf("unexpected path %s", r.URL.Path) } _, _ = w.Write([]byte(`{"object":"list","data":[{"id":"model-a"},{"id":"model-b"}]}`)) })) defer server.Close() adapter := New(config.OpenAICompatConf{Provider: "lemonade", Endpoint: server.URL}, zap.NewNop()) res, err := adapter.ProbeProvider(context.Background(), "model-a") if err != nil { t.Fatalf("ProbeProvider failed: %v", err) } if res.Status != runtime.ProviderStatusAvailable { t.Errorf("expected available, got %s", res.Status) } if len(res.Targets) != 2 || res.Targets[0] != "model-a" { t.Errorf("unexpected Targets: %+v", res.Targets) } if res.Metadata["provider"] != "lemonade" { t.Errorf("expected provider metadata, got %+v", res.Metadata) } }) t.Run("200_ok_and_target_miss", func(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte(`{"object":"list","data":[{"id":"model-a"}]}`)) })) defer server.Close() adapter := New(config.OpenAICompatConf{Endpoint: server.URL}, zap.NewNop()) res, err := adapter.ProbeProvider(context.Background(), "model-b") if err != nil { t.Fatalf("ProbeProvider failed: %v", err) } if res.Status != runtime.ProviderStatusUnavailable { t.Errorf("expected unavailable, got %s", res.Status) } if !strings.Contains(res.Detail, "not found") { t.Errorf("expected 'not found' in detail, got %s", res.Detail) } }) t.Run("500_internal_error", func(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) })) defer server.Close() adapter := New(config.OpenAICompatConf{Endpoint: server.URL}, zap.NewNop()) res, err := adapter.ProbeProvider(context.Background(), "model-a") if err != nil { t.Fatalf("ProbeProvider failed: %v", err) } if res.Status != runtime.ProviderStatusUnavailable { t.Errorf("expected unavailable, got %s", res.Status) } }) t.Run("empty_target", func(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { _, _ = w.Write([]byte(`{"object":"list","data":[{"id":"model-a"}]}`)) })) defer server.Close() adapter := New(config.OpenAICompatConf{Endpoint: server.URL}, zap.NewNop()) res, err := adapter.ProbeProvider(context.Background(), "") if err != nil { t.Fatalf("ProbeProvider failed: %v", err) } if res.Status != runtime.ProviderStatusAvailable { t.Errorf("expected available, got %s", res.Status) } }) }