package provider import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "time" "neuroforge/internal/core" "neuroforge/internal/store" ) func TestRouterHasNoGlobalInferenceTimeout(t *testing.T) { s, err := store.New(t.TempDir()) if err != nil { t.Fatal(err) } defer s.Close() r := NewRouter(s) if r.http.Timeout != 0 { t.Fatalf("global http client timeout=%v, want 0", r.http.Timeout) } tr, ok := r.http.Transport.(*http.Transport) if !ok { t.Fatalf("transport type %T", r.http.Transport) } if tr.ResponseHeaderTimeout != 0 { t.Fatalf("response header timeout=%v, want 0 for long non-streaming inference", tr.ResponseHeaderTimeout) } } func TestOllamaRuntimeOptionsAreSent(t *testing.T) { var got map[string]any fake := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/chat" { http.NotFound(w, r) return } if err := json.NewDecoder(r.Body).Decode(&got); err != nil { t.Fatal(err) } _ = json.NewEncoder(w).Encode(map[string]any{ "message": map[string]any{"content": "ok"}, "prompt_eval_count": 4, "eval_count": 3, }) })) defer fake.Close() s, err := store.New(t.TempDir()) if err != nil { t.Fatal(err) } defer s.Close() cfg := s.Config() cfg.Routing.ChatProvider = "ollama" cfg.Routing.ChatNodeID = "local" cfg.Ollama = []core.OllamaServer{{ ID: "local", Name: "Local", BaseURL: fake.URL, ChatModel: "qwen-test", EmbeddingModel: "embed-test", Weight: 1, Enabled: true, RequestTimeoutSeconds: 0, NumCtx: 8192, NumPredict: 512, Think: "low", ChatKeepAlive: "30m", EmbeddingKeepAlive: "5m", }} if err := s.UpdateConfig(cfg); err != nil { t.Fatal(err) } r := NewRouter(s) if _, err := r.Chat(context.Background(), "ollama", "", "", "hello", 1400); err != nil { t.Fatal(err) } if got["keep_alive"] != "30m" || got["think"] != "low" { t.Fatalf("runtime body=%#v", got) } opts, ok := got["options"].(map[string]any) if !ok { t.Fatalf("options missing: %#v", got) } if opts["num_ctx"] != float64(8192) || opts["num_predict"] != float64(512) { t.Fatalf("options=%#v", opts) } } func TestOllamaExplicitRequestTimeoutStillWorks(t *testing.T) { fake := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(1200 * time.Millisecond) _ = json.NewEncoder(w).Encode(map[string]any{"message": map[string]any{"content": "late"}}) })) defer fake.Close() s, err := store.New(t.TempDir()) if err != nil { t.Fatal(err) } defer s.Close() cfg := s.Config() cfg.Ollama[0].BaseURL = fake.URL cfg.Ollama[0].RequestTimeoutSeconds = 1 if err := s.UpdateConfig(cfg); err != nil { t.Fatal(err) } r := NewRouter(s) start := time.Now() _, err = r.ChatOn(context.Background(), "ollama", "", "local", "", "hello", 32) if err == nil { t.Fatal("expected configured timeout") } if time.Since(start) > 2*time.Second { t.Fatalf("configured timeout was not enforced promptly: %v", time.Since(start)) } }